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