toolkit/modules/DirectoryLinksProvider.jsm

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 "use strict";
michael@0 6
michael@0 7 this.EXPORTED_SYMBOLS = ["DirectoryLinksProvider"];
michael@0 8
michael@0 9 const Ci = Components.interfaces;
michael@0 10 const Cc = Components.classes;
michael@0 11 const Cu = Components.utils;
michael@0 12
michael@0 13 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 14 Cu.import("resource://gre/modules/Services.jsm");
michael@0 15
michael@0 16 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
michael@0 17 "resource://gre/modules/NetUtil.jsm");
michael@0 18
michael@0 19 /**
michael@0 20 * Gets the currently selected locale for display.
michael@0 21 * @return the selected locale or "en-US" if none is selected
michael@0 22 */
michael@0 23 function getLocale() {
michael@0 24 let matchOS;
michael@0 25 try {
michael@0 26 matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE);
michael@0 27 }
michael@0 28 catch (e) {}
michael@0 29
michael@0 30 if (matchOS) {
michael@0 31 return Services.locale.getLocaleComponentForUserAgent();
michael@0 32 }
michael@0 33
michael@0 34 try {
michael@0 35 let locale = Services.prefs.getComplexValue(PREF_SELECTED_LOCALE,
michael@0 36 Ci.nsIPrefLocalizedString);
michael@0 37 if (locale) {
michael@0 38 return locale.data;
michael@0 39 }
michael@0 40 }
michael@0 41 catch (e) {}
michael@0 42
michael@0 43 try {
michael@0 44 return Services.prefs.getCharPref(PREF_SELECTED_LOCALE);
michael@0 45 }
michael@0 46 catch (e) {}
michael@0 47
michael@0 48 return "en-US";
michael@0 49 }
michael@0 50
michael@0 51 // The preference that tells whether to match the OS locale
michael@0 52 const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
michael@0 53
michael@0 54 // The preference that tells what locale the user selected
michael@0 55 const PREF_SELECTED_LOCALE = "general.useragent.locale";
michael@0 56
michael@0 57 // The preference that tells where to obtain directory links
michael@0 58 const PREF_DIRECTORY_SOURCE = "browser.newtabpage.directorySource";
michael@0 59
michael@0 60 // The frecency of a directory link
michael@0 61 const DIRECTORY_FRECENCY = 1000;
michael@0 62
michael@0 63 const LINK_TYPES = Object.freeze([
michael@0 64 "sponsored",
michael@0 65 "affiliate",
michael@0 66 "organic",
michael@0 67 ]);
michael@0 68
michael@0 69 /**
michael@0 70 * Singleton that serves as the provider of directory links.
michael@0 71 * Directory links are a hard-coded set of links shown if a user's link
michael@0 72 * inventory is empty.
michael@0 73 */
michael@0 74 let DirectoryLinksProvider = {
michael@0 75
michael@0 76 __linksURL: null,
michael@0 77
michael@0 78 _observers: [],
michael@0 79
michael@0 80 get _prefs() Object.freeze({
michael@0 81 linksURL: PREF_DIRECTORY_SOURCE,
michael@0 82 matchOSLocale: PREF_MATCH_OS_LOCALE,
michael@0 83 prefSelectedLocale: PREF_SELECTED_LOCALE,
michael@0 84 }),
michael@0 85
michael@0 86 get _linksURL() {
michael@0 87 if (!this.__linksURL) {
michael@0 88 try {
michael@0 89 this.__linksURL = Services.prefs.getCharPref(this._prefs["linksURL"]);
michael@0 90 }
michael@0 91 catch (e) {
michael@0 92 Cu.reportError("Error fetching directory links url from prefs: " + e);
michael@0 93 }
michael@0 94 }
michael@0 95 return this.__linksURL;
michael@0 96 },
michael@0 97
michael@0 98 get linkTypes() LINK_TYPES,
michael@0 99
michael@0 100 observe: function DirectoryLinksProvider_observe(aSubject, aTopic, aData) {
michael@0 101 if (aTopic == "nsPref:changed") {
michael@0 102 if (aData == this._prefs["linksURL"]) {
michael@0 103 delete this.__linksURL;
michael@0 104 }
michael@0 105 this._callObservers("onManyLinksChanged");
michael@0 106 }
michael@0 107 },
michael@0 108
michael@0 109 _addPrefsObserver: function DirectoryLinksProvider_addObserver() {
michael@0 110 for (let pref in this._prefs) {
michael@0 111 let prefName = this._prefs[pref];
michael@0 112 Services.prefs.addObserver(prefName, this, false);
michael@0 113 }
michael@0 114 },
michael@0 115
michael@0 116 _removePrefsObserver: function DirectoryLinksProvider_removeObserver() {
michael@0 117 for (let pref in this._prefs) {
michael@0 118 let prefName = this._prefs[pref];
michael@0 119 Services.prefs.removeObserver(prefName, this);
michael@0 120 }
michael@0 121 },
michael@0 122
michael@0 123 /**
michael@0 124 * Fetches the current set of directory links.
michael@0 125 * @param aCallback a callback that is provided a set of links.
michael@0 126 */
michael@0 127 _fetchLinks: function DirectoryLinksProvider_fetchLinks(aCallback) {
michael@0 128 try {
michael@0 129 NetUtil.asyncFetch(this._linksURL, (aInputStream, aResult, aRequest) => {
michael@0 130 let output;
michael@0 131 if (Components.isSuccessCode(aResult)) {
michael@0 132 try {
michael@0 133 let json = NetUtil.readInputStreamToString(aInputStream,
michael@0 134 aInputStream.available(),
michael@0 135 {charset: "UTF-8"});
michael@0 136 let locale = getLocale();
michael@0 137 output = JSON.parse(json)[locale];
michael@0 138 }
michael@0 139 catch (e) {
michael@0 140 Cu.reportError(e);
michael@0 141 }
michael@0 142 }
michael@0 143 else {
michael@0 144 Cu.reportError(new Error("the fetch of " + this._linksURL + "was unsuccessful"));
michael@0 145 }
michael@0 146 aCallback(output || []);
michael@0 147 });
michael@0 148 }
michael@0 149 catch (e) {
michael@0 150 Cu.reportError(e);
michael@0 151 aCallback([]);
michael@0 152 }
michael@0 153 },
michael@0 154
michael@0 155 /**
michael@0 156 * Gets the current set of directory links.
michael@0 157 * @param aCallback The function that the array of links is passed to.
michael@0 158 */
michael@0 159 getLinks: function DirectoryLinksProvider_getLinks(aCallback) {
michael@0 160 this._fetchLinks(rawLinks => {
michael@0 161 // all directory links have a frecency of DIRECTORY_FRECENCY
michael@0 162 aCallback(rawLinks.map((link, position) => {
michael@0 163 link.frecency = DIRECTORY_FRECENCY;
michael@0 164 link.lastVisitDate = rawLinks.length - position;
michael@0 165 return link;
michael@0 166 }));
michael@0 167 });
michael@0 168 },
michael@0 169
michael@0 170 init: function DirectoryLinksProvider_init() {
michael@0 171 this._addPrefsObserver();
michael@0 172 },
michael@0 173
michael@0 174 /**
michael@0 175 * Return the object to its pre-init state
michael@0 176 */
michael@0 177 reset: function DirectoryLinksProvider_reset() {
michael@0 178 delete this.__linksURL;
michael@0 179 this._removePrefsObserver();
michael@0 180 this._removeObservers();
michael@0 181 },
michael@0 182
michael@0 183 addObserver: function DirectoryLinksProvider_addObserver(aObserver) {
michael@0 184 this._observers.push(aObserver);
michael@0 185 },
michael@0 186
michael@0 187 _callObservers: function DirectoryLinksProvider__callObservers(aMethodName, aArg) {
michael@0 188 for (let obs of this._observers) {
michael@0 189 if (typeof(obs[aMethodName]) == "function") {
michael@0 190 try {
michael@0 191 obs[aMethodName](this, aArg);
michael@0 192 } catch (err) {
michael@0 193 Cu.reportError(err);
michael@0 194 }
michael@0 195 }
michael@0 196 }
michael@0 197 },
michael@0 198
michael@0 199 _removeObservers: function() {
michael@0 200 while (this._observers.length) {
michael@0 201 this._observers.pop();
michael@0 202 }
michael@0 203 }
michael@0 204 };

mercurial