mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Bug 1223634 - Support exclude_globs/include_globs in webext manifests. r=kmag
--HG-- extra : rebase_source : e6a951c77581b08fa8613852f54665506e9fb0ba
This commit is contained in:
parent
1f813aa1a3
commit
3f7b262a15
@ -29,6 +29,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "LanguageDetector",
|
||||
"resource:///modules/translation/LanguageDetector.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "MatchPattern",
|
||||
"resource://gre/modules/MatchPattern.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "MatchGlobs",
|
||||
"resource://gre/modules/MatchPattern.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
|
||||
@ -152,8 +154,8 @@ function Script(options, deferred = PromiseUtils.defer()) {
|
||||
// TODO: MatchPattern should pre-mangle host-only patterns so that we
|
||||
// don't need to call a separate match function.
|
||||
this.matches_host_ = new MatchPattern(this.options.matchesHost || null);
|
||||
|
||||
// TODO: Support glob patterns.
|
||||
this.include_globs_ = new MatchGlobs(this.options.include_globs);
|
||||
this.exclude_globs_ = new MatchGlobs(this.options.exclude_globs);
|
||||
}
|
||||
|
||||
Script.prototype = {
|
||||
@ -167,6 +169,16 @@ Script.prototype = {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.options.include_globs != null) {
|
||||
if (!this.include_globs_.matches(uri)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.exclude_globs_.matches(uri)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.options.frame_id != null) {
|
||||
if (WebNavigationFrames.getFrameId(window) != this.options.frame_id) {
|
||||
return false;
|
||||
|
@ -232,6 +232,16 @@
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "MatchPattern" }
|
||||
},
|
||||
"include_globs": {
|
||||
"type": "array",
|
||||
"optional": true,
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"exclude_globs": {
|
||||
"type": "array",
|
||||
"optional": true,
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"css": {
|
||||
"type": "array",
|
||||
"optional": true,
|
||||
|
@ -33,6 +33,7 @@ skip-if = buildapp == 'b2g' # runat != document_idle is not supported.
|
||||
[test_ext_contentscript_create_iframe.html]
|
||||
[test_ext_contentscript_api_injection.html]
|
||||
[test_ext_downloads.html]
|
||||
[test_ext_exclude_include_globs.html]
|
||||
[test_ext_i18n_css.html]
|
||||
[test_ext_generate.html]
|
||||
[test_ext_idle.html]
|
||||
|
@ -0,0 +1,92 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for content script</title>
|
||||
<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>
|
||||
<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(function* test_contentscript() {
|
||||
function backgroundScript() {
|
||||
browser.runtime.onMessage.addListener(([script], sender) => {
|
||||
browser.test.sendMessage("run", {script});
|
||||
browser.test.sendMessage("run-" + script);
|
||||
});
|
||||
browser.test.sendMessage("running");
|
||||
}
|
||||
|
||||
function contentScriptAll() {
|
||||
browser.runtime.sendMessage(["all"]);
|
||||
}
|
||||
function contentScriptIncludesTest1() {
|
||||
browser.runtime.sendMessage(["includes-test1"]);
|
||||
}
|
||||
function contentScriptExcludesTest1() {
|
||||
browser.runtime.sendMessage(["excludes-test1"]);
|
||||
}
|
||||
|
||||
let extensionData = {
|
||||
manifest: {
|
||||
content_scripts: [
|
||||
{
|
||||
"matches": ["http://example.org/", "http://*.example.org/"],
|
||||
"exclude_globs": [],
|
||||
"include_globs": ["*"],
|
||||
"js": ["content_script_all.js"],
|
||||
},
|
||||
{
|
||||
"matches": ["http://example.org/", "http://*.example.org/"],
|
||||
"include_globs": ["*test1*"],
|
||||
"js": ["content_script_includes_test1.js"],
|
||||
},
|
||||
{
|
||||
"matches": ["http://example.org/", "http://*.example.org/"],
|
||||
"exclude_globs": ["*test1*"],
|
||||
"js": ["content_script_excludes_test1.js"],
|
||||
},
|
||||
],
|
||||
},
|
||||
background: "(" + backgroundScript.toString() + ")()",
|
||||
|
||||
files: {
|
||||
"content_script_all.js": "(" + contentScriptAll.toString() + ")()",
|
||||
"content_script_includes_test1.js": "(" + contentScriptIncludesTest1.toString() + ")()",
|
||||
"content_script_excludes_test1.js": "(" + contentScriptExcludesTest1.toString() + ")()",
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||
|
||||
let ran = 0;
|
||||
extension.onMessage("run", ({script}) => {
|
||||
ran++;
|
||||
});
|
||||
|
||||
yield Promise.all([extension.startup(), extension.awaitMessage("running")]);
|
||||
info("extension loaded");
|
||||
|
||||
let win = window.open("http://example.org/");
|
||||
yield Promise.all([extension.awaitMessage("run-all"), extension.awaitMessage("run-excludes-test1")]);
|
||||
win.close();
|
||||
is(ran, 2);
|
||||
|
||||
win = window.open("http://test1.example.org/");
|
||||
yield Promise.all([extension.awaitMessage("run-all"), extension.awaitMessage("run-includes-test1")]);
|
||||
win.close();
|
||||
is(ran, 4);
|
||||
|
||||
yield extension.unload();
|
||||
info("extension unloaded");
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -11,9 +11,9 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["MatchPattern"];
|
||||
this.EXPORTED_SYMBOLS = ["MatchPattern", "MatchGlobs"];
|
||||
|
||||
/* globals MatchPattern */
|
||||
/* globals MatchPattern, MatchGlobs */
|
||||
|
||||
const PERMITTED_SCHEMES = ["http", "https", "file", "ftp", "app", "data"];
|
||||
const PERMITTED_SCHEMES_REGEXP = PERMITTED_SCHEMES.join("|");
|
||||
@ -172,3 +172,24 @@ MatchPattern.prototype = {
|
||||
return this.pat;
|
||||
},
|
||||
};
|
||||
|
||||
// Globs can match everything. Be careful, this DOES NOT filter by allowed schemes!
|
||||
this.MatchGlobs = function(globs) {
|
||||
if (globs) {
|
||||
this.regexps = Array.from(globs, (glob) => globToRegexp(glob, true));
|
||||
} else {
|
||||
this.regexps = [];
|
||||
}
|
||||
};
|
||||
|
||||
MatchGlobs.prototype = {
|
||||
matches(uri) {
|
||||
let spec = uri.spec;
|
||||
for (let regexp of this.regexps) {
|
||||
if (regexp.test(spec)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
58
toolkit/modules/tests/xpcshell/test_MatchGlobs.js
Normal file
58
toolkit/modules/tests/xpcshell/test_MatchGlobs.js
Normal file
@ -0,0 +1,58 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/MatchPattern.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function test(url, pattern) {
|
||||
let uri = Services.io.newURI(url, null, null);
|
||||
let m = new MatchGlobs(pattern);
|
||||
return m.matches(uri);
|
||||
}
|
||||
|
||||
function pass({url, pattern}) {
|
||||
ok(test(url, pattern), `Expected match: ${JSON.stringify(pattern)}, ${url}`);
|
||||
}
|
||||
|
||||
function fail({url, pattern}) {
|
||||
ok(!test(url, pattern), `Expected no match: ${JSON.stringify(pattern)}, ${url}`);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let moz = "http://mozilla.org";
|
||||
|
||||
pass({url: moz, pattern: ["*"]});
|
||||
pass({url: moz, pattern: ["http://*"]}),
|
||||
pass({url: moz, pattern: ["*mozilla*"]});
|
||||
pass({url: moz, pattern: ["*example*", "*mozilla*"]});
|
||||
|
||||
pass({url: moz, pattern: ["*://*"]});
|
||||
pass({url: "https://mozilla.org", pattern: ["*://*"]});
|
||||
|
||||
// Documentation example
|
||||
pass({url: "http://www.example.com/foo/bar", pattern: ["http://???.example.com/foo/*"]});
|
||||
pass({url: "http://the.example.com/foo/", pattern: ["http://???.example.com/foo/*"]});
|
||||
fail({url: "http://my.example.com/foo/bar", pattern: ["http://???.example.com/foo/*"]});
|
||||
fail({url: "http://example.com/foo/", pattern: ["http://???.example.com/foo/*"]});
|
||||
fail({url: "http://www.example.com/foo", pattern: ["http://???.example.com/foo/*"]});
|
||||
|
||||
// Matches path
|
||||
let path = moz + "/abc/def";
|
||||
pass({url: path, pattern: ["*def"]});
|
||||
pass({url: path, pattern: ["*c/d*"]});
|
||||
pass({url: path, pattern: ["*org/abc*"]});
|
||||
fail({url: path + "/", pattern: ["*def"]});
|
||||
|
||||
// Trailing slash
|
||||
pass({url: moz, pattern: ["*.org/"]});
|
||||
fail({url: moz, pattern: ["*.org"]});
|
||||
|
||||
// Wrong TLD
|
||||
fail({url: moz, pattern: ["www*.m*.com/"]});
|
||||
// Case sensitive
|
||||
fail({url: moz, pattern: ["*.ORG/"]});
|
||||
|
||||
fail({url: moz, pattern: []});
|
||||
}
|
@ -25,6 +25,8 @@ skip-if = toolkit == 'android'
|
||||
skip-if = toolkit == 'android'
|
||||
[test_MatchPattern.js]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_MatchGlobs.js]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_NewTabUtils.js]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_ObjectUtils.js]
|
||||
|
Loading…
Reference in New Issue
Block a user