summaryrefslogtreecommitdiff
path: root/mobile/android/chrome/content/aboutHealthReport.js
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/chrome/content/aboutHealthReport.js')
-rw-r--r--mobile/android/chrome/content/aboutHealthReport.js192
1 files changed, 192 insertions, 0 deletions
diff --git a/mobile/android/chrome/content/aboutHealthReport.js b/mobile/android/chrome/content/aboutHealthReport.js
new file mode 100644
index 0000000000..070eb821df
--- /dev/null
+++ b/mobile/android/chrome/content/aboutHealthReport.js
@@ -0,0 +1,192 @@
+// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
+/* 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";
+
+var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Messaging.jsm");
+Cu.import("resource://gre/modules/SharedPreferences.jsm");
+
+// Name of Android SharedPreference controlling whether to upload
+// health reports.
+const PREF_UPLOAD_ENABLED = "android.not_a_preference.healthreport.uploadEnabled";
+
+// Name of Gecko Pref specifying report content location.
+const PREF_REPORTURL = "datareporting.healthreport.about.reportUrl";
+
+// Monotonically increasing wrapper API version number.
+const WRAPPER_VERSION = 1;
+
+const EVENT_HEALTH_REQUEST = "HealthReport:Request";
+const EVENT_HEALTH_RESPONSE = "HealthReport:Response";
+
+// about:healthreport prefs are stored in Firefox's default Android
+// SharedPreferences.
+var sharedPrefs = SharedPreferences.forApp();
+
+var healthReportWrapper = {
+ init: function () {
+ let iframe = document.getElementById("remote-report");
+ iframe.addEventListener("load", healthReportWrapper.initRemotePage, false);
+ let report = this._getReportURI();
+ iframe.src = report.spec;
+ console.log("AboutHealthReport: loading content from " + report.spec);
+
+ sharedPrefs.addObserver(PREF_UPLOAD_ENABLED, this, false);
+ Services.obs.addObserver(this, EVENT_HEALTH_RESPONSE, false);
+ },
+
+ observe: function (subject, topic, data) {
+ if (topic == PREF_UPLOAD_ENABLED) {
+ this.updatePrefState();
+ } else if (topic == EVENT_HEALTH_RESPONSE) {
+ this.updatePayload(data);
+ }
+ },
+
+ uninit: function () {
+ sharedPrefs.removeObserver(PREF_UPLOAD_ENABLED, this);
+ Services.obs.removeObserver(this, EVENT_HEALTH_RESPONSE);
+ },
+
+ _getReportURI: function () {
+ let url = Services.urlFormatter.formatURLPref(PREF_REPORTURL);
+ // This handles URLs that already have query parameters.
+ let uri = Services.io.newURI(url, null, null).QueryInterface(Ci.nsIURL);
+ uri.query += ((uri.query != "") ? "&v=" : "v=") + WRAPPER_VERSION;
+ return uri;
+ },
+
+ onOptIn: function () {
+ console.log("AboutHealthReport: page sent opt-in command.");
+ sharedPrefs.setBoolPref(PREF_UPLOAD_ENABLED, true);
+ this.updatePrefState();
+ },
+
+ onOptOut: function () {
+ console.log("AboutHealthReport: page sent opt-out command.");
+ sharedPrefs.setBoolPref(PREF_UPLOAD_ENABLED, false);
+ this.updatePrefState();
+ },
+
+ updatePrefState: function () {
+ console.log("AboutHealthReport: sending pref state to page.");
+ try {
+ let prefs = {
+ enabled: sharedPrefs.getBoolPref(PREF_UPLOAD_ENABLED),
+ };
+ this.injectData("prefs", prefs);
+ } catch (e) {
+ this.reportFailure(this.ERROR_PREFS_FAILED);
+ }
+ },
+
+ refreshPayload: function () {
+ console.log("AboutHealthReport: page requested fresh payload.");
+ Messaging.sendRequest({
+ type: EVENT_HEALTH_REQUEST,
+ });
+ },
+
+ updatePayload: function (data) {
+ healthReportWrapper.injectData("payload", data);
+ // Data is supposed to be a string, so the length should be
+ // defined. Just in case, we do this after injecting the data.
+ console.log("AboutHealthReport: sending payload to page " +
+ "(" + typeof(data) + " of length " + data.length + ").");
+ },
+
+ 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;
+
+ let data = {
+ type: type,
+ content: content,
+ };
+
+ let iframe = document.getElementById("remote-report");
+ iframe.contentWindow.postMessage(data, reportUrl);
+ },
+
+ showSettings: function () {
+ console.log("AboutHealthReport: showing settings.");
+ Messaging.sendRequest({
+ type: "Settings:Show",
+ resource: "preferences_vendor",
+ });
+ },
+
+ launchUpdater: function () {
+ console.log("AboutHealthReport: launching updater.");
+ Messaging.sendRequest({
+ type: "Updater:Launch",
+ });
+ },
+
+ handleRemoteCommand: function (evt) {
+ switch (evt.detail.command) {
+ case "DisableDataSubmission":
+ this.onOptOut();
+ break;
+ case "EnableDataSubmission":
+ this.onOptIn();
+ break;
+ case "RequestCurrentPrefs":
+ this.updatePrefState();
+ break;
+ case "RequestCurrentPayload":
+ this.refreshPayload();
+ break;
+ case "ShowSettings":
+ this.showSettings();
+ break;
+ case "LaunchUpdater":
+ this.launchUpdater();
+ break;
+ default:
+ Cu.reportError("Unexpected remote command received: " + evt.detail.command +
+ ". Ignoring command.");
+ break;
+ }
+ },
+
+ initRemotePage: function () {
+ let iframe = document.getElementById("remote-report").contentDocument;
+ iframe.addEventListener("RemoteHealthReportCommand",
+ function onCommand(e) {healthReportWrapper.handleRemoteCommand(e);},
+ false);
+ healthReportWrapper.injectData("begin", null);
+ },
+
+ // error handling
+ ERROR_INIT_FAILED: 1,
+ ERROR_PAYLOAD_FAILED: 2,
+ ERROR_PREFS_FAILED: 3,
+
+ reportFailure: function (error) {
+ let details = {
+ errorType: error,
+ };
+ healthReportWrapper.injectData("error", details);
+ },
+
+ handleInitFailure: function () {
+ healthReportWrapper.reportFailure(healthReportWrapper.ERROR_INIT_FAILED);
+ },
+
+ handlePayloadFailure: function () {
+ healthReportWrapper.reportFailure(healthReportWrapper.ERROR_PAYLOAD_FAILED);
+ },
+};
+
+window.addEventListener("load", healthReportWrapper.init.bind(healthReportWrapper), false);
+window.addEventListener("unload", healthReportWrapper.uninit.bind(healthReportWrapper), false);