зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1688040 - part9: Implement setting/clearing and reporting browser.runtime.lastError from ChromeCompatCallbackHandler::RejectedCallback. r=baku
This patch does: - add to ExtensionBrowser two new data members to keep track of value for the browser.runtime.lastError and if it was checked while the chrome compatible callback was being executed - add to ExtensionBrowser 3 new methods to set, get and clear the lastError value - add a reference to the ExtensionBrowser to all API namespaces and API objects classes, because it has to be then propagated to the ChromeCompatCallbackHandler instances that are being attached to the promise result of the async API methods calls if the caller did pass the optional callback parameter - tweak the ChromeCompatCallbackHandler class to set the lastError value before calling the callback in ChromeCompatCallbackHAndler::RejectedCallback and then clear it after the call has been completed and report it to the console if it wasn't checked - change the ExtensionRuntime::GetLastError methhod to restrieve and return the value from the ExtensionBrowser instance Differential Revision: https://phabricator.services.mozilla.com/D107327
This commit is contained in:
Родитель
7105532924
Коммит
7b70ba9812
|
@ -421,3 +421,6 @@ ElementSetCaptureWarning=Element.setCapture() is deprecated. Use Element.setPoin
|
|||
ElementReleaseCaptureWarning=Element.releaseCapture() is deprecated. Use Element.releasePointerCapture() instead. For more help https://developer.mozilla.org/docs/Web/API/Element/releasePointerCapture
|
||||
# LOCALIZATION NOTE: Do not translate "Document.releaseCapture()" and "Element.releasePointerCapture()".
|
||||
DocumentReleaseCaptureWarning=Document.releaseCapture() is deprecated. Use Element.releasePointerCapture() instead. For more help https://developer.mozilla.org/docs/Web/API/Element/releasePointerCapture
|
||||
|
||||
# LOCALIZATION NOTE: Don't translate browser.runtime.lastError, %S is the error message from the unchecked value set on browser.runtime.lastError.
|
||||
WebExtensionUncheckedLastError=browser.runtime.lastError value was not checked: %S
|
||||
|
|
|
@ -365,3 +365,33 @@ add_task(async function test_sw_api_request_bgsw_runtime_onConnect() {
|
|||
await extPage.close();
|
||||
await extension.unload();
|
||||
});
|
||||
|
||||
add_task(async function test_sw_runtime_lastError() {
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
useAddonManager: "temporary",
|
||||
manifest: {
|
||||
background: {
|
||||
service_worker: "sw.js",
|
||||
},
|
||||
applications: { gecko: { id: "test-bg-sw@mochi.test" } },
|
||||
},
|
||||
files: {
|
||||
"page.html": "<!DOCTYPE html><body></body>",
|
||||
"sw.js": async function() {
|
||||
browser.runtime.sendMessage(() => {
|
||||
const lastError = browser.runtime.lastError;
|
||||
if (!(lastError instanceof Error)) {
|
||||
browser.test.fail(
|
||||
`lastError isn't an Error instance: ${lastError}`
|
||||
);
|
||||
}
|
||||
browser.test.sendMessage("test-lastError-completed");
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
await extension.awaitMessage("test-lastError-completed");
|
||||
await extension.unload();
|
||||
});
|
||||
|
|
|
@ -11,9 +11,11 @@
|
|||
#include "ExtensionAPICallFunctionNoReturn.h"
|
||||
#include "ExtensionAPICallSyncFunction.h"
|
||||
#include "ExtensionAPIGetProperty.h"
|
||||
#include "ExtensionBrowser.h"
|
||||
#include "ExtensionEventManager.h"
|
||||
#include "ExtensionPort.h"
|
||||
|
||||
#include "mozilla/ConsoleReportCollector.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/SerializedStackHolder.h"
|
||||
#include "mozilla/dom/FunctionBinding.h"
|
||||
|
@ -29,12 +31,14 @@ NS_IMPL_ISUPPORTS0(ChromeCompatCallbackHandler)
|
|||
|
||||
// static
|
||||
void ChromeCompatCallbackHandler::Create(
|
||||
dom::Promise* aPromise, const RefPtr<dom::Function>& aCallback) {
|
||||
ExtensionBrowser* aExtensionBrowser, dom::Promise* aPromise,
|
||||
const RefPtr<dom::Function>& aCallback) {
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_ASSERT(aExtensionBrowser);
|
||||
MOZ_ASSERT(aCallback);
|
||||
|
||||
RefPtr<ChromeCompatCallbackHandler> handler =
|
||||
new ChromeCompatCallbackHandler(aCallback);
|
||||
new ChromeCompatCallbackHandler(aExtensionBrowser, aCallback);
|
||||
|
||||
aPromise->AppendNativeHandler(handler);
|
||||
}
|
||||
|
@ -53,7 +57,37 @@ void ChromeCompatCallbackHandler::RejectedCallback(
|
|||
// Call the chrome-compatible callback without any parameter, the errors
|
||||
// isn't passed to the callback as a parameter but the extension will be
|
||||
// able to retrieve it from chrome.runtime.lastError.
|
||||
mExtensionBrowser->SetLastError(aValue);
|
||||
MOZ_KnownLive(mCallback)->Call({}, &retval, rv);
|
||||
if (mExtensionBrowser->ClearLastError()) {
|
||||
ReportUncheckedLastError(aCx, aValue);
|
||||
}
|
||||
}
|
||||
|
||||
void ChromeCompatCallbackHandler::ReportUncheckedLastError(
|
||||
JSContext* aCx, JS::Handle<JS::Value> aValue) {
|
||||
nsCString sourceSpec;
|
||||
uint32_t line = 0;
|
||||
uint32_t column = 0;
|
||||
nsString valueString;
|
||||
|
||||
nsContentUtils::ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column,
|
||||
valueString);
|
||||
|
||||
nsTArray<nsString> params;
|
||||
params.AppendElement(valueString);
|
||||
|
||||
RefPtr<ConsoleReportCollector> reporter = new ConsoleReportCollector();
|
||||
reporter->AddConsoleReport(nsIScriptError::errorFlag, "content javascript"_ns,
|
||||
nsContentUtils::eDOM_PROPERTIES, sourceSpec, line,
|
||||
column, "WebExtensionUncheckedLastError"_ns,
|
||||
params);
|
||||
|
||||
dom::WorkerPrivate* workerPrivate = dom::GetWorkerPrivateFromContext(aCx);
|
||||
RefPtr<Runnable> r = NS_NewRunnableFunction(
|
||||
"ChromeCompatCallbackHandler::ReportUncheckedLastError",
|
||||
[reporter]() { reporter->FlushReportsToConsole(0); });
|
||||
workerPrivate->DispatchToMainThread(r.forget());
|
||||
}
|
||||
|
||||
// WebExtensionStub methods shared between multiple API namespaces.
|
||||
|
@ -138,8 +172,8 @@ already_AddRefed<ExtensionPort> ExtensionAPIBase::CallWebExtMethodReturnsPort(
|
|||
}
|
||||
|
||||
IgnoredErrorResult rv;
|
||||
RefPtr<ExtensionPort> port =
|
||||
ExtensionPort::Create(GetGlobalObject(), apiResult, rv);
|
||||
RefPtr<ExtensionPort> port = ExtensionPort::Create(
|
||||
GetGlobalObject(), GetExtensionBrowser(), apiResult, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
// ExtensionPort::Create doesn't throw the js exception with the generic
|
||||
// error message as the "api request forwarding" helper classes.
|
||||
|
@ -173,7 +207,8 @@ void ExtensionAPIBase::CallWebExtMethodAsyncInternal(
|
|||
// The async method has been called with the chrome-compatible callback
|
||||
// convention.
|
||||
if (aCallback) {
|
||||
ChromeCompatCallbackHandler::Create(domPromise, aCallback);
|
||||
ChromeCompatCallbackHandler::Create(GetExtensionBrowser(), domPromise,
|
||||
aCallback);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -261,8 +296,8 @@ void ExtensionAPIBase::GetWebExtPropertyAsJSValue(
|
|||
already_AddRefed<ExtensionEventManager> ExtensionAPIBase::CreateEventManager(
|
||||
const nsAString& aEventName) {
|
||||
RefPtr<ExtensionEventManager> eventMgr = new ExtensionEventManager(
|
||||
GetGlobalObject(), GetAPINamespace(), aEventName, GetAPIObjectType(),
|
||||
GetAPIObjectId());
|
||||
GetGlobalObject(), GetExtensionBrowser(), GetAPINamespace(), aEventName,
|
||||
GetAPIObjectType(), GetAPIObjectId());
|
||||
return eventMgr.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,12 +26,14 @@ class ExtensionAPICallFunctionNoReturn;
|
|||
class ExtensionAPICallSyncFunction;
|
||||
class ExtensionAPICallAsyncFunction;
|
||||
class ExtensionAPIGetProperty;
|
||||
class ExtensionBrowser;
|
||||
class ExtensionEventManager;
|
||||
class ExtensionPort;
|
||||
|
||||
class ExtensionAPIBase {
|
||||
protected:
|
||||
virtual nsIGlobalObject* GetGlobalObject() const = 0;
|
||||
virtual ExtensionBrowser* GetExtensionBrowser() const = 0;
|
||||
virtual nsString GetAPINamespace() const = 0;
|
||||
virtual nsString GetAPIObjectType() const = 0;
|
||||
virtual nsString GetAPIObjectId() const = 0;
|
||||
|
@ -133,7 +135,8 @@ class ChromeCompatCallbackHandler final : public dom::PromiseNativeHandler {
|
|||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
static void Create(dom::Promise* aPromise,
|
||||
static void Create(ExtensionBrowser* aExtensionBrowser,
|
||||
dom::Promise* aPromise,
|
||||
const RefPtr<dom::Function>& aCallback);
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT void ResolvedCallback(
|
||||
|
@ -142,14 +145,19 @@ class ChromeCompatCallbackHandler final : public dom::PromiseNativeHandler {
|
|||
JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
private:
|
||||
explicit ChromeCompatCallbackHandler(const RefPtr<dom::Function>& aCallback)
|
||||
: mCallback(aCallback) {
|
||||
ChromeCompatCallbackHandler(ExtensionBrowser* aExtensionBrowser,
|
||||
const RefPtr<dom::Function>& aCallback)
|
||||
: mCallback(aCallback), mExtensionBrowser(aExtensionBrowser) {
|
||||
MOZ_ASSERT(aCallback);
|
||||
MOZ_ASSERT(aExtensionBrowser);
|
||||
}
|
||||
|
||||
~ChromeCompatCallbackHandler() = default;
|
||||
|
||||
void ReportUncheckedLastError(JSContext* aCx, JS::Handle<JS::Value> aValue);
|
||||
|
||||
RefPtr<dom::Function> mCallback;
|
||||
RefPtr<ExtensionBrowser> mExtensionBrowser;
|
||||
};
|
||||
|
||||
} // namespace extensions
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace extensions {
|
|||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionAlarms);
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ExtensionAlarms)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ExtensionAlarms, mGlobal,
|
||||
mOnAlarmEventMgr);
|
||||
mExtensionBrowser, mOnAlarmEventMgr);
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ExtensionAlarms)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
|
@ -24,8 +24,9 @@ NS_INTERFACE_MAP_END
|
|||
|
||||
ExtensionAlarms::ExtensionAlarms(nsIGlobalObject* aGlobal,
|
||||
ExtensionBrowser* aExtensionBrowser)
|
||||
: mGlobal(aGlobal) {
|
||||
: mGlobal(aGlobal), mExtensionBrowser(aExtensionBrowser) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mExtensionBrowser);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -30,6 +30,7 @@ class ExtensionAlarms final : public nsISupports,
|
|||
public nsWrapperCache,
|
||||
public ExtensionAPINamespace {
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<ExtensionBrowser> mExtensionBrowser;
|
||||
RefPtr<ExtensionEventManager> mOnAlarmEventMgr;
|
||||
|
||||
~ExtensionAlarms() = default;
|
||||
|
@ -41,6 +42,10 @@ class ExtensionAlarms final : public nsISupports,
|
|||
// ExtensionAPIBase methods
|
||||
nsIGlobalObject* GetGlobalObject() const override { return mGlobal; }
|
||||
|
||||
ExtensionBrowser* GetExtensionBrowser() const override {
|
||||
return mExtensionBrowser;
|
||||
}
|
||||
|
||||
nsString GetAPINamespace() const override { return u"alarms"_ns; }
|
||||
|
||||
// nsWrapperCache interface methods
|
||||
|
|
|
@ -17,17 +17,38 @@
|
|||
namespace mozilla {
|
||||
namespace extensions {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionBrowser);
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(ExtensionBrowser)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionBrowser)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ExtensionBrowser)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ExtensionBrowser, mGlobal,
|
||||
mExtensionAlarms, mExtensionMockAPI,
|
||||
mExtensionRuntime, mExtensionTest);
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ExtensionBrowser)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ExtensionBrowser)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionAlarms)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionMockAPI)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionRuntime)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionTest)
|
||||
tmp->mLastError.setUndefined();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ExtensionBrowser)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionAlarms)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionMockAPI)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionRuntime)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionTest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ExtensionBrowser)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLastError)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
ExtensionBrowser::ExtensionBrowser(nsIGlobalObject* aGlobal)
|
||||
: mGlobal(aGlobal) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
|
||||
|
@ -73,6 +94,22 @@ bool ExtensionAPIAllowed(JSContext* aCx, JSObject* aGlobal) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void ExtensionBrowser::SetLastError(JS::Handle<JS::Value> aLastError) {
|
||||
mLastError.set(aLastError);
|
||||
mCheckedLastError = false;
|
||||
}
|
||||
|
||||
void ExtensionBrowser::GetLastError(JS::MutableHandle<JS::Value> aRetVal) {
|
||||
aRetVal.set(mLastError);
|
||||
mCheckedLastError = true;
|
||||
}
|
||||
|
||||
bool ExtensionBrowser::ClearLastError() {
|
||||
bool shouldReport = !mCheckedLastError;
|
||||
mLastError.setUndefined();
|
||||
return shouldReport;
|
||||
}
|
||||
|
||||
ExtensionAlarms* ExtensionBrowser::GetExtensionAlarms() {
|
||||
if (!mExtensionAlarms) {
|
||||
mExtensionAlarms = new ExtensionAlarms(mGlobal, this);
|
||||
|
|
|
@ -28,6 +28,8 @@ bool ExtensionAPIAllowed(JSContext* aCx, JSObject* aGlobal);
|
|||
|
||||
class ExtensionBrowser final : public nsISupports, public nsWrapperCache {
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
JS::Heap<JS::Value> mLastError;
|
||||
bool mCheckedLastError;
|
||||
RefPtr<ExtensionAlarms> mExtensionAlarms;
|
||||
RefPtr<ExtensionMockAPI> mExtensionMockAPI;
|
||||
RefPtr<ExtensionRuntime> mExtensionRuntime;
|
||||
|
@ -38,6 +40,16 @@ class ExtensionBrowser final : public nsISupports, public nsWrapperCache {
|
|||
public:
|
||||
explicit ExtensionBrowser(nsIGlobalObject* aGlobal);
|
||||
|
||||
// Helpers used for the expected behavior of the browser.runtime.lastError
|
||||
// and browser.extension.lastError.
|
||||
void SetLastError(JS::Handle<JS::Value> aLastError);
|
||||
void GetLastError(JS::MutableHandle<JS::Value> aRetVal);
|
||||
// ClearLastError is used by ChromeCompatCallbackHandler::RejectedCallback
|
||||
// to clear the lastError property. When this method returns true the
|
||||
// caller will know that the error value wasn't checked by the callback and
|
||||
// should be reported to the console
|
||||
bool ClearLastError();
|
||||
|
||||
// nsWrapperCache interface methods
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
|
|
@ -164,11 +164,12 @@ NS_IMPL_ISUPPORTS(ExtensionEventListener, mozIExtensionEventListener)
|
|||
|
||||
// static
|
||||
already_AddRefed<ExtensionEventListener> ExtensionEventListener::Create(
|
||||
nsIGlobalObject* aGlobal, dom::Function* aCallback,
|
||||
CleanupCallback&& aCleanupCallback, ErrorResult& aRv) {
|
||||
nsIGlobalObject* aGlobal, ExtensionBrowser* aExtensionBrowser,
|
||||
dom::Function* aCallback, CleanupCallback&& aCleanupCallback,
|
||||
ErrorResult& aRv) {
|
||||
MOZ_ASSERT(dom::IsCurrentThreadRunningWorker());
|
||||
RefPtr<ExtensionEventListener> extCb =
|
||||
new ExtensionEventListener(aGlobal, aCallback);
|
||||
new ExtensionEventListener(aGlobal, aExtensionBrowser, aCallback);
|
||||
|
||||
auto* workerPrivate = dom::GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
@ -335,6 +336,11 @@ bool ExtensionListenerCallWorkerRunnable::WorkerRun(
|
|||
return true;
|
||||
}
|
||||
|
||||
RefPtr<ExtensionBrowser> extensionBrowser = mListener->GetExtensionBrowser();
|
||||
if (NS_WARN_IF(!extensionBrowser)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto fn = mListener->GetCallback();
|
||||
if (NS_WARN_IF(!fn)) {
|
||||
return true;
|
||||
|
@ -397,8 +403,8 @@ bool ExtensionListenerCallWorkerRunnable::WorkerRun(
|
|||
// until we will need to expect it to support other object types that
|
||||
// some specific API may need.
|
||||
MOZ_ASSERT(mAPIObjectType == APIObjectType::RUNTIME_PORT);
|
||||
RefPtr<ExtensionPort> port =
|
||||
ExtensionPort::Create(global, apiObjectDescriptor, rv);
|
||||
RefPtr<ExtensionPort> port = ExtensionPort::Create(global, extensionBrowser,
|
||||
apiObjectDescriptor, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
retPromise->MaybeReject(rv.StealNSResult());
|
||||
return true;
|
||||
|
|
|
@ -46,8 +46,9 @@ class ExtensionEventListener final : public mozIExtensionEventListener {
|
|||
using CallbackType = ListenerCallOptions::CallbackType;
|
||||
|
||||
static already_AddRefed<ExtensionEventListener> Create(
|
||||
nsIGlobalObject* aGlobal, dom::Function* aCallback,
|
||||
CleanupCallback&& aCleanupCallback, ErrorResult& aRv);
|
||||
nsIGlobalObject* aGlobal, ExtensionBrowser* aExtensionBrowser,
|
||||
dom::Function* aCallback, CleanupCallback&& aCleanupCallback,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static bool IsPromise(JSContext* aCx, JS::Handle<JS::Value> aValue) {
|
||||
if (!aValue.isObject()) {
|
||||
|
@ -67,6 +68,8 @@ class ExtensionEventListener final : public mozIExtensionEventListener {
|
|||
return global;
|
||||
}
|
||||
|
||||
ExtensionBrowser* GetExtensionBrowser() const { return mExtensionBrowser; }
|
||||
|
||||
void Cleanup() {
|
||||
if (mWorkerRef) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
@ -77,13 +80,21 @@ class ExtensionEventListener final : public mozIExtensionEventListener {
|
|||
|
||||
mGlobal = nullptr;
|
||||
mCallback = nullptr;
|
||||
mExtensionBrowser = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
ExtensionEventListener(nsIGlobalObject* aGlobal, dom::Function* aCallback)
|
||||
ExtensionEventListener(nsIGlobalObject* aGlobal,
|
||||
ExtensionBrowser* aExtensionBrowser,
|
||||
dom::Function* aCallback)
|
||||
: mGlobal(do_GetWeakReference(aGlobal)),
|
||||
mExtensionBrowser(aExtensionBrowser),
|
||||
mCallback(aCallback),
|
||||
mMutex("ExtensionEventListener::mMutex"){};
|
||||
mMutex("ExtensionEventListener::mMutex") {
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT(aExtensionBrowser);
|
||||
MOZ_ASSERT(aCallback);
|
||||
};
|
||||
|
||||
static UniquePtr<dom::StructuredCloneHolder> SerializeCallArguments(
|
||||
const nsTArray<JS::Value>& aArgs, JSContext* aCx, ErrorResult& aRv);
|
||||
|
@ -95,6 +106,7 @@ class ExtensionEventListener final : public mozIExtensionEventListener {
|
|||
|
||||
// Accessed only on the owning thread.
|
||||
nsWeakPtr mGlobal;
|
||||
RefPtr<ExtensionBrowser> mExtensionBrowser;
|
||||
RefPtr<dom::Function> mCallback;
|
||||
|
||||
// Used to make sure we are not going to release the
|
||||
|
|
|
@ -19,11 +19,13 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(ExtensionEventManager)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ExtensionEventManager)
|
||||
tmp->mListeners.clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionBrowser)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ExtensionEventManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionBrowser)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ExtensionEventManager)
|
||||
|
@ -38,17 +40,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ExtensionEventManager)
|
|||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
ExtensionEventManager::ExtensionEventManager(nsIGlobalObject* aGlobal,
|
||||
const nsAString& aNamespace,
|
||||
const nsAString& aEventName,
|
||||
const nsAString& aObjectType,
|
||||
const nsAString& aObjectId)
|
||||
ExtensionEventManager::ExtensionEventManager(
|
||||
nsIGlobalObject* aGlobal, ExtensionBrowser* aExtensionBrowser,
|
||||
const nsAString& aNamespace, const nsAString& aEventName,
|
||||
const nsAString& aObjectType, const nsAString& aObjectId)
|
||||
: mGlobal(aGlobal),
|
||||
mExtensionBrowser(aExtensionBrowser),
|
||||
mAPINamespace(aNamespace),
|
||||
mEventName(aEventName),
|
||||
mAPIObjectType(aObjectType),
|
||||
mAPIObjectId(aObjectId) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mExtensionBrowser);
|
||||
|
||||
RefPtr<ExtensionEventManager> self = this;
|
||||
mozilla::HoldJSObjects(this);
|
||||
|
@ -93,7 +96,7 @@ void ExtensionEventManager::AddListener(
|
|||
|
||||
IgnoredErrorResult rv;
|
||||
RefPtr<ExtensionEventListener> wrappedCb = ExtensionEventListener::Create(
|
||||
mGlobal, &aCallback,
|
||||
mGlobal, mExtensionBrowser, &aCallback,
|
||||
[self = std::move(self)]() { self->ReleaseListeners(); }, rv);
|
||||
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
|
|
|
@ -38,6 +38,7 @@ class ExtensionEventManager final : public nsISupports,
|
|||
public nsWrapperCache,
|
||||
public ExtensionAPIBase {
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<ExtensionBrowser> mExtensionBrowser;
|
||||
nsString mAPINamespace;
|
||||
nsString mEventName;
|
||||
nsString mAPIObjectType;
|
||||
|
@ -57,6 +58,9 @@ class ExtensionEventManager final : public nsISupports,
|
|||
protected:
|
||||
// ExtensionAPIBase methods
|
||||
nsIGlobalObject* GetGlobalObject() const override { return mGlobal; }
|
||||
ExtensionBrowser* GetExtensionBrowser() const override {
|
||||
return mExtensionBrowser;
|
||||
}
|
||||
|
||||
nsString GetAPINamespace() const override { return mAPINamespace; }
|
||||
|
||||
|
@ -65,7 +69,9 @@ class ExtensionEventManager final : public nsISupports,
|
|||
nsString GetAPIObjectId() const override { return mAPIObjectId; }
|
||||
|
||||
public:
|
||||
ExtensionEventManager(nsIGlobalObject* aGlobal, const nsAString& aNamespace,
|
||||
ExtensionEventManager(nsIGlobalObject* aGlobal,
|
||||
ExtensionBrowser* aExtensionBrowser,
|
||||
const nsAString& aNamespace,
|
||||
const nsAString& aEventName,
|
||||
const nsAString& aObjectType = VoidString(),
|
||||
const nsAString& aObjectId = VoidString());
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace extensions {
|
|||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionMockAPI);
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ExtensionMockAPI)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ExtensionMockAPI, mGlobal,
|
||||
mOnTestEventMgr);
|
||||
mExtensionBrowser, mOnTestEventMgr);
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ExtensionMockAPI)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
|
@ -25,8 +25,9 @@ NS_INTERFACE_MAP_END
|
|||
|
||||
ExtensionMockAPI::ExtensionMockAPI(nsIGlobalObject* aGlobal,
|
||||
ExtensionBrowser* aExtensionBrowser)
|
||||
: mGlobal(aGlobal) {
|
||||
: mGlobal(aGlobal), mExtensionBrowser(aExtensionBrowser) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mExtensionBrowser);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -33,6 +33,7 @@ class ExtensionMockAPI final : public nsISupports,
|
|||
public nsWrapperCache,
|
||||
public ExtensionAPINamespace {
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<ExtensionBrowser> mExtensionBrowser;
|
||||
RefPtr<ExtensionEventManager> mOnTestEventMgr;
|
||||
|
||||
~ExtensionMockAPI() = default;
|
||||
|
@ -41,6 +42,10 @@ class ExtensionMockAPI final : public nsISupports,
|
|||
// ExtensionAPIBase methods
|
||||
nsIGlobalObject* GetGlobalObject() const override { return mGlobal; }
|
||||
|
||||
ExtensionBrowser* GetExtensionBrowser() const override {
|
||||
return mExtensionBrowser;
|
||||
}
|
||||
|
||||
nsString GetAPINamespace() const override { return u"mockExtensionAPI"_ns; }
|
||||
|
||||
public:
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace extensions {
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionPort);
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ExtensionPort)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ExtensionPort, mGlobal,
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ExtensionPort, mGlobal, mExtensionBrowser,
|
||||
mOnDisconnectEventMgr,
|
||||
mOnMessageEventMgr);
|
||||
|
||||
|
@ -27,8 +27,8 @@ NS_INTERFACE_MAP_END
|
|||
|
||||
// static
|
||||
already_AddRefed<ExtensionPort> ExtensionPort::Create(
|
||||
nsIGlobalObject* aGlobal, JS::Handle<JS::Value> aDescriptorValue,
|
||||
ErrorResult& aRv) {
|
||||
nsIGlobalObject* aGlobal, ExtensionBrowser* aExtensionBrowser,
|
||||
JS::Handle<JS::Value> aDescriptorValue, ErrorResult& aRv) {
|
||||
if (!aDescriptorValue.isObject()) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
|
@ -43,15 +43,18 @@ already_AddRefed<ExtensionPort> ExtensionPort::Create(
|
|||
}
|
||||
|
||||
RefPtr<ExtensionPort> port =
|
||||
new ExtensionPort(aGlobal, std::move(portDescriptor));
|
||||
new ExtensionPort(aGlobal, aExtensionBrowser, std::move(portDescriptor));
|
||||
return port.forget();
|
||||
}
|
||||
|
||||
ExtensionPort::ExtensionPort(
|
||||
nsIGlobalObject* aGlobal,
|
||||
nsIGlobalObject* aGlobal, ExtensionBrowser* aExtensionBrowser,
|
||||
UniquePtr<dom::ExtensionPortDescriptor> aPortDescriptor)
|
||||
: mGlobal(aGlobal), mPortDescriptor(std::move(aPortDescriptor)) {
|
||||
: mGlobal(aGlobal),
|
||||
mExtensionBrowser(aExtensionBrowser),
|
||||
mPortDescriptor(std::move(aPortDescriptor)) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mExtensionBrowser);
|
||||
}
|
||||
|
||||
nsString ExtensionPort::GetAPIObjectId() const {
|
||||
|
|
|
@ -31,18 +31,23 @@ class ExtensionPort final : public nsISupports,
|
|||
public nsWrapperCache,
|
||||
public ExtensionAPIBase {
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<ExtensionBrowser> mExtensionBrowser;
|
||||
RefPtr<ExtensionEventManager> mOnDisconnectEventMgr;
|
||||
RefPtr<ExtensionEventManager> mOnMessageEventMgr;
|
||||
UniquePtr<dom::ExtensionPortDescriptor> mPortDescriptor;
|
||||
|
||||
~ExtensionPort() = default;
|
||||
ExtensionPort(nsIGlobalObject* aGlobal,
|
||||
ExtensionPort(nsIGlobalObject* aGlobal, ExtensionBrowser* aExtensionBrowser,
|
||||
UniquePtr<dom::ExtensionPortDescriptor> aPortDescriptor);
|
||||
|
||||
protected:
|
||||
// ExtensionAPIBase methods
|
||||
nsIGlobalObject* GetGlobalObject() const override { return mGlobal; }
|
||||
|
||||
ExtensionBrowser* GetExtensionBrowser() const override {
|
||||
return mExtensionBrowser;
|
||||
}
|
||||
|
||||
nsString GetAPINamespace() const override { return u"runtime"_ns; }
|
||||
|
||||
nsString GetAPIObjectType() const override { return u"Port"_ns; }
|
||||
|
@ -51,8 +56,8 @@ class ExtensionPort final : public nsISupports,
|
|||
|
||||
public:
|
||||
static already_AddRefed<ExtensionPort> Create(
|
||||
nsIGlobalObject* aGlobal, JS::Handle<JS::Value> aDescriptorValue,
|
||||
ErrorResult& aRv);
|
||||
nsIGlobalObject* aGlobal, ExtensionBrowser* aExtensionBrowser,
|
||||
JS::Handle<JS::Value> aDescriptorValue, ErrorResult& aRv);
|
||||
|
||||
// nsWrapperCache interface methods
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
|
|
|
@ -15,9 +15,9 @@ namespace extensions {
|
|||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionRuntime);
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ExtensionRuntime)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(
|
||||
ExtensionRuntime, mGlobal, mOnStartupEventMgr, mOnInstalledEventMgr,
|
||||
mOnUpdateAvailableEventMgr, mOnConnectEventMgr, mOnConnectExternalEventMgr,
|
||||
mOnMessageEventMgr, mOnMessageExternalEventMgr);
|
||||
ExtensionRuntime, mGlobal, mExtensionBrowser, mOnStartupEventMgr,
|
||||
mOnInstalledEventMgr, mOnUpdateAvailableEventMgr, mOnConnectEventMgr,
|
||||
mOnConnectExternalEventMgr, mOnMessageEventMgr, mOnMessageExternalEventMgr);
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ExtensionRuntime)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
|
@ -26,8 +26,9 @@ NS_INTERFACE_MAP_END
|
|||
|
||||
ExtensionRuntime::ExtensionRuntime(nsIGlobalObject* aGlobal,
|
||||
ExtensionBrowser* aExtensionBrowser)
|
||||
: mGlobal(aGlobal) {
|
||||
: mGlobal(aGlobal), mExtensionBrowser(aExtensionBrowser) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mExtensionBrowser);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -44,9 +45,7 @@ nsIGlobalObject* ExtensionRuntime::GetParentObject() const { return mGlobal; }
|
|||
|
||||
void ExtensionRuntime::GetLastError(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aRetval) {
|
||||
// TODO: special case this, using
|
||||
// GetWebExtPropertyAsErrorObject(aCx, u"lastError"_ns, aRetval);
|
||||
// doesn't seem a good solution nor an easy one in this case.
|
||||
mExtensionBrowser->GetLastError(aRetval);
|
||||
}
|
||||
|
||||
void ExtensionRuntime::GetId(DOMString& aRetval) {
|
||||
|
|
|
@ -30,6 +30,7 @@ class ExtensionRuntime final : public nsISupports,
|
|||
public nsWrapperCache,
|
||||
public ExtensionAPINamespace {
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<ExtensionBrowser> mExtensionBrowser;
|
||||
RefPtr<ExtensionEventManager> mOnStartupEventMgr;
|
||||
RefPtr<ExtensionEventManager> mOnInstalledEventMgr;
|
||||
RefPtr<ExtensionEventManager> mOnUpdateAvailableEventMgr;
|
||||
|
@ -47,6 +48,10 @@ class ExtensionRuntime final : public nsISupports,
|
|||
// ExtensionAPIBase methods
|
||||
nsIGlobalObject* GetGlobalObject() const override { return mGlobal; }
|
||||
|
||||
ExtensionBrowser* GetExtensionBrowser() const override {
|
||||
return mExtensionBrowser;
|
||||
}
|
||||
|
||||
nsString GetAPINamespace() const override { return u"runtime"_ns; }
|
||||
|
||||
// nsWrapperCache interface methods
|
||||
|
|
|
@ -20,7 +20,7 @@ bool IsInAutomation(JSContext* aCx, JSObject* aGlobal) {
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionTest);
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ExtensionTest)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ExtensionTest, mGlobal,
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ExtensionTest, mGlobal, mExtensionBrowser,
|
||||
mOnMessageEventMgr);
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ExtensionTest)
|
||||
|
@ -30,8 +30,9 @@ NS_INTERFACE_MAP_END
|
|||
|
||||
ExtensionTest::ExtensionTest(nsIGlobalObject* aGlobal,
|
||||
ExtensionBrowser* aExtensionBrowser)
|
||||
: mGlobal(aGlobal) {
|
||||
: mGlobal(aGlobal), mExtensionBrowser(aExtensionBrowser) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mExtensionBrowser);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -32,6 +32,7 @@ class ExtensionTest final : public nsISupports,
|
|||
public nsWrapperCache,
|
||||
public ExtensionAPINamespace {
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<ExtensionBrowser> mExtensionBrowser;
|
||||
RefPtr<ExtensionEventManager> mOnMessageEventMgr;
|
||||
|
||||
~ExtensionTest() = default;
|
||||
|
@ -42,6 +43,10 @@ class ExtensionTest final : public nsISupports,
|
|||
// ExtensionAPIBase methods
|
||||
nsIGlobalObject* GetGlobalObject() const override { return mGlobal; }
|
||||
|
||||
ExtensionBrowser* GetExtensionBrowser() const override {
|
||||
return mExtensionBrowser;
|
||||
}
|
||||
|
||||
nsString GetAPINamespace() const override { return u"test"_ns; }
|
||||
|
||||
// nsWrapperCache interface methods
|
||||
|
|
Загрузка…
Ссылка в новой задаче