Bug 1857841 - pt 3. Add a new page kind named "fresh" r=glandium
[gecko.git] / dom / clients / manager / ClientSourceOpChild.cpp
blob01176d7dca382746aaf22a512991b30e2c40f4bb
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ClientSourceOpChild.h"
9 #include "ClientSource.h"
10 #include "ClientSourceChild.h"
11 #include "mozilla/Assertions.h"
12 #include "mozilla/Unused.h"
14 namespace mozilla::dom {
16 ClientSource* ClientSourceOpChild::GetSource() const {
17 auto actor = static_cast<ClientSourceChild*>(Manager());
18 return actor->GetSource();
21 template <typename Method, typename... Args>
22 void ClientSourceOpChild::DoSourceOp(Method aMethod, Args&&... aArgs) {
23 RefPtr<ClientOpPromise> promise;
24 nsCOMPtr<nsISerialEventTarget> target;
26 // Some ClientSource operations can cause the ClientSource to be destroyed.
27 // This means we should reference the ClientSource pointer for the minimum
28 // possible to start the operation. Use an extra block scope here to help
29 // enforce this and prevent accidental usage later in the method.
31 ClientSource* source = GetSource();
32 if (!source) {
33 CopyableErrorResult rv;
34 rv.ThrowAbortError("Unknown Client");
35 Unused << PClientSourceOpChild::Send__delete__(this, rv);
36 return;
39 target = source->EventTarget();
41 // This may cause the ClientSource object to be destroyed. Do not
42 // use the source variable after this call.
43 promise = (source->*aMethod)(std::forward<Args>(aArgs)...);
46 // The ClientSource methods are required to always return a promise. If
47 // they encounter an error they should just immediately resolve or reject
48 // the promise as appropriate.
49 MOZ_DIAGNOSTIC_ASSERT(promise);
51 // Capture 'this' is safe here because we disconnect the promise
52 // ActorDestroy() which ensures neither lambda is called if the
53 // actor is destroyed before the source operation completes.
55 // Also capture the promise to ensure it lives until we get a reaction
56 // or the actor starts shutting down and we disconnect our Thenable.
57 // If the ClientSource is doing something async it may throw away the
58 // promise on its side if the global is closed.
59 promise
60 ->Then(
61 target, __func__,
62 [this, promise](const mozilla::dom::ClientOpResult& aResult) {
63 mPromiseRequestHolder.Complete();
64 Unused << PClientSourceOpChild::Send__delete__(this, aResult);
66 [this, promise](const CopyableErrorResult& aRv) {
67 mPromiseRequestHolder.Complete();
68 Unused << PClientSourceOpChild::Send__delete__(this, aRv);
70 ->Track(mPromiseRequestHolder);
73 void ClientSourceOpChild::ActorDestroy(ActorDestroyReason aReason) {
74 Cleanup();
77 void ClientSourceOpChild::Init(const ClientOpConstructorArgs& aArgs) {
78 switch (aArgs.type()) {
79 case ClientOpConstructorArgs::TClientControlledArgs: {
80 DoSourceOp(&ClientSource::Control, aArgs.get_ClientControlledArgs());
81 break;
83 case ClientOpConstructorArgs::TClientFocusArgs: {
84 DoSourceOp(&ClientSource::Focus, aArgs.get_ClientFocusArgs());
85 break;
87 case ClientOpConstructorArgs::TClientPostMessageArgs: {
88 DoSourceOp(&ClientSource::PostMessage, aArgs.get_ClientPostMessageArgs());
89 break;
91 case ClientOpConstructorArgs::TClientClaimArgs: {
92 MOZ_ASSERT_UNREACHABLE("shouldn't happen with parent intercept");
93 break;
95 case ClientOpConstructorArgs::TClientGetInfoAndStateArgs: {
96 DoSourceOp(&ClientSource::GetInfoAndState,
97 aArgs.get_ClientGetInfoAndStateArgs());
98 break;
100 case ClientOpConstructorArgs::TClientEvictBFCacheArgs: {
101 DoSourceOp(&ClientSource::EvictFromBFCacheOp);
102 break;
104 default: {
105 MOZ_ASSERT_UNREACHABLE("unknown client operation!");
106 break;
110 mInitialized.Flip();
112 if (mDeletionRequested) {
113 Cleanup();
114 delete this;
118 void ClientSourceOpChild::ScheduleDeletion() {
119 if (mInitialized) {
120 Cleanup();
121 delete this;
122 return;
125 mDeletionRequested.Flip();
128 ClientSourceOpChild::~ClientSourceOpChild() {
129 MOZ_DIAGNOSTIC_ASSERT(mInitialized);
132 void ClientSourceOpChild::Cleanup() {
133 mPromiseRequestHolder.DisconnectIfExists();
136 } // namespace mozilla::dom