Bug 1682632 - part2.1: ExtensionEventListener. r=baku,mixedpuppy

An ExtensionEventListener xpcom interface that wraps an API event callback
and included in the API requests forwarded to the API request handler.

The ExtensionEventListener xpcom interface provides a method to forward
to the worker thread the calls to the wrapped API event callpack originated
from the WebExtensions framework running on the main thread.

Depends on D75311

Differential Revision: https://phabricator.services.mozilla.com/D80609
This commit is contained in:
Luca Greco 2021-06-10 09:34:53 +00:00
Родитель c7b8bcd1f4
Коммит 0e7d3adbed
8 изменённых файлов: 115 добавлений и 3 удалений

Просмотреть файл

@ -13,6 +13,12 @@ interface mozIExtensionServiceWorkerInfo : nsISupports
readonly attribute AString scriptURL;
readonly attribute AString clientInfoId;
};
[scriptable, builtinclass, uuid(e68e3c19-1b35-4112-8faa-5c5b84086a5b)]
interface mozIExtensionEventListener : nsISupports
{
void callListener(in Array<jsval> args);
};
[scriptable, builtinclass, uuid(0fee1c8f-e363-46a6-bd0c-d3c3338e2534)]
interface mozIExtensionAPIRequest : nsISupports
@ -53,6 +59,9 @@ interface mozIExtensionAPIRequest : nsISupports
// Set for requests coming from an extension service worker.
readonly attribute mozIExtensionServiceWorkerInfo serviceWorkerInfo;
// Set for `addListener`/`removeListener` API requests.
readonly attribute mozIExtensionEventListener eventListener;
};
[scriptable, uuid(59fd4097-d88e-40fd-8664-fedd8ab67ab6)]

Просмотреть файл

@ -56,6 +56,7 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionAPIRequest)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ExtensionAPIRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ExtensionAPIRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSWInfo)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -65,6 +66,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ExtensionAPIRequest)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ExtensionAPIRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSWInfo)
tmp->mStack.setUndefined();
tmp->mArgs.setUndefined();
@ -200,5 +202,13 @@ ExtensionAPIRequest::GetServiceWorkerInfo(
return NS_OK;
}
NS_IMETHODIMP
ExtensionAPIRequest::GetEventListener(mozIExtensionEventListener** aListener) {
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(aListener);
NS_IF_ADDREF(*aListener = mEventListener);
return NS_OK;
}
} // namespace extensions
} // namespace mozilla

Просмотреть файл

@ -7,6 +7,8 @@
#ifndef mozilla_extensions_ExtensionAPIRequest_h
#define mozilla_extensions_ExtensionAPIRequest_h
#include "ExtensionEventListener.h"
#include "mozIExtensionAPIRequestHandling.h"
#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/dom/ClientInfo.h"
@ -82,11 +84,17 @@ class ExtensionAPIRequest : public mozIExtensionAPIRequest {
bool ShouldHaveResult() const { return ShouldHaveResult(mRequestType); }
void SetEventListener(const RefPtr<ExtensionEventListener>& aListener) {
MOZ_ASSERT(!mEventListener);
mEventListener = aListener;
}
private:
virtual ~ExtensionAPIRequest() {
mSWClientInfo = Nothing();
mArgs.setUndefined();
mStack.setUndefined();
mEventListener = nullptr;
mozilla::DropJSObjects(this);
};
@ -96,6 +104,9 @@ class ExtensionAPIRequest : public mozIExtensionAPIRequest {
JS::Heap<JS::Value> mArgs;
Maybe<dom::ClientInfo> mSWClientInfo;
RefPtr<ExtensionServiceWorkerInfo> mSWInfo;
// Only set for addListener/removeListener API requests.
RefPtr<ExtensionEventListener> mEventListener;
};
} // namespace extensions

Просмотреть файл

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ExtensionAPIRequestForwarder.h"
#include "ExtensionEventListener.h"
#include "js/Promise.h"
#include "mozilla/dom/Client.h"
@ -251,6 +252,7 @@ RequestWorkerRunnable::RequestWorkerRunnable(
void RequestWorkerRunnable::Init(nsIGlobalObject* aGlobal, JSContext* aCx,
const dom::Sequence<JS::Value>& aArgs,
ExtensionEventListener* aListener,
ErrorResult& aRv) {
MOZ_ASSERT(dom::IsCurrentThreadRunningWorker());
@ -274,6 +276,7 @@ void RequestWorkerRunnable::Init(nsIGlobalObject* aGlobal, JSContext* aCx,
}
SerializeCallerStack(aCx);
mEventListener = aListener;
}
void RequestWorkerRunnable::Init(nsIGlobalObject* aGlobal, JSContext* aCx,
@ -289,7 +292,7 @@ void RequestWorkerRunnable::Init(nsIGlobalObject* aGlobal, JSContext* aCx,
ExtensionAPIRequestStructuredCloneWrite,
};
Init(aGlobal, aCx, aArgs, aRv);
Init(aGlobal, aCx, aArgs, /* aListener */ nullptr, aRv);
if (aRv.Failed()) {
return;
}
@ -378,6 +381,11 @@ already_AddRefed<ExtensionAPIRequest> RequestWorkerRunnable::CreateAPIRequest(
RefPtr<ExtensionAPIRequest> request = new ExtensionAPIRequest(
mOuterRequest->GetRequestType(), *mOuterRequest->GetRequestTarget());
request->Init(mClientInfo, callArgs, callerStackValue);
if (mEventListener) {
request->SetEventListener(mEventListener.forget());
}
return request.forget();
}

Просмотреть файл

@ -83,7 +83,8 @@ class ExtensionAPIRequestForwarder {
private:
already_AddRefed<ExtensionAPIRequest> CreateAPIRequest(
nsIGlobalObject* aGlobal, JSContext* aCx,
const dom::Sequence<JS::Value>& aArgs, ErrorResult& aRv);
const dom::Sequence<JS::Value>& aArgs, ExtensionEventListener* aListener,
ErrorResult& aRv);
APIRequestType mRequestType;
ExtensionAPIRequestTarget mRequestTarget;
@ -113,8 +114,28 @@ class RequestWorkerRunnable : public dom::WorkerMainThreadRunnable {
RequestWorkerRunnable(dom::WorkerPrivate* aWorkerPrivate,
ExtensionAPIRequestForwarder* aOuterAPIRequest);
/**
* Init a request runnable for AddListener and RemoveListener API requests
* (which do have an event callback callback and do not expect any return
* value).
*/
void Init(nsIGlobalObject* aGlobal, JSContext* aCx,
const dom::Sequence<JS::Value>& aArgs, ErrorResult& aRv);
const dom::Sequence<JS::Value>& aArgs,
ExtensionEventListener* aListener, ErrorResult& aRv);
/**
* Init a request runnable for CallFunctionNoReturn API requests (which do
* do not expect any return value).
*/
void Init(nsIGlobalObject* aGlobal, JSContext* aCx,
const dom::Sequence<JS::Value>& aArgs, ErrorResult& aRv) {
Init(aGlobal, aCx, aArgs, nullptr, aRv);
}
/**
* Init a request runnable for CallAsyncFunction API requests (which do
* expect a promise as return value).
*/
void Init(nsIGlobalObject* aGlobal, JSContext* aCx,
const dom::Sequence<JS::Value>& aArgs,
const RefPtr<dom::Promise>& aPromiseRetval, ErrorResult& aRv);
@ -150,6 +171,9 @@ class RequestWorkerRunnable : public dom::WorkerMainThreadRunnable {
Maybe<UniquePtr<dom::SerializedStackHolder>> mStackHolder;
Maybe<dom::ClientInfo> mClientInfo;
// Only set for addListener/removeListener API requests.
RefPtr<ExtensionEventListener> mEventListener;
// The outer request object is kept alive by the caller for the
// entire life of the inner worker runnable.
ExtensionAPIRequestForwarder* mOuterRequest;

Просмотреть файл

@ -0,0 +1,20 @@
/* 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 "ExtensionEventListener.h"
#include "nsThreadManager.h" // NS_IsMainThread
namespace mozilla {
namespace extensions {
NS_IMETHODIMP ExtensionEventListener::CallListener(
const nsTArray<JS::Value>& aArgs) {
MOZ_ASSERT(NS_IsMainThread());
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace extensions
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,29 @@
/* -*- 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/. */
#ifndef mozilla_extensions_ExtensionEventListener_h
#define mozilla_extensions_ExtensionEventListener_h
#include "mozIExtensionAPIRequestHandling.h"
namespace mozilla {
namespace extensions {
// A class that represents a callback parameter (passed to addListener /
// removeListener), instances of this class are received by the
// mozIExtensionAPIRequestHandler as a property of the mozIExtensionAPIRequest.
// The mozIExtensionEventListener xpcom interface provides methods that allow
// the mozIExtensionAPIRequestHandler running in the Main Thread to call the
// underlying callback Function on its owning thread.
class ExtensionEventListener : public mozIExtensionEventListener {
public:
NS_DECL_MOZIEXTENSIONEVENTLISTENER
};
} // namespace extensions
} // namespace mozilla
#endif // mozilla_extensions_ExtensionEventListener_h

Просмотреть файл

@ -12,6 +12,7 @@ UNIFIED_SOURCES += [
"ExtensionAPIRequest.cpp",
"ExtensionAPIRequestForwarder.cpp",
"ExtensionBrowser.cpp",
"ExtensionEventListener.cpp",
"ExtensionEventManager.cpp",
]