зеркало из https://github.com/mozilla/gecko-dev.git
135 строки
4.2 KiB
C++
135 строки
4.2 KiB
C++
/* -*- 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 "ClientSourceOpChild.h"
|
|
|
|
#include "ClientSource.h"
|
|
#include "ClientSourceChild.h"
|
|
#include "mozilla/Assertions.h"
|
|
#include "mozilla/Unused.h"
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
|
|
ClientSource* ClientSourceOpChild::GetSource() const {
|
|
auto actor = static_cast<ClientSourceChild*>(Manager());
|
|
return actor->GetSource();
|
|
}
|
|
|
|
template <typename Method, typename Args>
|
|
void ClientSourceOpChild::DoSourceOp(Method aMethod, const Args& aArgs) {
|
|
RefPtr<ClientOpPromise> promise;
|
|
nsCOMPtr<nsISerialEventTarget> target;
|
|
|
|
// Some ClientSource operations can cause the ClientSource to be destroyed.
|
|
// This means we should reference the ClientSource pointer for the minimum
|
|
// possible to start the operation. Use an extra block scope here to help
|
|
// enforce this and prevent accidental usage later in the method.
|
|
{
|
|
ClientSource* source = GetSource();
|
|
if (!source) {
|
|
CopyableErrorResult rv;
|
|
rv.ThrowAbortError("Unknown Client");
|
|
Unused << PClientSourceOpChild::Send__delete__(this, rv);
|
|
return;
|
|
}
|
|
|
|
target = source->EventTarget();
|
|
|
|
// This may cause the ClientSource object to be destroyed. Do not
|
|
// use the source variable after this call.
|
|
promise = (source->*aMethod)(aArgs);
|
|
}
|
|
|
|
// The ClientSource methods are required to always return a promise. If
|
|
// they encounter an error they should just immediately resolve or reject
|
|
// the promise as appropriate.
|
|
MOZ_DIAGNOSTIC_ASSERT(promise);
|
|
|
|
// Capture 'this' is safe here because we disconnect the promise
|
|
// ActorDestroy() which ensures neither lambda is called if the
|
|
// actor is destroyed before the source operation completes.
|
|
//
|
|
// Also capture the promise to ensure it lives until we get a reaction
|
|
// or the actor starts shutting down and we disconnect our Thenable.
|
|
// If the ClientSource is doing something async it may throw away the
|
|
// promise on its side if the global is closed.
|
|
promise
|
|
->Then(
|
|
target, __func__,
|
|
[this, promise](const mozilla::dom::ClientOpResult& aResult) {
|
|
mPromiseRequestHolder.Complete();
|
|
Unused << PClientSourceOpChild::Send__delete__(this, aResult);
|
|
},
|
|
[this, promise](const CopyableErrorResult& aRv) {
|
|
mPromiseRequestHolder.Complete();
|
|
Unused << PClientSourceOpChild::Send__delete__(this, aRv);
|
|
})
|
|
->Track(mPromiseRequestHolder);
|
|
}
|
|
|
|
void ClientSourceOpChild::ActorDestroy(ActorDestroyReason aReason) {
|
|
Cleanup();
|
|
}
|
|
|
|
void ClientSourceOpChild::Init(const ClientOpConstructorArgs& aArgs) {
|
|
switch (aArgs.type()) {
|
|
case ClientOpConstructorArgs::TClientControlledArgs: {
|
|
DoSourceOp(&ClientSource::Control, aArgs.get_ClientControlledArgs());
|
|
break;
|
|
}
|
|
case ClientOpConstructorArgs::TClientFocusArgs: {
|
|
DoSourceOp(&ClientSource::Focus, aArgs.get_ClientFocusArgs());
|
|
break;
|
|
}
|
|
case ClientOpConstructorArgs::TClientPostMessageArgs: {
|
|
DoSourceOp(&ClientSource::PostMessage, aArgs.get_ClientPostMessageArgs());
|
|
break;
|
|
}
|
|
case ClientOpConstructorArgs::TClientClaimArgs: {
|
|
DoSourceOp(&ClientSource::Claim, aArgs.get_ClientClaimArgs());
|
|
break;
|
|
}
|
|
case ClientOpConstructorArgs::TClientGetInfoAndStateArgs: {
|
|
DoSourceOp(&ClientSource::GetInfoAndState,
|
|
aArgs.get_ClientGetInfoAndStateArgs());
|
|
break;
|
|
}
|
|
default: {
|
|
MOZ_ASSERT_UNREACHABLE("unknown client operation!");
|
|
break;
|
|
}
|
|
}
|
|
|
|
mInitialized.Flip();
|
|
|
|
if (mDeletionRequested) {
|
|
Cleanup();
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
void ClientSourceOpChild::ScheduleDeletion() {
|
|
if (mInitialized) {
|
|
Cleanup();
|
|
delete this;
|
|
return;
|
|
}
|
|
|
|
mDeletionRequested.Flip();
|
|
}
|
|
|
|
ClientSourceOpChild::~ClientSourceOpChild() {
|
|
MOZ_DIAGNOSTIC_ASSERT(mInitialized);
|
|
}
|
|
|
|
void ClientSourceOpChild::Cleanup() {
|
|
mPromiseRequestHolder.DisconnectIfExists();
|
|
}
|
|
|
|
} // namespace dom
|
|
} // namespace mozilla
|