summaryrefslogtreecommitdiffstats
path: root/dom/clients/manager/ClientHandle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/clients/manager/ClientHandle.cpp')
-rw-r--r--dom/clients/manager/ClientHandle.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/dom/clients/manager/ClientHandle.cpp b/dom/clients/manager/ClientHandle.cpp
new file mode 100644
index 0000000000..7aa777b1c6
--- /dev/null
+++ b/dom/clients/manager/ClientHandle.cpp
@@ -0,0 +1,194 @@
+/* -*- 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 "ClientHandle.h"
+
+#include "ClientHandleChild.h"
+#include "ClientHandleOpChild.h"
+#include "ClientManager.h"
+#include "ClientPrincipalUtils.h"
+#include "ClientState.h"
+#include "mozilla/dom/PClientManagerChild.h"
+#include "mozilla/dom/ServiceWorkerDescriptor.h"
+#include "mozilla/dom/ipc/StructuredCloneData.h"
+
+namespace mozilla::dom {
+
+using mozilla::dom::ipc::StructuredCloneData;
+
+ClientHandle::~ClientHandle() { Shutdown(); }
+
+void ClientHandle::Shutdown() {
+ NS_ASSERT_OWNINGTHREAD(ClientSource);
+ if (IsShutdown()) {
+ return;
+ }
+
+ ShutdownThing();
+
+ mManager = nullptr;
+}
+
+void ClientHandle::StartOp(const ClientOpConstructorArgs& aArgs,
+ const ClientOpCallback&& aResolveCallback,
+ const ClientOpCallback&& aRejectCallback) {
+ // Hold a ref to the client until the remote operation completes. Otherwise
+ // the ClientHandle might get de-refed and teardown the actor before we
+ // get an answer.
+ RefPtr<ClientHandle> kungFuGrip = this;
+
+ MaybeExecute(
+ [&aArgs, kungFuGrip, aRejectCallback,
+ resolve = std::move(aResolveCallback)](ClientHandleChild* aActor) {
+ MOZ_DIAGNOSTIC_ASSERT(aActor);
+ ClientHandleOpChild* actor = new ClientHandleOpChild(
+ kungFuGrip, aArgs, std::move(resolve), std::move(aRejectCallback));
+ if (!aActor->SendPClientHandleOpConstructor(actor, aArgs)) {
+ // Constructor failure will call reject callback via ActorDestroy()
+ return;
+ }
+ },
+ [aRejectCallback] {
+ MOZ_DIAGNOSTIC_ASSERT(aRejectCallback);
+ CopyableErrorResult rv;
+ rv.ThrowInvalidStateError("Client has been destroyed");
+ aRejectCallback(rv);
+ });
+}
+
+void ClientHandle::OnShutdownThing() {
+ NS_ASSERT_OWNINGTHREAD(ClientHandle);
+ if (!mDetachPromise) {
+ return;
+ }
+ mDetachPromise->Resolve(true, __func__);
+}
+
+ClientHandle::ClientHandle(ClientManager* aManager,
+ nsISerialEventTarget* aSerialEventTarget,
+ const ClientInfo& aClientInfo)
+ : mManager(aManager),
+ mSerialEventTarget(aSerialEventTarget),
+ mClientInfo(aClientInfo) {
+ MOZ_DIAGNOSTIC_ASSERT(mManager);
+ MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
+ MOZ_ASSERT(mSerialEventTarget->IsOnCurrentThread());
+}
+
+void ClientHandle::Activate(PClientManagerChild* aActor) {
+ NS_ASSERT_OWNINGTHREAD(ClientHandle);
+
+ if (IsShutdown()) {
+ return;
+ }
+
+ RefPtr<ClientHandleChild> actor = new ClientHandleChild();
+ if (!aActor->SendPClientHandleConstructor(actor, mClientInfo.ToIPC())) {
+ Shutdown();
+ return;
+ }
+
+ ActivateThing(actor);
+}
+
+void ClientHandle::ExecutionReady(const ClientInfo& aClientInfo) {
+ mClientInfo = aClientInfo;
+}
+
+const ClientInfo& ClientHandle::Info() const { return mClientInfo; }
+
+RefPtr<GenericErrorResultPromise> ClientHandle::Control(
+ const ServiceWorkerDescriptor& aServiceWorker) {
+ RefPtr<GenericErrorResultPromise::Private> outerPromise =
+ new GenericErrorResultPromise::Private(__func__);
+
+ // We should never have a cross-origin controller. Since this would be
+ // same-origin policy violation we do a full release assertion here.
+ MOZ_RELEASE_ASSERT(ClientMatchPrincipalInfo(mClientInfo.PrincipalInfo(),
+ aServiceWorker.PrincipalInfo()));
+
+ StartOp(
+ ClientControlledArgs(aServiceWorker.ToIPC()),
+ [outerPromise](const ClientOpResult& aResult) {
+ outerPromise->Resolve(true, __func__);
+ },
+ [outerPromise](const ClientOpResult& aResult) {
+ outerPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
+ });
+
+ return outerPromise;
+}
+
+RefPtr<ClientStatePromise> ClientHandle::Focus(CallerType aCallerType) {
+ RefPtr<ClientStatePromise::Private> outerPromise =
+ new ClientStatePromise::Private(__func__);
+
+ StartOp(
+ ClientFocusArgs(aCallerType),
+ [outerPromise](const ClientOpResult& aResult) {
+ outerPromise->Resolve(
+ ClientState::FromIPC(aResult.get_IPCClientState()), __func__);
+ },
+ [outerPromise](const ClientOpResult& aResult) {
+ outerPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
+ });
+
+ return outerPromise;
+}
+
+RefPtr<GenericErrorResultPromise> ClientHandle::PostMessage(
+ StructuredCloneData& aData, const ServiceWorkerDescriptor& aSource) {
+ if (IsShutdown()) {
+ CopyableErrorResult rv;
+ rv.ThrowInvalidStateError("Client has been destroyed");
+ return GenericErrorResultPromise::CreateAndReject(rv, __func__);
+ }
+
+ ClientPostMessageArgs args;
+ args.serviceWorker() = aSource.ToIPC();
+
+ if (!aData.BuildClonedMessageData(args.clonedData())) {
+ CopyableErrorResult rv;
+ rv.ThrowInvalidStateError("Failed to clone data");
+ return GenericErrorResultPromise::CreateAndReject(rv, __func__);
+ }
+
+ RefPtr<GenericErrorResultPromise::Private> outerPromise =
+ new GenericErrorResultPromise::Private(__func__);
+
+ StartOp(
+ std::move(args),
+ [outerPromise](const ClientOpResult& aResult) {
+ outerPromise->Resolve(true, __func__);
+ },
+ [outerPromise](const ClientOpResult& aResult) {
+ outerPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
+ });
+
+ return outerPromise;
+}
+
+RefPtr<GenericPromise> ClientHandle::OnDetach() {
+ NS_ASSERT_OWNINGTHREAD(ClientSource);
+
+ if (!mDetachPromise) {
+ mDetachPromise = new GenericPromise::Private(__func__);
+ if (IsShutdown()) {
+ mDetachPromise->Resolve(true, __func__);
+ }
+ }
+
+ return mDetachPromise;
+}
+
+void ClientHandle::EvictFromBFCache() {
+ ClientEvictBFCacheArgs args;
+ StartOp(
+ std::move(args), [](const ClientOpResult& aResult) {},
+ [](const ClientOpResult& aResult) {});
+}
+
+} // namespace mozilla::dom