Files
tubestation/browser/components/newtab/aboutNewTabService.js

191 lines
5.8 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/.
*/
/* globals XPCOMUtils, NewTabPrefsProvider, Services,
Locale, UpdateUtils
*/
"use strict";
const {utils: Cu, interfaces: Ci} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
"resource://gre/modules/UpdateUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
"resource:///modules/NewTabPrefsProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Locale",
"resource://gre/modules/Locale.jsm");
const LOCAL_NEWTAB_URL = "chrome://browser/content/newtab/newTab.xhtml";
const REMOTE_NEWTAB_URL = "https://newtab.cdn.mozilla.net/" +
"v%VERSION%/%CHANNEL%/%LOCALE%/index.html";
// Pref that tells if remote newtab is enabled
const PREF_REMOTE_ENABLED = "browser.newtabpage.remote";
// The preference that tells whether to match the OS locale
const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
// The preference that tells what locale the user selected
const PREF_SELECTED_LOCALE = "general.useragent.locale";
const VALID_CHANNELS = new Set(["esr", "release", "beta", "aurora", "nightly"]);
const REMOTE_NEWTAB_VERSION = "0";
function AboutNewTabService() {
NewTabPrefsProvider.prefs.on(PREF_REMOTE_ENABLED, this._handleToggleEvent.bind(this));
// trigger remote change if needed, according to pref
this.toggleRemote(Services.prefs.getBoolPref(PREF_REMOTE_ENABLED));
}
AboutNewTabService.prototype = {
_newTabURL: LOCAL_NEWTAB_URL,
_remoteEnabled: false,
_overridden: false,
classID: Components.ID("{cef25b06-0ef6-4c50-a243-e69f943ef23d}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutNewTabService]),
_xpcom_categories: [{
service: true
}],
_handleToggleEvent(prefName, stateEnabled, forceState) { //jshint unused:false
this.toggleRemote(stateEnabled, forceState);
},
/**
* React to changes to the remote newtab pref. Only act
* if there is a change of state and if not overridden.
*
* @returns {Boolean} Returns if there has been a state change
*
* @param {Boolean} stateEnabled remote state to set to
* @param {Boolean} forceState force state change
*/
toggleRemote(stateEnabled, forceState) {
if (!forceState && (this._overriden || stateEnabled === this._remoteEnabled)) {
// exit there is no change of state
return false;
}
if (stateEnabled) {
this._newTabURL = this.generateRemoteURL();
NewTabPrefsProvider.prefs.on(
PREF_SELECTED_LOCALE,
this._updateRemoteMaybe.bind(this));
NewTabPrefsProvider.prefs.on(
PREF_MATCH_OS_LOCALE,
this._updateRemoteMaybe.bind(this));
this._remoteEnabled = true;
} else {
this._newTabURL = LOCAL_NEWTAB_URL;
NewTabPrefsProvider.prefs.off(PREF_SELECTED_LOCALE, this._updateRemoteMaybe);
NewTabPrefsProvider.prefs.off(PREF_MATCH_OS_LOCALE, this._updateRemoteMaybe);
this._remoteEnabled = false;
}
return true;
},
/*
* Generate a default url based on locale and update channel
*/
generateRemoteURL() {
let releaseName = this.releaseFromUpdateChannel(UpdateUtils.UpdateChannel);
let url = REMOTE_NEWTAB_URL
.replace("%VERSION%", REMOTE_NEWTAB_VERSION)
.replace("%LOCALE%", Locale.getLocale())
.replace("%CHANNEL%", releaseName);
return url;
},
/*
* Updates the remote location when the page is not overriden.
*
* Useful when there is a dependent pref change
*/
_updateRemoteMaybe() {
if (!this._remoteEnabled || this._overridden) {
return;
}
let url = this.generateRemoteURL();
if (url !== this._newTabURL) {
this._newTabURL = url;
Services.obs.notifyObservers(null, "newtab-url-changed",
this._newTabURL);
}
},
/**
* Returns the release name from an Update Channel name
*
* @return {String} a release name based on the update channel. Defaults to nightly
*/
releaseFromUpdateChannel(channelName) {
return VALID_CHANNELS.has(channelName) ? channelName : "nightly";
},
get newTabURL() {
return this._newTabURL;
},
get remoteVersion() {
return REMOTE_NEWTAB_VERSION;
},
get remoteReleaseName() {
return this.releaseFromUpdateChannel(UpdateUtils.UpdateChannel);
},
set newTabURL(aNewTabURL) {
if (aNewTabURL === "about:newtab") {
// avoid infinite redirects in case one sets the URL to about:newtab
this.resetNewTabURL();
return;
}
let remoteURL = this.generateRemoteURL();
let prefRemoteEnabled = Services.prefs.getBoolPref(PREF_REMOTE_ENABLED);
let isResetLocal = !prefRemoteEnabled && aNewTabURL === LOCAL_NEWTAB_URL;
let isResetRemote = prefRemoteEnabled && aNewTabURL === remoteURL;
if (isResetLocal || isResetRemote) {
if (this._overriden) {
// only trigger a reset if previously overridden
this.resetNewTabURL();
}
return;
}
// turn off remote state if needed
this.toggleRemote(false);
this._newTabURL = aNewTabURL;
this._overridden = true;
Services.obs.notifyObservers(null, "newtab-url-changed", this._newTabURL);
},
get overridden() {
return this._overridden;
},
get remoteEnabled() {
return this._remoteEnabled;
},
resetNewTabURL() {
this._overridden = false;
this.toggleRemote(Services.prefs.getBoolPref(PREF_REMOTE_ENABLED), true);
Services.obs.notifyObservers(null, "newtab-url-changed", this._newTabURL);
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AboutNewTabService]);