summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/mochitest/test_ext_activityLog.html
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/mochitest/test_ext_activityLog.html')
-rw-r--r--toolkit/components/extensions/test/mochitest/test_ext_activityLog.html390
1 files changed, 390 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/mochitest/test_ext_activityLog.html b/toolkit/components/extensions/test/mochitest/test_ext_activityLog.html
new file mode 100644
index 0000000000..c426913373
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_activityLog.html
@@ -0,0 +1,390 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>WebExtension activityLog test</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+ <script type="text/javascript" src="head.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<script type="text/javascript">
+"use strict";
+
+add_task(async function test_api() {
+ let URL =
+ "http://mochi.test:8888/tests/toolkit/components/extensions/test/mochitest/file_sample.html";
+
+ // Test that an unspecified extension is not logged by the watcher extension.
+ let unlogged = ExtensionTestUtils.loadExtension({
+ isPrivileged: true,
+ manifest: {
+ browser_specific_settings: { gecko: { id: "unlogged@tests.mozilla.org" } },
+ permissions: ["webRequest", "webRequestBlocking", "<all_urls>"],
+ },
+ background() {
+ // This privileged test extension should not affect the webRequest
+ // data received by non-privileged extensions (See Bug 1576272).
+ browser.webRequest.onBeforeRequest.addListener(
+ details => {
+ return { cancel: false };
+ },
+ { urls: ["http://mochi.test/*/file_sample.html"] },
+ ["blocking"]
+ );
+ },
+ });
+ await unlogged.startup();
+
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ browser_specific_settings: { gecko: { id: "watched@tests.mozilla.org" } },
+ permissions: [
+ "tabs",
+ "tabHide",
+ "storage",
+ "webRequest",
+ "webRequestBlocking",
+ "<all_urls>",
+ ],
+ content_scripts: [
+ {
+ matches: ["http://mochi.test/*/file_sample.html"],
+ js: ["content_script.js"],
+ run_at: "document_idle",
+ },
+ ],
+ },
+ files: {
+ "content_script.js": () => {
+ browser.test.sendMessage("content_script");
+ },
+ "registered_script.js": () => {
+ browser.test.sendMessage("registered_script");
+ },
+ },
+ async background() {
+ let listen = () => {};
+ async function runTest() {
+ // Test activity for a child function call.
+ browser.test.assertEq(
+ undefined,
+ browser.activityLog,
+ "activityLog requires permission"
+ );
+
+ // Test a child event manager.
+ browser.storage.onChanged.addListener(listen);
+ browser.storage.onChanged.removeListener(listen);
+
+ // Test a parent event manager.
+ let webRequestListener = details => {
+ browser.webRequest.onBeforeRequest.removeListener(webRequestListener);
+ return { cancel: false };
+ };
+ browser.webRequest.onBeforeRequest.addListener(
+ webRequestListener,
+ { urls: ["http://mochi.test/*/file_sample.html"] },
+ ["blocking"]
+ );
+
+ // A manifest based content script is already
+ // registered, we do a dynamic registration here.
+ await browser.contentScripts.register({
+ js: [{ file: "registered_script.js" }],
+ matches: ["http://mochi.test/*/file_sample.html"],
+ runAt: "document_start",
+ });
+ browser.test.sendMessage("ready");
+ }
+ browser.test.onMessage.addListener((msg, data) => {
+ // Logging has started here so this listener is logged, but the
+ // call adding it was not. We do an additional onMessage.addListener
+ // call in the test function to validate child based event managers.
+ if (msg == "runtest") {
+ browser.test.assertTrue(true, msg);
+ runTest();
+ }
+ if (msg == "hideTab") {
+ browser.tabs.hide(data);
+ }
+ });
+ browser.test.sendMessage("url", browser.runtime.getURL(""));
+ },
+ });
+
+ async function backgroundScript(expectedUrl, extensionUrl) {
+ let expecting = [
+ // Test child-only api_call.
+ {
+ type: "api_call",
+ name: "test.assertTrue",
+ data: { args: [true, "runtest"] },
+ },
+
+ // Test child-only api_call.
+ {
+ type: "api_call",
+ name: "test.assertEq",
+ data: {
+ args: [undefined, undefined, "activityLog requires permission"],
+ },
+ },
+ // Test child addListener calls.
+ {
+ type: "api_call",
+ name: "storage.onChanged.addListener",
+ data: {
+ args: [],
+ },
+ },
+ {
+ type: "api_call",
+ name: "storage.onChanged.removeListener",
+ data: {
+ args: [],
+ },
+ },
+ // Test parent addListener calls.
+ {
+ type: "api_call",
+ name: "webRequest.onBeforeRequest.addListener",
+ data: {
+ args: [
+ {
+ incognito: null,
+ tabId: null,
+ types: null,
+ urls: ["http://mochi.test/*/file_sample.html"],
+ windowId: null,
+ },
+ ["blocking"],
+ ],
+ },
+ },
+ // Test an api that makes use of callParentAsyncFunction.
+ {
+ type: "api_call",
+ name: "contentScripts.register",
+ data: {
+ args: [
+ {
+ allFrames: null,
+ css: null,
+ excludeGlobs: null,
+ excludeMatches: null,
+ includeGlobs: null,
+ js: [
+ {
+ file: `${extensionUrl}registered_script.js`,
+ },
+ ],
+ matchAboutBlank: null,
+ matches: ["http://mochi.test/*/file_sample.html"],
+ runAt: "document_start",
+ },
+ ],
+ },
+ },
+ // Test child api_event calls.
+ {
+ type: "api_event",
+ name: "test.onMessage",
+ data: { args: ["runtest"] },
+ },
+ {
+ type: "api_call",
+ name: "test.sendMessage",
+ data: { args: ["ready"] },
+ },
+ // Test parent api_event calls.
+ {
+ type: "api_call",
+ name: "webRequest.onBeforeRequest.removeListener",
+ data: {
+ args: [],
+ },
+ },
+ {
+ type: "api_event",
+ name: "webRequest.onBeforeRequest",
+ data: {
+ args: [
+ {
+ url: expectedUrl,
+ method: "GET",
+ type: "main_frame",
+ frameId: 0,
+ parentFrameId: -1,
+ incognito: false,
+ thirdParty: false,
+ ip: null,
+ frameAncestors: [],
+ urlClassification: { firstParty: [], thirdParty: [] },
+ requestSize: 0,
+ responseSize: 0,
+ },
+ ],
+ result: {
+ cancel: false,
+ },
+ },
+ },
+ // Test manifest based content script.
+ {
+ type: "content_script",
+ name: "content_script.js",
+ data: { url: expectedUrl, tabId: 1 },
+ },
+ // registered script test
+ {
+ type: "content_script",
+ name: `${extensionUrl}registered_script.js`,
+ data: { url: expectedUrl, tabId: 1 },
+ },
+ {
+ type: "api_call",
+ name: "test.sendMessage",
+ data: { args: ["registered_script"], tabId: 1 },
+ },
+ {
+ type: "api_call",
+ name: "test.sendMessage",
+ data: { args: ["content_script"], tabId: 1 },
+ },
+ // Child api call
+ {
+ type: "api_call",
+ name: "tabs.hide",
+ data: { args: ["__TAB_ID"] },
+ },
+ {
+ type: "api_event",
+ name: "test.onMessage",
+ data: { args: ["hideTab", "__TAB_ID"] },
+ },
+ ];
+ browser.test.assertTrue(browser.activityLog, "activityLog is privileged");
+
+ // Slightly less than a normal deep equal, we want to know that the values
+ // in our expected data are the same in the actual data, but we don't care
+ // if actual data has additional data or if data is in the same order in objects.
+ // This allows us to ignore keys that may be variable, or that are set in
+ // the api with an undefined value.
+ function deepEquivalent(a, b) {
+ if (a === b) {
+ return true;
+ }
+ if (
+ typeof a != "object" ||
+ typeof b != "object" ||
+ a === null ||
+ b === null
+ ) {
+ return false;
+ }
+ for (let k in a) {
+ if (!deepEquivalent(a[k], b[k])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ let tab;
+ let handler = async details => {
+ browser.test.log(`onExtensionActivity ${JSON.stringify(details)}`);
+ let test = expecting.shift();
+ if (!test) {
+ browser.test.notifyFail(`no test for ${details.name}`);
+ }
+
+ // On multiple runs, tabId will be different. Set the current
+ // tabId where we need it.
+ if (test.data.tabId !== undefined) {
+ test.data.tabId = tab.id;
+ }
+ if (test.data.args !== undefined) {
+ test.data.args = test.data.args.map(value =>
+ value === "__TAB_ID" ? tab.id : value
+ );
+ }
+
+ browser.test.assertEq(test.type, details.type, "type matches");
+ if (test.type == "content_script") {
+ browser.test.assertTrue(
+ details.name.includes(test.name),
+ "content script name matches"
+ );
+ } else {
+ browser.test.assertEq(test.name, details.name, "name matches");
+ }
+
+ browser.test.assertTrue(
+ deepEquivalent(test.data, details.data),
+ `expected ${JSON.stringify(
+ test.data
+ )} included in actual ${JSON.stringify(details.data)}`
+ );
+ if (!expecting.length) {
+ await browser.tabs.remove(tab.id);
+ browser.test.notifyPass("activity");
+ }
+ };
+ browser.activityLog.onExtensionActivity.addListener(
+ handler,
+ "watched@tests.mozilla.org"
+ );
+
+ browser.test.onMessage.addListener(async msg => {
+ if (msg === "opentab") {
+ tab = await browser.tabs.create({ url: expectedUrl });
+ browser.test.sendMessage("tabid", tab.id);
+ }
+ if (msg === "done") {
+ browser.activityLog.onExtensionActivity.removeListener(
+ handler,
+ "watched@tests.mozilla.org"
+ );
+ }
+ });
+ }
+
+ await extension.startup();
+ let extensionUrl = await extension.awaitMessage("url");
+
+ let logger = ExtensionTestUtils.loadExtension({
+ isPrivileged: true,
+ manifest: {
+ browser_specific_settings: { gecko: { id: "watcher@tests.mozilla.org" } },
+ permissions: ["activityLog"],
+ },
+ background: `(${backgroundScript})("${URL}", "${extensionUrl}")`,
+ });
+ await logger.startup();
+ extension.sendMessage("runtest");
+ await extension.awaitMessage("ready");
+ logger.sendMessage("opentab");
+ let id = await logger.awaitMessage("tabid");
+
+ await Promise.all([
+ extension.awaitMessage("content_script"),
+ extension.awaitMessage("registered_script"),
+ ]);
+
+ extension.sendMessage("hideTab", id);
+ await logger.awaitFinish("activity");
+
+ // Stop watching because we get extra calls on extension shutdown
+ // such as listener removal.
+ logger.sendMessage("done");
+
+ await extension.unload();
+ await unlogged.unload();
+ await logger.unload();
+});
+</script>
+
+</body>
+</html>