зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1525125 block newtab and homepage overrides in private windows r=rpl,Gijs
Differential Revision: https://phabricator.services.mozilla.com/D18730 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
a32ea7277b
Коммит
75718b91a4
|
@ -2174,7 +2174,7 @@ function BrowserHome(aEvent) {
|
|||
aEvent.button == 2) // right-click: do nothing
|
||||
return;
|
||||
|
||||
var homePage = HomePage.get();
|
||||
var homePage = HomePage.get(window);
|
||||
var where = whereToOpenLink(aEvent, false, true);
|
||||
var urls;
|
||||
var notifyObservers;
|
||||
|
|
|
@ -24,10 +24,19 @@ XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
|
|||
Object.defineProperty(this, "BROWSER_NEW_TAB_URL", {
|
||||
enumerable: true,
|
||||
get() {
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(window) &&
|
||||
!PrivateBrowsingUtils.permanentPrivateBrowsing &&
|
||||
!aboutNewTabService.overridden) {
|
||||
return "about:privatebrowsing";
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
|
||||
if (!PrivateBrowsingUtils.permanentPrivateBrowsing &&
|
||||
!aboutNewTabService.overridden) {
|
||||
return "about:privatebrowsing";
|
||||
}
|
||||
// If the extension does not have private browsing permission,
|
||||
// use about:privatebrowsing.
|
||||
if (aboutNewTabService.newTabURL.startsWith("moz-extension")) {
|
||||
let url = new URL(aboutNewTabService.newTabURL);
|
||||
if (!WebExtensionPolicy.getByHostname(url.hostname).privateBrowsingAllowed) {
|
||||
return "about:privatebrowsing";
|
||||
}
|
||||
}
|
||||
}
|
||||
return aboutNewTabService.newTabURL;
|
||||
},
|
||||
|
|
|
@ -31,6 +31,8 @@ ChromeUtils.defineModuleGetter(this, "CustomizableUI",
|
|||
"resource:///modules/CustomizableUI.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
|
||||
"resource://gre/modules/ExtensionSettingsStore.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
let {
|
||||
makeWidgetId,
|
||||
|
@ -195,6 +197,12 @@ class ExtensionControlledPopup {
|
|||
extensionId = item && item.id;
|
||||
}
|
||||
|
||||
let win = targetWindow || this.topWindow;
|
||||
let isPrivate = PrivateBrowsingUtils.isWindowPrivate(win);
|
||||
if (isPrivate && extensionId && !WebExtensionPolicy.getByID(extensionId).privateBrowsingAllowed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The item should have an extension and the user shouldn't have confirmed
|
||||
// the change here, but just to be sure check that it is still controlled
|
||||
// and the user hasn't already confirmed the change.
|
||||
|
@ -203,7 +211,6 @@ class ExtensionControlledPopup {
|
|||
return;
|
||||
}
|
||||
|
||||
let win = targetWindow || this.topWindow;
|
||||
// If the window closes while waiting for focus, this might reject/throw,
|
||||
// and we should stop trying to show the popup.
|
||||
try {
|
||||
|
|
|
@ -191,8 +191,13 @@ this.windows = class extends ExtensionAPI {
|
|||
args.appendElement(mkstr(createData.url));
|
||||
}
|
||||
} else {
|
||||
let url = createData.incognito && !PrivateBrowsingUtils.permanentPrivateBrowsing ?
|
||||
"about:privatebrowsing" : HomePage.get().split("|", 1)[0];
|
||||
let url;
|
||||
if (createData.incognito) {
|
||||
url = PrivateBrowsingUtils.permanentPrivateBrowsing ?
|
||||
HomePage.getPrivate().split("|", 1)[0] : "about:privatebrowsing";
|
||||
} else {
|
||||
url = HomePage.get().split("|", 1)[0];
|
||||
}
|
||||
args.appendElement(mkstr(url));
|
||||
|
||||
if (url.startsWith("about:") &&
|
||||
|
|
|
@ -422,3 +422,119 @@ add_task(async function test_doorhanger_new_window() {
|
|||
|
||||
ok(!isConfirmed(ext1Id), "The confirmation is cleaned up on uninstall");
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_home_page_incognito_not_allowed() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
chrome_settings_overrides: {"homepage": "home.html"},
|
||||
name: "extension",
|
||||
},
|
||||
background() {
|
||||
browser.test.sendMessage("url", browser.runtime.getURL("home.html"));
|
||||
},
|
||||
files: {"home.html": "<h1>1</h1>"},
|
||||
useAddonManager: "temporary",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
let url = await extension.awaitMessage("url");
|
||||
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow({url});
|
||||
let win = OpenBrowserWindow();
|
||||
await windowOpenedPromise;
|
||||
let doc = win.document;
|
||||
let description = doc.getElementById("extension-homepage-notification-description");
|
||||
let panel = doc.getElementById("extension-notification-panel");
|
||||
await promisePopupShown(panel);
|
||||
|
||||
let popupnotification = description.closest("popupnotification");
|
||||
is(description.textContent,
|
||||
"An extension, extension, changed what you see when you open your homepage and new windows.Learn more",
|
||||
"The extension name is in the popup");
|
||||
is(popupnotification.hidden, false, "The expected popup notification is visible");
|
||||
|
||||
ok(win.gURLBar.value.endsWith("home.html"), "extension is in control");
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
|
||||
// Verify a private window does not open the extension page.
|
||||
windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
win.BrowserHome();
|
||||
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
|
||||
|
||||
is(win.gURLBar.value, "", "home page not used in private window");
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_home_page_incognito_not_allowed_bypass() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
name: "extension",
|
||||
},
|
||||
background() {
|
||||
browser.test.sendMessage("url", browser.runtime.getURL("home.html"));
|
||||
},
|
||||
files: {"home.html": "<h1>1</h1>"},
|
||||
useAddonManager: "temporary",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
let url = await extension.awaitMessage("url");
|
||||
|
||||
// Verify manually setting the pref to the extension page does not work.
|
||||
let changed = promisePrefChangeObserved(HOMEPAGE_URL_PREF);
|
||||
Services.prefs.setStringPref(HOMEPAGE_URL_PREF, url);
|
||||
await changed;
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
win.BrowserHome();
|
||||
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
|
||||
|
||||
is(win.gURLBar.value, "", "home page not used in private window");
|
||||
changed = promisePrefChangeObserved(HOMEPAGE_URL_PREF);
|
||||
Services.prefs.clearUserPref(HOMEPAGE_URL_PREF);
|
||||
await changed;
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_home_page_incognito_spanning() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
chrome_settings_overrides: {"homepage": "home.html"},
|
||||
name: "private extension",
|
||||
applications: {
|
||||
gecko: {id: "@spanning-home"},
|
||||
},
|
||||
},
|
||||
files: {"home.html": "<h1>1</h1>"},
|
||||
useAddonManager: "permanent",
|
||||
incognitoOverride: "spanning",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
let doc = win.document;
|
||||
let panel = doc.getElementById("extension-notification-panel");
|
||||
win.BrowserHome();
|
||||
await promisePopupShown(panel);
|
||||
|
||||
ok(win.gURLBar.value.endsWith("home.html"), "extension is in control in private window");
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
|
||||
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
|
||||
"resource://gre/modules/ExtensionSettingsStore.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
|
||||
"@mozilla.org/browser/aboutnewtab-service;1",
|
||||
"nsIAboutNewTabService");
|
||||
|
||||
const NEWTAB_URI_1 = "webext-newtab-1.html";
|
||||
|
||||
|
@ -522,3 +525,189 @@ add_task(async function dontTemporarilyShowAboutExtensionPath() {
|
|||
BrowserTestUtils.removeTab(tab);
|
||||
await extension.unload();
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_newtab_incognito_not_allowed() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let panel = getNewTabDoorhanger().closest("panel");
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
chrome_url_overrides: {"newtab": "newtab.html"},
|
||||
name: "extension",
|
||||
applications: {
|
||||
gecko: {id: "@not-allowed-newtab"},
|
||||
},
|
||||
},
|
||||
files: {
|
||||
"newtab.html": `
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8"/></head>
|
||||
<html>
|
||||
<body>
|
||||
<script src="newtab.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
|
||||
"newtab.js": function() {
|
||||
window.onload = () => {
|
||||
browser.test.sendMessage("from-newtab-page", window.location.href);
|
||||
};
|
||||
},
|
||||
},
|
||||
useAddonManager: "permanent",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
let popupShown = promisePopupShown(panel);
|
||||
BrowserOpenTab();
|
||||
await popupShown;
|
||||
|
||||
let url = await extension.awaitMessage("from-newtab-page");
|
||||
ok(url.endsWith("newtab.html"),
|
||||
"Newtab url is overridden by the extension.");
|
||||
|
||||
// This will show a confirmation doorhanger, make sure we don't leave it open.
|
||||
let popupHidden = promisePopupHidden(panel);
|
||||
panel.hidePopup();
|
||||
await popupHidden;
|
||||
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
||||
// Verify a private window does not open the extension page. We would
|
||||
// get an extra notification that we don't listen for if it gets loaded.
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
|
||||
let newTabOpened = waitForNewTab();
|
||||
win.BrowserOpenTab();
|
||||
await newTabOpened;
|
||||
|
||||
is(win.gURLBar.value, "", "newtab not used in private window");
|
||||
|
||||
// Verify setting the pref directly doesn't bypass permissions.
|
||||
let origUrl = aboutNewTabService.newTabURL;
|
||||
aboutNewTabService.newTabURL = url;
|
||||
newTabOpened = waitForNewTab();
|
||||
win.BrowserOpenTab();
|
||||
await newTabOpened;
|
||||
|
||||
is(win.gURLBar.value, "", "directly set newtab not used in private window");
|
||||
|
||||
aboutNewTabService.newTabURL = origUrl;
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_newtab_incognito_not_allowed_bypass() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
name: "extension",
|
||||
applications: {
|
||||
gecko: {id: "@not-allowed-newtab"},
|
||||
},
|
||||
},
|
||||
background() {
|
||||
browser.test.sendMessage("url", browser.runtime.getURL("newtab.html"));
|
||||
},
|
||||
files: {
|
||||
"newtab.html": `
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8"/></head>
|
||||
<html>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
},
|
||||
useAddonManager: "permanent",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
let url = await extension.awaitMessage("url");
|
||||
|
||||
// Verify setting the pref directly doesn't bypass permissions.
|
||||
let origUrl = aboutNewTabService.newTabURL;
|
||||
aboutNewTabService.newTabURL = url;
|
||||
|
||||
// Verify a private window does not open the extension page. We would
|
||||
// get an extra notification that we don't listen for if it gets loaded.
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
|
||||
let newTabOpened = waitForNewTab();
|
||||
win.BrowserOpenTab();
|
||||
await newTabOpened;
|
||||
|
||||
is(win.gURLBar.value, "", "directly set newtab not used in private window");
|
||||
|
||||
aboutNewTabService.newTabURL = origUrl;
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
||||
add_task(async function test_overriding_newtab_incognito_spanning() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
chrome_url_overrides: {"newtab": "newtab.html"},
|
||||
name: "extension",
|
||||
applications: {
|
||||
gecko: {id: "@spanning-newtab"},
|
||||
},
|
||||
},
|
||||
files: {
|
||||
"newtab.html": `
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8"/></head>
|
||||
<html>
|
||||
<body>
|
||||
<script src="newtab.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
|
||||
"newtab.js": function() {
|
||||
window.onload = () => {
|
||||
browser.test.sendMessage("from-newtab-page", window.location.href);
|
||||
};
|
||||
},
|
||||
},
|
||||
useAddonManager: "permanent",
|
||||
incognitoOverride: "spanning",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
await windowOpenedPromise;
|
||||
let panel = win.document.getElementById("extension-new-tab-notification").closest("panel");
|
||||
let popupShown = promisePopupShown(panel);
|
||||
win.BrowserOpenTab();
|
||||
await popupShown;
|
||||
|
||||
let url = await extension.awaitMessage("from-newtab-page");
|
||||
ok(url.endsWith("newtab.html"),
|
||||
"Newtab url is overridden by the extension.");
|
||||
|
||||
// This will show a confirmation doorhanger, make sure we don't leave it open.
|
||||
let popupHidden = promisePopupHidden(panel);
|
||||
panel.hidePopup();
|
||||
await popupHidden;
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
|
|
@ -207,7 +207,7 @@ function openBrowserWindow(cmdLine, triggeringPrincipal, urlOrUrlList, postData
|
|||
let args;
|
||||
if (!urlOrUrlList) {
|
||||
// Just pass in the defaultArgs directly. We'll use system principal on the other end.
|
||||
args = [gBrowserContentHandler.defaultArgs];
|
||||
args = [gBrowserContentHandler.getDefaultArgs(forcePrivate)];
|
||||
} else {
|
||||
let pService = Cc["@mozilla.org/toolkit/profile-service;1"].
|
||||
getService(Ci.nsIToolkitProfileService);
|
||||
|
@ -522,7 +522,7 @@ nsBrowserContentHandler.prototype = {
|
|||
|
||||
/* nsIBrowserHandler */
|
||||
|
||||
get defaultArgs() {
|
||||
getDefaultArgs(forcePrivate = false) {
|
||||
var prefb = Services.prefs;
|
||||
|
||||
if (!gFirstWindow) {
|
||||
|
@ -607,7 +607,7 @@ nsBrowserContentHandler.prototype = {
|
|||
try {
|
||||
var choice = prefb.getIntPref("browser.startup.page");
|
||||
if (choice == 1 || choice == 3)
|
||||
startPage = HomePage.get();
|
||||
startPage = forcePrivate ? HomePage.getPrivate() : HomePage.get();
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
@ -625,6 +625,10 @@ nsBrowserContentHandler.prototype = {
|
|||
return overridePage || startPage || "about:blank";
|
||||
},
|
||||
|
||||
get defaultArgs() {
|
||||
return this.getDefaultArgs(PrivateBrowsingUtils.permanentPrivateBrowsing);
|
||||
},
|
||||
|
||||
mFeatures: null,
|
||||
|
||||
getFeatures: function bch_features(cmdLine) {
|
||||
|
|
|
@ -3341,7 +3341,7 @@ var SessionStoreInternal = {
|
|||
let tabbrowser = aWindow.gBrowser;
|
||||
let startupPref = this._prefBranch.getIntPref("startup.page");
|
||||
if (startupPref == 1)
|
||||
homePages = homePages.concat(HomePage.get().split("|"));
|
||||
homePages = homePages.concat(HomePage.get(aWindow).split("|"));
|
||||
|
||||
for (let i = tabbrowser._numPinnedTabs; i < tabbrowser.tabs.length; i++) {
|
||||
let tab = tabbrowser.tabs[i];
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
var EXPORTED_SYMBOLS = ["HomePage"];
|
||||
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
const kPrefName = "browser.startup.homepage";
|
||||
|
||||
|
@ -43,7 +45,11 @@ function getHomepagePref(useDefault) {
|
|||
}
|
||||
|
||||
let HomePage = {
|
||||
get() {
|
||||
get(aWindow) {
|
||||
if (PrivateBrowsingUtils.permanentPrivateBrowsing ||
|
||||
(aWindow && PrivateBrowsingUtils.isWindowPrivate(aWindow))) {
|
||||
return this.getPrivate();
|
||||
}
|
||||
return getHomepagePref();
|
||||
},
|
||||
|
||||
|
@ -51,6 +57,24 @@ let HomePage = {
|
|||
return getHomepagePref(true);
|
||||
},
|
||||
|
||||
getPrivate() {
|
||||
let homePages = getHomepagePref();
|
||||
if (!homePages.includes("moz-extension")) {
|
||||
return homePages;
|
||||
}
|
||||
// Verify private access and build a new list.
|
||||
let privateHomePages = homePages.split("|").filter(page => {
|
||||
let url = new URL(page);
|
||||
if (url.protocol !== "moz-extension:") {
|
||||
return true;
|
||||
}
|
||||
let policy = WebExtensionPolicy.getByHostname(url.hostname);
|
||||
return policy && policy.privateBrowsingAllowed;
|
||||
});
|
||||
// Extensions may not be ready on startup, fallback to defaults.
|
||||
return privateHomePages.join("|") || this.getDefault();
|
||||
},
|
||||
|
||||
get overridden() {
|
||||
return Services.prefs.prefHasUserValue(kPrefName);
|
||||
},
|
||||
|
|
Загрузка…
Ссылка в новой задаче