Bug 1196762 - Part 1: Initial Prefs Provider module for the remote newtab page r=Mardak draft
authorOlivier Yiptong <olivier@olivieryiptong.com>
Fri, 13 Nov 2015 05:39:41 -0500
changeset 308621 df54d572ab0f8e2061563cfac8c22564bb913f49
parent 307896 cc473fe5dc512c450634506f68cbacfb40a06a23
child 308622 cbb1af56e7a6edc1d775a79e01462dd1db9b4aed
push id7503
push userolivier@olivieryiptong.com
push dateFri, 13 Nov 2015 10:40:54 +0000
reviewersMardak
bugs1196762
milestone45.0a1
Bug 1196762 - Part 1: Initial Prefs Provider module for the remote newtab page r=Mardak
browser/components/newtab/NewTabPrefsProvider.jsm
browser/components/newtab/moz.build
browser/components/newtab/tests/xpcshell/test_NewTabPrefsProvider.js
browser/components/newtab/tests/xpcshell/xpcshell.ini
browser/components/nsBrowserGlue.js
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/NewTabPrefsProvider.jsm
@@ -0,0 +1,84 @@
+/* global Services, Preferences, EventEmitter, XPCOMUtils */
+/* exported NewTabPrefsProvider */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["NewTabPrefsProvider"];
+
+const {interfaces: Ci, utils: Cu} = Components;
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Preferences.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "EventEmitter", function() {
+  const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
+  return EventEmitter;
+});
+
+// Supported prefs and data type
+const gPrefsMap = new Map([
+  ["browser.newtabpage.enabled", "bool"],
+  ["browser.newtabpage.enhanced", "bool"],
+  ["browser.newtabpage.pinned", "str"],
+  ["intl.locale.matchOS", "bool"],
+  ["general.useragent.locale", "localized"],
+]);
+
+let PrefsProvider = function PrefsProvider() {
+  EventEmitter.decorate(this);
+};
+
+PrefsProvider.prototype = {
+
+  observe(subject, topic, data) { // jshint ignore:line
+    if (topic === "nsPref:changed") {
+      if (gPrefsMap.has(data)) {
+        switch (gPrefsMap.get(data)) {
+          case "bool":
+            this.emit(data, Preferences.get(data, false));
+            break;
+          case "str":
+            this.emit(data, Preferences.get(data, ""));
+            break;
+          case "localized":
+            try {
+              this.emit(data, Preferences.get(data, "", Ci.nsIPrefLocalizedString));
+            } catch (e) {
+              this.emit(data, Preferences.get(data, ""));
+            }
+            break;
+          default:
+            this.emit(data);
+            break;
+        }
+      }
+    } else {
+      Cu.reportError(new Error("NewTabPrefsProvider observing unknown topic"));
+    }
+  },
+
+  get prefsMap() {
+    return gPrefsMap;
+  },
+
+  init() {
+    for (let pref of gPrefsMap.keys()) {
+      Services.prefs.addObserver(pref, this, false);
+    }
+  },
+
+  uninit() {
+    for (let pref of gPrefsMap.keys()) {
+      Services.prefs.removeObserver(pref, this, false);
+    }
+  }
+};
+
+/**
+ * Singleton that serves as the default new tab pref provider for the grid.
+ */
+const gPrefs = new PrefsProvider();
+
+let NewTabPrefsProvider = {
+  prefs: gPrefs,
+};
--- a/browser/components/newtab/moz.build
+++ b/browser/components/newtab/moz.build
@@ -6,14 +6,15 @@
 
 BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
 
 XPCSHELL_TESTS_MANIFESTS += [
     'tests/xpcshell/xpcshell.ini',
 ]
 
 EXTRA_JS_MODULES += [
+    'NewTabPrefsProvider.jsm',
     'NewTabURL.jsm',
     'PlacesProvider.jsm',
     'RemoteAboutNewTab.jsm',
     'RemoteNewTabLocation.jsm',
     'RemoteNewTabUtils.jsm',
 ]
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/tests/xpcshell/test_NewTabPrefsProvider.js
@@ -0,0 +1,51 @@
+"use strict";
+
+/* global XPCOMUtils, equal, Preferences, NewTabPrefsProvider, run_next_test */
+/* exported run_test */
+/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
+
+const Cu = Components.utils;
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Preferences.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
+    "resource:///modules/NewTabPrefsProvider.jsm");
+
+function run_test() {
+  run_next_test();
+}
+
+add_task(function* test_observe() {
+  let prefsMap = NewTabPrefsProvider.prefs.prefsMap;
+  for (let prefName of prefsMap.keys()) {
+    let prefValueType = prefsMap.get(prefName);
+
+    let beforeVal;
+    let afterVal;
+
+    switch (prefValueType) {
+      case "bool":
+        beforeVal = false;
+        afterVal = true;
+        Preferences.set(prefName, beforeVal);
+        break;
+      case "localized":
+      case "str":
+        beforeVal = "";
+        afterVal = "someStr";
+        Preferences.set(prefName, beforeVal);
+        break;
+    }
+    NewTabPrefsProvider.prefs.init();
+    let promise = new Promise(resolve => {
+      NewTabPrefsProvider.prefs.once(prefName, (name, data) => { // jshint ignore:line
+        resolve([name, data]);
+      });
+    });
+    Preferences.set(prefName, afterVal);
+    let [actualName, actualData] = yield promise;
+    equal(prefName, actualName, `emitter sent the correct pref: ${prefName}`);
+    equal(afterVal, actualData, `emitter collected correct pref data for ${prefName}`);
+    NewTabPrefsProvider.prefs.uninit();
+  }
+});
--- a/browser/components/newtab/tests/xpcshell/xpcshell.ini
+++ b/browser/components/newtab/tests/xpcshell/xpcshell.ini
@@ -1,11 +1,12 @@
 [DEFAULT]
 head =
 tail =
 firefox-appdir = browser
 skip-if = toolkit == 'android' || toolkit == 'gonk'
 
 [test_AboutNewTabService.js]
+[test_NewTabPrefsProvider.js]
 [test_NewTabURL.js]
 [test_PlacesProvider.js]
 [test_RemoteNewTabLocation.js]
 [test_RemoteNewTabUtils.js]
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -27,16 +27,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/NewTabUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "RemoteAboutNewTab",
                                   "resource:///modules/RemoteAboutNewTab.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabUtils",
                                   "resource:///modules/RemoteNewTabUtils.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
+                                  "resource:///modules/NewTabPrefsProvider.jsm");
+
 XPCOMUtils.defineLazyModuleGetter(this, "UITour",
                                   "resource:///modules/UITour.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                   "resource://gre/modules/AddonManager.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ContentClick",
                                   "resource:///modules/ContentClick.jsm");
@@ -843,16 +846,17 @@ BrowserGlue.prototype = {
     DirectoryLinksProvider.init();
     NewTabUtils.init();
     NewTabUtils.links.addProvider(DirectoryLinksProvider);
     AboutNewTab.init();
 
     RemoteNewTabUtils.init();
     RemoteNewTabUtils.links.addProvider(DirectoryLinksProvider);
     RemoteAboutNewTab.init();
+    NewTabPrefsProvider.prefs.init();
 
     SessionStore.init();
     BrowserUITelemetry.init();
     ContentSearch.init();
     FormValidationHandler.init();
 
     ContentClick.init();
     RemotePrompt.init();
@@ -1164,16 +1168,17 @@ BrowserGlue.prototype = {
     }
 
     SelfSupportBackend.uninit();
 
     CustomizationTabPreloader.uninit();
     WebappManager.uninit();
 
     RemoteAboutNewTab.uninit();
+    NewTabPrefsProvider.prefs.uninit();
     AboutNewTab.uninit();
 #ifdef NIGHTLY_BUILD
     if (Services.prefs.getBoolPref("dom.identity.enabled")) {
       SignInToWebsiteUX.uninit();
     }
 #endif
     webrtcUI.uninit();
     FormValidationHandler.uninit();