Bug 1535049 - If the homepage is referenced in the ignore list, reset it soon after startup or when the ignore list is updated. r=daleharvey

Differential Revision: https://phabricator.services.mozilla.com/D40392

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Mark Banner 2019-08-05 21:52:43 +00:00
parent 1c00bcc8e8
commit a8f61c87b4
3 changed files with 198 additions and 15 deletions

View File

@ -2035,6 +2035,7 @@ var gBrowserInit = {
BrowserSearch.delayedStartupInit();
AutoShowBookmarksToolbar.init();
gProtectionsHandler.init();
HomePage.init().catch(Cu.reportError);
let safeMode = document.getElementById("helpSafeMode");
if (Services.appinfo.inSafeMode) {

View File

@ -2,22 +2,25 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* globals ChromeUtils, Services */
/* exported HomePage */
"use strict";
var EXPORTED_SYMBOLS = ["HomePage"];
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.defineModuleGetter(
this,
"PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm"
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
XPCOMUtils.defineLazyModuleGetters(this, {
IgnoreLists: "resource://gre/modules/IgnoreLists.jsm",
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
Services: "resource://gre/modules/Services.jsm",
});
const kPrefName = "browser.startup.homepage";
const kDefaultHomePage = "about:home";
const kExtensionControllerPref =
"browser.startup.homepage_override.extensionControlled";
const kHomePageIgnoreListId = "homepage-urls";
function getHomepagePref(useDefault) {
let homePage;
@ -47,7 +50,55 @@ function getHomepagePref(useDefault) {
return homePage;
}
/**
* HomePage provides tools to keep try of the current homepage, and the
* applications's default homepage. It includes tools to insure that certain
* urls are ignored. As a result, all set/get requests for the homepage
* preferences should be routed through here.
*/
let HomePage = {
// This is an array of strings that should be matched against URLs to see
// if they should be ignored or not.
_ignoreList: [],
// A promise that is set when initialization starts and resolved when it
// completes.
_initializationPromise: null,
/**
* Used to initialise the ignore lists. This may be called later than
* the first call to get or set, which may cause a used to get an ignored
* homepage, but this is deemed acceptable, as we'll correct it once
* initialised.
*/
async init() {
if (this._initializationPromise) {
await this._initializationPromise;
return;
}
// Now we have the values, listen for future updates.
this._ignoreListListener = this._handleIgnoreListUpdated.bind(this);
this._initializationPromise = IgnoreLists.getAndSubscribe(
this._ignoreListListener
);
const current = await this._initializationPromise;
await this._handleIgnoreListUpdated({ data: { current } });
},
/**
* Gets the homepage for the given window.
*
* @param {DOMWindow} [aWindow]
* The window associated with the get, used to check for private browsing
* mode. If not supplied, normal mode is assumed.
* @returns {string}
* Returns the home page value, this could be a single url, or a `|`
* separated list of URLs.
*/
get(aWindow) {
let homePages = getHomepagePref();
if (
@ -57,7 +108,7 @@ let HomePage = {
// If an extension controls the setting and does not have private
// browsing permission, use the default setting.
let extensionControlled = Services.prefs.getBoolPref(
"browser.startup.homepage_override.extensionControlled",
kExtensionControllerPref,
false
);
let privateAllowed = Services.prefs.getBoolPref(
@ -77,31 +128,88 @@ let HomePage = {
return homePages;
},
/**
* @returns {string}
* Returns the application default homepage.
*/
getDefault() {
return getHomepagePref(true);
},
/**
* @returns {boolean}
* Returns true if the homepage has been changed.
*/
get overridden() {
return Services.prefs.prefHasUserValue(kPrefName);
},
/**
* @returns {boolean}
* Returns true if the homepage preference is locked.
*/
get locked() {
return Services.prefs.prefIsLocked(kPrefName);
},
/**
* @returns {boolean}
* Returns true if the current homepage is the application default.
*/
get isDefault() {
return HomePage.get() === kDefaultHomePage;
},
/**
* Sets the homepage preference to a new page.
*
* @param {string} value
* The new value to set the preference to. This could be a single url, or a
* `|` separated list of URLs.
*/
set(value) {
Services.prefs.setStringPref(kPrefName, value);
},
/**
* Clears the homepage preference if it is not the default. Note that for
* policy/locking use, the default homepage might not be about:home after this.
*/
clear() {
Services.prefs.clearUserPref(kPrefName);
},
/**
* Resets the homepage preference to be about:home.
*/
reset() {
Services.prefs.setStringPref(kPrefName, kDefaultHomePage);
},
/**
* Handles updates of the ignore list, checking the existing preference and
* correcting it as necessary.
*
* @param {Object} eventData
* The event data as received from RemoteSettings.
*/
_handleIgnoreListUpdated({ data: { current } }) {
for (const entry of current) {
if (entry.id == kHomePageIgnoreListId) {
this._ignoreList = [...entry.matches];
}
}
// Only check if we're overridden as we assume the default value is fine,
// or won't be changeable (e.g. enterprise policy).
if (this.overridden) {
let homePages = getHomepagePref().toLowerCase();
if (
this._ignoreList.some(code => homePages.includes(code.toLowerCase()))
) {
this.clear();
Services.prefs.clearUserPref(kExtensionControllerPref);
}
}
},
};

View File

@ -2,13 +2,41 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/* globals ChromeUtils, Services, Cc, Ci, HomePage, Assert, add_task */
"use strict";
const { HomePage } = ChromeUtils.import("resource:///modules/HomePage.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
add_task(function testHomePage() {
XPCOMUtils.defineLazyModuleGetters(this, {
HomePage: "resource:///modules/HomePage.jsm",
Services: "resource://gre/modules/Services.jsm",
RemoteSettings: "resource://services-settings/remote-settings.js",
// RemoteSettingsClient: "resource://services-settings/RemoteSettingsClient.jsm",
sinon: "resource://testing-common/Sinon.jsm",
});
const HOMEPAGE_IGNORELIST = "homepage-urls";
/**
* Provides a basic set of remote settings for use in tests.
*/
async function setupRemoteSettings() {
const settings = await RemoteSettings("hijack-blocklists");
sinon.stub(settings, "get").returns([
{
id: HOMEPAGE_IGNORELIST,
matches: ["ignore=me"],
_status: "synced",
},
]);
}
add_task(async function setup() {
await setupRemoteSettings();
});
add_task(function test_HomePage() {
Assert.ok(
!HomePage.overridden,
"Homepage should not be overriden by default."
@ -34,7 +62,7 @@ add_task(function testHomePage() {
);
});
add_task(function readLocalizedHomepage() {
add_task(function test_readLocalizedHomepage() {
let newvalue = "data:text/plain,browser.startup.homepage%3Dabout%3Alocalized";
let complexvalue = Cc["@mozilla.org/pref-localizedstring;1"].createInstance(
Ci.nsIPrefLocalizedString
@ -51,7 +79,7 @@ add_task(function readLocalizedHomepage() {
Assert.equal(HomePage.get(), "about:localized", "Get value from bundle");
});
add_task(function recoverEmptyHomepage() {
add_task(function test_recoverEmptyHomepage() {
Assert.ok(
!HomePage.overridden,
"Homepage should not be overriden by default."
@ -61,3 +89,49 @@ add_task(function recoverEmptyHomepage() {
Assert.equal(HomePage.get(), HomePage.getDefault(), "Recover is default");
Assert.ok(!HomePage.overridden, "Recover should have set default");
});
add_task(async function test_initWithIgnoredPageCausesReset() {
HomePage.set("http://bad/?ignore=me");
Assert.ok(HomePage.overridden, "Should have overriden the homepage");
await HomePage.init();
Assert.ok(
!HomePage.overridden,
"Should no longer be overriding the homepage."
);
Assert.equal(
HomePage.get(),
HomePage.getDefault(),
"Should have reset to the default preference"
);
});
add_task(async function test_updateIgnoreListCausesReset() {
HomePage.set("http://bad/?new=ignore");
Assert.ok(HomePage.overridden, "Should have overriden the homepage");
// Simulate an ignore list update.
await RemoteSettings("hijack-blocklists").emit("sync", {
data: {
current: [
{
id: HOMEPAGE_IGNORELIST,
schema: 1553857697843,
last_modified: 1553859483588,
matches: ["ignore=me", "new=ignore"],
},
],
},
});
Assert.ok(
!HomePage.overridden,
"Should no longer be overriding the homepage."
);
Assert.equal(
HomePage.get(),
HomePage.getDefault(),
"Should have reset to the default preference"
);
});