Bug 1296900 - Add test for availability of default WebExtension APIs r?kmag
MozReview-Commit-ID: LIr5Nsv51I3
--- a/browser/components/extensions/moz.build
+++ b/browser/components/extensions/moz.build
@@ -8,9 +8,10 @@ JAR_MANIFESTS += ['jar.mn']
EXTRA_COMPONENTS += [
'extensions-browser.manifest',
]
DIRS += ['schemas']
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
+MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/mochitest/mochitest.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+support-files =
+ ../../../../../toolkit/components/extensions/test/mochitest/test_ext_all_apis.js
+tags = webextensions
+
+[test_ext_all_apis.html]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/mochitest/test_ext_all_apis.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>WebExtension test</title>
+ <meta charset="utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+<script>
+"use strict";
+/* exported expectedContentApisTargetSpecific, expectedBackgroundApisTargetSpecific */
+let expectedContentApisTargetSpecific = [
+];
+
+let expectedBackgroundApisTargetSpecific = [
+ // TODO(robwu): commands API should be hidden by default, and only be visible
+ // if the commands manifest attribute is set.
+ "commands.getAll",
+ "commands.onCommand",
+ "tabs.MutedInfoReason",
+ "tabs.TAB_ID_NONE",
+ "tabs.TabStatus",
+ "tabs.WindowType",
+ "tabs.ZoomSettingsMode",
+ "tabs.ZoomSettingsScope",
+ "tabs.connect",
+ "tabs.create",
+ "tabs.detectLanguage",
+ "tabs.duplicate",
+ "tabs.executeScript",
+ "tabs.get",
+ "tabs.getCurrent",
+ "tabs.getZoom",
+ "tabs.getZoomSettings",
+ "tabs.highlight",
+ "tabs.insertCSS",
+ "tabs.move",
+ "tabs.onActivated",
+ "tabs.onAttached",
+ "tabs.onCreated",
+ "tabs.onDetached",
+ "tabs.onHighlighted",
+ "tabs.onMoved",
+ "tabs.onRemoved",
+ "tabs.onReplaced",
+ "tabs.onUpdated",
+ "tabs.onZoomChange",
+ "tabs.query",
+ "tabs.reload",
+ "tabs.remove",
+ "tabs.removeCSS",
+ "tabs.sendMessage",
+ "tabs.setZoom",
+ "tabs.setZoomSettings",
+ "tabs.update",
+ "windows.CreateType",
+ "windows.WINDOW_ID_CURRENT",
+ "windows.WINDOW_ID_NONE",
+ "windows.WindowState",
+ "windows.WindowType",
+ "windows.create",
+ "windows.get",
+ "windows.getAll",
+ "windows.getCurrent",
+ "windows.getLastFocused",
+ "windows.onCreated",
+ "windows.onFocusChanged",
+ "windows.onRemoved",
+ "windows.remove",
+ "windows.update",
+];
+</script>
+<script src="test_ext_all_apis.js"></script>
+
+</body>
+</html>
--- a/mobile/android/components/extensions/moz.build
+++ b/mobile/android/components/extensions/moz.build
@@ -7,9 +7,10 @@
JAR_MANIFESTS += ['jar.mn']
EXTRA_COMPONENTS += [
'extensions-mobile.manifest',
]
DIRS += ['schemas']
-MOCHITEST_CHROME_MANIFESTS += ['test/mochitest/chrome.ini']
\ No newline at end of file
+MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
+MOCHITEST_CHROME_MANIFESTS += ['test/mochitest/chrome.ini']
new file mode 100644
--- /dev/null
+++ b/mobile/android/components/extensions/test/mochitest/mochitest.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+support-files =
+ ../../../../../../toolkit/components/extensions/test/mochitest/test_ext_all_apis.js
+tags = webextensions
+
+[test_ext_all_apis.html]
new file mode 100644
--- /dev/null
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_all_apis.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>WebExtension test</title>
+ <meta charset="utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+<script>
+"use strict";
+/* exported expectedContentApisTargetSpecific, expectedBackgroundApisTargetSpecific */
+let expectedContentApisTargetSpecific = [
+];
+
+let expectedBackgroundApisTargetSpecific = [
+];
+</script>
+<script src="test_ext_all_apis.js"></script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_all_apis.js
@@ -0,0 +1,154 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+// Tests whether not too many APIs are visible by default.
+// This file is used by test_ext_all_apis.html in browser/ and mobile/android/,
+// which may modify the following variables to add or remove expected APIs.
+/* globals expectedContentApisTargetSpecific */
+/* globals expectedBackgroundApisTargetSpecific */
+
+// Generates a list of expectations.
+function generateExpectations(list) {
+ return list.reduce((allApis, path) => {
+ return allApis.concat(`browser.${path}`, `chrome.${path}`);
+ }, []).sort();
+}
+
+let expectedCommonApis = [
+ "extension.getURL",
+ "extension.inIncognitoContext",
+ "extension.lastError",
+ "i18n.detectLanguage",
+ "i18n.getAcceptLanguages",
+ "i18n.getMessage",
+ "i18n.getUILanguage",
+ "runtime.OnInstalledReason",
+ "runtime.OnRestartRequiredReason",
+ "runtime.PlatformArch",
+ "runtime.PlatformOs",
+ "runtime.RequestUpdateCheckStatus",
+ "runtime.getManifest",
+ "runtime.connect",
+ "runtime.getURL",
+ "runtime.id",
+ "runtime.lastError",
+ "runtime.onConnect",
+ "runtime.onMessage",
+ "runtime.sendMessage",
+ // If you want to add a new powerful test API, please see bug 1287233.
+ "test.assertEq",
+ "test.assertFalse",
+ "test.assertTrue",
+ "test.fail",
+ "test.log",
+ "test.notifyFail",
+ "test.notifyPass",
+ "test.onMessage",
+ "test.sendMessage",
+ "test.succeed",
+];
+
+let expectedContentApis = [
+ ...expectedCommonApis,
+ ...expectedContentApisTargetSpecific,
+];
+
+let expectedBackgroundApis = [
+ ...expectedCommonApis,
+ ...expectedBackgroundApisTargetSpecific,
+ "extension.ViewType",
+ "extension.getBackgroundPage",
+ "extension.getViews",
+ "extension.isAllowedFileSchemeAccess",
+ "extension.isAllowedIncognitoAccess",
+ // Note: extensionTypes is not visible in Chrome.
+ "extensionTypes.ImageFormat",
+ "extensionTypes.RunAt",
+ "management.ExtensionDisabledReason",
+ "management.ExtensionInstallType",
+ "management.ExtensionType",
+ "management.getSelf",
+ "management.uninstallSelf",
+ "runtime.getBackgroundPage",
+ "runtime.getBrowserInfo",
+ "runtime.getPlatformInfo",
+ "runtime.onUpdateAvailable",
+ "runtime.openOptionsPage",
+ "runtime.reload",
+ "runtime.setUninstallURL",
+];
+
+function sendAllApis() {
+ function isEvent(key, val) {
+ if (!/^on[A-Z]/.test(key)) {
+ return false;
+ }
+ let eventKeys = [];
+ for (let prop in val) {
+ eventKeys.push(prop);
+ }
+ eventKeys = eventKeys.sort().join();
+ return eventKeys === "addListener,hasListener,removeListener";
+ }
+ function mayRecurse(key, val) {
+ if (Object.keys(val).filter(k => !/^[A-Z\-0-9_]+$/.test(k)).length === 0) {
+ // Don't recurse on constants and empty objects.
+ return false;
+ }
+ return !isEvent(key, val);
+ }
+
+ let results = [];
+ function diveDeeper(path, obj) {
+ for (let key in obj) {
+ let val = obj[key];
+ if (typeof val == "object" && val !== null && mayRecurse(key, val)) {
+ diveDeeper(`${path}.${key}`, val);
+ } else {
+ results.push(`${path}.${key}`);
+ }
+ }
+ }
+ diveDeeper("browser", browser);
+ diveDeeper("chrome", chrome);
+ browser.test.sendMessage("allApis", results.sort());
+}
+
+add_task(function* test_enumerate_content_script_apis() {
+ let extensionData = {
+ manifest: {
+ content_scripts: [{
+ matches: ["http://mochi.test/*/file_sample.html"],
+ js: ["contentscript.js"],
+ run_at: "document_start",
+ }],
+ },
+ files: {
+ "contentscript.js": sendAllApis,
+ },
+ };
+ let extension = ExtensionTestUtils.loadExtension(extensionData);
+ yield extension.startup();
+
+ let win = window.open("file_sample.html");
+ let actualApis = yield extension.awaitMessage("allApis");
+ win.close();
+ let expectedApis = generateExpectations(expectedContentApis);
+ isDeeply(actualApis, expectedApis, "content script APIs");
+
+ yield extension.unload();
+});
+
+add_task(function* test_enumerate_background_script_apis() {
+ let extensionData = {
+ background: sendAllApis,
+ };
+ let extension = ExtensionTestUtils.loadExtension(extensionData);
+ yield extension.startup();
+ let actualApis = yield extension.awaitMessage("allApis");
+ let expectedApis = generateExpectations(expectedBackgroundApis);
+ isDeeply(actualApis, expectedApis, "background script APIs");
+
+ yield extension.unload();
+});