390 lines
11 KiB
HTML
390 lines
11 KiB
HTML
<!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(
|
|
() => {
|
|
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 = () => {
|
|
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>
|