Bug 1024668 - Extract core logic of abouthealth.js into new WebIDL interface. r=bz,gps,wchen
authorBirunthan Mohanathas <birunthan@mohanathas.com>
Tue, 29 Jul 2014 16:54:01 -0700
changeset 196956 e620a9b140faf4aecf9ade69c689861feddd750c
parent 196955 81f81a4777f1b7c0db87b03b4bb9383aa101e128
child 196957 e65279c96603e873f53e5585e82892a9c1ee99d3
push id27228
push usercbook@mozilla.com
push dateThu, 31 Jul 2014 10:58:52 +0000
treeherdermozilla-central@aa176fcc56b8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, gps, wchen
bugs1024668
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1024668 - Extract core logic of abouthealth.js into new WebIDL interface. r=bz,gps,wchen
browser/base/content/abouthealthreport/abouthealth.js
browser/components/moz.build
browser/components/selfsupport/SelfSupportService.js
browser/components/selfsupport/SelfSupportService.manifest
browser/components/selfsupport/moz.build
browser/installer/package-manifest.in
dom/webidl/MozSelfSupport.webidl
dom/webidl/moz.build
--- a/browser/base/content/abouthealthreport/abouthealth.js
+++ b/browser/base/content/abouthealthreport/abouthealth.js
@@ -4,85 +4,63 @@
 
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-const reporter = Cc["@mozilla.org/datareporting/service;1"]
-                   .getService(Ci.nsISupports)
-                   .wrappedJSObject
-                   .healthReporter;
-
-const policy = Cc["@mozilla.org/datareporting/service;1"]
-                 .getService(Ci.nsISupports)
-                 .wrappedJSObject
-                 .policy;
-
 const prefs = new Preferences("datareporting.healthreport.");
 
-
 let healthReportWrapper = {
   init: function () {
-    if (!reporter) {
-      healthReportWrapper.handleInitFailure();
-      return;
-    }
-
-    reporter.onInit().then(healthReportWrapper.refreshPayload,
-                           healthReportWrapper.handleInitFailure);
-
     let iframe = document.getElementById("remote-report");
     iframe.addEventListener("load", healthReportWrapper.initRemotePage, false);
-    let report = this._getReportURI();
-    iframe.src = report.spec;
+    iframe.src = this._getReportURI().spec;
+    iframe.onload = () => {
+      MozSelfSupport.getHealthReportPayload().then(this.updatePayload,
+                                                   this.handleInitFailure);
+    };
     prefs.observe("uploadEnabled", this.updatePrefState, healthReportWrapper);
   },
 
   uninit: function () {
     prefs.ignore("uploadEnabled", this.updatePrefState, healthReportWrapper);
   },
 
   _getReportURI: function () {
     let url = Services.urlFormatter.formatURLPref("datareporting.healthreport.about.reportUrl");
     return Services.io.newURI(url, null, null);
   },
 
-  onOptIn: function () {
-    policy.recordHealthReportUploadEnabled(true,
-                                           "Health report page sent opt-in command.");
-    this.updatePrefState();
-  },
-
-  onOptOut: function () {
-    policy.recordHealthReportUploadEnabled(false,
-                                           "Health report page sent opt-out command.");
+  setDataSubmission: function (enabled) {
+    MozSelfSupport.healthReportDataSubmissionEnabled = enabled;
     this.updatePrefState();
   },
 
   updatePrefState: function () {
     try {
       let prefs = {
-        enabled: policy.healthReportUploadEnabled,
-      }
-      this.injectData("prefs", prefs);
-    } catch (e) {
-      this.reportFailure(this.ERROR_PREFS_FAILED);
+        enabled: MozSelfSupport.healthReportDataSubmissionEnabled,
+      };
+      healthReportWrapper.injectData("prefs", prefs);
+    }
+    catch (ex) {
+      healthReportWrapper.reportFailure(healthReportWrapper.ERROR_PREFS_FAILED);
     }
   },
 
   refreshPayload: function () {
-    reporter.collectAndObtainJSONPayload().then(healthReportWrapper.updatePayload, 
-                                                healthReportWrapper.handlePayloadFailure);
+    MozSelfSupport.getHealthReportPayload().then(this.updatePayload,
+                                                 this.handlePayloadFailure);
   },
 
-  updatePayload: function (data) {
-    healthReportWrapper.injectData("payload", data);
+  updatePayload: function (payload) {
+    healthReportWrapper.injectData("payload", JSON.stringify(payload));
   },
 
   injectData: function (type, content) {
     let report = this._getReportURI();
     
     // file URIs can't be used for targetOrigin, so we use "*" for this special case
     // in all other cases, pass in the URL to the report so we properly restrict the message dispatch
     let reportUrl = report.scheme == "file" ? "*" : report.spec;
@@ -94,20 +72,20 @@ let healthReportWrapper = {
 
     let iframe = document.getElementById("remote-report");
     iframe.contentWindow.postMessage(data, reportUrl);
   },
 
   handleRemoteCommand: function (evt) {
     switch (evt.detail.command) {
       case "DisableDataSubmission":
-        this.onOptOut();
+        this.setDataSubmission(false);
         break;
       case "EnableDataSubmission":
-        this.onOptIn();
+        this.setDataSubmission(true);
         break;
       case "RequestCurrentPrefs":
         this.updatePrefState();
         break;
       case "RequestCurrentPayload":
         this.refreshPayload();
         break;
       default:
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -12,16 +12,17 @@ DIRS += [
     'feeds',
     'loop',
     'places',
     'preferences',
     'privatebrowsing',
     'search',
     'sessionstore',
     'shell',
+    'selfsupport',
     'sidebar',
     'tabview',
     'translation',
     'migration',
 ]
 
 DIRS += ['build']
 
new file mode 100644
--- /dev/null
+++ b/browser/components/selfsupport/SelfSupportService.js
@@ -0,0 +1,74 @@
+/* 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");
+
+const policy = Cc["@mozilla.org/datareporting/service;1"]
+                 .getService(Ci.nsISupports)
+                 .wrappedJSObject
+                 .policy;
+
+XPCOMUtils.defineLazyGetter(this, "reporter", () => {
+  return Cc["@mozilla.org/datareporting/service;1"]
+           .getService(Ci.nsISupports)
+           .wrappedJSObject
+           .healthReporter;
+});
+
+function MozSelfSupportInterface() {
+}
+
+MozSelfSupportInterface.prototype = {
+  classDescription: "MozSelfSupport",
+  classID: Components.ID("{d30aae8b-f352-4de3-b936-bb9d875df0bb}"),
+  contractID: "@mozilla.org/mozselfsupport;1",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
+                                         Ci.nsIObserver]),
+
+  _window: null,
+
+  init: function (window) {
+    this._window = window;
+
+    // FIXME: Remove this hack after static attributes work for JS-implemented
+    // WebIDL (see bug 863952). For a detailed description of how this works,
+    // see the comment accompanying the init function of amInstallTrigger.js.
+    return window.MozSelfSupportImpl._create(this._window, this);
+  },
+
+  get healthReportDataSubmissionEnabled() {
+    return policy.healthReportUploadEnabled;
+  },
+
+  set healthReportDataSubmissionEnabled(enabled) {
+    let reason = "Self-support interface sent " +
+                 (enabled ? "opt-in" : "opt-out") +
+                 " command.";
+    policy.recordHealthReportUploadEnabled(enabled, reason);
+  },
+
+  getHealthReportPayload: function () {
+    return new this._window.Promise(function (aResolve, aReject) {
+      if (reporter) {
+        let resolvePayload = function () {
+          reporter.collectAndObtainJSONPayload(true).then(aResolve, aReject);
+        };
+
+        if (reporter.initialized) {
+          resolvePayload();
+        } else {
+          reporter.onInit().then(resolvePayload, aReject);
+        }
+      } else {
+        aReject(new Error("No reporter"));
+      }
+    }.bind(this));
+  },
+}
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozSelfSupportInterface]);
new file mode 100644
--- /dev/null
+++ b/browser/components/selfsupport/SelfSupportService.manifest
@@ -0,0 +1,4 @@
+component {d30aae8b-f352-4de3-b936-bb9d875df0bb} SelfSupportService.js
+contract @mozilla.org/mozselfsupport;1 {d30aae8b-f352-4de3-b936-bb9d875df0bb}
+
+category JavaScript-global-privileged-property MozSelfSupport @mozilla.org/mozselfsupport;1
new file mode 100644
--- /dev/null
+++ b/browser/components/selfsupport/moz.build
@@ -0,0 +1,10 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+EXTRA_COMPONENTS += [
+    'SelfSupportService.js',
+    'SelfSupportService.manifest',
+]
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -484,16 +484,18 @@
 @BINPATH@/components/nsPrompter.manifest
 @BINPATH@/components/nsPrompter.js
 #ifdef MOZ_DATA_REPORTING
 @BINPATH@/components/DataReporting.manifest
 @BINPATH@/components/DataReportingService.js
 #endif
 #ifdef MOZ_SERVICES_HEALTHREPORT
 @BINPATH@/components/HealthReportComponents.manifest
+@BINPATH@/browser/components/SelfSupportService.manifest
+@BINPATH@/browser/components/SelfSupportService.js
 #endif
 #ifdef MOZ_SERVICES_SYNC
 @BINPATH@/components/SyncComponents.manifest
 @BINPATH@/components/Weave.js
 #endif
 #ifdef MOZ_CAPTIVEDETECT
 @BINPATH@/components/CaptivePortalDetectComponents.manifest
 @BINPATH@/components/captivedetect.js
new file mode 100644
--- /dev/null
+++ b/dom/webidl/MozSelfSupport.webidl
@@ -0,0 +1,41 @@
+/* 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/. */
+
+/**
+ * The MozSelfSupport interface allows external Mozilla support sites such as
+ * FHR and SUMO to access data and control settings that are not otherwise
+ * exposed to external content.
+ *
+ * At the moment, this is a ChromeOnly interface, but the plan is to allow
+ * specific Mozilla domains to access it directly.
+ */
+[ChromeOnly,
+ JSImplementation="@mozilla.org/mozselfsupport;1"]
+interface MozSelfSupportImpl
+{
+  /**
+   * Controls whether uploading FHR data is allowed.
+   */
+  attribute boolean healthReportDataSubmissionEnabled;
+
+  /**
+   * Retrieves the FHR payload object, which is of the form:
+   *
+   * {
+   *   version: Number,
+   *   clientID: String,
+   *   clientIDVersion: Number,
+   *   thisPingDate: String,
+   *   geckoAppInfo: Object,
+   *   data: Object
+   * }
+   *
+   * Refer to the getJSONPayload function in healthreporter.jsm for more
+   * information.
+   *
+   * @return Promise<Object>
+   *         Resolved when the FHR payload data has been collected.
+   */
+  Promise getHealthReportPayload();
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -255,16 +255,17 @@ WEBIDL_FILES = [
     'MimeTypeArray.webidl',
     'MouseEvent.webidl',
     'MouseScrollEvent.webidl',
     'MozActivity.webidl',
     'MozMmsMessage.webidl',
     'MozMobileMessageManager.webidl',
     'MozNamedAttrMap.webidl',
     'MozPowerManager.webidl',
+    'MozSelfSupport.webidl',
     'MozTimeManager.webidl',
     'MozWakeLock.webidl',
     'MutationEvent.webidl',
     'MutationObserver.webidl',
     'NativeOSFileInternals.webidl',
     'NetDashboard.webidl',
     'NetworkInformation.webidl',
     'NetworkOptions.webidl',