зеркало из https://github.com/mozilla/gecko-dev.git
bug 1272890 - implement match_about_blank for content scripts r=kmag
MozReview-Commit-ID: 3iZLpUw5LF4 --HG-- extra : rebase_source : d520a13211584af096f68cd0a2cfec022a72e413
This commit is contained in:
Родитель
0a5faee022
Коммит
47aa3f8372
|
@ -101,6 +101,7 @@ function Script(extension, options, deferred = PromiseUtils.defer()) {
|
|||
this.js = this.options.js || [];
|
||||
this.css = this.options.css || [];
|
||||
this.remove_css = this.options.remove_css;
|
||||
this.match_about_blank = this.options.match_about_blank;
|
||||
|
||||
this.deferred = deferred;
|
||||
|
||||
|
@ -140,6 +141,12 @@ Script.prototype = {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (this.match_about_blank && ["about:blank", "about:srcdoc"].includes(uri.spec)) {
|
||||
// When matching about:blank/srcdoc documents, the checks below
|
||||
// need to be performed against the "owner" document's URI.
|
||||
uri = window.document.nodePrincipal.URI;
|
||||
}
|
||||
|
||||
if (!(this.matches_.matches(uri) || this.matches_host_.matchesIgnoringPath(uri))) {
|
||||
return false;
|
||||
}
|
||||
|
@ -166,8 +173,6 @@ Script.prototype = {
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: match_about_blank.
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
@ -426,11 +431,13 @@ DocumentManager = {
|
|||
extensionPageWindows: new Map(),
|
||||
|
||||
init() {
|
||||
Services.obs.addObserver(this, "content-document-global-created", false);
|
||||
Services.obs.addObserver(this, "document-element-inserted", false);
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
},
|
||||
|
||||
uninit() {
|
||||
Services.obs.removeObserver(this, "content-document-global-created");
|
||||
Services.obs.removeObserver(this, "document-element-inserted");
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
},
|
||||
|
@ -447,13 +454,27 @@ DocumentManager = {
|
|||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
if (topic == "document-element-inserted") {
|
||||
// For some types of documents (about:blank), we only see the first
|
||||
// notification, for others (data: URIs) we only observe the second.
|
||||
if (topic == "content-document-global-created" || topic == "document-element-inserted") {
|
||||
let document = subject;
|
||||
let window = document && document.defaultView;
|
||||
|
||||
if (topic == "content-document-global-created") {
|
||||
window = subject;
|
||||
document = window && window.document;
|
||||
}
|
||||
|
||||
if (!document || !document.location || !window) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we always load exactly once (notice != used as logical XOR),
|
||||
// usually on document-element-inserted, except for about:blank documents.
|
||||
if ((topic == "content-document-global-created") != (window.location.href == "about:blank")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we only load into frames that ExtensionContent.init
|
||||
// was called on (i.e., not frames for social or sidebars).
|
||||
let mm = getWindowMessageManager(window);
|
||||
|
@ -482,7 +503,8 @@ DocumentManager = {
|
|||
}
|
||||
}
|
||||
|
||||
this.trigger("document_start", window);
|
||||
this.trigger(window);
|
||||
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
window.addEventListener("DOMContentLoaded", this, true);
|
||||
window.addEventListener("load", this, true);
|
||||
|
@ -526,9 +548,9 @@ DocumentManager = {
|
|||
// Need to check if we're still on the right page? Greasemonkey does this.
|
||||
|
||||
if (event.type == "DOMContentLoaded") {
|
||||
this.trigger("document_end", window);
|
||||
this.trigger(window);
|
||||
} else if (event.type == "load") {
|
||||
this.trigger("document_idle", window);
|
||||
this.trigger(window);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -666,7 +688,7 @@ DocumentManager = {
|
|||
}
|
||||
},
|
||||
|
||||
trigger(when, window) {
|
||||
trigger(window) {
|
||||
let state = this.getWindowState(window);
|
||||
|
||||
if (state == "document_start") {
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="a_b" src="about:blank"></iframe>
|
||||
<iframe srcdoc="galactica actual" src="adama"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -18,6 +18,7 @@ support-files =
|
|||
file_WebNavigation_page1.html
|
||||
file_WebNavigation_page2.html
|
||||
file_WebNavigation_page3.html
|
||||
file_with_about_blank.html
|
||||
file_image_good.png
|
||||
file_image_bad.png
|
||||
file_image_redirect.png
|
||||
|
@ -50,6 +51,8 @@ skip-if = os == 'android' # Android does not currently support windows.
|
|||
[test_ext_contentscript_devtools_metadata.html]
|
||||
[test_ext_contentscript_exporthelpers.html]
|
||||
[test_ext_contentscript_css.html]
|
||||
[test_ext_contentscript_about_blank.html]
|
||||
skip-if = (os == 'android') # bug 1312357
|
||||
[test_ext_contentscript_teardown.html]
|
||||
skip-if = (os == 'android') # Android does not support tabs API. Bug 1260250
|
||||
[test_ext_exclude_include_globs.html]
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test content script match_about_blank option</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.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 type="text/javascript">
|
||||
"use strict";
|
||||
|
||||
add_task(function* test_contentscript_about_blank() {
|
||||
const manifest = {
|
||||
content_scripts: [
|
||||
{
|
||||
match_about_blank: true,
|
||||
matches: ["http://mochi.test/*/file_with_about_blank.html", "http://example.com/*"],
|
||||
all_frames: true,
|
||||
css: ["all.css"],
|
||||
js: ["all.js"],
|
||||
}, {
|
||||
matches: ["http://mochi.test/*/file_with_about_blank.html"],
|
||||
css: ["mochi_without.css"],
|
||||
js: ["mochi_without.js"],
|
||||
all_frames: true,
|
||||
}, {
|
||||
match_about_blank: true,
|
||||
matches: ["http://mochi.test/*/file_with_about_blank.html"],
|
||||
css: ["mochi_with.css"],
|
||||
js: ["mochi_with.js"],
|
||||
all_frames: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const files = {
|
||||
"all.js": function() {
|
||||
browser.runtime.sendMessage("all");
|
||||
},
|
||||
"all.css": `
|
||||
body { color: red; }
|
||||
`,
|
||||
"mochi_without.js": function() {
|
||||
browser.runtime.sendMessage("mochi_without");
|
||||
},
|
||||
"mochi_without.css": `
|
||||
body { background: yellow; }
|
||||
`,
|
||||
"mochi_with.js": function() {
|
||||
browser.runtime.sendMessage("mochi_with");
|
||||
},
|
||||
"mochi_with.css": `
|
||||
body { text-align: right; }
|
||||
`,
|
||||
};
|
||||
|
||||
function background() {
|
||||
browser.runtime.onMessage.addListener((script, {url}) => {
|
||||
const kind = url.startsWith("about:") ? url : "top";
|
||||
browser.test.sendMessage("script", [script, kind, url]);
|
||||
browser.test.sendMessage(`${script}:${kind}`);
|
||||
});
|
||||
}
|
||||
|
||||
const PATH = "tests/toolkit/components/extensions/test/mochitest/file_with_about_blank.html";
|
||||
const extension = ExtensionTestUtils.loadExtension({manifest, files, background});
|
||||
yield extension.startup();
|
||||
|
||||
let count = 0;
|
||||
extension.onMessage("script", script => {
|
||||
info(`script ran: ${script}`);
|
||||
count++;
|
||||
});
|
||||
|
||||
let win = window.open("http://example.com/" + PATH);
|
||||
yield Promise.all([
|
||||
extension.awaitMessage("all:top"),
|
||||
extension.awaitMessage("all:about:blank"),
|
||||
extension.awaitMessage("all:about:srcdoc"),
|
||||
]);
|
||||
is(count, 3, "exactly 3 scripts ran");
|
||||
win.close();
|
||||
|
||||
win = window.open("http://mochi.test:8888/" + PATH);
|
||||
yield Promise.all([
|
||||
extension.awaitMessage("all:top"),
|
||||
extension.awaitMessage("all:about:blank"),
|
||||
extension.awaitMessage("all:about:srcdoc"),
|
||||
extension.awaitMessage("mochi_without:top"),
|
||||
extension.awaitMessage("mochi_with:top"),
|
||||
extension.awaitMessage("mochi_with:about:blank"),
|
||||
extension.awaitMessage("mochi_with:about:srcdoc"),
|
||||
]);
|
||||
|
||||
let style = win.getComputedStyle(win.document.body);
|
||||
is(style.color, "rgb(255, 0, 0)", "top window text color is red");
|
||||
is(style.backgroundColor, "rgb(255, 255, 0)", "top window background is yellow");
|
||||
is(style.textAlign, "right", "top window text is right-aligned");
|
||||
|
||||
let a_b = win.document.getElementById("a_b");
|
||||
style = a_b.contentWindow.getComputedStyle(a_b.contentDocument.body);
|
||||
is(style.color, "rgb(255, 0, 0)", "about:blank iframe text color is red");
|
||||
is(style.backgroundColor, "transparent", "about:blank iframe background is transparent");
|
||||
is(style.textAlign, "right", "about:blank text is right-aligned");
|
||||
|
||||
is(count, 10, "exactly 7 more scripts ran");
|
||||
win.close();
|
||||
|
||||
yield extension.unload();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче