Bug 1748315 - Part 3 - Generate WebIDL bindings for the scripting namespace. r=rpl,webidl,smaug

This patch adds WebIDL bindings for the `scripting` namespace.
Note that `scripting.executeScript()` is excluded for now.

Differential Revision: https://phabricator.services.mozilla.com/D141463
This commit is contained in:
William Durand 2022-08-02 14:22:39 +00:00
Родитель aa992883c5
Коммит d1b8a8c1d5
14 изменённых файлов: 338 добавлений и 59 удалений

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

@ -1706,6 +1706,11 @@ DOMInterfaces = {
'nativeType': 'mozilla::extensions::ExtensionRuntime',
},
'ExtensionScripting': {
'headerFile': 'mozilla/extensions/ExtensionScripting.h',
'nativeType': 'mozilla::extensions::ExtensionScripting',
},
'ExtensionTest': {
'headerFile': 'mozilla/extensions/ExtensionTest.h',
'nativeType': 'mozilla::extensions::ExtensionTest',

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

@ -40,6 +40,11 @@ interface ExtensionBrowser {
Func="mozilla::extensions::ExtensionRuntime::IsAllowed"]
readonly attribute ExtensionRuntime runtime;
// `browser.scripting` API namespace
[Replaceable, SameObject, BinaryName="GetExtensionScripting",
Func="mozilla::extensions::ExtensionScripting::IsAllowed"]
readonly attribute ExtensionScripting scripting;
// `browser.test` API namespace, available in tests.
[Replaceable, SameObject, BinaryName="GetExtensionTest",
Func="mozilla::extensions::ExtensionTest::IsAllowed"]

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

@ -0,0 +1,48 @@
/*
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT
*
* The content of this file has been generated based on the WebExtensions API
* JSONSchema using the following command:
*
* export SCRIPT_DIR="toolkit/components/extensions/webidl-api"
* mach python $SCRIPT_DIR/GenerateWebIDLBindings.py -- scripting
*
* More info about generating webidl API bindings for WebExtensions API at:
*
* https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/webidl_bindings.html
*/
/* 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/.
*
* You are granted a license to use, reproduce and create derivative works of
* this document.
*/
// WebIDL definition for the "scripting" WebExtensions API
[Exposed=(ServiceWorker), LegacyNoInterfaceObject]
interface ExtensionScripting {
// API methods.
[Throws, WebExtensionStub="NotImplementedAsync"]
any executeScript(any injection, optional Function callback);
[Throws, WebExtensionStub="Async"]
any insertCSS(any injection, optional Function callback);
[Throws, WebExtensionStub="Async"]
any removeCSS(any injection, optional Function callback);
[Throws, WebExtensionStub="Async"]
any registerContentScripts(any scripts, optional Function callback);
[Throws, WebExtensionStub="AsyncAmbiguous"]
any getRegisteredContentScripts(any... args);
[Throws, WebExtensionStub="AsyncAmbiguous"]
any unregisterContentScripts(any... args);
[Throws, WebExtensionStub="Async"]
any updateContentScripts(any scripts, optional Function callback);
};

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

@ -1098,6 +1098,7 @@ WEBIDL_FILES += [
"ExtensionMockAPI.webidl",
"ExtensionPort.webidl",
"ExtensionRuntime.webidl",
"ExtensionScripting.webidl",
"ExtensionTest.webidl",
]

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

@ -11,5 +11,14 @@ prefs =
dupe-manifest = true
# `test_verify_sw_mode.html` should be the first one, even if it breaks the
# alphabetical order.
[test_verify_sw_mode.html]
[test_ext_scripting_contentScripts.html]
[test_ext_scripting_executeScript.html]
skip-if = true # Bug 1748315 - Add WebIDL bindings for `scripting.executeScript()`
[test_ext_scripting_insertCSS.html]
skip-if = true # Bug 1748318 - Add WebIDL bindings for `tabs`
[test_ext_scripting_removeCSS.html]
skip-if = true # Bug 1748318 - Add WebIDL bindings for `tabs`
[test_ext_test.html]

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

@ -265,15 +265,13 @@ add_task(async function test_validate_registerContentScripts_persistAcrossSessio
];
for (const { title, params, expectedError } of TEST_CASES) {
try {
await browser.scripting.registerContentScripts(params);
browser.test.fail("registration should not be allowed");
} catch (err) {
browser.test.assertTrue(
expectedError.test(err.message),
`${title} - got expected error`
);
}
browser.test.assertThrows(
() => {
browser.scripting.registerContentScripts(params);
},
expectedError,
`${title} - got expected error`
);
}
let scripts = await browser.scripting.getRegisteredContentScripts();
@ -338,6 +336,18 @@ add_task(async function test_validate_getRegisteredContentScripts_params() {
});
browser.test.assertEq(0, scripts.length, "expected no registered scripts");
browser.test.log("test call with undefined filter and a chrome-compatible callback");
scripts = await new Promise(resolve => {
browser.scripting.getRegisteredContentScripts(undefined, resolve);
});
browser.test.assertEq(0, scripts.length, "expected no registered scripts");
browser.test.log("test call with only the chrome-compatible callback");
scripts = await new Promise(resolve => {
browser.scripting.getRegisteredContentScripts(resolve);
});
browser.test.assertEq(0, scripts.length, "expected no registered scripts");
browser.test.notifyPass("test-finished");
},
});
@ -953,6 +963,62 @@ add_task(async function test_validate_unregisterContentScripts_params() {
await extension.unload();
});
add_task(async function test_unregisterContentScripts_with_chrome_compatible_callback() {
let extension = makeExtension({
async background() {
let scripts = await browser.scripting.getRegisteredContentScripts();
browser.test.assertEq(0, scripts.length, "expected no script");
// Register a script that we can unregister after.
await browser.scripting.registerContentScripts([
{
id: "script-1",
js: ["script.js"],
matches: ["*://test1.example.com/*"],
persistAcrossSessions: false,
},
]);
scripts = await browser.scripting.getRegisteredContentScripts();
browser.test.assertEq(1, scripts.length, "expected 1 registered script");
browser.test.log("test call with undefined filter and a chrome-compatible callback");
await new Promise(resolve => {
browser.scripting.unregisterContentScripts(undefined, resolve);
});
scripts = await browser.scripting.getRegisteredContentScripts();
browser.test.assertEq(0, scripts.length, "expected no registered scripts");
// Re-register a script that we can unregister after.
await browser.scripting.registerContentScripts([
{
id: "script-1",
js: ["script.js"],
matches: ["*://test1.example.com/*"],
persistAcrossSessions: false,
},
]);
browser.test.log("test call with only the chrome-compatible callback");
await new Promise(resolve => {
browser.scripting.unregisterContentScripts(resolve);
});
scripts = await browser.scripting.getRegisteredContentScripts();
browser.test.assertEq(0, scripts.length, "expected no registered scripts");
browser.test.sendMessage("background-done");
},
files: {
"script.js": "",
},
});
await extension.startup();
await extension.awaitMessage("background-done");
await extension.unload();
});
add_task(async function test_unregisterContentScripts() {
let extension = makeExtension({
async background() {
@ -1526,20 +1592,18 @@ add_task(async function test_validate_updateContentScripts_persistAcrossSessions
await browser.scripting.registerContentScripts([script]);
try {
await browser.scripting.updateContentScripts([
{
id: script.id,
persistAcrossSessions: true,
},
]);
browser.test.fail("registration should not be allowed");
} catch (err) {
browser.test.assertTrue(
/persistAcrossSessions: Invalid value true/.test(err.message),
"got expected error"
);
}
browser.test.assertThrows(
() => {
browser.scripting.updateContentScripts([
{
id: script.id,
persistAcrossSessions: true,
},
]);
},
/persistAcrossSessions: Invalid value true/,
"got expected error"
);
browser.test.notifyPass("test-finished");
},

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

@ -154,41 +154,53 @@ add_task(
}
);
add_task(async function test_contentScripts_register() {
let extension = makeExtension({
manifest: {
manifest_version: 2,
},
async background() {
await browser.contentScripts.register({
js: [{ file: "script.js" }],
matches: ["http://*/*/*.html"],
});
browser.test.sendMessage("background-done");
},
});
await verifyRegistrationWithNewProcess(extension);
});
add_task(async function test_userScripts_register() {
let extension = makeExtension({
manifest: {
manifest_version: 2,
user_scripts: {
api_script: "inject_browser.js",
add_task(
{
// We don't have WebIDL bindings for `browser.contentScripts`.
skip_if: () => ExtensionTestUtils.isInBackgroundServiceWorkerTests(),
},
async function test_contentScripts_register() {
let extension = makeExtension({
manifest: {
manifest_version: 2,
},
},
async background() {
await browser.userScripts.register({
js: [{ file: "script.js" }],
matches: ["http://*/*/*.html"],
});
async background() {
await browser.contentScripts.register({
js: [{ file: "script.js" }],
matches: ["http://*/*/*.html"],
});
browser.test.sendMessage("background-done");
},
});
browser.test.sendMessage("background-done");
},
});
await verifyRegistrationWithNewProcess(extension);
});
await verifyRegistrationWithNewProcess(extension);
}
);
add_task(
{
// We don't have WebIDL bindings for `browser.userScripts`.
skip_if: () => ExtensionTestUtils.isInBackgroundServiceWorkerTests(),
},
async function test_userScripts_register() {
let extension = makeExtension({
manifest: {
manifest_version: 2,
user_scripts: {
api_script: "inject_browser.js",
},
},
async background() {
await browser.userScripts.register({
js: [{ file: "script.js" }],
matches: ["http://*/*/*.html"],
});
browser.test.sendMessage("background-done");
},
});
await verifyRegistrationWithNewProcess(extension);
}
);

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

@ -14,9 +14,14 @@ prefs =
extensions.backgroundServiceWorker.forceInTestExtension=true
extensions.webextensions.remote=true
[test_ext_background_service_worker.js]
[test_ext_alarms.js]
[test_ext_alarms_does_not_fire.js]
[test_ext_alarms_periodic.js]
[test_ext_alarms_replaces.js]
[test_ext_background_service_worker.js]
[test_ext_contentscript_dynamic_registration.js]
[test_ext_runtime_getBackgroundPage.js]
[test_ext_scripting_contentScripts.js]
[test_ext_scripting_contentScripts_css.js]
[test_ext_scripting_contentScripts_file.js]
[test_ext_scripting_updateContentScripts.js]

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

@ -13,6 +13,7 @@
#include "mozilla/extensions/ExtensionMockAPI.h"
#include "mozilla/extensions/ExtensionPort.h"
#include "mozilla/extensions/ExtensionRuntime.h"
#include "mozilla/extensions/ExtensionScripting.h"
#include "mozilla/extensions/ExtensionTest.h"
#include "mozilla/extensions/WebExtensionPolicy.h"
@ -33,6 +34,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ExtensionBrowser)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionAlarms)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionMockAPI)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionRuntime)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionScripting)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionTest)
tmp->mLastError.setUndefined();
tmp->mPortsLookup.Clear();
@ -44,6 +46,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ExtensionBrowser)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionAlarms)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionMockAPI)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionRuntime)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionScripting)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionTest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -210,6 +213,14 @@ ExtensionRuntime* ExtensionBrowser::GetExtensionRuntime() {
return mExtensionRuntime;
}
ExtensionScripting* ExtensionBrowser::GetExtensionScripting() {
if (!mExtensionScripting) {
mExtensionScripting = new ExtensionScripting(mGlobal, this);
}
return mExtensionScripting;
}
ExtensionTest* ExtensionBrowser::GetExtensionTest() {
if (!mExtensionTest) {
mExtensionTest = new ExtensionTest(mGlobal, this);

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

@ -24,6 +24,7 @@ class ExtensionAlarms;
class ExtensionMockAPI;
class ExtensionPort;
class ExtensionRuntime;
class ExtensionScripting;
class ExtensionTest;
bool ExtensionAPIAllowed(JSContext* aCx, JSObject* aGlobal);
@ -62,6 +63,7 @@ class ExtensionBrowser final : public nsISupports, public nsWrapperCache {
RefPtr<ExtensionAlarms> mExtensionAlarms;
RefPtr<ExtensionMockAPI> mExtensionMockAPI;
RefPtr<ExtensionRuntime> mExtensionRuntime;
RefPtr<ExtensionScripting> mExtensionScripting;
RefPtr<ExtensionTest> mExtensionTest;
nsTHashMap<nsStringHashKey, WeakPtr<ExtensionPort>> mPortsLookup;
@ -118,6 +120,7 @@ class ExtensionBrowser final : public nsISupports, public nsWrapperCache {
ExtensionAlarms* GetExtensionAlarms();
ExtensionMockAPI* GetExtensionMockAPI();
ExtensionRuntime* GetExtensionRuntime();
ExtensionScripting* GetExtensionScripting();
ExtensionTest* GetExtensionTest();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS

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

@ -0,0 +1,43 @@
/* 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 "ExtensionScripting.h"
#include "ExtensionEventManager.h"
#include "mozilla/dom/ExtensionScriptingBinding.h"
#include "nsIGlobalObject.h"
namespace mozilla::extensions {
NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionScripting);
NS_IMPL_CYCLE_COLLECTING_RELEASE(ExtensionScripting)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ExtensionScripting, mGlobal,
mExtensionBrowser);
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ExtensionScripting)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
ExtensionScripting::ExtensionScripting(nsIGlobalObject* aGlobal,
ExtensionBrowser* aExtensionBrowser)
: mGlobal(aGlobal), mExtensionBrowser(aExtensionBrowser) {
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
MOZ_DIAGNOSTIC_ASSERT(mExtensionBrowser);
}
/* static */
bool ExtensionScripting::IsAllowed(JSContext* aCx, JSObject* aGlobal) {
return true;
}
JSObject* ExtensionScripting::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
return dom::ExtensionScripting_Binding::Wrap(aCx, this, aGivenProto);
}
nsIGlobalObject* ExtensionScripting::GetParentObject() const { return mGlobal; }
} // namespace mozilla::extensions

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

@ -0,0 +1,66 @@
/* -*- 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_ExtensionScripting_h
#define mozilla_extensions_ExtensionScripting_h
#include "js/TypeDecls.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
#include "nsISupports.h"
#include "nsWrapperCache.h"
#include "ExtensionAPIBase.h"
#include "ExtensionBrowser.h"
class nsIGlobalObject;
namespace mozilla {
namespace extensions {
class ExtensionEventManager;
class ExtensionScripting final : public nsISupports,
public nsWrapperCache,
public ExtensionAPINamespace {
nsCOMPtr<nsIGlobalObject> mGlobal;
RefPtr<ExtensionBrowser> mExtensionBrowser;
~ExtensionScripting() = default;
public:
ExtensionScripting(nsIGlobalObject* aGlobal,
ExtensionBrowser* aExtensionBrowser);
// ExtensionAPIBase methods
nsIGlobalObject* GetGlobalObject() const override { return mGlobal; }
ExtensionBrowser* GetExtensionBrowser() const override {
return mExtensionBrowser;
}
nsString GetAPINamespace() const override { return u"scripting"_ns; }
// nsWrapperCache interface methods
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
// DOM bindings methods
static bool IsAllowed(JSContext* aCx, JSObject* aGlobal);
nsIGlobalObject* GetParentObject() const;
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ExtensionScripting)
};
} // namespace extensions
} // namespace mozilla
#endif // mozilla_extensions_ExtensionScripting_h

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

@ -63,6 +63,11 @@ WEBEXT_STUBS_MAPPING = {
"runtime.connect": "ReturnsPort",
"runtime.connectNative": "ReturnsPort",
"runtime.getURL": "ReturnsString",
# TODO: Bug 1782690 - This method accepts functions/args so we'll need to
# serialize them.
"scripting.executeScript": "NotImplementedAsync",
"scripting.getRegisteredContentScripts": "AsyncAmbiguous",
"scripting.unregisterContentScripts": "AsyncAmbiguous",
"test.assertEq": "AssertEq",
"test.assertRejects": False, # No WebExtensionStub attribute.
"test.assertThrows": False, # No WebExtensionStub attribute.

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

@ -29,12 +29,14 @@ EXPORTS.mozilla.extensions += [
UNIFIED_SOURCES += [
"ExtensionAlarms.cpp",
"ExtensionRuntime.cpp",
"ExtensionScripting.cpp",
"ExtensionTest.cpp",
]
EXPORTS.mozilla.extensions += [
"ExtensionAlarms.h",
"ExtensionRuntime.h",
"ExtensionScripting.h",
"ExtensionTest.h",
]