bug 1310331 - implement matchAboutBlank for tabs.executeScript
MozReview-Commit-ID: ApuakyrctzD
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -2110,38 +2110,40 @@
var aSkipAnimation;
var aAllowMixedContent;
var aForceNotRemote;
var aNoReferrer;
var aUserContextId;
var aEventDetail;
var aRelatedBrowser;
var aOriginPrincipal;
+ var aDisallowInheritPrincipal;
var aOpener;
if (arguments.length == 2 &&
typeof arguments[1] == "object" &&
!(arguments[1] instanceof Ci.nsIURI)) {
let params = arguments[1];
- aReferrerURI = params.referrerURI;
- aReferrerPolicy = params.referrerPolicy;
- aCharset = params.charset;
- aPostData = params.postData;
- aOwner = params.ownerTab;
- aAllowThirdPartyFixup = params.allowThirdPartyFixup;
- aFromExternal = params.fromExternal;
- aRelatedToCurrent = params.relatedToCurrent;
- aSkipAnimation = params.skipAnimation;
- aAllowMixedContent = params.allowMixedContent;
- aForceNotRemote = params.forceNotRemote;
- aNoReferrer = params.noReferrer;
- aUserContextId = params.userContextId;
- aEventDetail = params.eventDetail;
- aRelatedBrowser = params.relatedBrowser;
- aOriginPrincipal = params.originPrincipal;
- aOpener = params.opener;
+ aReferrerURI = params.referrerURI;
+ aReferrerPolicy = params.referrerPolicy;
+ aCharset = params.charset;
+ aPostData = params.postData;
+ aOwner = params.ownerTab;
+ aAllowThirdPartyFixup = params.allowThirdPartyFixup;
+ aFromExternal = params.fromExternal;
+ aRelatedToCurrent = params.relatedToCurrent;
+ aSkipAnimation = params.skipAnimation;
+ aAllowMixedContent = params.allowMixedContent;
+ aForceNotRemote = params.forceNotRemote;
+ aNoReferrer = params.noReferrer;
+ aUserContextId = params.userContextId;
+ aEventDetail = params.eventDetail;
+ aRelatedBrowser = params.relatedBrowser;
+ aOriginPrincipal = params.originPrincipal;
+ aDisallowInheritPrincipal = params.disallowInheritPrincipal;
+ aOpener = params.opener;
}
// if we're adding tabs, we're past interrupt mode, ditch the owner
if (this.mCurrentTab.owner)
this.mCurrentTab.owner = null;
var t = document.createElementNS(NS_XUL, "tab");
@@ -2218,31 +2220,33 @@
t.dispatchEvent(evt);
if (!usingPreloadedContent && aOriginPrincipal) {
b.createAboutBlankContentViewer(aOriginPrincipal);
}
// If we didn't swap docShells with a preloaded browser
// then let's just continue loading the page normally.
- if (!usingPreloadedContent && !uriIsAboutBlank) {
+ if (!usingPreloadedContent && (!uriIsAboutBlank || aDisallowInheritPrincipal)) {
// pretend the user typed this so it'll be available till
// the document successfully loads
if (aURI && gInitialPages.indexOf(aURI) == -1)
b.userTypedValue = aURI;
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
if (aAllowThirdPartyFixup) {
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
}
if (aFromExternal)
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL;
if (aAllowMixedContent)
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT;
+ if (aDisallowInheritPrincipal)
+ flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
try {
b.loadURIWithFlags(aURI, {
flags,
referrerURI: aNoReferrer ? null: aReferrerURI,
referrerPolicy: aReferrerPolicy,
charset: aCharset,
postData: aPostData,
});
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -543,16 +543,20 @@ extensions.registerSchemaAPI("tabs", "ad
if (!containerId) {
return Promise.reject({message: `No cookie store exists with ID ${createProperties.cookieStoreId}`});
}
options.userContextId = containerId;
}
}
+ // Make sure things like about:blank and data: URIs never inherit,
+ // and instead always get a NullPrincipal.
+ options.disallowInheritPrincipal = true;
+
tabListener.initTabReady();
let tab = window.gBrowser.addTab(url || window.BROWSER_NEW_TAB_URL, options);
let active = true;
if (createProperties.active !== null) {
active = createProperties.active;
}
if (active) {
--- a/browser/components/extensions/test/browser/browser_ext_tabs_executeScript.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_executeScript.js
@@ -83,16 +83,30 @@ add_task(function* testExecuteScript() {
browser.test.assertEq(2, result.length, "Result has correct length");
browser.test.assertTrue(/\/file_iframe_document\.html$/.test(result[0]), "First result is correct");
browser.test.assertEq("http://mochi.test:8888/", result[1], "Second result is correct");
}),
browser.tabs.executeScript({
code: "location.href;",
+ allFrames: true,
+ matchAboutBlank: true,
+ }).then(result => {
+ browser.test.assertTrue(Array.isArray(result), "Result is an array");
+
+ browser.test.assertEq(3, result.length, "Result has correct length");
+
+ browser.test.assertTrue(/\/file_iframe_document\.html$/.test(result[0]), "First result is correct");
+ browser.test.assertEq("http://mochi.test:8888/", result[1], "Second result is correct");
+ browser.test.assertEq("about:blank", result[2], "Thirds result is correct");
+ }),
+
+ browser.tabs.executeScript({
+ code: "location.href;",
runAt: "document_end",
}).then(result => {
browser.test.assertEq(1, result.length, "Expected callback result");
browser.test.assertEq("string", typeof result[0], "Result is a string");
browser.test.assertTrue(/\/file_iframe_document\.html$/.test(result[0]), "Result is correct");
}),
@@ -182,16 +196,22 @@ add_task(function* testExecuteScript() {
browser.tabs.create({url: "http://example.com/"}).then(async tab => {
let result = await browser.tabs.executeScript(tab.id, {code: "location.href"});
browser.test.assertEq("http://example.com/", result[0], "Script executed correctly in new tab");
await browser.tabs.remove(tab.id);
}),
+ browser.tabs.create({url: "about:blank"}).then(async tab => {
+ const result = await browser.tabs.executeScript(tab.id, {code: "location.href", matchAboutBlank: true});
+ browser.test.assertEq("about:blank", result[0], "Script executed correctly in new tab");
+ await browser.tabs.remove(tab.id);
+ }),
+
new Promise(resolve => {
browser.runtime.onMessage.addListener(message => {
browser.test.assertEq("script ran", message, "Expected runtime message");
resolve();
});
}),
]);
--- a/browser/components/extensions/test/browser/file_iframe_document.html
+++ b/browser/components/extensions/test/browser/file_iframe_document.html
@@ -1,10 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<iframe src="/"></iframe>
+ <iframe src="about:blank"></iframe>
</body>
</html>
--- a/toolkit/components/extensions/ExtensionContent.jsm
+++ b/toolkit/components/extensions/ExtensionContent.jsm
@@ -138,19 +138,26 @@ Script.prototype = {
// If mozAddonManager is present on this page, don't allow
// content scripts.
if (window.navigator.mozAddonManager !== undefined) {
return false;
}
if (this.match_about_blank && ["about:blank", "about:srcdoc"].includes(uri.spec)) {
- // When matching about:blank/srcdoc documents, the checks below
+ const principal = window.document.nodePrincipal;
+
+ // When matching top-level about:blank documents,
+ // allow loading into any with a NullPrincipal.
+ if (window === window.top && principal.isNullPrincipal) {
+ return true;
+ }
+ // When matching about:blank/srcdoc iframes, the checks below
// need to be performed against the "owner" document's URI.
- uri = window.document.nodePrincipal.URI;
+ uri = principal.URI;
}
if (!(this.matches_.matches(uri) || this.matches_host_.matchesIgnoringPath(uri))) {
return false;
}
if (this.exclude_matches_.matches(uri)) {
return false;
@@ -615,17 +622,17 @@ DocumentManager = {
return null;
};
let promises = Array.from(this.enumerateWindows(global.docShell), executeInWin)
.filter(promise => promise);
if (!promises.length) {
let details = {};
- for (let key of ["all_frames", "frame_id", "matches_about_blank", "matchesHost"]) {
+ for (let key of ["all_frames", "frame_id", "match_about_blank", "matchesHost"]) {
if (key in options) {
details[key] = options[key];
}
}
return Promise.reject({message: `No window matching ${JSON.stringify(details)}`});
}
if (!options.all_frames && promises.length > 1) {