bug 1301227 - add allowScriptsToClose option to windows.create(), r=kmag

MozReview-Commit-ID: 4p8A1y2FALX

--HG--
extra : rebase_source : 5be607adae5c5eb8de8061a76461d1c056786161
This commit is contained in:
Tomislav Jovanovic 2016-09-23 23:40:24 +02:00
parent 69bfe48899
commit 0c231aa27e
4 changed files with 94 additions and 13 deletions

View File

@ -930,6 +930,12 @@ addEventListener("unload", () => {
RefreshBlocker.uninit();
});
addMessageListener("AllowScriptsToClose", () => {
content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.allowScriptsToClose();
});
addEventListener("MozAfterPaint", function onFirstPaint() {
removeEventListener("MozAfterPaint", onFirstPaint);
sendAsyncMessage("Browser:FirstPaint");

View File

@ -13,8 +13,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
var {
EventManager,
promiseObserved,
} = ExtensionUtils;
function onXULFrameLoaderCreated({target}) {
target.messageManager.sendAsyncMessage("AllowScriptsToClose", {});
}
extensions.registerSchemaAPI("windows", "addon_parent", context => {
let {extension} = context;
return {
@ -94,6 +99,10 @@ extensions.registerSchemaAPI("windows", "addon_parent", context => {
return Promise.reject({message: "`tabId` may not be used in conjunction with `url`"});
}
if (createData.allowScriptsToClose) {
return Promise.reject({message: "`tabId` may not be used in conjunction with `allowScriptsToClose`"});
}
let tab = TabManager.getTab(createData.tabId, context);
// Private browsing tabs can only be moved to private browsing
@ -136,6 +145,11 @@ extensions.registerSchemaAPI("windows", "addon_parent", context => {
}
}
let {allowScriptsToClose, url} = createData;
if (allowScriptsToClose === null) {
allowScriptsToClose = typeof url === "string" && url.startsWith("moz-extension://");
}
let window = Services.ww.openWindow(null, "chrome://browser/content/browser.xul", "_blank",
features.join(","), args);
@ -151,23 +165,22 @@ extensions.registerSchemaAPI("windows", "addon_parent", context => {
(createData.state == "fullscreen" && AppConstants.platform != "macosx")) {
window.document.documentElement.setAttribute("sizemode", createData.state);
} else if (createData.state !== null) {
// window.minimize() has no useful effect until the window has
// been shown.
let obs = doc => {
if (doc === window.document) {
Services.obs.removeObserver(obs, "document-shown");
WindowManager.setState(window, createData.state);
resolve();
}
};
Services.obs.addObserver(obs, "document-shown", false);
return;
// window.minimize() has no effect until the window has been shown.
return promiseObserved("document-shown", doc => doc == window.document).then(() => {
WindowManager.setState(window, createData.state);
resolve();
});
}
resolve();
});
}).then(() => {
if (allowScriptsToClose) {
for (let {linkedBrowser} of window.gBrowser.tabs) {
onXULFrameLoaderCreated({target: linkedBrowser});
linkedBrowser.addEventListener( // eslint-disable-line mozilla/balanced-listeners
"XULFrameLoaderCreated", onXULFrameLoaderCreated);
}
}
return WindowManager.convert(extension, window);
});
},

View File

@ -328,6 +328,11 @@
"$ref": "WindowState",
"optional": true,
"description": "The initial state of the window. The 'minimized', 'maximized' and 'fullscreen' states cannot be combined with 'left', 'top', 'width' or 'height'."
},
"allowScriptsToClose": {
"type": "boolean",
"optional": true,
"description": "Allow scripts to close the window."
}
},
"optional": true

View File

@ -165,3 +165,60 @@ add_task(function* testWindowCreateParams() {
yield extension.unload();
});
// Tests allowScriptsToClose option
add_task(function* test_allowScriptsToClose() {
const files = {
"dummy.html": "<meta charset=utf-8><script src=close.js></script>",
"close.js": function() {
window.close();
if (!window.closed) {
browser.test.sendMessage("close-failed");
}
},
};
function background() {
browser.test.onMessage.addListener((msg, options) => {
function listener(_, {status}, {url}) {
if (status == "complete" && url == options.url) {
browser.tabs.onUpdated.removeListener(listener);
browser.tabs.executeScript({file: "close.js"});
}
}
options.url = browser.runtime.getURL(options.url);
browser.windows.create(options);
if (msg === "create+execute") {
browser.tabs.onUpdated.addListener(listener);
}
});
browser.test.notifyPass();
}
const example = "http://example.com/";
const manifest = {permissions: ["tabs", example]};
const extension = ExtensionTestUtils.loadExtension({files, background, manifest});
yield SpecialPowers.pushPrefEnv({set: [["dom.allow_scripts_to_close_windows", false]]});
yield extension.startup();
yield extension.awaitFinish();
extension.sendMessage("create", {url: "dummy.html"});
let win = yield BrowserTestUtils.waitForNewWindow();
yield BrowserTestUtils.windowClosed(win);
info("script allowed to close the window");
extension.sendMessage("create+execute", {url: example});
win = yield BrowserTestUtils.waitForNewWindow();
yield extension.awaitMessage("close-failed");
info("script prevented from closing the window");
win.close();
extension.sendMessage("create+execute", {url: example, allowScriptsToClose: true});
win = yield BrowserTestUtils.waitForNewWindow();
yield BrowserTestUtils.windowClosed(win);
info("script allowed to close the window");
yield SpecialPowers.popPrefEnv();
yield extension.unload();
});