From f7719bcd8d653fc57e6f25e176b9b6c200b07fb0 Mon Sep 17 00:00:00 2001 From: Mike Connor Date: Thu, 14 Mar 2013 21:25:04 -0400 Subject: [PATCH] Bug 840124 - implement postMessage API for remote report (code), r=jaws, f=gps+gavin --HG-- extra : rebase_source : d2ea2c4d5e237695d0f51ad35e5e3ad4dc263b61 --- .../content/abouthealthreport/abouthealth.css | 131 +---------- .../content/abouthealthreport/abouthealth.js | 204 ++++++++++-------- .../abouthealthreport/abouthealth.xhtml | 46 +--- .../chrome/browser/aboutHealthReport.dtd | 25 --- 4 files changed, 115 insertions(+), 291 deletions(-) diff --git a/browser/base/content/abouthealthreport/abouthealth.css b/browser/base/content/abouthealthreport/abouthealth.css index 6a9a8fa03bc..3dd40fc2431 100644 --- a/browser/base/content/abouthealthreport/abouthealth.css +++ b/browser/base/content/abouthealthreport/abouthealth.css @@ -7,134 +7,9 @@ html, body { height: 100%; } -body { - background-color: window; - color: windowtext; - font-family: "Trebuchet MS", "Helvetica"; -} - -#about-header { - padding: 6px 20px; - min-height: 60px; - border-bottom: 1px solid #999999; - margin-bottom: 12px; - display: flex; - align-items: center; - justify-content: space-between; - background-image: linear-gradient(to bottom, #E66000, #BB2200); - color: #FFFFFF; -} - -#control-container { - display: flex; - align-items: center; -} - -#content-line { - display: flex; - justify-content: space-between; - align-items: center; -} - -#content { - display: flex; - flex-direction: column; -} - -#state-intro { - background-image: linear-gradient(to bottom, #EAEFF2, #D4DDE4); - border: 1px solid #999999; - border-radius: 6px; - margin: 12px; - padding: 12px; -} - -#settings-controls { - padding-top: 15px; -} - -#control-container { - padding-top: 15px; -} - -#content[state="default"] #details-hide, -#content[state="default"] #btn-optin, -#content[state="default"] #intro-disabled { - display: none; -} - -#content[state="showDetails"] #details-show, -#content[state="showDetails"] #btn-optin, -#content[state="showDetails"] #intro-disabled { - display: none; -} - -#content[state="showReport"] #details-hide, -#content[state="showReport"] #report-show, -#content[state="showReport"] #btn-optin, -#content[state="showReport"] #intro-disabled { - display: none; -} - -#content[state="disabled"] #details-hide, -#content[state="disabled"] #details-show, -#content[state="disabled"] #btn-optout, -#content[state="disabled"] #intro-enabled { - display: none; -} - -#details-view, -#report-view { - display: none; -} - -#data-view { - height: auto; - margin-top: 8px; - align-items: center; - justify-content: center; - border: 1px solid #999999; - border-radius: 6px; - margin: 12px; -} - -#remote-report, -#report-view { - width: 100%; - height: 100%; - min-height: 600px; -} - -#report-show { - display: flex; - width: 100%; - height: 100%; - min-height: 60px; - font-size: 18px; - font-weight: bold; - background-image: linear-gradient(to bottom, #80BB2E, #547D1C); - color: #ffffff; - border-radius: 6px; -} - -#details-view { - border: 1px solid #999999; - border-radius: 6px; - margin: 12px; - padding: 12px; -} - -#content[state="showDetails"], -#content[state="showReport"], -#content[state="showDetails"] #details-view, -#content[state="showReport"] #report-view { - display: block; -} - -#content[state="showReport"] #report-show { - display: none; -} -#content[state="showReport"] #report-view, #remote-report { + width: 100%; + height: 100%; border: 0; + display: flex; } diff --git a/browser/base/content/abouthealthreport/abouthealth.js b/browser/base/content/abouthealthreport/abouthealth.js index 637d6c6cc22..a39e77f8577 100644 --- a/browser/base/content/abouthealthreport/abouthealth.js +++ b/browser/base/content/abouthealthreport/abouthealth.js @@ -7,6 +7,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; Cu.import("resource://services-common/preferences.js"); +Cu.import("resource://gre/modules/Services.jsm"); const reporter = Cc["@mozilla.org/datareporting/service;1"] .getService(Ci.nsISupports) @@ -18,99 +19,114 @@ const policy = Cc["@mozilla.org/datareporting/service;1"] .wrappedJSObject .policy; -const prefs = new Preferences("datareporting.healthreport.about."); +const prefs = new Preferences("datareporting.healthreport."); -function getLocale() { - return Cc["@mozilla.org/chrome/chrome-registry;1"] - .getService(Ci.nsIXULChromeRegistry) - .getSelectedLocale("global"); + +let healthReportWrapper = { + init: function () { + reporter.onInit().then(healthReportWrapper.refreshPayload, + healthReportWrapper.handleInitFailure); + + let iframe = document.getElementById("remote-report"); + iframe.addEventListener("load", healthReportWrapper.initRemotePage, false); + let report = Services.io.newURI(prefs.get("about.reportUrl"), null, null); + iframe.src = report.spec; + prefs.observe("uploadEnabled", this.updatePrefState, healthReportWrapper); + }, + + 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."); + this.updatePrefState(); + }, + + updatePrefState: function () { + try { + let prefs = { + enabled: policy.healthReportUploadEnabled, + } + this.injectData("prefs", prefs); + } catch (e) { + this.reportFailure(this.ERROR_PREFS_FAILED); + } + }, + + refreshPayload: function () { + reporter.collectAndObtainJSONPayload().then(healthReportWrapper.updatePayload, + healthReportWrapper.handlePayloadFailure); + }, + + updatePayload: function (data) { + healthReportWrapper.injectData("payload", data); + }, + + injectData: function (type, content) { + let report = Services.io.newURI(prefs.get("about.reportUrl"), null, null); + + // 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); + }, + + 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; + 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.updatePrefState(); + }, + + // 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); + }, } - -function init() { - refreshWithDataSubmissionFlag(policy.healthReportUploadEnabled); - refreshJSONPayload(); - document.getElementById("details-link").href = prefs.get("glossaryUrl"); -} - -/** - * Update the state of the page to reflect the current data submission state. - * - * @param enabled - * (bool) Whether data submission is enabled. - */ -function refreshWithDataSubmissionFlag(enabled) { - if (!enabled) { - updateView("disabled"); - } else { - updateView("default"); - } -} - -function updateView(state="default") { - let content = document.getElementById("content"); - let controlContainer = document.getElementById("control-container"); - content.setAttribute("state", state); - controlContainer.setAttribute("state", state); -} - -function refreshDataView(data) { - let noData = document.getElementById("data-no-data"); - let dataEl = document.getElementById("raw-data"); - - noData.style.display = data ? "none" : "inline"; - dataEl.style.display = data ? "block" : "none"; - if (data) { - dataEl.textContent = JSON.stringify(data, null, 2); - } -} - -/** - * Ensure the page has the latest version of the uploaded JSON payload. - */ -function refreshJSONPayload() { - reporter.getLastPayload().then(refreshDataView); -} - -function onOptInClick() { - policy.recordHealthReportUploadEnabled(true, - "Clicked opt in button on about page."); - refreshWithDataSubmissionFlag(true); -} - -function onOptOutClick() { - let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"] - .getService(Ci.nsIPromptService); - - let messages = document.getElementById("optout-confirmationPrompt"); - let title = messages.getAttribute("confirmationPrompt_title"); - let message = messages.getAttribute("confirmationPrompt_message"); - - if (!prompts.confirm(window, title, message)) { - return; - } - - policy.recordHealthReportUploadEnabled(false, - "Clicked opt out button on about page."); - refreshWithDataSubmissionFlag(false); - updateView("disabled"); -} - -function onShowRawDataClick() { - updateView("showDetails"); - refreshJSONPayload(); -} - -function onHideRawDataClick() { - updateView("default"); -} - -function onShowReportClick() { - updateView("showReport"); - document.getElementById("remote-report").src = prefs.get("reportUrl"); -} - -function onHideReportClick() { - updateView("default"); - document.getElementById("remote-report").src = ""; -} - diff --git a/browser/base/content/abouthealthreport/abouthealth.xhtml b/browser/base/content/abouthealthreport/abouthealth.xhtml index 4a98cf9f32f..7f6f49310a4 100644 --- a/browser/base/content/abouthealthreport/abouthealth.xhtml +++ b/browser/base/content/abouthealthreport/abouthealth.xhtml @@ -22,50 +22,8 @@