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.

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

mercurial