/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* eslint-env mozilla/remote-page */ var AboutTabCrashed = { /** * This can be set to true once this page receives a message from the * parent saying whether or not a crash report is available. */ hasReport: false, /** * The messages that we might receive from the parent. */ MESSAGES: ["SetCrashReportAvailable", "CrashReportSent", "UpdateCount"], /** * Items for which we will listen for click events. */ CLICK_TARGETS: ["closeTab", "restoreTab", "restoreAll", "sendReport"], /** * Returns information about this crashed tab. * * @return (Object) An object with the following properties: * title (String): * The title of the page that crashed. * URL (String): * The URL of the page that crashed. */ get pageData() { delete this.pageData; let URL = document.documentURI; let queryString = URL.replace(/^about:tabcrashed?e=tabcrashed/, ""); let titleMatch = queryString.match(/d=([^&]*)/); let URLMatch = queryString.match(/u=([^&]*)/); return (this.pageData = { title: titleMatch && titleMatch[1] ? decodeURIComponent(titleMatch[1]) : "", URL: URLMatch && URLMatch[1] ? decodeURIComponent(URLMatch[1]) : "", }); }, init() { addEventListener("DOMContentLoaded", this); document.title = this.pageData.title; }, receiveMessage(message) { switch (message.name) { case "UpdateCount": { this.setMultiple(message.data.count > 1); break; } case "SetCrashReportAvailable": { this.onSetCrashReportAvailable(message); break; } case "CrashReportSent": { this.onCrashReportSent(); break; } } }, handleEvent(event) { switch (event.type) { case "DOMContentLoaded": { this.onDOMContentLoaded(); break; } case "click": { this.onClick(event); break; } } }, onDOMContentLoaded() { this.MESSAGES.forEach(msg => RPMAddMessageListener(msg, this.receiveMessage.bind(this)) ); this.CLICK_TARGETS.forEach(targetID => { let el = document.getElementById(targetID); el.addEventListener("click", this); }); // Error pages are loaded as LOAD_BACKGROUND, so they don't get load events. let event = new CustomEvent("AboutTabCrashedLoad", { bubbles: true }); document.dispatchEvent(event); RPMSendAsyncMessage("Load"); }, onClick(event) { switch (event.target.id) { case "closeTab": { this.sendMessage("closeTab"); break; } case "restoreTab": { this.sendMessage("restoreTab"); break; } case "restoreAll": { this.sendMessage("restoreAll"); break; } case "sendReport": { this.showCrashReportUI(event.target.checked); break; } } }, /** * After this page tells the parent that it has loaded, the parent * will respond with whether or not a crash report is available. This * method handles that message. * * @param message * The message from the parent, which should contain a data * Object property with the following properties: * * hasReport (bool): * Whether or not there is a crash report. * * sendReport (bool): * Whether or not the the user prefers to send the report * by default. * * includeURL (bool): * Whether or not the user prefers to send the URL of * the tab that crashed. * * requestAutoSubmit (bool): * Whether or not we should ask the user to automatically * submit backlogged crash reports. * */ onSetCrashReportAvailable(message) { let data = message.data; if (data.hasReport) { this.hasReport = true; document.documentElement.classList.add("crashDumpAvailable"); document.getElementById("sendReport").checked = data.sendReport; document.getElementById("includeURL").checked = data.includeURL; this.showCrashReportUI(data.sendReport); } else { this.showCrashReportUI(false); } if (data.requestAutoSubmit) { document.getElementById("requestAutoSubmit").hidden = false; } let event = new CustomEvent("AboutTabCrashedReady", { bubbles: true }); document.dispatchEvent(event); }, /** * Handler for when the parent reports that the crash report associated * with this about:tabcrashed page has been sent. */ onCrashReportSent() { document.documentElement.classList.remove("crashDumpAvailable"); document.documentElement.classList.add("crashDumpSubmitted"); }, /** * Toggles the display of the crash report form. * * @param shouldShow (bool) * True if the crash report form should be shown */ showCrashReportUI(shouldShow) { let options = document.getElementById("options"); options.hidden = !shouldShow; }, /** * Toggles whether or not the page is one of several visible pages * showing the crash reporter. This controls some of the language * on the page, along with what the "primary" button is. * * @param hasMultiple (bool) * True if there are multiple crash report pages being shown. */ setMultiple(hasMultiple) { let main = document.getElementById("main"); main.setAttribute("multiple", hasMultiple); let restoreTab = document.getElementById("restoreTab"); // The "Restore All" button has the "primary" class by default, so // we only need to modify the "Restore Tab" button. if (hasMultiple) { restoreTab.classList.remove("primary"); } else { restoreTab.classList.add("primary"); } }, /** * Sends a message to the parent in response to the user choosing * one of the actions available on the page. This might also send up * crash report information if the user has chosen to submit a crash * report. * * @param messageName (String) * The message to send to the parent */ sendMessage(messageName) { let comments = ""; let URL = ""; let sendReport = false; let includeURL = false; let autoSubmit = false; if (this.hasReport) { sendReport = document.getElementById("sendReport").checked; if (sendReport) { comments = document.getElementById("comments").value.trim(); includeURL = document.getElementById("includeURL").checked; if (includeURL) { URL = this.pageData.URL.trim(); } } } let requestAutoSubmit = document.getElementById("requestAutoSubmit"); if (requestAutoSubmit.hidden) { // The checkbox is hidden if the user has already opted in to sending // backlogged crash reports. autoSubmit = true; } else { autoSubmit = document.getElementById("autoSubmit").checked; } RPMSendAsyncMessage(messageName, { sendReport, comments, includeURL, URL, autoSubmit, hasReport: this.hasReport, }); }, }; AboutTabCrashed.init();