Bug 1412856 part 1. Change ClientOpPromise to use a CopyableErrorResult for its rejection type. r=dom-workers-and-storage-reviewers,sg?

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Boris Zbarsky 2020-01-30 09:01:26 +00:00
parent 96b8905f87
commit a389959875
26 changed files with 250 additions and 163 deletions

View File

@ -44,6 +44,7 @@
#include "mozilla/dom/VisualViewport.h" #include "mozilla/dom/VisualViewport.h"
#include "mozilla/dom/WindowProxyHolder.h" #include "mozilla/dom/WindowProxyHolder.h"
#include "mozilla/IntegerPrintfMacros.h" #include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Result.h"
#if defined(MOZ_WIDGET_ANDROID) #if defined(MOZ_WIDGET_ANDROID)
# include "mozilla/dom/WindowOrientationObserver.h" # include "mozilla/dom/WindowOrientationObserver.h"
#endif #endif
@ -5439,10 +5440,11 @@ Maybe<ClientState> nsGlobalWindowInner::GetClientState() const {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
Maybe<ClientState> clientState; Maybe<ClientState> clientState;
if (mClientSource) { if (mClientSource) {
ClientState state; Result<ClientState, ErrorResult> res = mClientSource->SnapshotState();
nsresult rv = mClientSource->SnapshotState(&state); if (res.isOk()) {
if (NS_SUCCEEDED(rv)) { clientState.emplace(res.unwrap());
clientState.emplace(state); } else {
res.unwrapErr().SuppressException();
} }
} }
return clientState; return clientState;

View File

@ -724,6 +724,27 @@ class CopyableErrorResult
CopyableErrorResult(CopyableErrorResult&& aRHS) CopyableErrorResult(CopyableErrorResult&& aRHS)
: BaseErrorResult(std::move(aRHS)) {} : BaseErrorResult(std::move(aRHS)) {}
explicit CopyableErrorResult(ErrorResult&& aRHS) : BaseErrorResult() {
// We must not copy JS exceptions since it can too easily lead to
// off-thread use. Assert this and fall back to a generic error
// in release builds.
MOZ_DIAGNOSTIC_ASSERT(
!aRHS.IsJSException(),
"Attempt to copy from ErrorResult with a JS exception value.");
if (aRHS.IsJSException()) {
aRHS.SuppressException();
Throw(NS_ERROR_FAILURE);
} else {
// We could avoid the cast here if we had a move constructor on
// TErrorResult templated on the cleanup policy type, but then we'd have
// to either inline the impl or force all possible instantiations or
// something. This is a bit simpler, and not that different from our copy
// constructor.
auto val = reinterpret_cast<CopyableErrorResult&&>(aRHS);
operator=(val);
}
}
explicit CopyableErrorResult(nsresult aRv) : BaseErrorResult(aRv) {} explicit CopyableErrorResult(nsresult aRv) : BaseErrorResult(aRv) {}
// This operator is deprecated and ideally shouldn't be used. // This operator is deprecated and ideally shouldn't be used.

View File

@ -161,9 +161,11 @@ already_AddRefed<Promise> Client::Focus(CallerType aCallerType,
ClientInfoAndState(ipcClientInfo, aResult.ToIPC())); ClientInfoAndState(ipcClientInfo, aResult.ToIPC()));
outerPromise->MaybeResolve(newClient); outerPromise->MaybeResolve(newClient);
}, },
[holder, outerPromise](nsresult aResult) { [holder, outerPromise](const CopyableErrorResult& aResult) {
holder->Complete(); holder->Complete();
outerPromise->MaybeReject(aResult); // MaybeReject needs a non-const result, so make a copy.
CopyableErrorResult result(aResult);
outerPromise->MaybeReject(result);
}) })
->Track(*holder); ->Track(*holder);
@ -198,7 +200,7 @@ already_AddRefed<Promise> Client::Navigate(const nsAString& aURL,
new Client(self->mGlobal, aResult.get_ClientInfoAndState()); new Client(self->mGlobal, aResult.get_ClientInfoAndState());
outerPromise->MaybeResolve(newClient); outerPromise->MaybeResolve(newClient);
}, },
[self, outerPromise](nsresult aResult) { [self, outerPromise](const CopyableErrorResult& aResult) {
// TODO: Improve this error in bug 1412856. Ideally we should throw // TODO: Improve this error in bug 1412856. Ideally we should throw
// the TypeError in the child process and pass it back to here. // the TypeError in the child process and pass it back to here.
outerPromise->MaybeReject(NS_ERROR_DOM_TYPE_ERR); outerPromise->MaybeReject(NS_ERROR_DOM_TYPE_ERR);

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/ClientOpPromise.h" #include "mozilla/dom/ClientOpPromise.h"
#include "mozilla/dom/DOMMozPromiseRequestHolder.h" #include "mozilla/dom/DOMMozPromiseRequestHolder.h"
#include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/ErrorResult.h"
class nsIGlobalObject; class nsIGlobalObject;
@ -37,7 +38,7 @@ void StartClientManagerOp(Func aFunc, const Arg& aArg, nsIGlobalObject* aGlobal,
holder->Complete(); holder->Complete();
aResolve(aResult); aResolve(aResult);
}, },
[aReject, holder](nsresult aResult) { [aReject, holder](const CopyableErrorResult& aResult) {
holder->Complete(); holder->Complete();
aReject(aResult); aReject(aResult);
}) })

View File

@ -103,7 +103,7 @@ already_AddRefed<Promise> Clients::Get(const nsAString& aClientID,
SystemGroup::Dispatch(TaskCategory::Other, r.forget()); SystemGroup::Dispatch(TaskCategory::Other, r.forget());
outerPromise->MaybeResolveWithUndefined(); outerPromise->MaybeResolveWithUndefined();
}, },
[outerPromise, holder](nsresult aResult) { [outerPromise, holder](const CopyableErrorResult& aResult) {
holder->Complete(); holder->Complete();
outerPromise->MaybeResolveWithUndefined(); outerPromise->MaybeResolveWithUndefined();
}) })
@ -188,7 +188,11 @@ already_AddRefed<Promise> Clients::MatchAll(const ClientQueryOptions& aOptions,
clientList.Sort(MatchAllComparator()); clientList.Sort(MatchAllComparator());
outerPromise->MaybeResolve(clientList); outerPromise->MaybeResolve(clientList);
}, },
[outerPromise](nsresult aResult) { outerPromise->MaybeReject(aResult); }); [outerPromise](const CopyableErrorResult& aResult) {
// MaybeReject needs a non-const result, so make a copy.
CopyableErrorResult result(aResult);
outerPromise->MaybeReject(result);
});
return outerPromise.forget(); return outerPromise.forget();
} }
@ -237,7 +241,7 @@ already_AddRefed<Promise> Clients::OpenWindow(const nsAString& aURL,
new Client(global, aResult.get_ClientInfoAndState()); new Client(global, aResult.get_ClientInfoAndState());
outerPromise->MaybeResolve(client); outerPromise->MaybeResolve(client);
}, },
[outerPromise](nsresult aResult) { [outerPromise](const CopyableErrorResult& aResult) {
// TODO: Improve this error in bug 1412856. Ideally we should throw // TODO: Improve this error in bug 1412856. Ideally we should throw
// the TypeError in the child process and pass it back to here. // the TypeError in the child process and pass it back to here.
outerPromise->MaybeReject(NS_ERROR_DOM_TYPE_ERR); outerPromise->MaybeReject(NS_ERROR_DOM_TYPE_ERR);
@ -272,7 +276,11 @@ already_AddRefed<Promise> Clients::Claim(ErrorResult& aRv) {
[outerPromise](const ClientOpResult& aResult) { [outerPromise](const ClientOpResult& aResult) {
outerPromise->MaybeResolveWithUndefined(); outerPromise->MaybeResolveWithUndefined();
}, },
[outerPromise](nsresult aResult) { outerPromise->MaybeReject(aResult); }); [outerPromise](const CopyableErrorResult& aResult) {
// MaybeReject needs a non-const result, so make a copy.
CopyableErrorResult result(aResult);
outerPromise->MaybeReject(result);
});
return outerPromise.forget(); return outerPromise.forget();
} }

View File

@ -54,7 +54,9 @@ void ClientHandle::StartOp(const ClientOpConstructorArgs& aArgs,
}, },
[aRejectCallback] { [aRejectCallback] {
MOZ_DIAGNOSTIC_ASSERT(aRejectCallback); MOZ_DIAGNOSTIC_ASSERT(aRejectCallback);
aRejectCallback(NS_ERROR_DOM_INVALID_STATE_ERR); CopyableErrorResult rv;
rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
aRejectCallback(rv);
}); });
} }
@ -100,10 +102,10 @@ void ClientHandle::ExecutionReady(const ClientInfo& aClientInfo) {
const ClientInfo& ClientHandle::Info() const { return mClientInfo; } const ClientInfo& ClientHandle::Info() const { return mClientInfo; }
RefPtr<GenericPromise> ClientHandle::Control( RefPtr<GenericErrorResultPromise> ClientHandle::Control(
const ServiceWorkerDescriptor& aServiceWorker) { const ServiceWorkerDescriptor& aServiceWorker) {
RefPtr<GenericPromise::Private> outerPromise = RefPtr<GenericErrorResultPromise::Private> outerPromise =
new GenericPromise::Private(__func__); new GenericErrorResultPromise::Private(__func__);
// We should never have a cross-origin controller. Since this would be // We should never have a cross-origin controller. Since this would be
// same-origin policy violation we do a full release assertion here. // same-origin policy violation we do a full release assertion here.
@ -116,7 +118,7 @@ RefPtr<GenericPromise> ClientHandle::Control(
outerPromise->Resolve(true, __func__); outerPromise->Resolve(true, __func__);
}, },
[outerPromise](const ClientOpResult& aResult) { [outerPromise](const ClientOpResult& aResult) {
outerPromise->Reject(aResult.get_nsresult(), __func__); outerPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
}); });
return outerPromise.forget(); return outerPromise.forget();
@ -133,17 +135,18 @@ RefPtr<ClientStatePromise> ClientHandle::Focus(CallerType aCallerType) {
ClientState::FromIPC(aResult.get_IPCClientState()), __func__); ClientState::FromIPC(aResult.get_IPCClientState()), __func__);
}, },
[outerPromise](const ClientOpResult& aResult) { [outerPromise](const ClientOpResult& aResult) {
outerPromise->Reject(aResult.get_nsresult(), __func__); outerPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
}); });
return outerPromise.forget(); return outerPromise.forget();
} }
RefPtr<GenericPromise> ClientHandle::PostMessage( RefPtr<GenericErrorResultPromise> ClientHandle::PostMessage(
StructuredCloneData& aData, const ServiceWorkerDescriptor& aSource) { StructuredCloneData& aData, const ServiceWorkerDescriptor& aSource) {
if (IsShutdown()) { if (IsShutdown()) {
return GenericPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, CopyableErrorResult rv;
__func__); rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return GenericErrorResultPromise::CreateAndReject(rv, __func__);
} }
ClientPostMessageArgs args; ClientPostMessageArgs args;
@ -151,12 +154,13 @@ RefPtr<GenericPromise> ClientHandle::PostMessage(
if (!aData.BuildClonedMessageDataForBackgroundChild( if (!aData.BuildClonedMessageDataForBackgroundChild(
GetActor()->Manager()->Manager(), args.clonedData())) { GetActor()->Manager()->Manager(), args.clonedData())) {
return GenericPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, CopyableErrorResult rv;
__func__); rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return GenericErrorResultPromise::CreateAndReject(rv, __func__);
} }
RefPtr<GenericPromise::Private> outerPromise = RefPtr<GenericErrorResultPromise::Private> outerPromise =
new GenericPromise::Private(__func__); new GenericErrorResultPromise::Private(__func__);
StartOp( StartOp(
std::move(args), std::move(args),
@ -164,7 +168,7 @@ RefPtr<GenericPromise> ClientHandle::PostMessage(
outerPromise->Resolve(true, __func__); outerPromise->Resolve(true, __func__);
}, },
[outerPromise](const ClientOpResult& aResult) { [outerPromise](const ClientOpResult& aResult) {
outerPromise->Reject(aResult.get_nsresult(), __func__); outerPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
}); });
return outerPromise.forget(); return outerPromise.forget();

View File

@ -71,7 +71,8 @@ class ClientHandle final : public ClientThing<ClientHandleChild> {
// Mark the ClientSource attached to this handle as controlled by the // Mark the ClientSource attached to this handle as controlled by the
// given service worker. The promise will resolve true if the ClientSource // given service worker. The promise will resolve true if the ClientSource
// is successfully marked or reject if the operation could not be completed. // is successfully marked or reject if the operation could not be completed.
RefPtr<GenericPromise> Control(const ServiceWorkerDescriptor& aServiceWorker); RefPtr<GenericErrorResultPromise> Control(
const ServiceWorkerDescriptor& aServiceWorker);
// Focus the Client if possible. If successful the promise will resolve with // Focus the Client if possible. If successful the promise will resolve with
// a new ClientState snapshot after focus has completed. If focusing fails // a new ClientState snapshot after focus has completed. If focusing fails
@ -84,8 +85,8 @@ class ClientHandle final : public ClientThing<ClientHandleChild> {
// returned promise will resolve if the MessageEvent is dispatched or if // returned promise will resolve if the MessageEvent is dispatched or if
// it triggers an error handled in the Client's context. Other errors // it triggers an error handled in the Client's context. Other errors
// will result in the promise rejecting. // will result in the promise rejecting.
RefPtr<GenericPromise> PostMessage(ipc::StructuredCloneData& aData, RefPtr<GenericErrorResultPromise> PostMessage(
const ServiceWorkerDescriptor& aSource); ipc::StructuredCloneData& aData, const ServiceWorkerDescriptor& aSource);
// Return a Promise that resolves when the ClientHandle object is detached // Return a Promise that resolves when the ClientHandle object is detached
// from its remote actors. This will happen if the ClientSource is destroyed // from its remote actors. This will happen if the ClientSource is destroyed

View File

@ -13,15 +13,17 @@ namespace dom {
void ClientHandleOpChild::ActorDestroy(ActorDestroyReason aReason) { void ClientHandleOpChild::ActorDestroy(ActorDestroyReason aReason) {
mClientHandle = nullptr; mClientHandle = nullptr;
mRejectCallback(NS_ERROR_DOM_ABORT_ERR); CopyableErrorResult rv;
rv.Throw(NS_ERROR_DOM_ABORT_ERR);
mRejectCallback(rv);
} }
mozilla::ipc::IPCResult ClientHandleOpChild::Recv__delete__( mozilla::ipc::IPCResult ClientHandleOpChild::Recv__delete__(
const ClientOpResult& aResult) { const ClientOpResult& aResult) {
mClientHandle = nullptr; mClientHandle = nullptr;
if (aResult.type() == ClientOpResult::Tnsresult && if (aResult.type() == ClientOpResult::TCopyableErrorResult &&
NS_FAILED(aResult.get_nsresult())) { aResult.get_CopyableErrorResult().Failed()) {
mRejectCallback(aResult.get_nsresult()); mRejectCallback(aResult.get_CopyableErrorResult());
return IPC_OK(); return IPC_OK();
} }
mResolveCallback(aResult); mResolveCallback(aResult);

View File

@ -49,8 +49,9 @@ void ClientHandleOpParent::Init(ClientOpConstructorArgs&& aArgs) {
orig.clonedData()); orig.clonedData());
if (!data.BuildClonedMessageDataForBackgroundParent( if (!data.BuildClonedMessageDataForBackgroundParent(
source->Manager()->Manager(), rebuild.clonedData())) { source->Manager()->Manager(), rebuild.clonedData())) {
Unused << PClientHandleOpParent::Send__delete__( CopyableErrorResult rv;
this, NS_ERROR_DOM_ABORT_ERR); rv.Throw(NS_ERROR_DOM_ABORT_ERR);
Unused << PClientHandleOpParent::Send__delete__(this, rv);
return; return;
} }
@ -72,7 +73,7 @@ void ClientHandleOpParent::Init(ClientOpConstructorArgs&& aArgs) {
Unused << PClientHandleOpParent::Send__delete__(this, Unused << PClientHandleOpParent::Send__delete__(this,
aResult); aResult);
}, },
[this](nsresult aRv) { [this](const CopyableErrorResult& aRv) {
mPromiseRequestHolder.Complete(); mPromiseRequestHolder.Complete();
Unused << PClientHandleOpParent::Send__delete__(this, aRv); Unused << PClientHandleOpParent::Send__delete__(this, aRv);
}) })
@ -80,8 +81,9 @@ void ClientHandleOpParent::Init(ClientOpConstructorArgs&& aArgs) {
}, },
[=](nsresult failure) { [=](nsresult failure) {
mSourcePromiseRequestHolder.Complete(); mSourcePromiseRequestHolder.Complete();
Unused << PClientHandleOpParent::Send__delete__( CopyableErrorResult rv;
this, NS_ERROR_DOM_ABORT_ERR); rv.Throw(NS_ERROR_DOM_ABORT_ERR);
Unused << PClientHandleOpParent::Send__delete__(this, rv);
return; return;
}) })
->Track(mSourcePromiseRequestHolder); ->Track(mSourcePromiseRequestHolder);

View File

@ -13,6 +13,7 @@ using FrameType from "mozilla/dom/ClientIPCUtils.h";
using mozilla::StorageAccess from "mozilla/dom/ClientIPCUtils.h"; using mozilla::StorageAccess from "mozilla/dom/ClientIPCUtils.h";
using VisibilityState from "mozilla/dom/ClientIPCUtils.h"; using VisibilityState from "mozilla/dom/ClientIPCUtils.h";
using CallerType from "mozilla/dom/BindingIPCUtils.h"; using CallerType from "mozilla/dom/BindingIPCUtils.h";
using mozilla::CopyableErrorResult from "ipc/ErrorIPCUtils.h";
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@ -144,7 +145,7 @@ struct ClientNavigateOpConstructorArgs
union ClientOpResult union ClientOpResult
{ {
nsresult; CopyableErrorResult;
IPCClientState; IPCClientState;
ClientInfoAndState; ClientInfoAndState;
ClientList; ClientList;

View File

@ -23,9 +23,9 @@ void ClientManagerOpChild::ActorDestroy(ActorDestroyReason aReason) {
mozilla::ipc::IPCResult ClientManagerOpChild::Recv__delete__( mozilla::ipc::IPCResult ClientManagerOpChild::Recv__delete__(
const ClientOpResult& aResult) { const ClientOpResult& aResult) {
mClientManager = nullptr; mClientManager = nullptr;
if (aResult.type() == ClientOpResult::Tnsresult && if (aResult.type() == ClientOpResult::TCopyableErrorResult &&
NS_FAILED(aResult.get_nsresult())) { aResult.get_CopyableErrorResult().Failed()) {
mPromise->Reject(aResult.get_nsresult(), __func__); mPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
mPromise = nullptr; mPromise = nullptr;
return IPC_OK(); return IPC_OK();
} }

View File

@ -30,7 +30,7 @@ void ClientManagerOpParent::DoServiceOp(Method aMethod, Args&&... aArgs) {
mPromiseRequestHolder.Complete(); mPromiseRequestHolder.Complete();
Unused << PClientManagerOpParent::Send__delete__(this, aResult); Unused << PClientManagerOpParent::Send__delete__(this, aResult);
}, },
[this](nsresult aRv) { [this](const CopyableErrorResult& aRv) {
mPromiseRequestHolder.Complete(); mPromiseRequestHolder.Complete();
Unused << PClientManagerOpParent::Send__delete__(this, aRv); Unused << PClientManagerOpParent::Send__delete__(this, aRv);
}) })

View File

@ -280,7 +280,9 @@ RefPtr<ClientOpPromise> ClientManagerService::Navigate(
ClientSourceParent* source = ClientSourceParent* source =
FindSource(aArgs.target().id(), aArgs.target().principalInfo()); FindSource(aArgs.target().id(), aArgs.target().principalInfo());
if (!source) { if (!source) {
return ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); CopyableErrorResult rv;
rv.Throw(NS_ERROR_FAILURE);
return ClientOpPromise::CreateAndReject(rv, __func__);
} }
PClientManagerParent* manager = source->Manager(); PClientManagerParent* manager = source->Manager();
@ -362,7 +364,9 @@ class PromiseListHolder final {
self->ProcessCompletion(); self->ProcessCompletion();
} }
}, },
[self](nsresult aResult) { self->ProcessCompletion(); }); [self](const CopyableErrorResult& aResult) {
self->ProcessCompletion();
});
} }
void MaybeFinish() { void MaybeFinish() {
@ -442,11 +446,16 @@ RefPtr<ClientOpPromise> ClaimOnMainThread(
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
NS_ENSURE_TRUE_VOID(swm); NS_ENSURE_TRUE_VOID(swm);
RefPtr<GenericPromise> inner = swm->MaybeClaimClient(clientInfo, desc); RefPtr<GenericErrorResultPromise> inner =
swm->MaybeClaimClient(clientInfo, desc);
inner->Then( inner->Then(
SystemGroup::EventTargetFor(TaskCategory::Other), __func__, SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
[promise](bool aResult) { promise->Resolve(NS_OK, __func__); }, [promise](bool aResult) {
[promise](nsresult aRv) { promise->Reject(aRv, __func__); }); promise->Resolve(CopyableErrorResult(), __func__);
},
[promise](const CopyableErrorResult& aRv) {
promise->Reject(aRv, __func__);
});
scopeExit.release(); scopeExit.release();
}); });
@ -516,7 +525,9 @@ RefPtr<ClientOpPromise> ClientManagerService::GetInfoAndState(
ClientSourceParent* source = FindSource(aArgs.id(), aArgs.principalInfo()); ClientSourceParent* source = FindSource(aArgs.id(), aArgs.principalInfo());
if (!source) { if (!source) {
return ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); CopyableErrorResult rv;
rv.Throw(NS_ERROR_FAILURE);
return ClientOpPromise::CreateAndReject(rv, __func__);
} }
if (!source->ExecutionReady()) { if (!source->ExecutionReady()) {
@ -530,7 +541,9 @@ RefPtr<ClientOpPromise> ClientManagerService::GetInfoAndState(
self->FindSource(aArgs.id(), aArgs.principalInfo()); self->FindSource(aArgs.id(), aArgs.principalInfo());
if (!source) { if (!source) {
return ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); CopyableErrorResult rv;
rv.Throw(NS_ERROR_FAILURE);
return ClientOpPromise::CreateAndReject(rv, __func__);
} }
return source->StartOp(aArgs); return source->StartOp(aArgs);

View File

@ -73,7 +73,7 @@ class NavigateLoadListener final : public nsIWebProgressListener,
// console you also need to update the 'aFromPrivateWindow' argument. // console you also need to update the 'aFromPrivateWindow' argument.
rv = ssm->CheckSameOriginURI(mBaseURL, channelURL, false, false); rv = ssm->CheckSameOriginURI(mBaseURL, channelURL, false, false);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mPromise->Resolve(NS_OK, __func__); mPromise->Resolve(CopyableErrorResult(), __func__);
return NS_OK; return NS_OK;
} }
@ -158,14 +158,16 @@ RefPtr<ClientOpPromise> ClientNavigateOpChild::DoNavigate(
ClientSource* target = targetActor->GetSource(); ClientSource* target = targetActor->GetSource();
if (!target) { if (!target) {
return ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, CopyableErrorResult rv;
__func__); rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return ClientOpPromise::CreateAndReject(rv, __func__);
} }
window = target->GetInnerWindow(); window = target->GetInnerWindow();
if (!window) { if (!window) {
return ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, CopyableErrorResult rv;
__func__); rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return ClientOpPromise::CreateAndReject(rv, __func__);
} }
} }
@ -180,7 +182,11 @@ RefPtr<ClientOpPromise> ClientNavigateOpChild::DoNavigate(
nsCOMPtr<nsIURI> baseURL; nsCOMPtr<nsIURI> baseURL;
nsresult rv = NS_NewURI(getter_AddRefs(baseURL), aArgs.baseURL()); nsresult rv = NS_NewURI(getter_AddRefs(baseURL), aArgs.baseURL());
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return ClientOpPromise::CreateAndReject(rv, __func__); // This is rather unexpected: This is the worker URL we passed from the
// parent, so we expect this to parse fine!
CopyableErrorResult result;
result.Throw(rv);
return ClientOpPromise::CreateAndReject(result, __func__);
} }
// There is an edge case for view-source url here. According to the wpt test // There is an edge case for view-source url here. According to the wpt test
@ -201,29 +207,32 @@ RefPtr<ClientOpPromise> ClientNavigateOpChild::DoNavigate(
rv = NS_NewURI(getter_AddRefs(url), aArgs.url(), nullptr, rv = NS_NewURI(getter_AddRefs(url), aArgs.url(), nullptr,
shouldUseBaseURL ? baseURL.get() : nullptr); shouldUseBaseURL ? baseURL.get() : nullptr);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return ClientOpPromise::CreateAndReject(rv, __func__); CopyableErrorResult result;
result.Throw(rv);
return ClientOpPromise::CreateAndReject(result, __func__);
} }
if (url->GetSpecOrDefault().EqualsLiteral("about:blank")) { if (url->GetSpecOrDefault().EqualsLiteral("about:blank")) {
return ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); CopyableErrorResult result;
result.Throw(NS_ERROR_FAILURE);
return ClientOpPromise::CreateAndReject(result, __func__);
} }
RefPtr<Document> doc = window->GetExtantDoc(); RefPtr<Document> doc = window->GetExtantDoc();
if (!doc || !doc->IsActive()) { if (!doc || !doc->IsActive()) {
return ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, CopyableErrorResult result;
__func__); result.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return ClientOpPromise::CreateAndReject(result, __func__);
} }
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal(); nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
if (!principal) {
return ClientOpPromise::CreateAndReject(rv, __func__);
}
nsCOMPtr<nsIDocShell> docShell = window->GetDocShell(); nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell); nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
if (!docShell || !webProgress) { if (!docShell || !webProgress) {
return ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, CopyableErrorResult result;
__func__); result.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return ClientOpPromise::CreateAndReject(result, __func__);
} }
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(url); RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(url);
@ -240,7 +249,9 @@ RefPtr<ClientOpPromise> ClientNavigateOpChild::DoNavigate(
loadState->SetFirstParty(true); loadState->SetFirstParty(true);
rv = docShell->LoadURI(loadState, false); rv = docShell->LoadURI(loadState, false);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return ClientOpPromise::CreateAndReject(rv, __func__); CopyableErrorResult result;
result.Throw(rv);
return ClientOpPromise::CreateAndReject(result, __func__);
} }
RefPtr<ClientOpPromise::Private> promise = RefPtr<ClientOpPromise::Private> promise =
@ -286,7 +297,7 @@ void ClientNavigateOpChild::Init(const ClientNavigateOpConstructorArgs& aArgs) {
mPromiseRequestHolder.Complete(); mPromiseRequestHolder.Complete();
PClientNavigateOpChild::Send__delete__(this, aResult); PClientNavigateOpChild::Send__delete__(this, aResult);
}, },
[this](nsresult aResult) { [this](const CopyableErrorResult& aResult) {
mPromiseRequestHolder.Complete(); mPromiseRequestHolder.Complete();
PClientNavigateOpChild::Send__delete__(this, aResult); PClientNavigateOpChild::Send__delete__(this, aResult);
}) })

View File

@ -20,9 +20,9 @@ void ClientNavigateOpParent::ActorDestroy(ActorDestroyReason aReason) {
IPCResult ClientNavigateOpParent::Recv__delete__( IPCResult ClientNavigateOpParent::Recv__delete__(
const ClientOpResult& aResult) { const ClientOpResult& aResult) {
if (aResult.type() == ClientOpResult::Tnsresult && if (aResult.type() == ClientOpResult::TCopyableErrorResult &&
NS_FAILED(aResult.get_nsresult())) { aResult.get_CopyableErrorResult().Failed()) {
mPromise->Reject(aResult.get_nsresult(), __func__); mPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
mPromise = nullptr; mPromise = nullptr;
return IPC_OK(); return IPC_OK();
} }

View File

@ -6,6 +6,7 @@
#ifndef _mozilla_dom_ClientOpPromise_h #ifndef _mozilla_dom_ClientOpPromise_h
#define _mozilla_dom_ClientOpPromise_h #define _mozilla_dom_ClientOpPromise_h
#include "mozilla/ErrorResult.h"
#include "mozilla/MozPromise.h" #include "mozilla/MozPromise.h"
namespace mozilla { namespace mozilla {
@ -14,9 +15,12 @@ namespace dom {
class ClientOpResult; class ClientOpResult;
class ClientState; class ClientState;
typedef MozPromise<ClientOpResult, nsresult, false> ClientOpPromise; typedef MozPromise<ClientOpResult, CopyableErrorResult, false> ClientOpPromise;
typedef MozPromise<ClientState, nsresult, false> ClientStatePromise; typedef MozPromise<ClientState, CopyableErrorResult, false> ClientStatePromise;
typedef MozPromise<bool, CopyableErrorResult, /* IsExclusive = */ true>
GenericErrorResultPromise;
typedef std::function<void(const ClientOpResult&)> ClientOpCallback; typedef std::function<void(const ClientOpResult&)> ClientOpCallback;

View File

@ -28,7 +28,7 @@ void ClientOpenWindowOpChild::Init(const ClientOpenWindowArgs& aArgs) {
mPromiseRequestHolder.Complete(); mPromiseRequestHolder.Complete();
PClientOpenWindowOpChild::Send__delete__(this, aResult); PClientOpenWindowOpChild::Send__delete__(this, aResult);
}, },
[this](nsresult aResult) { [this](const CopyableErrorResult& aResult) {
mPromiseRequestHolder.Complete(); mPromiseRequestHolder.Complete();
PClientOpenWindowOpChild::Send__delete__(this, aResult); PClientOpenWindowOpChild::Send__delete__(this, aResult);
}) })

View File

@ -20,9 +20,9 @@ void ClientOpenWindowOpParent::ActorDestroy(ActorDestroyReason aReason) {
IPCResult ClientOpenWindowOpParent::Recv__delete__( IPCResult ClientOpenWindowOpParent::Recv__delete__(
const ClientOpResult& aResult) { const ClientOpResult& aResult) {
if (aResult.type() == ClientOpResult::Tnsresult && if (aResult.type() == ClientOpResult::TCopyableErrorResult &&
NS_FAILED(aResult.get_nsresult())) { aResult.get_CopyableErrorResult().Failed()) {
mPromise->Reject(aResult.get_nsresult(), __func__); mPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
mPromise = nullptr; mPromise = nullptr;
return IPC_OK(); return IPC_OK();
} }

View File

@ -75,7 +75,7 @@ class WebProgressListener final : public nsIWebProgressListener,
nsresult rv = securityManager->CheckSameOriginURI( nsresult rv = securityManager->CheckSameOriginURI(
doc->GetOriginalURI(), mBaseURI, false, isPrivateWin); doc->GetOriginalURI(), mBaseURI, false, isPrivateWin);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mPromise->Resolve(NS_OK, __func__); mPromise->Resolve(CopyableErrorResult(), __func__);
mPromise = nullptr; mPromise = nullptr;
return NS_OK; return NS_OK;
} }
@ -295,7 +295,7 @@ void WaitForLoad(const ClientOpenWindowArgs& aArgs,
ref->Then( ref->Then(
aOuterWindow->EventTargetFor(TaskCategory::Other), __func__, aOuterWindow->EventTargetFor(TaskCategory::Other), __func__,
[listener](const ClientOpResult& aResult) {}, [listener](const ClientOpResult& aResult) {},
[listener](nsresult aResult) {}); [listener](const CopyableErrorResult& aResult) {});
} }
#ifdef MOZ_WIDGET_ANDROID #ifdef MOZ_WIDGET_ANDROID

View File

@ -72,35 +72,32 @@ void ClientSource::ExecutionReady(const ClientSourceExecutionReadyArgs& aArgs) {
}); });
} }
nsresult ClientSource::SnapshotWindowState(ClientState* aStateOut) { Result<ClientState, ErrorResult> ClientSource::SnapshotWindowState() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsPIDOMWindowInner* window = GetInnerWindow(); nsPIDOMWindowInner* window = GetInnerWindow();
if (!window || !window->IsCurrentInnerWindow() || if (!window || !window->IsCurrentInnerWindow() ||
!window->HasActiveDocument()) { !window->HasActiveDocument()) {
*aStateOut = ClientState(ClientWindowState( return ClientState(ClientWindowState(VisibilityState::Hidden, TimeStamp(),
VisibilityState::Hidden, TimeStamp(), StorageAccess::eDeny, false)); StorageAccess::eDeny, false));
return NS_OK;
} }
Document* doc = window->GetExtantDoc(); Document* doc = window->GetExtantDoc();
ErrorResult rv;
if (NS_WARN_IF(!doc)) { if (NS_WARN_IF(!doc)) {
return NS_ERROR_UNEXPECTED; rv.Throw(NS_ERROR_UNEXPECTED);
return Err(std::move(rv));
} }
ErrorResult rv;
bool focused = doc->HasFocus(rv); bool focused = doc->HasFocus(rv);
if (NS_WARN_IF(rv.Failed())) { if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException(); return Err(std::move(rv));
return rv.StealNSResult();
} }
StorageAccess storage = StorageAllowedForDocument(doc); StorageAccess storage = StorageAllowedForDocument(doc);
*aStateOut = ClientState(ClientWindowState( return ClientState(ClientWindowState(doc->VisibilityState(),
doc->VisibilityState(), doc->LastFocusTime(), storage, focused)); doc->LastFocusTime(), storage, focused));
return NS_OK;
} }
WorkerPrivate* ClientSource::GetWorkerPrivate() const { WorkerPrivate* ClientSource::GetWorkerPrivate() const {
@ -448,13 +445,14 @@ RefPtr<ClientOpPromise> ClientSource::Control(
} }
if (NS_WARN_IF(!controlAllowed)) { if (NS_WARN_IF(!controlAllowed)) {
return ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, CopyableErrorResult rv;
__func__); rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return ClientOpPromise::CreateAndReject(rv, __func__);
} }
SetController(ServiceWorkerDescriptor(aArgs.serviceWorker())); SetController(ServiceWorkerDescriptor(aArgs.serviceWorker()));
return ClientOpPromise::CreateAndResolve(NS_OK, __func__); return ClientOpPromise::CreateAndResolve(CopyableErrorResult(), __func__);
} }
void ClientSource::InheritController( void ClientSource::InheritController(
@ -534,8 +532,9 @@ RefPtr<ClientOpPromise> ClientSource::Focus(const ClientFocusArgs& aArgs) {
NS_ASSERT_OWNINGTHREAD(ClientSource); NS_ASSERT_OWNINGTHREAD(ClientSource);
if (mClientInfo.Type() != ClientType::Window) { if (mClientInfo.Type() != ClientType::Window) {
return ClientOpPromise::CreateAndReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, CopyableErrorResult rv;
__func__); rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return ClientOpPromise::CreateAndReject(rv, __func__);
} }
nsPIDOMWindowOuter* outer = nullptr; nsPIDOMWindowOuter* outer = nullptr;
@ -550,20 +549,21 @@ RefPtr<ClientOpPromise> ClientSource::Focus(const ClientFocusArgs& aArgs) {
} }
if (!outer) { if (!outer) {
return ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, CopyableErrorResult rv;
__func__); rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return ClientOpPromise::CreateAndReject(rv, __func__);
} }
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsFocusManager::FocusWindow(outer, aArgs.callerType()); nsFocusManager::FocusWindow(outer, aArgs.callerType());
ClientState state; Result<ClientState, ErrorResult> state = SnapshotState();
nsresult rv = SnapshotState(&state); if (state.isErr()) {
if (NS_FAILED(rv)) { return ClientOpPromise::CreateAndReject(
return ClientOpPromise::CreateAndReject(rv, __func__); CopyableErrorResult(state.unwrapErr()), __func__);
} }
return ClientOpPromise::CreateAndResolve(state.ToIPC(), __func__); return ClientOpPromise::CreateAndResolve(state.inspect().ToIPC(), __func__);
} }
RefPtr<ClientOpPromise> ClientSource::PostMessage( RefPtr<ClientOpPromise> ClientSource::PostMessage(
@ -577,10 +577,12 @@ RefPtr<ClientOpPromise> ClientSource::PostMessage(
const RefPtr<ServiceWorkerContainer> container = const RefPtr<ServiceWorkerContainer> container =
window->Navigator()->ServiceWorker(); window->Navigator()->ServiceWorker();
container->ReceiveMessage(aArgs); container->ReceiveMessage(aArgs);
return ClientOpPromise::CreateAndResolve(NS_OK, __func__); return ClientOpPromise::CreateAndResolve(CopyableErrorResult(), __func__);
} }
return ClientOpPromise::CreateAndReject(NS_ERROR_NOT_IMPLEMENTED, __func__); CopyableErrorResult rv;
rv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return ClientOpPromise::CreateAndReject(rv, __func__);
} }
RefPtr<ClientOpPromise> ClientSource::Claim(const ClientClaimArgs& aArgs) { RefPtr<ClientOpPromise> ClientSource::Claim(const ClientClaimArgs& aArgs) {
@ -591,8 +593,9 @@ RefPtr<ClientOpPromise> ClientSource::Claim(const ClientClaimArgs& aArgs) {
nsIGlobalObject* global = GetGlobal(); nsIGlobalObject* global = GetGlobal();
if (NS_WARN_IF(!global)) { if (NS_WARN_IF(!global)) {
return ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, CopyableErrorResult rv;
__func__); rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return ClientOpPromise::CreateAndReject(rv, __func__);
} }
// Note, we cannot just mark the ClientSource controlled. We must go through // Note, we cannot just mark the ClientSource controlled. We must go through
@ -601,8 +604,8 @@ RefPtr<ClientOpPromise> ClientSource::Claim(const ClientClaimArgs& aArgs) {
// mode. In parent-process service worker mode the SWM is notified in the // mode. In parent-process service worker mode the SWM is notified in the
// parent-process in ClientManagerService::Claim(). // parent-process in ClientManagerService::Claim().
RefPtr<GenericPromise::Private> innerPromise = RefPtr<GenericErrorResultPromise::Private> innerPromise =
new GenericPromise::Private(__func__); new GenericErrorResultPromise::Private(__func__);
ServiceWorkerDescriptor swd(aArgs.serviceWorker()); ServiceWorkerDescriptor swd(aArgs.serviceWorker());
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
@ -614,7 +617,8 @@ RefPtr<ClientOpPromise> ClientSource::Claim(const ClientClaimArgs& aArgs) {
return; return;
} }
RefPtr<GenericPromise> p = swm->MaybeClaimClient(clientInfo, swd); RefPtr<GenericErrorResultPromise> p =
swm->MaybeClaimClient(clientInfo, swd);
p->ChainTo(innerPromise.forget(), __func__); p->ChainTo(innerPromise.forget(), __func__);
}); });
@ -627,16 +631,17 @@ RefPtr<ClientOpPromise> ClientSource::Claim(const ClientClaimArgs& aArgs) {
RefPtr<ClientOpPromise::Private> outerPromise = RefPtr<ClientOpPromise::Private> outerPromise =
new ClientOpPromise::Private(__func__); new ClientOpPromise::Private(__func__);
auto holder = MakeRefPtr<DOMMozPromiseRequestHolder<GenericPromise>>(global); auto holder =
MakeRefPtr<DOMMozPromiseRequestHolder<GenericErrorResultPromise>>(global);
innerPromise innerPromise
->Then( ->Then(
mEventTarget, __func__, mEventTarget, __func__,
[outerPromise, holder](bool aResult) { [outerPromise, holder](bool aResult) {
holder->Complete(); holder->Complete();
outerPromise->Resolve(NS_OK, __func__); outerPromise->Resolve(CopyableErrorResult(), __func__);
}, },
[outerPromise, holder](nsresult aResult) { [outerPromise, holder](const CopyableErrorResult& aResult) {
holder->Complete(); holder->Complete();
outerPromise->Reject(aResult, __func__); outerPromise->Reject(aResult, __func__);
}) })
@ -647,36 +652,33 @@ RefPtr<ClientOpPromise> ClientSource::Claim(const ClientClaimArgs& aArgs) {
RefPtr<ClientOpPromise> ClientSource::GetInfoAndState( RefPtr<ClientOpPromise> ClientSource::GetInfoAndState(
const ClientGetInfoAndStateArgs& aArgs) { const ClientGetInfoAndStateArgs& aArgs) {
ClientState state; Result<ClientState, ErrorResult> state = SnapshotState();
nsresult rv = SnapshotState(&state); if (state.isErr()) {
if (NS_FAILED(rv)) { return ClientOpPromise::CreateAndReject(
return ClientOpPromise::CreateAndReject(rv, __func__); CopyableErrorResult(state.unwrapErr()), __func__);
} }
return ClientOpPromise::CreateAndResolve( return ClientOpPromise::CreateAndResolve(
ClientInfoAndState(mClientInfo.ToIPC(), state.ToIPC()), __func__); ClientInfoAndState(mClientInfo.ToIPC(), state.inspect().ToIPC()),
__func__);
} }
nsresult ClientSource::SnapshotState(ClientState* aStateOut) { Result<ClientState, ErrorResult> ClientSource::SnapshotState() {
NS_ASSERT_OWNINGTHREAD(ClientSource); NS_ASSERT_OWNINGTHREAD(ClientSource);
MOZ_DIAGNOSTIC_ASSERT(aStateOut);
if (mClientInfo.Type() == ClientType::Window) { if (mClientInfo.Type() == ClientType::Window) {
MaybeCreateInitialDocument(); MaybeCreateInitialDocument();
nsresult rv = SnapshotWindowState(aStateOut); return SnapshotWindowState();
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
} }
WorkerPrivate* workerPrivate = GetWorkerPrivate(); WorkerPrivate* workerPrivate = GetWorkerPrivate();
if (!workerPrivate) { if (!workerPrivate) {
return NS_ERROR_DOM_INVALID_STATE_ERR; ErrorResult rv;
rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return Err(std::move(rv));
} }
*aStateOut = ClientState(ClientWorkerState(workerPrivate->StorageAccess())); return ClientState(ClientWorkerState(workerPrivate->StorageAccess()));
return NS_OK;
} }
nsISerialEventTarget* ClientSource::EventTarget() const { return mEventTarget; } nsISerialEventTarget* ClientSource::EventTarget() const { return mEventTarget; }

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/ClientOpPromise.h" #include "mozilla/dom/ClientOpPromise.h"
#include "mozilla/dom/ClientThing.h" #include "mozilla/dom/ClientThing.h"
#include "mozilla/dom/ServiceWorkerDescriptor.h" #include "mozilla/dom/ServiceWorkerDescriptor.h"
#include "mozilla/Result.h"
#include "mozilla/Variant.h" #include "mozilla/Variant.h"
#ifdef XP_WIN #ifdef XP_WIN
@ -78,7 +79,7 @@ class ClientSource final : public ClientThing<ClientSourceChild> {
void MaybeCreateInitialDocument(); void MaybeCreateInitialDocument();
nsresult SnapshotWindowState(ClientState* aStateOut); Result<ClientState, ErrorResult> SnapshotWindowState();
// Private methods called by ClientManager // Private methods called by ClientManager
ClientSource(ClientManager* aManager, nsISerialEventTarget* aEventTarget, ClientSource(ClientManager* aManager, nsISerialEventTarget* aEventTarget,
@ -145,7 +146,7 @@ class ClientSource final : public ClientThing<ClientSourceChild> {
RefPtr<ClientOpPromise> GetInfoAndState( RefPtr<ClientOpPromise> GetInfoAndState(
const ClientGetInfoAndStateArgs& aArgs); const ClientGetInfoAndStateArgs& aArgs);
nsresult SnapshotState(ClientState* aStateOut); Result<ClientState, ErrorResult> SnapshotState();
nsISerialEventTarget* EventTarget() const; nsISerialEventTarget* EventTarget() const;

View File

@ -30,8 +30,9 @@ void ClientSourceOpChild::DoSourceOp(Method aMethod, const Args& aArgs) {
{ {
ClientSource* source = GetSource(); ClientSource* source = GetSource();
if (!source) { if (!source) {
Unused << PClientSourceOpChild::Send__delete__(this, CopyableErrorResult rv;
NS_ERROR_DOM_ABORT_ERR); rv.Throw(NS_ERROR_DOM_ABORT_ERR);
Unused << PClientSourceOpChild::Send__delete__(this, rv);
return; return;
} }
@ -62,7 +63,7 @@ void ClientSourceOpChild::DoSourceOp(Method aMethod, const Args& aArgs) {
mPromiseRequestHolder.Complete(); mPromiseRequestHolder.Complete();
Unused << PClientSourceOpChild::Send__delete__(this, aResult); Unused << PClientSourceOpChild::Send__delete__(this, aResult);
}, },
[this, promise](nsresult aRv) { [this, promise](const CopyableErrorResult& aRv) {
mPromiseRequestHolder.Complete(); mPromiseRequestHolder.Complete();
Unused << PClientSourceOpChild::Send__delete__(this, aRv); Unused << PClientSourceOpChild::Send__delete__(this, aRv);
}) })

View File

@ -21,8 +21,8 @@ void ClientSourceOpParent::ActorDestroy(ActorDestroyReason aReason) {
} }
IPCResult ClientSourceOpParent::Recv__delete__(const ClientOpResult& aResult) { IPCResult ClientSourceOpParent::Recv__delete__(const ClientOpResult& aResult) {
if (aResult.type() == ClientOpResult::Tnsresult && if (aResult.type() == ClientOpResult::TCopyableErrorResult &&
NS_FAILED(aResult.get_nsresult())) { aResult.get_CopyableErrorResult().Failed()) {
// If a control message fails then clear the controller from // If a control message fails then clear the controller from
// the ClientSourceParent. We eagerly marked it controlled at // the ClientSourceParent. We eagerly marked it controlled at
// the start of the operation. // the start of the operation.
@ -33,7 +33,7 @@ IPCResult ClientSourceOpParent::Recv__delete__(const ClientOpResult& aResult) {
} }
} }
mPromise->Reject(aResult.get_nsresult(), __func__); mPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
mPromise = nullptr; mPromise = nullptr;
return IPC_OK(); return IPC_OK();
} }

View File

@ -377,13 +377,13 @@ void ServiceWorkerManager::Init(ServiceWorkerRegistrar* aRegistrar) {
mActor = static_cast<ServiceWorkerManagerChild*>(actor); mActor = static_cast<ServiceWorkerManagerChild*>(actor);
} }
RefPtr<GenericPromise> ServiceWorkerManager::StartControllingClient( RefPtr<GenericErrorResultPromise> ServiceWorkerManager::StartControllingClient(
const ClientInfo& aClientInfo, const ClientInfo& aClientInfo,
ServiceWorkerRegistrationInfo* aRegistrationInfo, ServiceWorkerRegistrationInfo* aRegistrationInfo,
bool aControlClientHandle) { bool aControlClientHandle) {
MOZ_DIAGNOSTIC_ASSERT(aRegistrationInfo->GetActive()); MOZ_DIAGNOSTIC_ASSERT(aRegistrationInfo->GetActive());
RefPtr<GenericPromise> promise; RefPtr<GenericErrorResultPromise> promise;
RefPtr<ServiceWorkerManager> self(this); RefPtr<ServiceWorkerManager> self(this);
const ServiceWorkerDescriptor& active = const ServiceWorkerDescriptor& active =
@ -397,7 +397,7 @@ RefPtr<GenericPromise> ServiceWorkerManager::StartControllingClient(
if (aControlClientHandle) { if (aControlClientHandle) {
promise = entry.Data()->mClientHandle->Control(active); promise = entry.Data()->mClientHandle->Control(active);
} else { } else {
promise = GenericPromise::CreateAndResolve(false, __func__); promise = GenericErrorResultPromise::CreateAndResolve(false, __func__);
} }
entry.Data()->mRegistrationInfo = aRegistrationInfo; entry.Data()->mRegistrationInfo = aRegistrationInfo;
@ -415,12 +415,12 @@ RefPtr<GenericPromise> ServiceWorkerManager::StartControllingClient(
SystemGroup::EventTargetFor(TaskCategory::Other), __func__, SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
[](bool) { [](bool) {
// do nothing on success // do nothing on success
return GenericPromise::CreateAndResolve(true, __func__); return GenericErrorResultPromise::CreateAndResolve(true, __func__);
}, },
[self, aClientInfo](nsresult aRv) { [self, aClientInfo](const CopyableErrorResult& aRv) {
// failed to control, forget about this client // failed to control, forget about this client
self->StopControllingClient(aClientInfo); self->StopControllingClient(aClientInfo);
return GenericPromise::CreateAndReject(aRv, __func__); return GenericErrorResultPromise::CreateAndReject(aRv, __func__);
}); });
} }
@ -430,7 +430,7 @@ RefPtr<GenericPromise> ServiceWorkerManager::StartControllingClient(
if (aControlClientHandle) { if (aControlClientHandle) {
promise = clientHandle->Control(active); promise = clientHandle->Control(active);
} else { } else {
promise = GenericPromise::CreateAndResolve(false, __func__); promise = GenericErrorResultPromise::CreateAndResolve(false, __func__);
} }
aRegistrationInfo->StartControllingClient(); aRegistrationInfo->StartControllingClient();
@ -451,12 +451,12 @@ RefPtr<GenericPromise> ServiceWorkerManager::StartControllingClient(
SystemGroup::EventTargetFor(TaskCategory::Other), __func__, SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
[](bool) { [](bool) {
// do nothing on success // do nothing on success
return GenericPromise::CreateAndResolve(true, __func__); return GenericErrorResultPromise::CreateAndResolve(true, __func__);
}, },
[self, aClientInfo](nsresult aRv) { [self, aClientInfo](const CopyableErrorResult& aRv) {
// failed to control, forget about this client // failed to control, forget about this client
self->StopControllingClient(aClientInfo); self->StopControllingClient(aClientInfo);
return GenericPromise::CreateAndReject(aRv, __func__); return GenericErrorResultPromise::CreateAndReject(aRv, __func__);
}); });
} }
@ -2241,7 +2241,7 @@ void ServiceWorkerManager::UpdateControlledClient(
RefPtr<ServiceWorkerManager> self = this; RefPtr<ServiceWorkerManager> self = this;
RefPtr<GenericPromise> p = RefPtr<GenericErrorResultPromise> p =
StartControllingClient(aNewClientInfo, registration); StartControllingClient(aNewClientInfo, registration);
p->Then( p->Then(
SystemGroup::EventTargetFor(TaskCategory::Other), __func__, SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
@ -2251,7 +2251,7 @@ void ServiceWorkerManager::UpdateControlledClient(
}, },
// Controlling the new ClientInfo fail, do nothing. // Controlling the new ClientInfo fail, do nothing.
// Probably need to call LoadInfo::ClearController // Probably need to call LoadInfo::ClearController
[](nsresult aRv) {}); [](const CopyableErrorResult& aRv) {});
} }
void ServiceWorkerManager::SoftUpdate(const OriginAttributes& aOriginAttributes, void ServiceWorkerManager::SoftUpdate(const OriginAttributes& aOriginAttributes,
@ -2467,20 +2467,23 @@ void ServiceWorkerManager::UpdateInternal(
queue->ScheduleJob(job); queue->ScheduleJob(job);
} }
RefPtr<GenericPromise> ServiceWorkerManager::MaybeClaimClient( RefPtr<GenericErrorResultPromise> ServiceWorkerManager::MaybeClaimClient(
const ClientInfo& aClientInfo, const ClientInfo& aClientInfo,
ServiceWorkerRegistrationInfo* aWorkerRegistration) { ServiceWorkerRegistrationInfo* aWorkerRegistration) {
MOZ_DIAGNOSTIC_ASSERT(aWorkerRegistration); MOZ_DIAGNOSTIC_ASSERT(aWorkerRegistration);
if (!aWorkerRegistration->GetActive()) { if (!aWorkerRegistration->GetActive()) {
return GenericPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, CopyableErrorResult rv;
__func__); rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return GenericErrorResultPromise::CreateAndReject(rv, __func__);
} }
// Same origin check // Same origin check
nsCOMPtr<nsIPrincipal> principal(aClientInfo.GetPrincipal()); nsCOMPtr<nsIPrincipal> principal(aClientInfo.GetPrincipal());
if (!aWorkerRegistration->Principal()->Equals(principal)) { if (!aWorkerRegistration->Principal()->Equals(principal)) {
return GenericPromise::CreateAndReject(NS_ERROR_DOM_SECURITY_ERR, __func__); CopyableErrorResult rv;
rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return GenericErrorResultPromise::CreateAndReject(rv, __func__);
} }
// The registration that should be controlling the client // The registration that should be controlling the client
@ -2493,18 +2496,18 @@ RefPtr<GenericPromise> ServiceWorkerManager::MaybeClaimClient(
if (aWorkerRegistration != matchingRegistration || if (aWorkerRegistration != matchingRegistration ||
aWorkerRegistration == controllingRegistration) { aWorkerRegistration == controllingRegistration) {
return GenericPromise::CreateAndResolve(true, __func__); return GenericErrorResultPromise::CreateAndResolve(true, __func__);
} }
return StartControllingClient(aClientInfo, aWorkerRegistration); return StartControllingClient(aClientInfo, aWorkerRegistration);
} }
RefPtr<GenericPromise> ServiceWorkerManager::MaybeClaimClient( RefPtr<GenericErrorResultPromise> ServiceWorkerManager::MaybeClaimClient(
const ClientInfo& aClientInfo, const ClientInfo& aClientInfo,
const ServiceWorkerDescriptor& aServiceWorker) { const ServiceWorkerDescriptor& aServiceWorker) {
nsCOMPtr<nsIPrincipal> principal = aServiceWorker.GetPrincipal(); nsCOMPtr<nsIPrincipal> principal = aServiceWorker.GetPrincipal();
if (!principal) { if (!principal) {
return GenericPromise::CreateAndResolve(false, __func__); return GenericErrorResultPromise::CreateAndResolve(false, __func__);
} }
RefPtr<ServiceWorkerRegistrationInfo> registration = RefPtr<ServiceWorkerRegistrationInfo> registration =
@ -2516,7 +2519,7 @@ RefPtr<GenericPromise> ServiceWorkerManager::MaybeClaimClient(
// are done. The fix for this is to move the SWM to the parent process // are done. The fix for this is to move the SWM to the parent process
// so there are no consistency errors. // so there are no consistency errors.
if (NS_WARN_IF(!registration) || NS_WARN_IF(!registration->GetActive())) { if (NS_WARN_IF(!registration) || NS_WARN_IF(!registration->GetActive())) {
return GenericPromise::CreateAndResolve(false, __func__); return GenericErrorResultPromise::CreateAndResolve(false, __func__);
} }
return MaybeClaimClient(aClientInfo, registration); return MaybeClaimClient(aClientInfo, registration);
@ -2564,7 +2567,8 @@ void ServiceWorkerManager::UpdateClientControllers(
// Fire event after iterating mControlledClients is done to prevent // Fire event after iterating mControlledClients is done to prevent
// modification by reentering from the event handlers during iteration. // modification by reentering from the event handlers during iteration.
for (auto& handle : handleList) { for (auto& handle : handleList) {
RefPtr<GenericPromise> p = handle->Control(activeWorker->Descriptor()); RefPtr<GenericErrorResultPromise> p =
handle->Control(activeWorker->Descriptor());
RefPtr<ServiceWorkerManager> self = this; RefPtr<ServiceWorkerManager> self = this;
@ -2575,7 +2579,7 @@ void ServiceWorkerManager::UpdateClientControllers(
[](bool) { [](bool) {
// do nothing on success // do nothing on success
}, },
[self, clientInfo = handle->Info()](nsresult aRv) { [self, clientInfo = handle->Info()](const CopyableErrorResult& aRv) {
// failed to control, forget about this client // failed to control, forget about this client
self->StopControllingClient(clientInfo); self->StopControllingClient(clientInfo);
}); });

View File

@ -238,11 +238,11 @@ class ServiceWorkerManager final : public nsIServiceWorkerManager,
const nsString& aLine, uint32_t aLineNumber, const nsString& aLine, uint32_t aLineNumber,
uint32_t aColumnNumber, uint32_t aFlags, JSExnType aExnType); uint32_t aColumnNumber, uint32_t aFlags, JSExnType aExnType);
MOZ_MUST_USE RefPtr<GenericPromise> MaybeClaimClient( MOZ_MUST_USE RefPtr<GenericErrorResultPromise> MaybeClaimClient(
const ClientInfo& aClientInfo, const ClientInfo& aClientInfo,
ServiceWorkerRegistrationInfo* aWorkerRegistration); ServiceWorkerRegistrationInfo* aWorkerRegistration);
MOZ_MUST_USE RefPtr<GenericPromise> MaybeClaimClient( MOZ_MUST_USE RefPtr<GenericErrorResultPromise> MaybeClaimClient(
const ClientInfo& aClientInfo, const ClientInfo& aClientInfo,
const ServiceWorkerDescriptor& aServiceWorker); const ServiceWorkerDescriptor& aServiceWorker);
@ -308,7 +308,7 @@ class ServiceWorkerManager final : public nsIServiceWorkerManager,
void Init(ServiceWorkerRegistrar* aRegistrar); void Init(ServiceWorkerRegistrar* aRegistrar);
RefPtr<GenericPromise> StartControllingClient( RefPtr<GenericErrorResultPromise> StartControllingClient(
const ClientInfo& aClientInfo, const ClientInfo& aClientInfo,
ServiceWorkerRegistrationInfo* aRegistrationInfo, ServiceWorkerRegistrationInfo* aRegistrationInfo,
bool aControlClientHandle = true); bool aControlClientHandle = true);

View File

@ -14,6 +14,7 @@
#include "js/MemoryMetrics.h" #include "js/MemoryMetrics.h"
#include "js/SourceText.h" #include "js/SourceText.h"
#include "MessageEventRunnable.h" #include "MessageEventRunnable.h"
#include "mozilla/Result.h"
#include "mozilla/ScopeExit.h" #include "mozilla/ScopeExit.h"
#include "mozilla/StaticPrefs_dom.h" #include "mozilla/StaticPrefs_dom.h"
#include "mozilla/dom/BlobURLProtocolHandler.h" #include "mozilla/dom/BlobURLProtocolHandler.h"
@ -3079,9 +3080,15 @@ Maybe<ClientInfo> WorkerPrivate::GetClientInfo() const {
const ClientState WorkerPrivate::GetClientState() const { const ClientState WorkerPrivate::GetClientState() const {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data); MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
MOZ_DIAGNOSTIC_ASSERT(data->mClientSource); MOZ_DIAGNOSTIC_ASSERT(data->mClientSource);
ClientState state; Result<ClientState, ErrorResult> res = data->mClientSource->SnapshotState();
data->mClientSource->SnapshotState(&state); if (res.isOk()) {
return state; return res.unwrap();
}
// XXXbz Why is it OK to just ignore errors and return a default-initialized
// state here?
res.unwrapErr().SuppressException();
return ClientState();
} }
const Maybe<ServiceWorkerDescriptor> WorkerPrivate::GetController() { const Maybe<ServiceWorkerDescriptor> WorkerPrivate::GetController() {