Remove about:home snippets.

This commit is contained in:
wolfbeast 2018-04-06 14:07:27 +02:00 committed by Roy Tam
commit 5934916122
6 changed files with 5 additions and 380 deletions

View file

@ -229,11 +229,6 @@ pref("browser.slowStartup.notificationDisabled", false);
pref("browser.slowStartup.timeThreshold", 40000);
pref("browser.slowStartup.maxSamples", 5);
// This url, if changed, MUST continue to point to an https url. Pulling arbitrary content to inject into
// this page over http opens us up to a man-in-the-middle attack that we'd rather not face. If you are a downstream
// repackager of this code using an alternate snippet url, please keep your users safe
pref("browser.aboutHomeSnippets.updateUrl", "https://snippets.cdn.mozilla.net/%STARTPAGE_VERSION%/%NAME%/%VERSION%/%APPBUILDID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/");
pref("browser.enable_automatic_image_resizing", true);
pref("browser.casting.enabled", false);
pref("browser.chrome.site_icons", true);

View file

@ -49,8 +49,7 @@ a {
background-repeat: no-repeat;
}
#searchIconAndTextContainer,
#snippets {
#searchIconAndTextContainer {
width: 470px;
}
@ -168,48 +167,6 @@ a {
transition-duration: 0ms;
}
#defaultSnippet1,
#defaultSnippet2,
#rightsSnippet {
display: block;
min-height: 38px;
background: 0 center no-repeat;
padding: 6px 0;
padding-inline-start: 49px;
}
#rightsSnippet[hidden] {
display: none;
}
#defaultSnippet1:dir(rtl),
#defaultSnippet2:dir(rtl),
#rightsSnippet:dir(rtl) {
background-position: right 0 center;
}
#defaultSnippet1 {
background-image: url("chrome://browser/content/abouthome/snippet1.png");
}
#defaultSnippet2 {
background-image: url("chrome://browser/content/abouthome/snippet2.png");
}
#snippets {
display: inline-block;
text-align: start;
margin: 12px 0;
color: #3c3c3c;
font-size: 75%;
/* 12px is the computed font size, 15px the computed line height of the snippets
with Segoe UI on a default Windows 7 setup. The 15/12 multiplier approximately
converts em from units of font-size to units of line-height. The goal is to
preset the height of a three-line snippet to avoid visual moving/flickering as
the snippets load. */
min-height: calc(15/12 * 3em);
}
#launcher {
display: -moz-box;
-moz-box-align: center;
@ -385,20 +342,6 @@ body[narrow] #restorePreviousSession::before {
background-image: url("chrome://branding/content/about-logo@2x.png");
}
#defaultSnippet1,
#defaultSnippet2,
#rightsSnippet {
background-size: 40px;
}
#defaultSnippet1 {
background-image: url("chrome://browser/content/abouthome/snippet1@2x.png");
}
#defaultSnippet2 {
background-image: url("chrome://browser/content/abouthome/snippet2@2x.png");
}
.launchButton::before,
#aboutMozilla::before {
transform: scale(.5);

View file

@ -6,23 +6,10 @@
/* import-globals-from ../contentSearchUI.js */
// The process of adding a new default snippet involves:
// * add a new entity to aboutHome.dtd
// * add a <span/> for it in aboutHome.xhtml
// * add an entry here in the proper ordering (based on spans)
// The <a/> part of the snippet will be linked to the corresponding url.
const DEFAULT_SNIPPETS_URLS = [
"https://www.mozilla.org/firefox/features/?utm_source=snippet&utm_medium=snippet&utm_campaign=default+feature+snippet"
, "https://addons.mozilla.org/firefox/?utm_source=snippet&utm_medium=snippet&utm_campaign=addons"
];
const SNIPPETS_UPDATE_INTERVAL_MS = 14400000; // 4 hours.
// IndexedDB storage constants.
const DATABASE_NAME = "abouthome";
const DATABASE_VERSION = 1;
const DATABASE_STORAGE = "persistent";
const SNIPPETS_OBJECTSTORE_NAME = "snippets";
var searchText;
// This global tracks if the page has been set up before, to prevent double inits
@ -33,13 +20,6 @@ var gObserver = new MutationObserver(function (mutations) {
if (mutation.attributeName == "session") {
fitToWidth();
}
if (mutation.attributeName == "snippetsVersion") {
if (!gInitialized) {
ensureSnippetsMapThen(loadSnippets);
gInitialized = true;
}
return;
}
}
});
@ -90,126 +70,6 @@ window.addEventListener("keypress", ev => {
searchText.value += ev.key;
});
// This object has the same interface as Map and is used to store and retrieve
// the snippets data. It is lazily initialized by ensureSnippetsMapThen(), so
// be sure its callback returned before trying to use it.
var gSnippetsMap;
var gSnippetsMapCallbacks = [];
/**
* Ensure the snippets map is properly initialized.
*
* @param aCallback
* Invoked once the map has been initialized, gets the map as argument.
* @note Snippets should never directly manage the underlying storage, since
* it may change inadvertently.
*/
function ensureSnippetsMapThen(aCallback)
{
if (gSnippetsMap) {
aCallback(gSnippetsMap);
return;
}
// Handle multiple requests during the async initialization.
gSnippetsMapCallbacks.push(aCallback);
if (gSnippetsMapCallbacks.length > 1) {
// We are already updating, the callbacks will be invoked when done.
return;
}
let invokeCallbacks = function () {
if (!gSnippetsMap) {
gSnippetsMap = Object.freeze(new Map());
}
for (let callback of gSnippetsMapCallbacks) {
callback(gSnippetsMap);
}
gSnippetsMapCallbacks.length = 0;
}
let openRequest = indexedDB.open(DATABASE_NAME, {version: DATABASE_VERSION,
storage: DATABASE_STORAGE});
openRequest.onerror = function (event) {
// Try to delete the old database so that we can start this process over
// next time.
indexedDB.deleteDatabase(DATABASE_NAME);
invokeCallbacks();
};
openRequest.onupgradeneeded = function (event) {
let db = event.target.result;
if (!db.objectStoreNames.contains(SNIPPETS_OBJECTSTORE_NAME)) {
db.createObjectStore(SNIPPETS_OBJECTSTORE_NAME);
}
}
openRequest.onsuccess = function (event) {
let db = event.target.result;
db.onerror = function (event) {
invokeCallbacks();
}
db.onversionchange = function (event) {
event.target.close();
invokeCallbacks();
}
let cache = new Map();
let cursorRequest;
try {
cursorRequest = db.transaction(SNIPPETS_OBJECTSTORE_NAME)
.objectStore(SNIPPETS_OBJECTSTORE_NAME).openCursor();
} catch (ex) {
console.error(ex);
invokeCallbacks();
return;
}
cursorRequest.onerror = function (event) {
invokeCallbacks();
}
cursorRequest.onsuccess = function(event) {
let cursor = event.target.result;
// Populate the cache from the persistent storage.
if (cursor) {
cache.set(cursor.key, cursor.value);
cursor.continue();
return;
}
// The cache has been filled up, create the snippets map.
gSnippetsMap = Object.freeze({
get: (aKey) => cache.get(aKey),
set: function (aKey, aValue) {
db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite")
.objectStore(SNIPPETS_OBJECTSTORE_NAME).put(aValue, aKey);
return cache.set(aKey, aValue);
},
has: (aKey) => cache.has(aKey),
delete: function (aKey) {
db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite")
.objectStore(SNIPPETS_OBJECTSTORE_NAME).delete(aKey);
return cache.delete(aKey);
},
clear: function () {
db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite")
.objectStore(SNIPPETS_OBJECTSTORE_NAME).clear();
return cache.clear();
},
get size() { return cache.size; },
});
setTimeout(invokeCallbacks, 0);
}
}
}
function onSearchSubmit(aEvent)
{
gContentSearchController.search(aEvent);
@ -246,146 +106,6 @@ function setupSearch()
*/
function loadCompleted()
{
var event = new CustomEvent("AboutHomeLoadSnippetsCompleted", {bubbles:true});
document.dispatchEvent(event);
}
/**
* Update the local snippets from the remote storage, then show them through
* showSnippets.
*/
function loadSnippets()
{
if (!gSnippetsMap)
throw new Error("Snippets map has not properly been initialized");
// Allow tests to modify the snippets map before using it.
var event = new CustomEvent("AboutHomeLoadSnippets", {bubbles:true});
document.dispatchEvent(event);
// Check cached snippets version.
let cachedVersion = gSnippetsMap.get("snippets-cached-version") || 0;
let currentVersion = document.documentElement.getAttribute("snippetsVersion");
if (cachedVersion < currentVersion) {
// The cached snippets are old and unsupported, restart from scratch.
gSnippetsMap.clear();
}
// Check last snippets update.
let lastUpdate = gSnippetsMap.get("snippets-last-update");
let updateURL = document.documentElement.getAttribute("snippetsURL");
let shouldUpdate = !lastUpdate ||
Date.now() - lastUpdate > SNIPPETS_UPDATE_INTERVAL_MS;
if (updateURL && shouldUpdate) {
// Try to update from network.
let xhr = new XMLHttpRequest();
xhr.timeout = 5000;
// Even if fetching should fail we don't want to spam the server, thus
// set the last update time regardless its results. Will retry tomorrow.
gSnippetsMap.set("snippets-last-update", Date.now());
xhr.onloadend = function (event) {
if (xhr.status == 200) {
gSnippetsMap.set("snippets", xhr.responseText);
gSnippetsMap.set("snippets-cached-version", currentVersion);
}
showSnippets();
loadCompleted();
};
try {
xhr.open("GET", updateURL, true);
xhr.send(null);
} catch (ex) {
showSnippets();
loadCompleted();
return;
}
} else {
showSnippets();
loadCompleted();
}
}
/**
* Shows locally cached remote snippets, or default ones when not available.
*
* @note: snippets should never invoke showSnippets(), or they may cause
* a "too much recursion" exception.
*/
var _snippetsShown = false;
function showSnippets()
{
let snippetsElt = document.getElementById("snippets");
// Show about:rights notification, if needed.
let showRights = document.documentElement.getAttribute("showKnowYourRights");
if (showRights) {
let rightsElt = document.getElementById("rightsSnippet");
let anchor = rightsElt.getElementsByTagName("a")[0];
anchor.href = "about:rights";
snippetsElt.appendChild(rightsElt);
rightsElt.removeAttribute("hidden");
return;
}
if (!gSnippetsMap)
throw new Error("Snippets map has not properly been initialized");
if (_snippetsShown) {
// There's something wrong with the remote snippets, just in case fall back
// to the default snippets.
showDefaultSnippets();
throw new Error("showSnippets should never be invoked multiple times");
}
_snippetsShown = true;
let snippets = gSnippetsMap.get("snippets");
// If there are remotely fetched snippets, try to to show them.
if (snippets) {
// Injecting snippets can throw if they're invalid XML.
try {
snippetsElt.innerHTML = snippets;
// Scripts injected by innerHTML are inactive, so we have to relocate them
// through DOM manipulation to activate their contents.
Array.forEach(snippetsElt.getElementsByTagName("script"), function(elt) {
let relocatedScript = document.createElement("script");
relocatedScript.type = "text/javascript;version=1.8";
relocatedScript.text = elt.text;
elt.parentNode.replaceChild(relocatedScript, elt);
});
return;
} catch (ex) {
// Bad content, continue to show default snippets.
}
}
showDefaultSnippets();
}
/**
* Clear snippets element contents and show default snippets.
*/
function showDefaultSnippets()
{
// Clear eventual contents...
let snippetsElt = document.getElementById("snippets");
snippetsElt.innerHTML = "";
// ...then show default snippets.
let defaultSnippetsElt = document.getElementById("defaultSnippets");
let entries = defaultSnippetsElt.querySelectorAll("span");
// Choose a random snippet. Assume there is always at least one.
let randIndex = Math.floor(Math.random() * entries.length);
let entry = entries[randIndex];
// Inject url in the eventual link.
if (DEFAULT_SNIPPETS_URLS[randIndex]) {
let links = entry.getElementsByTagName("a");
// Default snippets can have only one link, otherwise something is messed
// up in the translation.
if (links.length == 1) {
links[0].href = DEFAULT_SNIPPETS_URLS[randIndex];
}
}
// Move the default snippet to the snippets element.
snippetsElt.appendChild(entry);
}
function fitToWidth() {

View file

@ -46,15 +46,6 @@
<input id="searchSubmit" type="button" onclick="onSearchSubmit(event)"
title="&contentSearchSubmit.tooltip;"/>
</div>
<div id="snippetContainer">
<div id="defaultSnippets" hidden="true">
<span id="defaultSnippet1">&abouthome.defaultSnippet1.v1;</span>
<span id="defaultSnippet2">&abouthome.defaultSnippet2.v1;</span>
</div>
<span id="rightsSnippet" hidden="true">&abouthome.rightsSnippet;</span>
<div id="snippets"/>
</div>
</div>
<div class="spacer"/>
@ -73,7 +64,5 @@
<button class="launchButton" id="restorePreviousSession">&historyRestoreLastSession.label;</button>
</div>
<a id="aboutMozilla" href="https://www.mozilla.org/about/?utm_source=about-home&amp;utm_medium=Referral"
aria-label="&abouthome.aboutMozilla.label;"/>
</body>
</html>

View file

@ -147,13 +147,10 @@ var AboutHomeListener = {
if (aData.showRestoreLastSession && !PrivateBrowsingUtils.isContentWindowPrivate(content))
doc.getElementById("launcher").setAttribute("session", "true");
// Inject search engine and snippets URL.
// Inject search engine URL.
let docElt = doc.documentElement;
// Set snippetsVersion last, which triggers to show the snippets when it's set.
docElt.setAttribute("snippetsURL", aData.snippetsURL);
if (aData.showKnowYourRights)
docElt.setAttribute("showKnowYourRights", "true");
docElt.setAttribute("snippetsVersion", aData.snippetsVersion);
},
onPageLoad: function() {

View file

@ -24,17 +24,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.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 = 4;
// Should be bumped up if any data content format changes.
const STARTPAGE_VERSION = 5;
this.AboutHomeUtils = {
get snippetsVersion() {
return STARTPAGE_VERSION;
},
/*
* showKnowYourRights - Determines if the user should be shown the
* about:rights notification. The notification should *not* be shown if
@ -76,16 +69,6 @@ this.AboutHomeUtils = {
}
};
/**
* 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);
});
/**
* This code provides services to the about:home page. Whenever
* about:home needs to do something chrome-privileged, it sends a
@ -169,9 +152,7 @@ var AboutHome = {
ss.promiseInitialized.then(function() {
let data = {
showRestoreLastSession: ss.canRestoreLastSession,
snippetsURL: AboutHomeUtils.snippetsURL,
showKnowYourRights: AboutHomeUtils.showKnowYourRights,
snippetsVersion: AboutHomeUtils.snippetsVersion,
showKnowYourRights: AboutHomeUtils.showKnowYourRights
};
if (AboutHomeUtils.showKnowYourRights) {