mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 1231213 - Implement ServiceWorkerOp and its subclasses. r=asuth
Differential Revision: https://phabricator.services.mozilla.com/D26172 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
5b603200f7
commit
bbc5dad9a8
@ -18,6 +18,7 @@
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/dom/RemoteWorkerChild.h"
|
||||
#include "mozilla/dom/RemoteWorkerService.h"
|
||||
#include "mozilla/dom/ServiceWorkerOp.h"
|
||||
#include "mozilla/dom/WorkerCommon.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/IPCStreamUtils.h"
|
||||
@ -54,6 +55,7 @@ nsresult GetIPCSynthesizeResponseArgs(
|
||||
void FetchEventOpProxyChild::Initialize(
|
||||
const ServiceWorkerFetchEventOpArgs& aArgs) {
|
||||
MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread());
|
||||
MOZ_ASSERT(!mOp);
|
||||
|
||||
mInternalRequest = new InternalRequest(aArgs.internalRequest());
|
||||
|
||||
@ -77,6 +79,60 @@ void FetchEventOpProxyChild::Initialize(
|
||||
|
||||
Unused << self->Send__delete__(self, aResult);
|
||||
};
|
||||
|
||||
RefPtr<FetchEventOp> op = ServiceWorkerOp::Create(aArgs, std::move(callback))
|
||||
.template downcast<FetchEventOp>();
|
||||
|
||||
MOZ_ASSERT(op);
|
||||
|
||||
op->SetActor(this);
|
||||
mOp = op;
|
||||
|
||||
op->GetRespondWithPromise()
|
||||
->Then(GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[self = std::move(self)](
|
||||
FetchEventRespondWithPromise::ResolveOrRejectValue&& aResult) {
|
||||
self->mRespondWithPromiseRequestHolder.Complete();
|
||||
|
||||
if (NS_WARN_IF(aResult.IsReject())) {
|
||||
MOZ_ASSERT(NS_FAILED(aResult.RejectValue()));
|
||||
|
||||
Unused << self->SendRespondWith(
|
||||
CancelInterceptionArgs(aResult.RejectValue()));
|
||||
return;
|
||||
}
|
||||
|
||||
auto& result = aResult.ResolveValue();
|
||||
|
||||
if (result.is<SynthesizeResponseArgs>()) {
|
||||
IPCSynthesizeResponseArgs ipcArgs;
|
||||
UniquePtr<AutoIPCStream> autoBodyStream =
|
||||
MakeUnique<AutoIPCStream>();
|
||||
UniquePtr<AutoIPCStream> autoAlternativeBodyStream =
|
||||
MakeUnique<AutoIPCStream>();
|
||||
nsresult rv = GetIPCSynthesizeResponseArgs(
|
||||
&ipcArgs, result.extract<SynthesizeResponseArgs>(),
|
||||
autoBodyStream, autoAlternativeBodyStream);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
Unused << self->SendRespondWith(CancelInterceptionArgs(rv));
|
||||
return;
|
||||
}
|
||||
|
||||
Unused << self->SendRespondWith(ipcArgs);
|
||||
autoBodyStream->TakeOptionalValue();
|
||||
autoAlternativeBodyStream->TakeOptionalValue();
|
||||
} else if (result.is<ResetInterceptionArgs>()) {
|
||||
Unused << self->SendRespondWith(
|
||||
result.extract<ResetInterceptionArgs>());
|
||||
} else {
|
||||
Unused << self->SendRespondWith(
|
||||
result.extract<CancelInterceptionArgs>());
|
||||
}
|
||||
})
|
||||
->Track(mRespondWithPromiseRequestHolder);
|
||||
|
||||
manager->MaybeStartOp(std::move(op));
|
||||
}
|
||||
|
||||
RefPtr<InternalRequest> FetchEventOpProxyChild::ExtractInternalRequest() {
|
||||
@ -89,6 +145,9 @@ RefPtr<InternalRequest> FetchEventOpProxyChild::ExtractInternalRequest() {
|
||||
void FetchEventOpProxyChild::ActorDestroy(ActorDestroyReason) {
|
||||
Unused << NS_WARN_IF(mRespondWithPromiseRequestHolder.Exists());
|
||||
mRespondWithPromiseRequestHolder.DisconnectIfExists();
|
||||
|
||||
mOp->RevokeActor(this);
|
||||
mOp = nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
#include "ServiceWorkerOp.h"
|
||||
#include "ServiceWorkerOpPromise.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/dom/InternalRequest.h"
|
||||
@ -41,6 +42,8 @@ class FetchEventOpProxyChild final : public PFetchEventOpProxyChild {
|
||||
MozPromiseRequestHolder<FetchEventRespondWithPromise>
|
||||
mRespondWithPromiseRequestHolder;
|
||||
|
||||
RefPtr<FetchEventOp> mOp;
|
||||
|
||||
// Initialized on RemoteWorkerService::Thread, read on a worker thread.
|
||||
RefPtr<InternalRequest> mInternalRequest;
|
||||
};
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include "ServiceWorkerEvents.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIConsoleReportCollector.h"
|
||||
@ -41,6 +43,7 @@
|
||||
#include "mozilla/dom/PushMessageDataBinding.h"
|
||||
#include "mozilla/dom/PushUtil.h"
|
||||
#include "mozilla/dom/Request.h"
|
||||
#include "mozilla/dom/ServiceWorkerOp.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "mozilla/dom/Response.h"
|
||||
#include "mozilla/dom/WorkerScope.h"
|
||||
@ -136,6 +139,14 @@ void FetchEvent::PostInit(
|
||||
mScriptSpec.Assign(aScriptSpec);
|
||||
}
|
||||
|
||||
void FetchEvent::PostInit(const nsACString& aScriptSpec,
|
||||
RefPtr<FetchEventOp> aRespondWithHandler) {
|
||||
MOZ_ASSERT(aRespondWithHandler);
|
||||
|
||||
mScriptSpec.Assign(aScriptSpec);
|
||||
mRespondWithHandler = std::move(aRespondWithHandler);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
already_AddRefed<FetchEvent> FetchEvent::Constructor(
|
||||
const GlobalObject& aGlobal, const nsAString& aType,
|
||||
@ -795,11 +806,21 @@ void FetchEvent::RespondWith(JSContext* aCx, Promise& aArg, ErrorResult& aRv) {
|
||||
|
||||
StopImmediatePropagation();
|
||||
mWaitToRespond = true;
|
||||
RefPtr<RespondWithHandler> handler = new RespondWithHandler(
|
||||
mChannel, mRegistration, mRequest->Mode(), ir->IsClientRequest(),
|
||||
mRequest->Redirect(), mScriptSpec, NS_ConvertUTF8toUTF16(requestURL),
|
||||
ir->GetFragment(), spec, line, column);
|
||||
aArg.AppendNativeHandler(handler);
|
||||
|
||||
if (mChannel) {
|
||||
RefPtr<RespondWithHandler> handler = new RespondWithHandler(
|
||||
mChannel, mRegistration, mRequest->Mode(), ir->IsClientRequest(),
|
||||
mRequest->Redirect(), mScriptSpec, NS_ConvertUTF8toUTF16(requestURL),
|
||||
ir->GetFragment(), spec, line, column);
|
||||
|
||||
aArg.AppendNativeHandler(handler);
|
||||
} else {
|
||||
MOZ_ASSERT(mRespondWithHandler);
|
||||
|
||||
mRespondWithHandler->RespondWithCalledAt(spec, line, column);
|
||||
aArg.AppendNativeHandler(mRespondWithHandler);
|
||||
mRespondWithHandler = nullptr;
|
||||
}
|
||||
|
||||
if (!WaitOnPromise(aArg)) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
@ -838,9 +859,16 @@ void FetchEvent::ReportCanceled() {
|
||||
// nsString requestURL;
|
||||
// CopyUTF8toUTF16(url, requestURL);
|
||||
|
||||
::AsyncLog(mChannel.get(), mPreventDefaultScriptSpec,
|
||||
mPreventDefaultLineNumber, mPreventDefaultColumnNumber,
|
||||
NS_LITERAL_CSTRING("InterceptionCanceledWithURL"), requestURL);
|
||||
if (mChannel) {
|
||||
::AsyncLog(mChannel.get(), mPreventDefaultScriptSpec,
|
||||
mPreventDefaultLineNumber, mPreventDefaultColumnNumber,
|
||||
NS_LITERAL_CSTRING("InterceptionCanceledWithURL"), requestURL);
|
||||
} else {
|
||||
mRespondWithHandler->ReportCanceled(mPreventDefaultScriptSpec,
|
||||
mPreventDefaultLineNumber,
|
||||
mPreventDefaultColumnNumber);
|
||||
mRespondWithHandler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -26,6 +26,7 @@ namespace dom {
|
||||
|
||||
class Blob;
|
||||
class Client;
|
||||
class FetchEventOp;
|
||||
class MessagePort;
|
||||
struct PushEventInit;
|
||||
class Request;
|
||||
@ -50,6 +51,15 @@ class CancelChannelRunnable final : public Runnable {
|
||||
NS_IMETHOD Run() override;
|
||||
};
|
||||
|
||||
enum ExtendableEventResult { Rejected = 0, Resolved };
|
||||
|
||||
class ExtendableEventCallback {
|
||||
public:
|
||||
virtual void FinishedWithResult(ExtendableEventResult aResult) = 0;
|
||||
|
||||
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
|
||||
};
|
||||
|
||||
class ExtendableEvent : public Event {
|
||||
public:
|
||||
class ExtensionsHandler {
|
||||
@ -66,7 +76,7 @@ class ExtendableEvent : public Event {
|
||||
bool WaitOnPromise(Promise& aPromise);
|
||||
|
||||
explicit ExtendableEvent(mozilla::dom::EventTarget* aOwner);
|
||||
~ExtendableEvent() {}
|
||||
~ExtendableEvent() = default;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -102,6 +112,7 @@ class ExtendableEvent : public Event {
|
||||
};
|
||||
|
||||
class FetchEvent final : public ExtendableEvent {
|
||||
RefPtr<FetchEventOp> mRespondWithHandler;
|
||||
nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel;
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
RefPtr<Request> mRequest;
|
||||
@ -132,6 +143,9 @@ class FetchEvent final : public ExtendableEvent {
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration,
|
||||
const nsACString& aScriptSpec);
|
||||
|
||||
void PostInit(const nsACString& aScriptSpec,
|
||||
RefPtr<FetchEventOp> aRespondWithHandler);
|
||||
|
||||
static already_AddRefed<FetchEvent> Constructor(
|
||||
const GlobalObject& aGlobal, const nsAString& aType,
|
||||
const FetchEventInit& aOptions, ErrorResult& aRv);
|
||||
@ -153,10 +167,6 @@ class FetchEvent final : public ExtendableEvent {
|
||||
|
||||
void RespondWith(JSContext* aCx, Promise& aArg, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> ForwardTo(const nsAString& aUrl);
|
||||
|
||||
already_AddRefed<Promise> Default();
|
||||
|
||||
// Pull in the Event version of PreventDefault so we don't get
|
||||
// shadowing warnings.
|
||||
using Event::PreventDefault;
|
||||
@ -199,7 +209,7 @@ class PushEvent final : public ExtendableEvent {
|
||||
|
||||
protected:
|
||||
explicit PushEvent(mozilla::dom::EventTarget* aOwner);
|
||||
~PushEvent() {}
|
||||
~PushEvent() = default;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
1699
dom/serviceworkers/ServiceWorkerOp.cpp
Normal file
1699
dom/serviceworkers/ServiceWorkerOp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
172
dom/serviceworkers/ServiceWorkerOp.h
Normal file
172
dom/serviceworkers/ServiceWorkerOp.h
Normal file
@ -0,0 +1,172 @@
|
||||
/* -*- 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_serviceworkerop_h__
|
||||
#define mozilla_dom_serviceworkerop_h__
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
#include "ServiceWorkerEvents.h"
|
||||
#include "ServiceWorkerOpPromise.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||
#include "mozilla/dom/RemoteWorkerChild.h"
|
||||
#include "mozilla/dom/ServiceWorkerOpArgs.h"
|
||||
#include "mozilla/dom/WorkerRunnable.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FetchEventOpProxyChild;
|
||||
|
||||
class ServiceWorkerOp : public RemoteWorkerChild::Op {
|
||||
public:
|
||||
// `aCallback` will be called when the operation completes or is canceled.
|
||||
static already_AddRefed<ServiceWorkerOp> Create(
|
||||
const ServiceWorkerOpArgs& aArgs,
|
||||
std::function<void(const ServiceWorkerOpResult&)>&& aCallback);
|
||||
|
||||
ServiceWorkerOp(
|
||||
const ServiceWorkerOpArgs& aArgs,
|
||||
std::function<void(const ServiceWorkerOpResult&)>&& aCallback);
|
||||
|
||||
ServiceWorkerOp(const ServiceWorkerOp&) = delete;
|
||||
|
||||
ServiceWorkerOp& operator=(const ServiceWorkerOp&) = delete;
|
||||
|
||||
ServiceWorkerOp(ServiceWorkerOp&&) = default;
|
||||
|
||||
ServiceWorkerOp& operator=(ServiceWorkerOp&&) = default;
|
||||
|
||||
// Returns `true` if the operation has started and `false` otherwise.
|
||||
bool MaybeStart(RemoteWorkerChild* aOwner,
|
||||
RemoteWorkerChild::State& aState) final;
|
||||
|
||||
void Cancel() final;
|
||||
|
||||
protected:
|
||||
~ServiceWorkerOp();
|
||||
|
||||
bool Started() const;
|
||||
|
||||
bool IsTerminationOp() const;
|
||||
|
||||
// Override to provide a runnable that's not a `ServiceWorkerOpRunnable.`
|
||||
virtual RefPtr<WorkerRunnable> GetRunnable(WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
virtual bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) = 0;
|
||||
|
||||
// Override to reject any additional MozPromises that subclasses may contain.
|
||||
virtual void RejectAll(nsresult aStatus);
|
||||
|
||||
ServiceWorkerOpArgs mArgs;
|
||||
|
||||
// Subclasses must settle this promise when appropriate.
|
||||
MozPromiseHolder<ServiceWorkerOpPromise> mPromiseHolder;
|
||||
|
||||
private:
|
||||
class ServiceWorkerOpRunnable;
|
||||
|
||||
bool mStarted = false;
|
||||
};
|
||||
|
||||
class ExtendableEventOp : public ServiceWorkerOp,
|
||||
public ExtendableEventCallback {
|
||||
using ServiceWorkerOp::ServiceWorkerOp;
|
||||
|
||||
protected:
|
||||
~ExtendableEventOp() = default;
|
||||
|
||||
void FinishedWithResult(ExtendableEventResult aResult) override;
|
||||
};
|
||||
|
||||
class FetchEventOp final : public ExtendableEventOp,
|
||||
public PromiseNativeHandler {
|
||||
using ExtendableEventOp::ExtendableEventOp;
|
||||
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
/**
|
||||
* This must be called once and only once before the first call to
|
||||
* `MaybeStart()`; `aActor` will be used for `AsyncLog()` and
|
||||
* `ReportCanceled().`
|
||||
*/
|
||||
void SetActor(RefPtr<FetchEventOpProxyChild> aActor);
|
||||
|
||||
void RevokeActor(FetchEventOpProxyChild* aActor);
|
||||
|
||||
// This must be called at most once before the first call to `MaybeStart().`
|
||||
RefPtr<FetchEventRespondWithPromise> GetRespondWithPromise();
|
||||
|
||||
// This must be called when `FetchEvent::RespondWith()` is called.
|
||||
void RespondWithCalledAt(const nsCString& aRespondWithScriptSpec,
|
||||
uint32_t aRespondWithLineNumber,
|
||||
uint32_t aRespondWithColumnNumber);
|
||||
|
||||
void ReportCanceled(const nsCString& aPreventDefaultScriptSpec,
|
||||
uint32_t aPreventDefaultLineNumber,
|
||||
uint32_t aPreventDefaultColumnNumber);
|
||||
|
||||
private:
|
||||
class AutoCancel;
|
||||
|
||||
~FetchEventOp();
|
||||
|
||||
bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override;
|
||||
|
||||
void RejectAll(nsresult aStatus) override;
|
||||
|
||||
void FinishedWithResult(ExtendableEventResult aResult) override;
|
||||
|
||||
/**
|
||||
* `{Resolved,Reject}Callback()` are use to handle the
|
||||
* `FetchEvent::RespondWith()` promise.
|
||||
*/
|
||||
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
void MaybeFinished();
|
||||
|
||||
// Requires mRespondWithClosure to be non-empty.
|
||||
void AsyncLog(const nsCString& aMessageName, nsTArray<nsString> aParams);
|
||||
|
||||
void AsyncLog(const nsCString& aScriptSpec, uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber, const nsCString& aMessageName,
|
||||
nsTArray<nsString> aParams);
|
||||
|
||||
void GetRequestURL(nsAString& aOutRequestURL);
|
||||
|
||||
// A failure code means that the dispatch failed.
|
||||
nsresult DispatchFetchEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
// Worker Launcher thread only. Used for `AsyncLog().`
|
||||
RefPtr<FetchEventOpProxyChild> mActor;
|
||||
|
||||
/**
|
||||
* Created on the Worker Launcher thread and settled on the worker thread.
|
||||
* If this isn't settled before `mPromiseHolder` (which it should be),
|
||||
* `FetchEventOpChild` will cancel the intercepted network request.
|
||||
*/
|
||||
MozPromiseHolder<FetchEventRespondWithPromise> mRespondWithPromiseHolder;
|
||||
|
||||
// Worker thread only.
|
||||
Maybe<ExtendableEventResult> mResult;
|
||||
bool mPostDispatchChecksDone = false;
|
||||
|
||||
// Worker thread only; set when `FetchEvent::RespondWith()` is called.
|
||||
Maybe<FetchEventRespondWithClosure> mRespondWithClosure;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_serviceworkerop_h__
|
@ -195,15 +195,6 @@ nsresult ServiceWorkerPrivate::CheckScriptEvaluation(
|
||||
|
||||
namespace {
|
||||
|
||||
enum ExtendableEventResult { Rejected = 0, Resolved };
|
||||
|
||||
class ExtendableEventCallback {
|
||||
public:
|
||||
virtual void FinishedWithResult(ExtendableEventResult aResult) = 0;
|
||||
|
||||
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
|
||||
};
|
||||
|
||||
class KeepAliveHandler final : public ExtendableEvent::ExtensionsHandler,
|
||||
public PromiseNativeHandler {
|
||||
// This class manages lifetime extensions added by calling WaitUntil()
|
||||
|
@ -25,6 +25,7 @@ EXPORTS.mozilla.dom += [
|
||||
'ServiceWorkerManager.h',
|
||||
'ServiceWorkerManagerChild.h',
|
||||
'ServiceWorkerManagerParent.h',
|
||||
'ServiceWorkerOp.h',
|
||||
'ServiceWorkerOpPromise.h',
|
||||
'ServiceWorkerRegistrar.h',
|
||||
'ServiceWorkerRegistration.h',
|
||||
@ -61,6 +62,7 @@ UNIFIED_SOURCES += [
|
||||
'ServiceWorkerManagerChild.cpp',
|
||||
'ServiceWorkerManagerParent.cpp',
|
||||
'ServiceWorkerManagerService.cpp',
|
||||
'ServiceWorkerOp.cpp',
|
||||
'ServiceWorkerParent.cpp',
|
||||
'ServiceWorkerPrivate.cpp',
|
||||
'ServiceWorkerProxy.cpp',
|
||||
|
@ -26,7 +26,9 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ErrorValue;
|
||||
class FetchEventOpProxyChild;
|
||||
class RemoteWorkerData;
|
||||
class ServiceWorkerOp;
|
||||
class WeakWorkerRef;
|
||||
class WorkerErrorReport;
|
||||
class WorkerPrivate;
|
||||
@ -34,7 +36,9 @@ class WorkerPrivate;
|
||||
class RemoteWorkerChild final
|
||||
: public SupportsThreadSafeWeakPtr<RemoteWorkerChild>,
|
||||
public PRemoteWorkerChild {
|
||||
friend class FetchEventOpProxyChild;
|
||||
friend class PRemoteWorkerChild;
|
||||
friend class ServiceWorkerOp;
|
||||
|
||||
public:
|
||||
MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(RemoteWorkerChild)
|
||||
|
Loading…
Reference in New Issue
Block a user