Bug 1570115 - Add do_QueryActor to query JS-implemented interfaces. r=kmag

This allows querying an actor for interfaces implemented in JS.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Agi Sferro 2019-09-20 18:01:07 +00:00
parent 29e0543f01
commit 3a3968887a
4 changed files with 83 additions and 0 deletions

View File

@ -10,6 +10,8 @@
#include "mozilla/dom/PWindowGlobal.h"
#include "mozilla/dom/Promise.h"
#include "js/Promise.h"
#include "xpcprivate.h"
#include "nsIXPConnect.h"
namespace mozilla {
namespace dom {
@ -31,6 +33,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(JSWindowActor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingQueries)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWrappedJS)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(JSWindowActor)
@ -71,6 +74,26 @@ void JSWindowActor::InvokeCallback(CallbackFunction callback) {
}
}
nsresult JSWindowActor::QueryInterfaceActor(const nsIID& aIID, void** aPtr) {
if (!mWrappedJS) {
AutoEntryScript aes(GetParentObject(), "JSWindowActor query interface");
JSContext* cx = aes.cx();
JS::Rooted<JSObject*> self(cx, GetWrapper());
JSAutoRealm ar(cx, self);
RefPtr<nsXPCWrappedJS> wrappedJS;
nsresult rv = nsXPCWrappedJS::GetNewOrUsed(
cx, self, NS_GET_IID(nsISupports), getter_AddRefs(wrappedJS));
NS_ENSURE_SUCCESS(rv, rv);
mWrappedJS = do_QueryInterface(wrappedJS);
MOZ_ASSERT(mWrappedJS);
}
return mWrappedJS->QueryInterface(aIID, aPtr);
}
void JSWindowActor::RejectPendingQueries() {
// Take our queries out, in case somehow rejecting promises can trigger
// additions or removals.

View File

@ -13,8 +13,10 @@
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "nsRefPtrHashtable.h"
#include "nsIXPConnect.h"
class nsIGlobalObject;
class nsQueryActor;
namespace mozilla {
namespace dom {
@ -77,6 +79,10 @@ class JSWindowActor : public nsISupports, public nsWrapperCache {
void InvokeCallback(CallbackFunction willDestroy);
private:
friend class ::nsQueryActor; // for QueryInterfaceActor
nsresult QueryInterfaceActor(const nsIID& aIID, void** aPtr);
void ReceiveMessageOrQuery(JSContext* aCx,
const JSWindowActorMessageMeta& aMetadata,
JS::Handle<JS::Value> aData, ErrorResult& aRv);
@ -112,6 +118,7 @@ class JSWindowActor : public nsISupports, public nsWrapperCache {
uint64_t mQueryId;
};
nsCOMPtr<nsISupports> mWrappedJS;
nsString mName;
nsRefPtrHashtable<nsUint64HashKey, Promise> mPendingQueries;
uint64_t mNextQueryId;

View File

@ -78,6 +78,10 @@ EXPORTS.mozilla += [
'ProcessPriorityManager.h',
]
EXPORTS += [
'nsQueryActor.h',
]
UNIFIED_SOURCES += [
'BrowserBridgeChild.cpp',
'BrowserBridgeHost.cpp',

49
dom/ipc/nsQueryActor.h Normal file
View File

@ -0,0 +1,49 @@
/* 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/. */
#ifndef nsQueryActor_h
#define nsQueryActor_h
#include "nsCOMPtr.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/JSWindowActorChild.h"
#include "mozilla/dom/WindowGlobalChild.h"
class MOZ_STACK_CLASS nsQueryActor final : public nsCOMPtr_helper {
public:
nsQueryActor(const nsDependentString aActorName, nsPIDOMWindowOuter* aWindow)
: mActorName(aActorName), mWindow(aWindow) {}
virtual nsresult NS_FASTCALL operator()(const nsIID& aIID,
void** aResult) const override {
if (NS_WARN_IF(!mWindow) || NS_WARN_IF(!mWindow->GetCurrentInnerWindow())) {
return NS_ERROR_NO_INTERFACE;
}
RefPtr<mozilla::dom::WindowGlobalChild> wgc(
mWindow->GetCurrentInnerWindow()->GetWindowGlobalChild());
if (!wgc) {
return NS_ERROR_NO_INTERFACE;
}
RefPtr<mozilla::dom::JSWindowActorChild> actor =
wgc->GetActor(mActorName, mozilla::IgnoreErrors());
if (!actor) {
return NS_ERROR_NO_INTERFACE;
}
return actor->QueryInterfaceActor(aIID, aResult);
}
private:
const nsDependentString mActorName;
nsPIDOMWindowOuter* mWindow;
};
inline nsQueryActor do_QueryActor(const char16_t* aActorName,
nsPIDOMWindowOuter* aWindow) {
return nsQueryActor(nsDependentString(aActorName), aWindow);
}
#endif // defined nsQueryActor_h