Bug 749477 - Stop abusing about:home localStorage from browser code.

r=fryn
This commit is contained in:
Marco Bonardo 2012-09-12 12:02:03 +02:00
parent 52db8cd7aa
commit 7bf4cedb77
6 changed files with 109 additions and 136 deletions

View File

@ -112,28 +112,38 @@ const DEFAULT_SNIPPETS_URLS = [
const SNIPPETS_UPDATE_INTERVAL_MS = 86400000; // 1 Day.
let gSearchEngine;
document.addEventListener("DOMContentLoaded", function init() {
setupSearchEngine();
loadSnippets();
let gObserver = new MutationObserver(function (mutations) {
for (let mutation of mutations) {
if (mutation.attributeName == "searchEngineURL") {
gObserver.disconnect();
setupSearchEngine();
loadSnippets();
return;
}
}
});
window.addEventListener("load", function () {
// Delay search engine setup, cause browser.js::BrowserOnAboutPageLoad runs
// later and may use asynchronous getters.
window.gObserver.observe(document.documentElement, { attributes: true });
fitToWidth();
});
window.addEventListener("load", fitToWidth);
window.addEventListener("resize", fitToWidth);
function onSearchSubmit(aEvent)
{
let searchTerms = document.getElementById("searchText").value;
if (gSearchEngine && searchTerms.length > 0) {
let searchURL = document.documentElement.getAttribute("searchEngineURL");
if (searchURL && searchTerms.length > 0) {
const SEARCH_TOKENS = {
"_searchTerms_": encodeURIComponent(searchTerms)
}
let url = gSearchEngine.searchUrl;
for (let key in SEARCH_TOKENS) {
url = url.replace(key, SEARCH_TOKENS[key]);
searchURL = searchURL.replace(key, SEARCH_TOKENS[key]);
}
window.location.href = url;
window.location.href = searchURL;
}
aEvent.preventDefault();
@ -142,27 +152,24 @@ function onSearchSubmit(aEvent)
function setupSearchEngine()
{
gSearchEngine = JSON.parse(localStorage["search-engine"]);
if (!gSearchEngine)
let searchEngineName = document.documentElement.getAttribute("searchEngineName");
let searchEngineInfo = SEARCH_ENGINES[searchEngineName];
if (!searchEngineInfo) {
return;
// Look for extended information, like logo and links.
let searchEngineInfo = SEARCH_ENGINES[gSearchEngine.name];
if (searchEngineInfo) {
for (let prop in searchEngineInfo)
gSearchEngine[prop] = searchEngineInfo[prop];
}
// Enqueue additional params if required by the engine definition.
if (gSearchEngine.params)
gSearchEngine.searchUrl += "&" + gSearchEngine.params;
if (searchEngineInfo.params) {
let searchEngineURL = document.documentElement.getAttribute("searchEngineURL");
searchEngineURL += "&" + searchEngineInfo.params;
document.documentElement.setAttribute("searchEngineURL", searchEngineURL);
}
// Add search engine logo.
if (gSearchEngine.image) {
if (searchEngineInfo.image) {
let logoElt = document.getElementById("searchEngineLogo");
logoElt.src = gSearchEngine.image;
logoElt.alt = gSearchEngine.name;
logoElt.src = searchEngineInfo.image;
logoElt.alt = searchEngineInfo.name;
}
// The "autofocus" attribute doesn't focus the form element
@ -180,7 +187,7 @@ function loadSnippets()
{
// Check last snippets update.
let lastUpdate = localStorage["snippets-last-update"];
let updateURL = localStorage["snippets-update-url"];
let updateURL = document.documentElement.getAttribute("snippetsURL");
if (updateURL && (!lastUpdate ||
Date.now() - lastUpdate > SNIPPETS_UPDATE_INTERVAL_MS)) {
// Try to update from network.

View File

@ -90,6 +90,9 @@ __defineSetter__("PluralForm", function (val) {
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
"resource://gre/modules/TelemetryStopwatch.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AboutHomeUtils",
"resource:///modules/AboutHomeUtils.jsm");
#ifdef MOZ_SERVICES_SYNC
XPCOMUtils.defineLazyGetter(this, "Weave", function() {
let tmp = {};
@ -2495,10 +2498,19 @@ function BrowserOnAboutPageLoad(document) {
// the hidden attribute set on the apps button in aboutHome.xhtml
if (getBoolPref("browser.aboutHome.apps", false))
document.getElementById("apps").removeAttribute("hidden");
let ss = Components.classes["@mozilla.org/browser/sessionstore;1"].
getService(Components.interfaces.nsISessionStore);
if (!ss.canRestoreLastSession)
document.getElementById("launcher").removeAttribute("session");
// Inject search engine and snippets URL.
let docElt = document.documentElement;
docElt.setAttribute("snippetsURL", AboutHomeUtils.snippetsURL);
docElt.setAttribute("searchEngineName",
AboutHomeUtils.defaultSearchEngine.name);
docElt.setAttribute("searchEngineURL",
AboutHomeUtils.defaultSearchEngine.searchURL);
}
}

View File

@ -15,64 +15,17 @@ registerCleanupFunction(function() {
let gTests = [
{
desc: "Check that rejecting cookies does not prevent page from working",
desc: "Check that clearing cookies does not clear storage",
setup: function ()
{
Services.prefs.setIntPref("network.cookies.cookieBehavior", 2);
Cc["@mozilla.org/dom/storagemanager;1"]
.getService(Ci.nsIObserver)
.observe(null, "cookie-changed", "cleared");
},
run: function ()
{
let storage = getStorage();
isnot(storage.getItem("search-engine"), null);
try {
Services.prefs.clearUserPref("network.cookies.cookieBehavior");
} catch (ex) {}
executeSoon(runNextTest);
}
},
{
desc: "Check that asking for cookies does not prevent page from working",
setup: function ()
{
Services.prefs.setIntPref("network.cookie.lifetimePolicy", 1);
},
run: function ()
{
let storage = getStorage();
isnot(storage.getItem("search-engine"), null);
try {
Services.prefs.clearUserPref("network.cookie.lifetimePolicy");
} catch (ex) {}
executeSoon(runNextTest);
}
},
{
desc: "Check that clearing cookies does not prevent page from working",
setup: function ()
{
Components.classes["@mozilla.org/dom/storagemanager;1"].
getService(Components.interfaces.nsIObserver).
observe(null, "cookie-changed", "cleared");
},
run: function ()
{
let storage = getStorage();
isnot(storage.getItem("search-engine"), null);
executeSoon(runNextTest);
}
},
{
desc: "Check normal status is working",
setup: function ()
{
},
run: function ()
{
let storage = getStorage();
isnot(storage.getItem("search-engine"), null);
isnot(storage.getItem("snippets-last-update"), null);
executeSoon(runNextTest);
}
},
@ -120,14 +73,6 @@ function test()
{
waitForExplicitFinish();
// browser-chrome test harness inits browser specifying an hardcoded page
// and this causes nsIBrowserHandler.defaultArgs to not be evaluated since
// there is a predefined argument.
// About:home localStorage is populated with overridden homepage, that is
// setup in the defaultArgs getter.
// Thus to populate about:home we need to get defaultArgs manually.
Cc["@mozilla.org/browser/clh;1"].getService(Ci.nsIBrowserHandler).defaultArgs;
// Ensure that by default we don't try to check for remote snippets since that
// could be tricky due to network bustages or slowness.
let storage = getStorage();
@ -148,10 +93,20 @@ function runNextTest()
info(test.desc);
test.setup();
let tab = gBrowser.selectedTab = gBrowser.addTab("about:home");
tab.linkedBrowser.addEventListener("load", function (event) {
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
// Some part of the page is populated on load, so enqueue on it.
executeSoon(test.run);
tab.linkedBrowser.addEventListener("load", function load(event) {
tab.linkedBrowser.removeEventListener("load", load, true);
let observer = new MutationObserver(function (mutations) {
for (let mutation of mutations) {
if (mutation.attributeName == "searchEngineURL") {
observer.disconnect();
executeSoon(test.run);
return;
}
}
});
let docElt = tab.linkedBrowser.contentDocument.documentElement;
observer.observe(docElt, { attributes: true });
}, true);
}
else {

View File

@ -577,10 +577,6 @@ nsBrowserContentHandler.prototype = {
} catch (ex) {}
let override = needHomepageOverride(prefb);
if (override != OVERRIDE_NONE) {
// Setup the default search engine to about:home page.
AboutHomeUtils.loadDefaultSearchEngine();
AboutHomeUtils.loadSnippetsURL();
switch (override) {
case OVERRIDE_NEW_PROFILE:
// New profile.
@ -603,13 +599,6 @@ nsBrowserContentHandler.prototype = {
break;
}
}
else {
// No need to override homepage, but update snippets url if the pref has
// been manually changed.
if (Services.prefs.prefHasUserValue(AboutHomeUtils.SNIPPETS_URL_PREF)) {
AboutHomeUtils.loadSnippetsURL();
}
}
} catch (ex) {}
// formatURLPref might return "about:blank" if getting the pref fails
@ -835,41 +824,5 @@ nsDefaultCommandLineHandler.prototype = {
helpInfo : "",
};
let AboutHomeUtils = {
SNIPPETS_URL_PREF: "browser.aboutHomeSnippets.updateUrl",
get _storage() {
let aboutHomeURI = Services.io.newURI("moz-safe-about:home", null, null);
let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"].
getService(Components.interfaces.nsIScriptSecurityManager).
getNoAppCodebasePrincipal(aboutHomeURI);
let dsm = Components.classes["@mozilla.org/dom/storagemanager;1"].
getService(Components.interfaces.nsIDOMStorageManager);
return dsm.getLocalStorageForPrincipal(principal, "");
},
loadDefaultSearchEngine: function AHU_loadDefaultSearchEngine()
{
let defaultEngine = Services.search.originalDefaultEngine;
let submission = defaultEngine.getSubmission("_searchTerms_");
if (submission.postData)
throw new Error("Home page does not support POST search engines.");
let engine = {
name: defaultEngine.name
, searchUrl: submission.uri.spec
}
this._storage.setItem("search-engine", JSON.stringify(engine));
},
loadSnippetsURL: function AHU_loadSnippetsURL()
{
const STARTPAGE_VERSION = 3;
let updateURL = Services.prefs
.getCharPref(this.SNIPPETS_URL_PREF)
.replace("%STARTPAGE_VERSION%", STARTPAGE_VERSION);
updateURL = Services.urlFormatter.formatURL(updateURL);
this._storage.setItem("snippets-update-url", updateURL);
},
};
var components = [nsBrowserContentHandler, nsDefaultCommandLineHandler];
var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);

View File

@ -0,0 +1,45 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
"use strict";
const EXPORTED_SYMBOLS = [ "AboutHomeUtils" ];
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
// Url to fetch snippets, in the urlFormatter service format.
const SNIPPETS_URL_PREF = "browser.aboutHomeSnippets.updateUrl";
// Should be bumped up if the snippets content format changes.
const STARTPAGE_VERSION = 3;
let AboutHomeUtils = new Object();
/**
* Returns an object containing the name and searchURL of the original default
* search engine.
*/
XPCOMUtils.defineLazyGetter(AboutHomeUtils, "defaultSearchEngine", function() {
let defaultEngine = Services.search.originalDefaultEngine;
let submission = defaultEngine.getSubmission("_searchTerms_");
if (submission.postData) {
throw new Error("Home page does not support POST search engines.");
}
return Object.freeze({
name: defaultEngine.name,
searchURL: submission.uri.spec
});
});
/**
* Returns the URL to fetch snippets from, in the urlFormatter service format.
*/
XPCOMUtils.defineLazyGetter(AboutHomeUtils, "snippetsURL", function() {
let updateURL = Services.prefs
.getCharPref(SNIPPETS_URL_PREF)
.replace("%STARTPAGE_VERSION%", STARTPAGE_VERSION);
return Services.urlFormatter.formatURL(updateURL);
});

View File

@ -14,6 +14,7 @@ include $(topsrcdir)/config/config.mk
TEST_DIRS += test
EXTRA_JS_MODULES = \
AboutHomeUtils.jsm \
BrowserNewTabPreloader.jsm \
openLocationLastURL.jsm \
NetworkPrioritizer.jsm \