diff --git a/dom/serviceworkers/PServiceWorkerRegistration.ipdl b/dom/serviceworkers/PServiceWorkerRegistration.ipdl index 9b6814b0c221..36812b86a939 100644 --- a/dom/serviceworkers/PServiceWorkerRegistration.ipdl +++ b/dom/serviceworkers/PServiceWorkerRegistration.ipdl @@ -16,6 +16,7 @@ protocol PServiceWorkerRegistration parent: async Teardown(); + async Unregister() returns (bool aSuccess, CopyableErrorResult aRv); async Update() returns (IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult aResult); child: diff --git a/dom/serviceworkers/RemoteServiceWorkerRegistrationImpl.cpp b/dom/serviceworkers/RemoteServiceWorkerRegistrationImpl.cpp index 7833bcc366f9..188a5ca2c14e 100644 --- a/dom/serviceworkers/RemoteServiceWorkerRegistrationImpl.cpp +++ b/dom/serviceworkers/RemoteServiceWorkerRegistrationImpl.cpp @@ -85,7 +85,25 @@ void RemoteServiceWorkerRegistrationImpl::Unregister(ServiceWorkerBoolCallback&& aSuccessCB, ServiceWorkerFailureCallback&& aFailureCB) { - // TODO + if (!mActor) { + aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR)); + return; + } + + mActor->SendUnregister( + [successCB = std::move(aSuccessCB), aFailureCB] + (Tuple&& aResult) { + if (Get<1>(aResult).Failed()) { + // application layer error + aFailureCB(Get<1>(aResult)); + return; + } + // success + successCB(Get<0>(aResult)); + }, [aFailureCB] (ResponseRejectReason aReason) { + // IPC layer error + aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR)); + }); } RemoteServiceWorkerRegistrationImpl::RemoteServiceWorkerRegistrationImpl(const ServiceWorkerRegistrationDescriptor& aDescriptor) diff --git a/dom/serviceworkers/ServiceWorkerRegistrationParent.cpp b/dom/serviceworkers/ServiceWorkerRegistrationParent.cpp index 32860ee9a33e..0e9c80c6a1c4 100644 --- a/dom/serviceworkers/ServiceWorkerRegistrationParent.cpp +++ b/dom/serviceworkers/ServiceWorkerRegistrationParent.cpp @@ -29,6 +29,36 @@ ServiceWorkerRegistrationParent::RecvTeardown() return IPC_OK(); } +namespace { + +void +ResolveUnregister(PServiceWorkerRegistrationParent::UnregisterResolver&& aResolver, + bool aSuccess, nsresult aRv) +{ + aResolver(Tuple( + aSuccess, CopyableErrorResult(aRv))); +} + +} // anonymous namespace + +IPCResult +ServiceWorkerRegistrationParent::RecvUnregister(UnregisterResolver&& aResolver) +{ + if (!mProxy) { + ResolveUnregister(std::move(aResolver), false, NS_ERROR_DOM_INVALID_STATE_ERR); + return IPC_OK(); + } + + mProxy->Unregister()->Then(GetCurrentThreadSerialEventTarget(), __func__, + [aResolver] (bool aSuccess) mutable { + ResolveUnregister(std::move(aResolver), aSuccess, NS_OK); + }, [aResolver] (nsresult aRv) mutable { + ResolveUnregister(std::move(aResolver), false, aRv); + }); + + return IPC_OK(); +} + IPCResult ServiceWorkerRegistrationParent::RecvUpdate(UpdateResolver&& aResolver) { diff --git a/dom/serviceworkers/ServiceWorkerRegistrationParent.h b/dom/serviceworkers/ServiceWorkerRegistrationParent.h index fea090194e21..a1be6808defa 100644 --- a/dom/serviceworkers/ServiceWorkerRegistrationParent.h +++ b/dom/serviceworkers/ServiceWorkerRegistrationParent.h @@ -27,6 +27,9 @@ class ServiceWorkerRegistrationParent final : public PServiceWorkerRegistrationP mozilla::ipc::IPCResult RecvTeardown() override; + mozilla::ipc::IPCResult + RecvUnregister(UnregisterResolver&& aResolver) override; + mozilla::ipc::IPCResult RecvUpdate(UpdateResolver&& aResolver) override; diff --git a/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp b/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp index e574ff65bae6..516cc382a518 100644 --- a/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp +++ b/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp @@ -172,6 +172,78 @@ ServiceWorkerRegistrationProxy::RevokeActor(ServiceWorkerRegistrationParent* aAc namespace { +class UnregisterCallback final : public nsIServiceWorkerUnregisterCallback +{ + RefPtr mPromise; + + ~UnregisterCallback() = default; + +public: + explicit UnregisterCallback(GenericPromise::Private* aPromise) + : mPromise(aPromise) + { + MOZ_DIAGNOSTIC_ASSERT(mPromise); + } + + NS_IMETHOD + UnregisterSucceeded(bool aState) override + { + mPromise->Resolve(aState, __func__); + return NS_OK; + } + + NS_IMETHOD + UnregisterFailed() override + { + mPromise->Reject(NS_ERROR_DOM_SECURITY_ERR, __func__); + return NS_OK; + } + + NS_DECL_ISUPPORTS +}; + +NS_IMPL_ISUPPORTS(UnregisterCallback, nsIServiceWorkerUnregisterCallback) + +} // anonymous namespace + +RefPtr +ServiceWorkerRegistrationProxy::Unregister() +{ + AssertIsOnBackgroundThread(); + + RefPtr self = this; + RefPtr promise = + new GenericPromise::Private(__func__); + + nsCOMPtr r = NS_NewRunnableFunction(__func__, + [self, promise] () mutable { + nsresult rv = NS_ERROR_DOM_INVALID_STATE_ERR; + auto scopeExit = MakeScopeExit([&] { + promise->Reject(rv, __func__); + }); + + NS_ENSURE_TRUE_VOID(self->mReg); + + RefPtr swm = ServiceWorkerManager::GetInstance(); + NS_ENSURE_TRUE_VOID(swm); + + RefPtr cb = new UnregisterCallback(promise); + + rv = swm->Unregister(self->mReg->Principal(), cb, + NS_ConvertUTF8toUTF16(self->mReg->Scope())); + NS_ENSURE_SUCCESS_VOID(rv); + + + scopeExit.release(); + }); + + MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other, r.forget())); + + return promise; +} + +namespace { + class UpdateCallback final : public ServiceWorkerUpdateFinishCallback { RefPtr mPromise; diff --git a/dom/serviceworkers/ServiceWorkerRegistrationProxy.h b/dom/serviceworkers/ServiceWorkerRegistrationProxy.h index f5bbcec93aeb..64d3985214ae 100644 --- a/dom/serviceworkers/ServiceWorkerRegistrationProxy.h +++ b/dom/serviceworkers/ServiceWorkerRegistrationProxy.h @@ -72,6 +72,9 @@ public: void RevokeActor(ServiceWorkerRegistrationParent* aActor); + RefPtr + Unregister(); + RefPtr Update();