Bug 1231213 - Implement PFetchEventOp(Proxy) IPDL protocols and FetchEventOp(Proxy){Parent,Child}. r=asuth

Differential Revision: https://phabricator.services.mozilla.com/D26171

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Perry Jiang 2019-08-15 17:27:07 +00:00
parent 200a71c58c
commit 5b603200f7
23 changed files with 1245 additions and 20 deletions

View File

@ -0,0 +1,487 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FetchEventOpChild.h"
#include <utility>
#include "MainThreadUtils.h"
#include "nsContentPolicyUtils.h"
#include "nsContentUtils.h"
#include "nsDebug.h"
#include "nsError.h"
#include "nsIChannel.h"
#include "nsIConsoleReportCollector.h"
#include "nsIContentPolicy.h"
#include "nsIInputStream.h"
#include "nsILoadInfo.h"
#include "nsINetworkInterceptController.h"
#include "nsIObserverService.h"
#include "nsIScriptError.h"
#include "nsISupportsImpl.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsProxyRelease.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
#include "ServiceWorkerPrivate.h"
#include "mozilla/Assertions.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/InternalHeaders.h"
#include "mozilla/dom/InternalResponse.h"
#include "mozilla/dom/PRemoteWorkerControllerChild.h"
#include "mozilla/dom/ServiceWorkerRegistrationInfo.h"
#include "mozilla/net/NeckoChannelParams.h"
namespace mozilla {
namespace dom {
namespace {
bool CSPPermitsResponse(nsILoadInfo* aLoadInfo, InternalResponse* aResponse,
const nsACString& aWorkerScriptSpec) {
AssertIsOnMainThread();
MOZ_ASSERT(aLoadInfo);
nsCString url = aResponse->GetUnfilteredURL();
if (url.IsEmpty()) {
// Synthetic response.
url = aWorkerScriptSpec;
}
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
int16_t decision = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(uri, aLoadInfo, EmptyCString(), &decision);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
return decision == nsIContentPolicy::ACCEPT;
}
void AsyncLog(nsIInterceptedChannel* aChannel, const nsACString& aScriptSpec,
uint32_t aLineNumber, uint32_t aColumnNumber,
const nsACString& aMessageName, nsTArray<nsString>&& aParams) {
AssertIsOnMainThread();
MOZ_ASSERT(aChannel);
nsCOMPtr<nsIConsoleReportCollector> reporter =
aChannel->GetConsoleReportCollector();
if (reporter) {
// NOTE: is appears that `const nsTArray<nsString>&` is required for
// nsIConsoleReportCollector::AddConsoleReport to resolve to the correct
// overload.
const nsTArray<nsString> params = std::move(aParams);
reporter->AddConsoleReport(
nsIScriptError::errorFlag,
NS_LITERAL_CSTRING("Service Worker Interception"),
nsContentUtils::eDOM_PROPERTIES, aScriptSpec, aLineNumber,
aColumnNumber, aMessageName, params);
}
}
class SynthesizeResponseWatcher final : public nsIInterceptedBodyCallback {
public:
NS_DECL_THREADSAFE_ISUPPORTS
SynthesizeResponseWatcher(
const nsMainThreadPtrHandle<nsIInterceptedChannel>& aInterceptedChannel,
const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration,
const bool aIsNonSubresourceRequest,
FetchEventRespondWithClosure&& aClosure, nsAString&& aRequestURL)
: mInterceptedChannel(aInterceptedChannel),
mRegistration(aRegistration),
mIsNonSubresourceRequest(aIsNonSubresourceRequest),
mClosure(std::move(aClosure)),
mRequestURL(std::move(aRequestURL)) {
AssertIsOnMainThread();
MOZ_ASSERT(mInterceptedChannel);
MOZ_ASSERT(mRegistration);
}
NS_IMETHOD
BodyComplete(nsresult aRv) override {
AssertIsOnMainThread();
MOZ_ASSERT(mInterceptedChannel);
if (NS_WARN_IF(NS_FAILED(aRv))) {
AsyncLog(mInterceptedChannel, mClosure.respondWithScriptSpec(),
mClosure.respondWithLineNumber(),
mClosure.respondWithColumnNumber(),
NS_LITERAL_CSTRING("InterceptionFailedWithURL"), {mRequestURL});
CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
return NS_OK;
}
nsresult rv = mInterceptedChannel->FinishSynthesizedResponse();
if (NS_WARN_IF(NS_FAILED(rv))) {
CancelInterception(rv);
}
mInterceptedChannel = nullptr;
return NS_OK;
}
// See FetchEventOpChild::MaybeScheduleRegistrationUpdate() for comments.
void CancelInterception(nsresult aStatus) {
AssertIsOnMainThread();
MOZ_ASSERT(mInterceptedChannel);
MOZ_ASSERT(mRegistration);
mInterceptedChannel->CancelInterception(aStatus);
if (mIsNonSubresourceRequest) {
mRegistration->MaybeScheduleUpdate();
} else {
mRegistration->MaybeScheduleTimeCheckAndUpdate();
}
mInterceptedChannel = nullptr;
mRegistration = nullptr;
}
private:
~SynthesizeResponseWatcher() {
if (NS_WARN_IF(mInterceptedChannel)) {
CancelInterception(NS_ERROR_DOM_ABORT_ERR);
}
}
nsMainThreadPtrHandle<nsIInterceptedChannel> mInterceptedChannel;
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
const bool mIsNonSubresourceRequest;
const FetchEventRespondWithClosure mClosure;
const nsString mRequestURL;
};
NS_IMPL_ISUPPORTS(SynthesizeResponseWatcher, nsIInterceptedBodyCallback)
} // anonymous namespace
/* static */ RefPtr<GenericPromise> FetchEventOpChild::Create(
PRemoteWorkerControllerChild* aManager,
ServiceWorkerFetchEventOpArgs&& aArgs,
nsCOMPtr<nsIInterceptedChannel> aInterceptedChannel,
RefPtr<ServiceWorkerRegistrationInfo> aRegistration,
RefPtr<KeepAliveToken>&& aKeepAliveToken) {
AssertIsOnMainThread();
MOZ_ASSERT(aManager);
MOZ_ASSERT(aInterceptedChannel);
MOZ_ASSERT(aKeepAliveToken);
FetchEventOpChild* actor = new FetchEventOpChild(
std::move(aArgs), std::move(aInterceptedChannel),
std::move(aRegistration), std::move(aKeepAliveToken));
Unused << aManager->SendPFetchEventOpConstructor(actor, actor->mArgs);
return actor->mPromiseHolder.Ensure(__func__);
}
FetchEventOpChild::~FetchEventOpChild() {
AssertIsOnMainThread();
MOZ_ASSERT(mInterceptedChannelHandled);
MOZ_DIAGNOSTIC_ASSERT(mPromiseHolder.IsEmpty());
}
FetchEventOpChild::FetchEventOpChild(
ServiceWorkerFetchEventOpArgs&& aArgs,
nsCOMPtr<nsIInterceptedChannel>&& aInterceptedChannel,
RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration,
RefPtr<KeepAliveToken>&& aKeepAliveToken)
: mArgs(std::move(aArgs)),
mInterceptedChannel(std::move(aInterceptedChannel)),
mRegistration(std::move(aRegistration)),
mKeepAliveToken(std::move(aKeepAliveToken)) {}
mozilla::ipc::IPCResult FetchEventOpChild::RecvAsyncLog(
const nsCString& aScriptSpec, const uint32_t& aLineNumber,
const uint32_t& aColumnNumber, const nsCString& aMessageName,
nsTArray<nsString>&& aParams) {
AssertIsOnMainThread();
MOZ_ASSERT(mInterceptedChannel);
AsyncLog(mInterceptedChannel, aScriptSpec, aLineNumber, aColumnNumber,
aMessageName, std::move(aParams));
return IPC_OK();
}
mozilla::ipc::IPCResult FetchEventOpChild::RecvRespondWith(
IPCFetchEventRespondWithResult&& aResult) {
AssertIsOnMainThread();
switch (aResult.type()) {
case IPCFetchEventRespondWithResult::TIPCSynthesizeResponseArgs:
SynthesizeResponse(std::move(aResult.get_IPCSynthesizeResponseArgs()));
break;
case IPCFetchEventRespondWithResult::TResetInterceptionArgs:
ResetInterception();
break;
case IPCFetchEventRespondWithResult::TCancelInterceptionArgs:
CancelInterception(aResult.get_CancelInterceptionArgs().status());
break;
default:
MOZ_CRASH("Unknown IPCFetchEventRespondWithResult type!");
break;
}
return IPC_OK();
}
mozilla::ipc::IPCResult FetchEventOpChild::Recv__delete__(
const ServiceWorkerFetchEventOpResult& aResult) {
AssertIsOnMainThread();
MOZ_ASSERT(mRegistration);
if (NS_WARN_IF(!mInterceptedChannelHandled)) {
MOZ_ASSERT(NS_FAILED(aResult.rv()));
NS_WARNING(
"Failed to handle intercepted network request; canceling "
"interception!");
CancelInterception(aResult.rv());
}
mPromiseHolder.ResolveIfExists(true, __func__);
/**
* This corresponds to the "Fire Functional Event" algorithm's step 9:
*
* "If the time difference in seconds calculated by the current time minus
* registration's last update check time is greater than 84600, invoke Soft
* Update algorithm with registration."
*
* TODO: this is probably being called later than it should be; it should be
* called ASAP after dispatching the FetchEvent.
*/
mRegistration->MaybeScheduleTimeCheckAndUpdate();
return IPC_OK();
}
void FetchEventOpChild::ActorDestroy(ActorDestroyReason) {
AssertIsOnMainThread();
// If `Recv__delete__` was called, it would have resolved the promise already.
mPromiseHolder.RejectIfExists(NS_ERROR_DOM_ABORT_ERR, __func__);
if (NS_WARN_IF(!mInterceptedChannelHandled)) {
Unused << Recv__delete__(NS_ERROR_DOM_ABORT_ERR);
}
}
nsresult FetchEventOpChild::StartSynthesizedResponse(
IPCSynthesizeResponseArgs&& aArgs) {
AssertIsOnMainThread();
MOZ_ASSERT(mInterceptedChannel);
MOZ_ASSERT(!mInterceptedChannelHandled);
MOZ_ASSERT(mRegistration);
/**
* TODO: moving the IPCInternalResponse won't do anything right now because
* there isn't a prefect-forwarding or rvalue-ref-parameter overload of
* `InternalResponse::FromIPC().`
*/
RefPtr<InternalResponse> response =
InternalResponse::FromIPC(aArgs.internalResponse());
if (NS_WARN_IF(!response)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIChannel> underlyingChannel;
nsresult rv =
mInterceptedChannel->GetChannel(getter_AddRefs(underlyingChannel));
if (NS_WARN_IF(NS_FAILED(rv)) || NS_WARN_IF(!underlyingChannel)) {
return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
}
nsCOMPtr<nsILoadInfo> loadInfo = underlyingChannel->LoadInfo();
if (!CSPPermitsResponse(loadInfo, response, mArgs.workerScriptSpec())) {
return NS_ERROR_CONTENT_BLOCKED;
}
MOZ_ASSERT(response->GetChannelInfo().IsInitialized());
ChannelInfo channelInfo = response->GetChannelInfo();
rv = mInterceptedChannel->SetChannelInfo(&channelInfo);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_INTERCEPTION_FAILED;
}
rv = mInterceptedChannel->SynthesizeStatus(
response->GetUnfilteredStatus(), response->GetUnfilteredStatusText());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
AutoTArray<InternalHeaders::Entry, 5> entries;
response->UnfilteredHeaders()->GetEntries(entries);
for (auto& entry : entries) {
mInterceptedChannel->SynthesizeHeader(entry.mName, entry.mValue);
}
auto castLoadInfo = static_cast<mozilla::net::LoadInfo*>(loadInfo.get());
castLoadInfo->SynthesizeServiceWorkerTainting(response->GetTainting());
// Get the preferred alternative data type of the outer channel
nsAutoCString preferredAltDataType(EmptyCString());
nsCOMPtr<nsICacheInfoChannel> outerChannel =
do_QueryInterface(underlyingChannel);
if (outerChannel &&
!outerChannel->PreferredAlternativeDataTypes().IsEmpty()) {
preferredAltDataType.Assign(
outerChannel->PreferredAlternativeDataTypes()[0].type());
}
nsCOMPtr<nsIInputStream> body;
if (preferredAltDataType.Equals(response->GetAlternativeDataType())) {
body = response->TakeAlternativeBody();
}
if (!body) {
response->GetUnfilteredBody(getter_AddRefs(body));
} else {
Telemetry::ScalarAdd(Telemetry::ScalarID::SW_ALTERNATIVE_BODY_USED_COUNT,
1);
}
// Propagate the URL to the content if the request mode is not "navigate".
// Note that, we only reflect the final URL if the response.redirected is
// false. We propagate all the URLs if the response.redirected is true.
const IPCInternalRequest& request = mArgs.internalRequest();
nsAutoCString responseURL;
if (request.requestMode() != RequestMode::Navigate) {
responseURL = response->GetUnfilteredURL();
// Similar to how we apply the request fragment to redirects automatically
// we also want to apply it automatically when propagating the response
// URL from a service worker interception. Currently response.url strips
// the fragment, so this will never conflict with an existing fragment
// on the response. In the future we will have to check for a response
// fragment and avoid overriding in that case.
if (!request.fragment().IsEmpty() && !responseURL.IsEmpty()) {
MOZ_ASSERT(!responseURL.Contains('#'));
responseURL.AppendLiteral("#");
responseURL.Append(request.fragment());
}
}
nsMainThreadPtrHandle<nsIInterceptedChannel> interceptedChannel(
new nsMainThreadPtrHolder<nsIInterceptedChannel>(
"nsIInterceptedChannel", mInterceptedChannel, false));
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> registration(
new nsMainThreadPtrHolder<ServiceWorkerRegistrationInfo>(
"ServiceWorkerRegistrationInfo", mRegistration, false));
nsCString requestURL = request.urlList().LastElement();
if (!request.fragment().IsEmpty()) {
requestURL.AppendLiteral("#");
requestURL.Append(request.fragment());
}
RefPtr<SynthesizeResponseWatcher> watcher = new SynthesizeResponseWatcher(
interceptedChannel, registration, mArgs.isNonSubresourceRequest(),
std::move(aArgs.closure()), NS_ConvertUTF8toUTF16(responseURL));
rv = mInterceptedChannel->StartSynthesizedResponse(
body, watcher, nullptr /* TODO */, responseURL, response->IsRedirected());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
if (obsService) {
obsService->NotifyObservers(underlyingChannel,
"service-worker-synthesized-response", nullptr);
}
return rv;
}
void FetchEventOpChild::SynthesizeResponse(IPCSynthesizeResponseArgs&& aArgs) {
AssertIsOnMainThread();
MOZ_ASSERT(mInterceptedChannel);
MOZ_ASSERT(!mInterceptedChannelHandled);
nsresult rv = StartSynthesizedResponse(std::move(aArgs));
if (NS_WARN_IF(NS_FAILED(rv))) {
NS_WARNING("Failed to synthesize response!");
mInterceptedChannel->CancelInterception(rv);
}
mInterceptedChannelHandled = true;
MaybeScheduleRegistrationUpdate();
}
void FetchEventOpChild::ResetInterception() {
AssertIsOnMainThread();
MOZ_ASSERT(mInterceptedChannel);
MOZ_ASSERT(!mInterceptedChannelHandled);
nsresult rv = mInterceptedChannel->ResetInterception();
if (NS_WARN_IF(NS_FAILED(rv))) {
NS_WARNING("Failed to resume intercepted network request!");
mInterceptedChannel->CancelInterception(rv);
}
mInterceptedChannelHandled = true;
MaybeScheduleRegistrationUpdate();
}
void FetchEventOpChild::CancelInterception(nsresult aStatus) {
AssertIsOnMainThread();
MOZ_ASSERT(mInterceptedChannel);
MOZ_ASSERT(!mInterceptedChannelHandled);
MOZ_ASSERT(NS_FAILED(aStatus));
mInterceptedChannel->CancelInterception(aStatus);
mInterceptedChannelHandled = true;
MaybeScheduleRegistrationUpdate();
}
/**
* This corresponds to the "Handle Fetch" algorithm's steps 20.3, 21.2, and
* 22.2:
*
* "If request is a non-subresource request, or request is a subresource
* request and the time difference in seconds calculated by the current time
* minus registration's last update check time is greater than 86400, invoke
* Soft Update algorithm with registration."
*/
void FetchEventOpChild::MaybeScheduleRegistrationUpdate() const {
AssertIsOnMainThread();
MOZ_ASSERT(mRegistration);
MOZ_ASSERT(mInterceptedChannelHandled);
if (mArgs.isNonSubresourceRequest()) {
mRegistration->MaybeScheduleUpdate();
} else {
mRegistration->MaybeScheduleTimeCheckAndUpdate();
}
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,83 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_fetcheventopchild_h__
#define mozilla_dom_fetcheventopchild_h__
#include "nsCOMPtr.h"
#include "mozilla/MozPromise.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/PFetchEventOpChild.h"
#include "mozilla/dom/ServiceWorkerOpArgs.h"
class nsIInterceptedChannel;
namespace mozilla {
namespace dom {
class KeepAliveToken;
class PRemoteWorkerControllerChild;
class ServiceWorkerRegistrationInfo;
/**
* FetchEventOpChild represents an in-flight FetchEvent operation.
*/
class FetchEventOpChild final : public PFetchEventOpChild {
friend class PFetchEventOpChild;
public:
static RefPtr<GenericPromise> Create(
PRemoteWorkerControllerChild* aManager,
ServiceWorkerFetchEventOpArgs&& aArgs,
nsCOMPtr<nsIInterceptedChannel> aInterceptedChannel,
RefPtr<ServiceWorkerRegistrationInfo> aRegistrationInfo,
RefPtr<KeepAliveToken>&& aKeepAliveToken);
~FetchEventOpChild();
private:
FetchEventOpChild(ServiceWorkerFetchEventOpArgs&& aArgs,
nsCOMPtr<nsIInterceptedChannel>&& aInterceptedChannel,
RefPtr<ServiceWorkerRegistrationInfo>&& aRegistrationInfo,
RefPtr<KeepAliveToken>&& aKeepAliveToken);
mozilla::ipc::IPCResult RecvAsyncLog(const nsCString& aScriptSpec,
const uint32_t& aLineNumber,
const uint32_t& aColumnNumber,
const nsCString& aMessageName,
nsTArray<nsString>&& aParams);
mozilla::ipc::IPCResult RecvRespondWith(
IPCFetchEventRespondWithResult&& aResult);
mozilla::ipc::IPCResult Recv__delete__(
const ServiceWorkerFetchEventOpResult& aResult) override;
void ActorDestroy(ActorDestroyReason) override;
nsresult StartSynthesizedResponse(IPCSynthesizeResponseArgs&& aArgs);
void SynthesizeResponse(IPCSynthesizeResponseArgs&& aArgs);
void ResetInterception();
void CancelInterception(nsresult aStatus);
void MaybeScheduleRegistrationUpdate() const;
const ServiceWorkerFetchEventOpArgs mArgs;
nsCOMPtr<nsIInterceptedChannel> mInterceptedChannel;
RefPtr<ServiceWorkerRegistrationInfo> mRegistration;
RefPtr<KeepAliveToken> mKeepAliveToken;
bool mInterceptedChannelHandled = false;
MozPromiseHolder<GenericPromise> mPromiseHolder;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_fetcheventopchild_h__

View File

@ -0,0 +1,50 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FetchEventOpParent.h"
#include "nsDebug.h"
#include "mozilla/Assertions.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/FetchEventOpProxyParent.h"
#include "mozilla/dom/RemoteWorkerControllerParent.h"
#include "mozilla/dom/RemoteWorkerParent.h"
#include "mozilla/ipc/BackgroundParent.h"
namespace mozilla {
using namespace ipc;
namespace dom {
void FetchEventOpParent::Initialize(
const ServiceWorkerFetchEventOpArgs& aArgs) {
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
RemoteWorkerControllerParent* manager =
static_cast<RemoteWorkerControllerParent*>(Manager());
MOZ_ASSERT(manager);
// This will be null when the manager's RemoteWorkerController has shutdown.
RefPtr<RemoteWorkerParent> proxyManager = manager->GetRemoteWorkerParent();
if (NS_WARN_IF(!proxyManager)) {
Unused << Send__delete__(this, NS_ERROR_DOM_ABORT_ERR);
return;
}
FetchEventOpProxyParent::Create(proxyManager.get(), aArgs, this);
}
void FetchEventOpParent::ActorDestroy(ActorDestroyReason) {
AssertIsOnBackgroundThread();
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_fetcheventopparent_h__
#define mozilla_dom_fetcheventopparent_h__
#include "nsISupports.h"
#include "mozilla/dom/PFetchEventOpParent.h"
namespace mozilla {
namespace dom {
class ServiceWorkerFetchEventOpArgs;
class FetchEventOpParent final : public PFetchEventOpParent {
friend class PFetchEventOpParent;
public:
NS_INLINE_DECL_REFCOUNTING(FetchEventOpParent)
FetchEventOpParent() = default;
void Initialize(const ServiceWorkerFetchEventOpArgs& aArgs);
private:
~FetchEventOpParent() = default;
void ActorDestroy(ActorDestroyReason) override;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_fetcheventopparent_h__

View File

@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FetchEventOpProxyChild.h"
#include <utility>
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsThreadUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/RemoteWorkerChild.h"
#include "mozilla/dom/RemoteWorkerService.h"
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/IPCStreamUtils.h"
namespace mozilla {
using namespace ipc;
namespace dom {
namespace {
nsresult GetIPCSynthesizeResponseArgs(
IPCSynthesizeResponseArgs* aIPCArgs, SynthesizeResponseArgs&& aArgs,
UniquePtr<AutoIPCStream>& aAutoBodyStream,
UniquePtr<AutoIPCStream>& aAutoAlternativeBodyStream) {
MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread());
PBackgroundChild* bgChild = BackgroundChild::GetOrCreateForCurrentThread();
if (NS_WARN_IF(!bgChild)) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
aArgs.first()->ToIPC(&aIPCArgs->internalResponse(), bgChild, aAutoBodyStream,
aAutoAlternativeBodyStream);
aIPCArgs->closure() = std::move(aArgs.second());
return NS_OK;
}
} // anonymous namespace
void FetchEventOpProxyChild::Initialize(
const ServiceWorkerFetchEventOpArgs& aArgs) {
MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread());
mInternalRequest = new InternalRequest(aArgs.internalRequest());
RemoteWorkerChild* manager = static_cast<RemoteWorkerChild*>(Manager());
MOZ_ASSERT(manager);
RefPtr<FetchEventOpProxyChild> self = this;
auto callback = [self](const ServiceWorkerOpResult& aResult) {
if (!self->CanSend()) {
return;
}
if (NS_WARN_IF(aResult.type() == ServiceWorkerOpResult::Tnsresult)) {
Unused << self->Send__delete__(self, aResult.get_nsresult());
return;
}
MOZ_ASSERT(aResult.type() ==
ServiceWorkerOpResult::TServiceWorkerFetchEventOpResult);
Unused << self->Send__delete__(self, aResult);
};
}
RefPtr<InternalRequest> FetchEventOpProxyChild::ExtractInternalRequest() {
MOZ_ASSERT(IsCurrentThreadRunningWorker());
MOZ_ASSERT(mInternalRequest);
return RefPtr<InternalRequest>(std::move(mInternalRequest));
}
void FetchEventOpProxyChild::ActorDestroy(ActorDestroyReason) {
Unused << NS_WARN_IF(mRespondWithPromiseRequestHolder.Exists());
mRespondWithPromiseRequestHolder.DisconnectIfExists();
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_fetcheventopproxychild_h__
#define mozilla_dom_fetcheventopproxychild_h__
#include "nsISupportsImpl.h"
#include "ServiceWorkerOpPromise.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/InternalRequest.h"
#include "mozilla/dom/PFetchEventOpProxyChild.h"
namespace mozilla {
namespace dom {
class InternalRequest;
class ServiceWorkerFetchEventOpArgs;
class FetchEventOpProxyChild final : public PFetchEventOpProxyChild {
friend class PFetchEventOpProxyChild;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FetchEventOpProxyChild)
FetchEventOpProxyChild() = default;
void Initialize(const ServiceWorkerFetchEventOpArgs& aArgs);
// Must only be called once and on a worker thread.
RefPtr<InternalRequest> ExtractInternalRequest();
private:
~FetchEventOpProxyChild() = default;
void ActorDestroy(ActorDestroyReason) override;
MozPromiseRequestHolder<FetchEventRespondWithPromise>
mRespondWithPromiseRequestHolder;
// Initialized on RemoteWorkerService::Thread, read on a worker thread.
RefPtr<InternalRequest> mInternalRequest;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_fetcheventopproxychild_h__

View File

@ -0,0 +1,165 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FetchEventOpProxyParent.h"
#include <utility>
#include "nsCOMPtr.h"
#include "nsIInputStream.h"
#include "mozilla/Assertions.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/FetchEventOpParent.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/IPCStreamUtils.h"
namespace mozilla {
using namespace ipc;
namespace dom {
namespace {
void MaybeDeserializeAndReserialize(const Maybe<IPCStream>& aDeserialize,
Maybe<IPCStream>& aReserialize,
UniquePtr<AutoIPCStream>& aAutoStream,
PBackgroundParent* aManager) {
nsCOMPtr<nsIInputStream> maybeDeserialized =
DeserializeIPCStream(aDeserialize);
if (!maybeDeserialized) {
return;
}
aAutoStream.reset(new AutoIPCStream(aReserialize));
DebugOnly<bool> ok = aAutoStream->Serialize(maybeDeserialized, aManager);
MOZ_ASSERT(ok);
}
} // anonymous namespace
/* static */ void FetchEventOpProxyParent::Create(
PRemoteWorkerParent* aManager, const ServiceWorkerFetchEventOpArgs& aArgs,
RefPtr<FetchEventOpParent> aReal) {
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aManager);
MOZ_ASSERT(aReal);
FetchEventOpProxyParent* actor =
new FetchEventOpProxyParent(std::move(aReal));
if (aArgs.internalRequest().body().isNothing()) {
Unused << aManager->SendPFetchEventOpProxyConstructor(actor, aArgs);
return;
}
ServiceWorkerFetchEventOpArgs copyArgs = aArgs;
IPCInternalRequest& copyRequest = copyArgs.internalRequest();
PBackgroundParent* bgParent = aManager->Manager();
MOZ_ASSERT(bgParent);
UniquePtr<AutoIPCStream> autoBodyStream = MakeUnique<AutoIPCStream>();
MaybeDeserializeAndReserialize(aArgs.internalRequest().body(),
copyRequest.body(), autoBodyStream, bgParent);
Unused << aManager->SendPFetchEventOpProxyConstructor(actor, copyArgs);
autoBodyStream->TakeOptionalValue();
}
FetchEventOpProxyParent::~FetchEventOpProxyParent() {
AssertIsOnBackgroundThread();
}
FetchEventOpProxyParent::FetchEventOpProxyParent(
RefPtr<FetchEventOpParent>&& aReal)
: mReal(std::move(aReal)) {}
mozilla::ipc::IPCResult FetchEventOpProxyParent::RecvAsyncLog(
const nsCString& aScriptSpec, const uint32_t& aLineNumber,
const uint32_t& aColumnNumber, const nsCString& aMessageName,
nsTArray<nsString>&& aParams) {
AssertIsOnBackgroundThread();
MOZ_ASSERT(mReal);
Unused << mReal->SendAsyncLog(aScriptSpec, aLineNumber, aColumnNumber,
aMessageName, aParams);
return IPC_OK();
}
mozilla::ipc::IPCResult FetchEventOpProxyParent::RecvRespondWith(
const IPCFetchEventRespondWithResult& aResult) {
AssertIsOnBackgroundThread();
MOZ_ASSERT(mReal);
// IPCSynthesizeResponseArgs possibly contains an IPCStream. If so,
// deserialize it and reserialize it before forwarding it to the main thread.
if (aResult.type() ==
IPCFetchEventRespondWithResult::TIPCSynthesizeResponseArgs) {
const IPCSynthesizeResponseArgs& originalArgs =
aResult.get_IPCSynthesizeResponseArgs();
const IPCInternalResponse& originalResponse =
originalArgs.internalResponse();
// Do nothing if neither the body nor the alt. body can be deserialized.
if (!originalResponse.body() && !originalResponse.alternativeBody()) {
Unused << mReal->SendRespondWith(aResult);
return IPC_OK();
}
IPCSynthesizeResponseArgs copyArgs = originalArgs;
IPCInternalResponse& copyResponse = copyArgs.internalResponse();
PRemoteWorkerControllerParent* manager = mReal->Manager();
MOZ_ASSERT(manager);
PBackgroundParent* bgParent = manager->Manager();
MOZ_ASSERT(bgParent);
UniquePtr<AutoIPCStream> autoBodyStream = MakeUnique<AutoIPCStream>();
UniquePtr<AutoIPCStream> autoAlternativeBodyStream =
MakeUnique<AutoIPCStream>();
MaybeDeserializeAndReserialize(originalResponse.body(), copyResponse.body(),
autoBodyStream, bgParent);
MaybeDeserializeAndReserialize(originalResponse.alternativeBody(),
copyResponse.alternativeBody(),
autoAlternativeBodyStream, bgParent);
Unused << mReal->SendRespondWith(copyArgs);
autoBodyStream->TakeOptionalValue();
autoAlternativeBodyStream->TakeOptionalValue();
} else {
Unused << mReal->SendRespondWith(aResult);
}
return IPC_OK();
}
mozilla::ipc::IPCResult FetchEventOpProxyParent::Recv__delete__(
const ServiceWorkerFetchEventOpResult& aResult) {
AssertIsOnBackgroundThread();
MOZ_ASSERT(mReal);
Unused << mReal->Send__delete__(mReal, aResult);
mReal = nullptr;
return IPC_OK();
}
void FetchEventOpProxyParent::ActorDestroy(ActorDestroyReason) {
AssertIsOnBackgroundThread();
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_fetcheventopproxyparent_h__
#define mozilla_dom_fetcheventopproxyparent_h__
#include "mozilla/RefPtr.h"
#include "mozilla/dom/PFetchEventOpProxyParent.h"
namespace mozilla {
namespace dom {
class FetchEventOpParent;
class PRemoteWorkerParent;
class ServiceWorkerFetchEventOpArgs;
/**
* FetchEventOpProxyParent owns a FetchEventOpParent and is responsible for
* calling PFetchEventOpParent::Send__delete__.
*/
class FetchEventOpProxyParent final : public PFetchEventOpProxyParent {
friend class PFetchEventOpProxyParent;
public:
static void Create(PRemoteWorkerParent* aManager,
const ServiceWorkerFetchEventOpArgs& aArgs,
RefPtr<FetchEventOpParent> aReal);
~FetchEventOpProxyParent();
private:
explicit FetchEventOpProxyParent(RefPtr<FetchEventOpParent>&& aReal);
mozilla::ipc::IPCResult RecvAsyncLog(const nsCString& aScriptSpec,
const uint32_t& aLineNumber,
const uint32_t& aColumnNumber,
const nsCString& aMessageName,
nsTArray<nsString>&& aParams);
mozilla::ipc::IPCResult RecvRespondWith(
const IPCFetchEventRespondWithResult& aResult);
mozilla::ipc::IPCResult Recv__delete__(
const ServiceWorkerFetchEventOpResult& aResult) override;
void ActorDestroy(ActorDestroyReason) override;
RefPtr<FetchEventOpParent> mReal;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_fetcheventopproxyparent_h__

View File

@ -0,0 +1,26 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PRemoteWorkerController;
include ServiceWorkerOpArgs;
namespace mozilla {
namespace dom {
protocol PFetchEventOp {
manager PRemoteWorkerController;
child:
async AsyncLog(nsCString aScriptSpec, uint32_t aLineNumber,
uint32_t aColumnNumber, nsCString aMessageName,
nsString[] aParams);
async RespondWith(IPCFetchEventRespondWithResult aResult);
async __delete__(ServiceWorkerFetchEventOpResult aResult);
};
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,26 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PRemoteWorker;
include ServiceWorkerOpArgs;
namespace mozilla {
namespace dom {
protocol PFetchEventOpProxy {
manager PRemoteWorker;
parent:
async AsyncLog(nsCString aScriptSpec, uint32_t aLineNumber,
uint32_t aColumnNumber, nsCString aMessageName,
nsString[] aParams);
async RespondWith(IPCFetchEventRespondWithResult aResult);
async __delete__(ServiceWorkerFetchEventOpResult aResult);
};
} // namespace dom
} // namespace mozilla

View File

@ -68,26 +68,17 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(ServiceWorkerPrivate, Release)
// still be a valid value since it was set prior to dispatching the runnable.
Atomic<uint32_t> gDOMDisableOpenClickDelay(0);
// Used to keep track of pending waitUntil as well as in-flight extendable
// events. When the last token is released, we attempt to terminate the worker.
class KeepAliveToken final : public nsISupports {
public:
NS_DECL_ISUPPORTS
KeepAliveToken::KeepAliveToken(ServiceWorkerPrivate* aPrivate)
: mPrivate(aPrivate) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrivate);
mPrivate->AddToken();
}
explicit KeepAliveToken(ServiceWorkerPrivate* aPrivate) : mPrivate(aPrivate) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrivate);
mPrivate->AddToken();
}
private:
~KeepAliveToken() {
MOZ_ASSERT(NS_IsMainThread());
mPrivate->ReleaseToken();
}
RefPtr<ServiceWorkerPrivate> mPrivate;
};
KeepAliveToken::~KeepAliveToken() {
MOZ_ASSERT(NS_IsMainThread());
mPrivate->ReleaseToken();
}
NS_IMPL_ISUPPORTS0(KeepAliveToken)

View File

@ -24,9 +24,9 @@ class JSObjectHolder;
namespace dom {
class ClientInfoAndState;
class KeepAliveToken;
class ServiceWorkerCloneData;
class ServiceWorkerInfo;
class ServiceWorkerPrivate;
class ServiceWorkerRegistrationInfo;
namespace ipc {
@ -41,6 +41,20 @@ class LifeCycleEventCallback : public Runnable {
virtual void SetResult(bool aResult) = 0;
};
// Used to keep track of pending waitUntil as well as in-flight extendable
// events. When the last token is released, we attempt to terminate the worker.
class KeepAliveToken final : public nsISupports {
public:
NS_DECL_ISUPPORTS
explicit KeepAliveToken(ServiceWorkerPrivate* aPrivate);
private:
~KeepAliveToken();
RefPtr<ServiceWorkerPrivate> mPrivate;
};
// ServiceWorkerPrivate is a wrapper for managing the on-demand aspect of
// service workers. It handles all event dispatching to the worker and ensures
// the worker thread is running when needed.

View File

@ -9,6 +9,10 @@ with Files("**"):
# Public stuff.
EXPORTS.mozilla.dom += [
'FetchEventOpChild.h',
'FetchEventOpParent.h',
'FetchEventOpProxyChild.h',
'FetchEventOpProxyParent.h',
'ServiceWorker.h',
'ServiceWorkerActors.h',
'ServiceWorkerCloneData.h',
@ -30,6 +34,10 @@ EXPORTS.mozilla.dom += [
]
UNIFIED_SOURCES += [
'FetchEventOpChild.cpp',
'FetchEventOpParent.cpp',
'FetchEventOpProxyChild.cpp',
'FetchEventOpProxyParent.cpp',
'RemoteServiceWorkerContainerImpl.cpp',
'RemoteServiceWorkerImpl.cpp',
'RemoteServiceWorkerRegistrationImpl.cpp',
@ -78,6 +86,8 @@ UNIFIED_SOURCES += [
IPDL_SOURCES += [
'IPCServiceWorkerDescriptor.ipdlh',
'IPCServiceWorkerRegistrationDescriptor.ipdlh',
'PFetchEventOp.ipdl',
'PFetchEventOpProxy.ipdl',
'PServiceWorker.ipdl',
'PServiceWorkerContainer.ipdl',
'PServiceWorkerManager.ipdl',

View File

@ -3,8 +3,10 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PFetchEventOpProxy;
include DOMTypes;
include ServiceWorkerOpArgs;
include RemoteWorkerTypes;
namespace mozilla {
@ -58,6 +60,8 @@ protocol PRemoteWorker
{
manager PBackground;
manages PFetchEventOpProxy;
parent:
async Created(bool aStatus);
@ -66,6 +70,8 @@ parent:
async Close();
child:
async PFetchEventOpProxy(ServiceWorkerFetchEventOpArgs aArgs);
async __delete__();
async ExecOp(RemoteWorkerOp op);

View File

@ -3,6 +3,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PFetchEventOp;
include RemoteWorkerTypes;
include ServiceWorkerOpArgs;
@ -13,6 +14,8 @@ namespace dom {
protocol PRemoteWorkerController {
manager PBackground;
manages PFetchEventOp;
child:
async CreationFailed();
@ -23,6 +26,8 @@ protocol PRemoteWorkerController {
async Terminated();
parent:
async PFetchEventOp(ServiceWorkerFetchEventOpArgs aArgs);
async __delete__();
async Shutdown() returns (bool aOk);

View File

@ -28,6 +28,7 @@
#include "mozilla/Services.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/FetchEventOpProxyChild.h"
#include "mozilla/dom/IndexedDatabaseManager.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/RemoteWorkerTypes.h"
@ -920,5 +921,35 @@ IPCResult RemoteWorkerChild::RecvExecOp(RemoteWorkerOp&& aOp) {
return IPC_OK();
}
/**
* PFetchEventOpProxy methods
*/
PFetchEventOpProxyChild* RemoteWorkerChild::AllocPFetchEventOpProxyChild(
const ServiceWorkerFetchEventOpArgs& aArgs) {
RefPtr<FetchEventOpProxyChild> actor = new FetchEventOpProxyChild();
return actor.forget().take();
}
IPCResult RemoteWorkerChild::RecvPFetchEventOpProxyConstructor(
PFetchEventOpProxyChild* aActor,
const ServiceWorkerFetchEventOpArgs& aArgs) {
MOZ_ASSERT(aActor);
(static_cast<FetchEventOpProxyChild*>(aActor))->Initialize(aArgs);
return IPC_OK();
}
bool RemoteWorkerChild::DeallocPFetchEventOpProxyChild(
PFetchEventOpProxyChild* aActor) {
MOZ_ASSERT(aActor);
RefPtr<FetchEventOpProxyChild> actor =
dont_AddRef(static_cast<FetchEventOpProxyChild*>(aActor));
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -101,6 +101,15 @@ class RemoteWorkerChild final
mozilla::ipc::IPCResult RecvExecOp(RemoteWorkerOp&& aOp);
PFetchEventOpProxyChild* AllocPFetchEventOpProxyChild(
const ServiceWorkerFetchEventOpArgs& aArgs);
mozilla::ipc::IPCResult RecvPFetchEventOpProxyConstructor(
PFetchEventOpProxyChild* aActor,
const ServiceWorkerFetchEventOpArgs& aArgs) override;
bool DeallocPFetchEventOpProxyChild(PFetchEventOpProxyChild* aActor);
nsresult ExecWorkerOnMainThread(RemoteWorkerData&& aData);
void InitializeOnWorker(already_AddRefed<WorkerPrivate> aWorkerPrivate);

View File

@ -15,6 +15,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/PFetchEventOpChild.h"
namespace mozilla {
@ -29,6 +30,21 @@ RemoteWorkerControllerChild::RemoteWorkerControllerChild(
MOZ_ASSERT(mObserver);
}
PFetchEventOpChild* RemoteWorkerControllerChild::AllocPFetchEventOpChild(
const ServiceWorkerFetchEventOpArgs& aArgs) {
MOZ_CRASH("PFetchEventOpChild actors must be manually constructed!");
return nullptr;
}
bool RemoteWorkerControllerChild::DeallocPFetchEventOpChild(
PFetchEventOpChild* aActor) {
AssertIsOnMainThread();
MOZ_ASSERT(aActor);
delete aActor;
return true;
}
void RemoteWorkerControllerChild::ActorDestroy(ActorDestroyReason aReason) {
AssertIsOnMainThread();

View File

@ -33,6 +33,11 @@ class RemoteWorkerControllerChild final : public PRemoteWorkerControllerChild {
private:
~RemoteWorkerControllerChild() = default;
PFetchEventOpChild* AllocPFetchEventOpChild(
const ServiceWorkerFetchEventOpArgs& aArgs);
bool DeallocPFetchEventOpChild(PFetchEventOpChild* aActor);
void ActorDestroy(ActorDestroyReason aReason) override;
mozilla::ipc::IPCResult RecvCreationFailed();

View File

@ -15,6 +15,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/FetchEventOpParent.h"
#include "mozilla/ipc/BackgroundParent.h"
namespace mozilla {
@ -46,6 +47,34 @@ RemoteWorkerControllerParent::~RemoteWorkerControllerParent() {
MOZ_ASSERT(!mRemoteWorkerController);
}
PFetchEventOpParent* RemoteWorkerControllerParent::AllocPFetchEventOpParent(
const ServiceWorkerFetchEventOpArgs& aArgs) {
AssertIsOnBackgroundThread();
RefPtr<FetchEventOpParent> actor = new FetchEventOpParent();
return actor.forget().take();
}
IPCResult RemoteWorkerControllerParent::RecvPFetchEventOpConstructor(
PFetchEventOpParent* aActor, const ServiceWorkerFetchEventOpArgs& aArgs) {
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
(static_cast<FetchEventOpParent*>(aActor))->Initialize(aArgs);
return IPC_OK();
}
bool RemoteWorkerControllerParent::DeallocPFetchEventOpParent(
PFetchEventOpParent* aActor) {
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
RefPtr<FetchEventOpParent> actor =
dont_AddRef(static_cast<FetchEventOpParent*>(aActor));
return true;
}
IPCResult RemoteWorkerControllerParent::RecvShutdown(
ShutdownResolver&& aResolve) {
AssertIsOnBackgroundThread();

View File

@ -34,6 +34,15 @@ class RemoteWorkerControllerParent final : public PRemoteWorkerControllerParent,
private:
~RemoteWorkerControllerParent();
PFetchEventOpParent* AllocPFetchEventOpParent(
const ServiceWorkerFetchEventOpArgs& aArgs);
mozilla::ipc::IPCResult RecvPFetchEventOpConstructor(
PFetchEventOpParent* aActor,
const ServiceWorkerFetchEventOpArgs& aArgs) override;
bool DeallocPFetchEventOpParent(PFetchEventOpParent* aActor);
mozilla::ipc::IPCResult RecvShutdown(ShutdownResolver&& aResolve);
mozilla::ipc::IPCResult Recv__delete__() override;

View File

@ -7,6 +7,7 @@
#include "RemoteWorkerParent.h"
#include "RemoteWorkerController.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/PFetchEventOpProxyParent.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/Unused.h"
#include "nsProxyRelease.h"
@ -67,6 +68,22 @@ void RemoteWorkerParent::Initialize() {
}
}
PFetchEventOpProxyParent* RemoteWorkerParent::AllocPFetchEventOpProxyParent(
const ServiceWorkerFetchEventOpArgs& aArgs) {
MOZ_CRASH("PFetchEventOpProxyParent actors must be manually constructed!");
return nullptr;
}
bool RemoteWorkerParent::DeallocPFetchEventOpProxyParent(
PFetchEventOpProxyParent* aActor) {
MOZ_ASSERT(XRE_IsParentProcess());
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
delete aActor;
return true;
}
void RemoteWorkerParent::ActorDestroy(IProtocol::ActorDestroyReason) {
AssertIsOnBackgroundThread();
MOZ_ASSERT(XRE_IsParentProcess());

View File

@ -31,6 +31,11 @@ class RemoteWorkerParent final : public PRemoteWorkerParent {
private:
~RemoteWorkerParent();
PFetchEventOpProxyParent* AllocPFetchEventOpProxyParent(
const ServiceWorkerFetchEventOpArgs& aArgs);
bool DeallocPFetchEventOpProxyParent(PFetchEventOpProxyParent* aActor);
void ActorDestroy(mozilla::ipc::IProtocol::ActorDestroyReason) override;
mozilla::ipc::IPCResult RecvError(const ErrorValue& aValue);