Merge mozilla-central to autoland. a=merge CLOSED TREE
[gecko.git] / browser / base / content / aboutTabCrashed.js
blob3ed15fa7045b9b9f374ad3a0ce8355e715b37a50
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/. */
5 /* eslint-env mozilla/remote-page */
7 var AboutTabCrashed = {
8   /**
9    * This can be set to true once this page receives a message from the
10    * parent saying whether or not a crash report is available.
11    */
12   hasReport: false,
14   /**
15    * The messages that we might receive from the parent.
16    */
17   MESSAGES: ["SetCrashReportAvailable", "CrashReportSent", "UpdateCount"],
19   /**
20    * Items for which we will listen for click events.
21    */
22   CLICK_TARGETS: ["closeTab", "restoreTab", "restoreAll", "sendReport"],
24   /**
25    * Returns information about this crashed tab.
26    *
27    * @return (Object) An object with the following properties:
28    *           title (String):
29    *             The title of the page that crashed.
30    *           URL (String):
31    *             The URL of the page that crashed.
32    */
33   get pageData() {
34     delete this.pageData;
36     let URL = document.documentURI;
37     let queryString = URL.replace(/^about:tabcrashed?e=tabcrashed/, "");
39     let titleMatch = queryString.match(/d=([^&]*)/);
40     let URLMatch = queryString.match(/u=([^&]*)/);
42     return (this.pageData = {
43       title:
44         titleMatch && titleMatch[1] ? decodeURIComponent(titleMatch[1]) : "",
45       URL: URLMatch && URLMatch[1] ? decodeURIComponent(URLMatch[1]) : "",
46     });
47   },
49   init() {
50     addEventListener("DOMContentLoaded", this);
52     document.title = this.pageData.title;
53   },
55   receiveMessage(message) {
56     switch (message.name) {
57       case "UpdateCount": {
58         this.setMultiple(message.data.count > 1);
59         break;
60       }
61       case "SetCrashReportAvailable": {
62         this.onSetCrashReportAvailable(message);
63         break;
64       }
65       case "CrashReportSent": {
66         this.onCrashReportSent();
67         break;
68       }
69     }
70   },
72   handleEvent(event) {
73     switch (event.type) {
74       case "DOMContentLoaded": {
75         this.onDOMContentLoaded();
76         break;
77       }
78       case "click": {
79         this.onClick(event);
80         break;
81       }
82     }
83   },
85   onDOMContentLoaded() {
86     this.MESSAGES.forEach(msg =>
87       RPMAddMessageListener(msg, this.receiveMessage.bind(this))
88     );
90     this.CLICK_TARGETS.forEach(targetID => {
91       let el = document.getElementById(targetID);
92       el.addEventListener("click", this);
93     });
95     // Error pages are loaded as LOAD_BACKGROUND, so they don't get load events.
96     let event = new CustomEvent("AboutTabCrashedLoad", { bubbles: true });
97     document.dispatchEvent(event);
99     RPMSendAsyncMessage("Load");
100   },
102   onClick(event) {
103     switch (event.target.id) {
104       case "closeTab": {
105         this.sendMessage("closeTab");
106         break;
107       }
109       case "restoreTab": {
110         this.sendMessage("restoreTab");
111         break;
112       }
114       case "restoreAll": {
115         this.sendMessage("restoreAll");
116         break;
117       }
119       case "sendReport": {
120         this.showCrashReportUI(event.target.checked);
121         break;
122       }
123     }
124   },
126   /**
127    * After this page tells the parent that it has loaded, the parent
128    * will respond with whether or not a crash report is available. This
129    * method handles that message.
130    *
131    * @param message
132    *        The message from the parent, which should contain a data
133    *        Object property with the following properties:
134    *
135    *        hasReport (bool):
136    *          Whether or not there is a crash report.
137    *
138    *        sendReport (bool):
139    *          Whether or not the the user prefers to send the report
140    *          by default.
141    *
142    *        includeURL (bool):
143    *          Whether or not the user prefers to send the URL of
144    *          the tab that crashed.
145    *
146    *        requestAutoSubmit (bool):
147    *          Whether or not we should ask the user to automatically
148    *          submit backlogged crash reports.
149    *
150    */
151   onSetCrashReportAvailable(message) {
152     let data = message.data;
154     if (data.hasReport) {
155       this.hasReport = true;
156       document.documentElement.classList.add("crashDumpAvailable");
158       document.getElementById("sendReport").checked = data.sendReport;
159       document.getElementById("includeURL").checked = data.includeURL;
161       this.showCrashReportUI(data.sendReport);
162     } else {
163       this.showCrashReportUI(false);
164     }
166     if (data.requestAutoSubmit) {
167       document.getElementById("requestAutoSubmit").hidden = false;
168     }
170     let event = new CustomEvent("AboutTabCrashedReady", { bubbles: true });
171     document.dispatchEvent(event);
172   },
174   /**
175    * Handler for when the parent reports that the crash report associated
176    * with this about:tabcrashed page has been sent.
177    */
178   onCrashReportSent() {
179     document.documentElement.classList.remove("crashDumpAvailable");
180     document.documentElement.classList.add("crashDumpSubmitted");
181   },
183   /**
184    * Toggles the display of the crash report form.
185    *
186    * @param shouldShow (bool)
187    *        True if the crash report form should be shown
188    */
189   showCrashReportUI(shouldShow) {
190     let options = document.getElementById("options");
191     options.hidden = !shouldShow;
192   },
194   /**
195    * Toggles whether or not the page is one of several visible pages
196    * showing the crash reporter. This controls some of the language
197    * on the page, along with what the "primary" button is.
198    *
199    * @param hasMultiple (bool)
200    *        True if there are multiple crash report pages being shown.
201    */
202   setMultiple(hasMultiple) {
203     let main = document.getElementById("main");
204     main.setAttribute("multiple", hasMultiple);
206     let restoreTab = document.getElementById("restoreTab");
208     // The "Restore All" button has the "primary" class by default, so
209     // we only need to modify the "Restore Tab" button.
210     if (hasMultiple) {
211       restoreTab.classList.remove("primary");
212     } else {
213       restoreTab.classList.add("primary");
214     }
215   },
217   /**
218    * Sends a message to the parent in response to the user choosing
219    * one of the actions available on the page. This might also send up
220    * crash report information if the user has chosen to submit a crash
221    * report.
222    *
223    * @param messageName (String)
224    *        The message to send to the parent
225    */
226   sendMessage(messageName) {
227     let comments = "";
228     let URL = "";
229     let sendReport = false;
230     let includeURL = false;
231     let autoSubmit = false;
233     if (this.hasReport) {
234       sendReport = document.getElementById("sendReport").checked;
235       if (sendReport) {
236         comments = document.getElementById("comments").value.trim();
238         includeURL = document.getElementById("includeURL").checked;
239         if (includeURL) {
240           URL = this.pageData.URL.trim();
241         }
242       }
243     }
245     let requestAutoSubmit = document.getElementById("requestAutoSubmit");
246     if (requestAutoSubmit.hidden) {
247       // The checkbox is hidden if the user has already opted in to sending
248       // backlogged crash reports.
249       autoSubmit = true;
250     } else {
251       autoSubmit = document.getElementById("autoSubmit").checked;
252     }
254     RPMSendAsyncMessage(messageName, {
255       sendReport,
256       comments,
257       includeURL,
258       URL,
259       autoSubmit,
260       hasReport: this.hasReport,
261     });
262   },
265 AboutTabCrashed.init();