mobile/android/chrome/content/aboutHealthReport.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/chrome/content/aboutHealthReport.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,193 @@
     1.4 +#filter substitution
     1.5 +// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +"use strict";
    1.11 +
    1.12 +const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
    1.13 +
    1.14 +Cu.import("resource://gre/modules/Services.jsm");
    1.15 +Cu.import("resource://gre/modules/Messaging.jsm");
    1.16 +Cu.import("resource://gre/modules/SharedPreferences.jsm");
    1.17 +
    1.18 +// Name of Android SharedPreference controlling whether to upload
    1.19 +// health reports.
    1.20 +const PREF_UPLOAD_ENABLED = "android.not_a_preference.healthreport.uploadEnabled";
    1.21 +
    1.22 +// Name of Gecko Pref specifying report content location.
    1.23 +const PREF_REPORTURL = "datareporting.healthreport.about.reportUrl";
    1.24 +
    1.25 +// Monotonically increasing wrapper API version number.
    1.26 +const WRAPPER_VERSION = 1;
    1.27 +
    1.28 +const EVENT_HEALTH_REQUEST = "HealthReport:Request";
    1.29 +const EVENT_HEALTH_RESPONSE = "HealthReport:Response";
    1.30 +
    1.31 +// about:healthreport prefs are stored in Firefox's default Android
    1.32 +// SharedPreferences.
    1.33 +let sharedPrefs = new SharedPreferences();
    1.34 +
    1.35 +let healthReportWrapper = {
    1.36 +  init: function () {
    1.37 +    let iframe = document.getElementById("remote-report");
    1.38 +    iframe.addEventListener("load", healthReportWrapper.initRemotePage, false);
    1.39 +    let report = this._getReportURI();
    1.40 +    iframe.src = report.spec;
    1.41 +    console.log("AboutHealthReport: loading content from " + report.spec);
    1.42 +
    1.43 +    sharedPrefs.addObserver(PREF_UPLOAD_ENABLED, this, false);
    1.44 +    Services.obs.addObserver(this, EVENT_HEALTH_RESPONSE, false);
    1.45 +  },
    1.46 +
    1.47 +  observe: function (subject, topic, data) {
    1.48 +    if (topic == PREF_UPLOAD_ENABLED) {
    1.49 +      this.updatePrefState();
    1.50 +    } else if (topic == EVENT_HEALTH_RESPONSE) {
    1.51 +      this.updatePayload(data);
    1.52 +    }
    1.53 +  },
    1.54 +
    1.55 +  uninit: function () {
    1.56 +    sharedPrefs.removeObserver(PREF_UPLOAD_ENABLED, this);
    1.57 +    Services.obs.removeObserver(this, EVENT_HEALTH_RESPONSE);
    1.58 +  },
    1.59 +
    1.60 +  _getReportURI: function () {
    1.61 +    let url = Services.urlFormatter.formatURLPref(PREF_REPORTURL);
    1.62 +    // This handles URLs that already have query parameters.
    1.63 +    let uri = Services.io.newURI(url, null, null).QueryInterface(Ci.nsIURL);
    1.64 +    uri.query += ((uri.query != "") ? "&v=" : "v=") + WRAPPER_VERSION;
    1.65 +    return uri;
    1.66 +  },
    1.67 +
    1.68 +  onOptIn: function () {
    1.69 +    console.log("AboutHealthReport: page sent opt-in command.");
    1.70 +    sharedPrefs.setBoolPref(PREF_UPLOAD_ENABLED, true);
    1.71 +    this.updatePrefState();
    1.72 +  },
    1.73 +
    1.74 +  onOptOut: function () {
    1.75 +    console.log("AboutHealthReport: page sent opt-out command.");
    1.76 +    sharedPrefs.setBoolPref(PREF_UPLOAD_ENABLED, false);
    1.77 +    this.updatePrefState();
    1.78 +  },
    1.79 +
    1.80 +  updatePrefState: function () {
    1.81 +    console.log("AboutHealthReport: sending pref state to page.");
    1.82 +    try {
    1.83 +      let prefs = {
    1.84 +        enabled: sharedPrefs.getBoolPref(PREF_UPLOAD_ENABLED),
    1.85 +      };
    1.86 +      this.injectData("prefs", prefs);
    1.87 +    } catch (e) {
    1.88 +      this.reportFailure(this.ERROR_PREFS_FAILED);
    1.89 +    }
    1.90 +  },
    1.91 +
    1.92 +  refreshPayload: function () {
    1.93 +    console.log("AboutHealthReport: page requested fresh payload.");
    1.94 +    sendMessageToJava({
    1.95 +      type: EVENT_HEALTH_REQUEST,
    1.96 +    });
    1.97 +  },
    1.98 +
    1.99 +  updatePayload: function (data) {
   1.100 +    healthReportWrapper.injectData("payload", data);
   1.101 +    // Data is supposed to be a string, so the length should be
   1.102 +    // defined.  Just in case, we do this after injecting the data.
   1.103 +    console.log("AboutHealthReport: sending payload to page " +
   1.104 +         "(" + typeof(data) + " of length " + data.length + ").");
   1.105 +  },
   1.106 +
   1.107 +  injectData: function (type, content) {
   1.108 +    let report = this._getReportURI();
   1.109 +
   1.110 +    // file: URIs can't be used for targetOrigin, so we use "*" for
   1.111 +    // this special case.  In all other cases, pass in the URL to the
   1.112 +    // report so we properly restrict the message dispatch.
   1.113 +    let reportUrl = (report.scheme == "file") ? "*" : report.spec;
   1.114 +
   1.115 +    let data = {
   1.116 +      type: type,
   1.117 +      content: content,
   1.118 +    };
   1.119 +
   1.120 +    let iframe = document.getElementById("remote-report");
   1.121 +    iframe.contentWindow.postMessage(data, reportUrl);
   1.122 +  },
   1.123 +
   1.124 +  showSettings: function () {
   1.125 +    console.log("AboutHealthReport: showing settings.");
   1.126 +    sendMessageToJava({
   1.127 +      type: "Settings:Show",
   1.128 +      resource: "preferences_vendor",
   1.129 +    });
   1.130 +  },
   1.131 +
   1.132 +  launchUpdater: function () {
   1.133 +    console.log("AboutHealthReport: launching updater.");
   1.134 +    sendMessageToJava({
   1.135 +      type: "Updater:Launch",
   1.136 +    });
   1.137 +  },
   1.138 +
   1.139 +  handleRemoteCommand: function (evt) {
   1.140 +    switch (evt.detail.command) {
   1.141 +      case "DisableDataSubmission":
   1.142 +        this.onOptOut();
   1.143 +        break;
   1.144 +      case "EnableDataSubmission":
   1.145 +        this.onOptIn();
   1.146 +        break;
   1.147 +      case "RequestCurrentPrefs":
   1.148 +        this.updatePrefState();
   1.149 +        break;
   1.150 +      case "RequestCurrentPayload":
   1.151 +        this.refreshPayload();
   1.152 +        break;
   1.153 +      case "ShowSettings":
   1.154 +        this.showSettings();
   1.155 +        break;
   1.156 +      case "LaunchUpdater":
   1.157 +        this.launchUpdater();
   1.158 +        break;
   1.159 +      default:
   1.160 +        Cu.reportError("Unexpected remote command received: " + evt.detail.command +
   1.161 +                       ". Ignoring command.");
   1.162 +        break;
   1.163 +    }
   1.164 +  },
   1.165 +
   1.166 +  initRemotePage: function () {
   1.167 +    let iframe = document.getElementById("remote-report").contentDocument;
   1.168 +    iframe.addEventListener("RemoteHealthReportCommand",
   1.169 +                            function onCommand(e) {healthReportWrapper.handleRemoteCommand(e);},
   1.170 +                            false);
   1.171 +    healthReportWrapper.injectData("begin", null);
   1.172 +  },
   1.173 +
   1.174 +  // error handling
   1.175 +  ERROR_INIT_FAILED:    1,
   1.176 +  ERROR_PAYLOAD_FAILED: 2,
   1.177 +  ERROR_PREFS_FAILED:   3,
   1.178 +
   1.179 +  reportFailure: function (error) {
   1.180 +    let details = {
   1.181 +      errorType: error,
   1.182 +    };
   1.183 +    healthReportWrapper.injectData("error", details);
   1.184 +  },
   1.185 +
   1.186 +  handleInitFailure: function () {
   1.187 +    healthReportWrapper.reportFailure(healthReportWrapper.ERROR_INIT_FAILED);
   1.188 +  },
   1.189 +
   1.190 +  handlePayloadFailure: function () {
   1.191 +    healthReportWrapper.reportFailure(healthReportWrapper.ERROR_PAYLOAD_FAILED);
   1.192 +  },
   1.193 +};
   1.194 +
   1.195 +window.addEventListener("load", healthReportWrapper.init.bind(healthReportWrapper), false);
   1.196 +window.addEventListener("unload", healthReportWrapper.uninit.bind(healthReportWrapper), false);
   1.197 \ No newline at end of file

mercurial