|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 "use strict"; |
|
6 |
|
7 const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
|
8 |
|
9 Cu.import("resource://gre/modules/Preferences.jsm"); |
|
10 Cu.import("resource://gre/modules/Services.jsm"); |
|
11 |
|
12 const reporter = Cc["@mozilla.org/datareporting/service;1"] |
|
13 .getService(Ci.nsISupports) |
|
14 .wrappedJSObject |
|
15 .healthReporter; |
|
16 |
|
17 const policy = Cc["@mozilla.org/datareporting/service;1"] |
|
18 .getService(Ci.nsISupports) |
|
19 .wrappedJSObject |
|
20 .policy; |
|
21 |
|
22 const prefs = new Preferences("datareporting.healthreport."); |
|
23 |
|
24 |
|
25 let healthReportWrapper = { |
|
26 init: function () { |
|
27 if (!reporter) { |
|
28 healthReportWrapper.handleInitFailure(); |
|
29 return; |
|
30 } |
|
31 |
|
32 reporter.onInit().then(healthReportWrapper.refreshPayload, |
|
33 healthReportWrapper.handleInitFailure); |
|
34 |
|
35 let iframe = document.getElementById("remote-report"); |
|
36 iframe.addEventListener("load", healthReportWrapper.initRemotePage, false); |
|
37 let report = this._getReportURI(); |
|
38 iframe.src = report.spec; |
|
39 prefs.observe("uploadEnabled", this.updatePrefState, healthReportWrapper); |
|
40 }, |
|
41 |
|
42 uninit: function () { |
|
43 prefs.ignore("uploadEnabled", this.updatePrefState, healthReportWrapper); |
|
44 }, |
|
45 |
|
46 _getReportURI: function () { |
|
47 let url = Services.urlFormatter.formatURLPref("datareporting.healthreport.about.reportUrl"); |
|
48 return Services.io.newURI(url, null, null); |
|
49 }, |
|
50 |
|
51 onOptIn: function () { |
|
52 policy.recordHealthReportUploadEnabled(true, |
|
53 "Health report page sent opt-in command."); |
|
54 this.updatePrefState(); |
|
55 }, |
|
56 |
|
57 onOptOut: function () { |
|
58 policy.recordHealthReportUploadEnabled(false, |
|
59 "Health report page sent opt-out command."); |
|
60 this.updatePrefState(); |
|
61 }, |
|
62 |
|
63 updatePrefState: function () { |
|
64 try { |
|
65 let prefs = { |
|
66 enabled: policy.healthReportUploadEnabled, |
|
67 } |
|
68 this.injectData("prefs", prefs); |
|
69 } catch (e) { |
|
70 this.reportFailure(this.ERROR_PREFS_FAILED); |
|
71 } |
|
72 }, |
|
73 |
|
74 refreshPayload: function () { |
|
75 reporter.collectAndObtainJSONPayload().then(healthReportWrapper.updatePayload, |
|
76 healthReportWrapper.handlePayloadFailure); |
|
77 }, |
|
78 |
|
79 updatePayload: function (data) { |
|
80 healthReportWrapper.injectData("payload", data); |
|
81 }, |
|
82 |
|
83 injectData: function (type, content) { |
|
84 let report = this._getReportURI(); |
|
85 |
|
86 // file URIs can't be used for targetOrigin, so we use "*" for this special case |
|
87 // in all other cases, pass in the URL to the report so we properly restrict the message dispatch |
|
88 let reportUrl = report.scheme == "file" ? "*" : report.spec; |
|
89 |
|
90 let data = { |
|
91 type: type, |
|
92 content: content |
|
93 } |
|
94 |
|
95 let iframe = document.getElementById("remote-report"); |
|
96 iframe.contentWindow.postMessage(data, reportUrl); |
|
97 }, |
|
98 |
|
99 handleRemoteCommand: function (evt) { |
|
100 switch (evt.detail.command) { |
|
101 case "DisableDataSubmission": |
|
102 this.onOptOut(); |
|
103 break; |
|
104 case "EnableDataSubmission": |
|
105 this.onOptIn(); |
|
106 break; |
|
107 case "RequestCurrentPrefs": |
|
108 this.updatePrefState(); |
|
109 break; |
|
110 case "RequestCurrentPayload": |
|
111 this.refreshPayload(); |
|
112 break; |
|
113 default: |
|
114 Cu.reportError("Unexpected remote command received: " + evt.detail.command + ". Ignoring command."); |
|
115 break; |
|
116 } |
|
117 }, |
|
118 |
|
119 initRemotePage: function () { |
|
120 let iframe = document.getElementById("remote-report").contentDocument; |
|
121 iframe.addEventListener("RemoteHealthReportCommand", |
|
122 function onCommand(e) {healthReportWrapper.handleRemoteCommand(e);}, |
|
123 false); |
|
124 healthReportWrapper.updatePrefState(); |
|
125 }, |
|
126 |
|
127 // error handling |
|
128 ERROR_INIT_FAILED: 1, |
|
129 ERROR_PAYLOAD_FAILED: 2, |
|
130 ERROR_PREFS_FAILED: 3, |
|
131 |
|
132 reportFailure: function (error) { |
|
133 let details = { |
|
134 errorType: error, |
|
135 } |
|
136 healthReportWrapper.injectData("error", details); |
|
137 }, |
|
138 |
|
139 handleInitFailure: function () { |
|
140 healthReportWrapper.reportFailure(healthReportWrapper.ERROR_INIT_FAILED); |
|
141 }, |
|
142 |
|
143 handlePayloadFailure: function () { |
|
144 healthReportWrapper.reportFailure(healthReportWrapper.ERROR_PAYLOAD_FAILED); |
|
145 }, |
|
146 } |
|
147 |
|
148 window.addEventListener("load", function () { healthReportWrapper.init(); }); |
|
149 window.addEventListener("unload", function () { healthReportWrapper.uninit(); }); |