forked from mirrors/gecko-dev
MozReview-Commit-ID: 81WygivxBoG --HG-- extra : rebase_source : 65149982c25646b7e7a20ee3f6a21a90dd7c05a8
215 lines
7.1 KiB
JavaScript
215 lines
7.1 KiB
JavaScript
/* 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 {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
Cu.importGlobalProperties(["fetch"]);
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
|
"resource://gre/modules/Services.jsm");
|
|
|
|
const ACTIVITY_STREAM_ENABLED_PREF = "browser.newtabpage.activity-stream.enabled";
|
|
const BROWSER_READY_NOTIFICATION = "sessionstore-windows-restored";
|
|
const PREF_CHANGED_TOPIC = "nsPref:changed";
|
|
const REASON_SHUTDOWN_ON_PREF_CHANGE = "PREF_OFF";
|
|
const REASON_STARTUP_ON_PREF_CHANGE = "PREF_ON";
|
|
const RESOURCE_BASE = "resource://activity-stream";
|
|
|
|
const ACTIVITY_STREAM_OPTIONS = {newTabURL: "about:newtab"};
|
|
|
|
let activityStream;
|
|
let modulesToUnload = new Set();
|
|
let startupData;
|
|
let startupReason;
|
|
let waitingForBrowserReady = true;
|
|
|
|
// Lazily load ActivityStream then find related modules to unload
|
|
XPCOMUtils.defineLazyModuleGetter(this, "ActivityStream",
|
|
"resource://activity-stream/lib/ActivityStream.jsm", null, null, () => {
|
|
// Helper to fetch a resource directory listing and call back with each item
|
|
const processListing = async (uri, cb) => (await (await fetch(uri)).text())
|
|
.split("\n").slice(2).forEach(line => cb(line.split(" ").slice(1)));
|
|
|
|
// Look for modules one level deeper than the top resource URI
|
|
processListing(RESOURCE_BASE, ([directory, , , type]) => {
|
|
if (type === "DIRECTORY") {
|
|
// Look into this directory for .jsm files
|
|
const subDir = `${RESOURCE_BASE}/${directory}`;
|
|
processListing(subDir, ([name]) => {
|
|
if (name && name.search(/\.jsm$/) !== -1) {
|
|
modulesToUnload.add(`${subDir}/${name}`);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
/**
|
|
* init - Initializes an instance of ActivityStream. This could be called by
|
|
* the startup() function exposed by bootstrap.js, or it could be called
|
|
* when ACTIVITY_STREAM_ENABLED_PREF is changed from false to true.
|
|
*
|
|
* @param {string} reason - Reason for initialization. Could be install, upgrade, or PREF_ON
|
|
*/
|
|
function init(reason) {
|
|
// Don't re-initialize
|
|
if (activityStream && activityStream.initialized) {
|
|
return;
|
|
}
|
|
const options = Object.assign({}, startupData || {}, ACTIVITY_STREAM_OPTIONS);
|
|
activityStream = new ActivityStream(options);
|
|
try {
|
|
activityStream.init(reason);
|
|
} catch (e) {
|
|
Cu.reportError(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* uninit - Uninitializes the activityStream instance, if it exsits.This could be
|
|
* called by the shutdown() function exposed by bootstrap.js, or it could
|
|
* be called when ACTIVITY_STREAM_ENABLED_PREF is changed from true to false.
|
|
*
|
|
* @param {type} reason Reason for uninitialization. Could be uninstall, upgrade, or PREF_OFF
|
|
*/
|
|
function uninit(reason) {
|
|
// Make sure to only uninit once in case both pref change and shutdown happen
|
|
if (activityStream) {
|
|
activityStream.uninit(reason);
|
|
activityStream = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* onPrefChanged - handler for changes to ACTIVITY_STREAM_ENABLED_PREF
|
|
*
|
|
*/
|
|
function onPrefChanged() {
|
|
if (Services.prefs.getBoolPref(ACTIVITY_STREAM_ENABLED_PREF, false)) {
|
|
init(REASON_STARTUP_ON_PREF_CHANGE);
|
|
} else {
|
|
uninit(REASON_SHUTDOWN_ON_PREF_CHANGE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if an old pref has a custom value to migrate. Clears the pref so that
|
|
* it's the default after migrating (to avoid future need to migrate).
|
|
*
|
|
* @param oldPrefName {string} Pref to check and migrate
|
|
* @param cbIfNotDefault {function} Callback that gets the current pref value
|
|
*/
|
|
function migratePref(oldPrefName, cbIfNotDefault) {
|
|
// Nothing to do if the user doesn't have a custom value
|
|
if (!Services.prefs.prefHasUserValue(oldPrefName)) {
|
|
return;
|
|
}
|
|
|
|
// Figure out what kind of pref getter to use
|
|
let prefGetter;
|
|
switch (Services.prefs.getPrefType(oldPrefName)) {
|
|
case Services.prefs.PREF_BOOL:
|
|
prefGetter = "getBoolPref";
|
|
break;
|
|
case Services.prefs.PREF_INT:
|
|
prefGetter = "getIntPref";
|
|
break;
|
|
case Services.prefs.PREF_STRING:
|
|
prefGetter = "getStringPref";
|
|
break;
|
|
}
|
|
|
|
// Give the callback the current value then clear the pref
|
|
cbIfNotDefault(Services.prefs[prefGetter](oldPrefName));
|
|
Services.prefs.clearUserPref(oldPrefName);
|
|
}
|
|
|
|
/**
|
|
* onBrowserReady - Continues startup of the add-on after browser is ready.
|
|
*/
|
|
function onBrowserReady() {
|
|
waitingForBrowserReady = false;
|
|
|
|
// Listen for changes to the pref that enables Activity Stream
|
|
Services.prefs.addObserver(ACTIVITY_STREAM_ENABLED_PREF, observe); // eslint-disable-line no-use-before-define
|
|
|
|
// Only initialize if the pref is true
|
|
if (Services.prefs.getBoolPref(ACTIVITY_STREAM_ENABLED_PREF, false)) {
|
|
init(startupReason);
|
|
}
|
|
|
|
// Do a one time migration of Tiles about:newtab prefs that have been modified
|
|
migratePref("browser.newtabpage.rows", rows => {
|
|
// Just disable top sites if rows are not desired
|
|
if (rows <= 0) {
|
|
Services.prefs.setBoolPref("browser.newtabpage.activity-stream.showTopSites", false);
|
|
} else {
|
|
// Assume we want a full row (6 sites per row)
|
|
Services.prefs.setIntPref("browser.newtabpage.activity-stream.topSitesCount", rows * 6);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* observe - nsIObserver callback to handle various browser notifications.
|
|
*/
|
|
function observe(subject, topic, data) {
|
|
switch (topic) {
|
|
case BROWSER_READY_NOTIFICATION:
|
|
Services.obs.removeObserver(observe, BROWSER_READY_NOTIFICATION);
|
|
// Avoid running synchronously during this event that's used for timing
|
|
Services.tm.dispatchToMainThread(() => onBrowserReady());
|
|
break;
|
|
case PREF_CHANGED_TOPIC:
|
|
if (data === ACTIVITY_STREAM_ENABLED_PREF) {
|
|
onPrefChanged();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// The functions below are required by bootstrap.js
|
|
|
|
this.install = function install(data, reason) {};
|
|
|
|
this.startup = function startup(data, reason) {
|
|
// Cache startup data which contains stuff like the version number, etc.
|
|
// so we can use it when we init
|
|
startupData = data;
|
|
startupReason = reason;
|
|
|
|
// Only start Activity Stream up when the browser UI is ready
|
|
if (Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup).startingUp) {
|
|
Services.obs.addObserver(observe, BROWSER_READY_NOTIFICATION);
|
|
} else {
|
|
// Handle manual install or automatic install after manual uninstall
|
|
onBrowserReady();
|
|
}
|
|
};
|
|
|
|
this.shutdown = function shutdown(data, reason) {
|
|
// Uninitialize Activity Stream
|
|
startupData = null;
|
|
startupReason = null;
|
|
uninit(reason);
|
|
|
|
// Stop waiting for browser to be ready
|
|
if (waitingForBrowserReady) {
|
|
Services.obs.removeObserver(observe, BROWSER_READY_NOTIFICATION);
|
|
} else {
|
|
// Stop listening to the pref that enables Activity Stream
|
|
Services.prefs.removeObserver(ACTIVITY_STREAM_ENABLED_PREF, observe);
|
|
}
|
|
|
|
// Unload any add-on modules that might might have been imported
|
|
modulesToUnload.forEach(Cu.unload);
|
|
};
|
|
|
|
this.uninstall = function uninstall(data, reason) {
|
|
if (activityStream) {
|
|
activityStream.uninstall(reason);
|
|
activityStream = null;
|
|
}
|
|
};
|