michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const { classes: Cc, utils: Cu, interfaces: Ci } = Components; michael@0: michael@0: var reportURL; michael@0: michael@0: Cu.import("resource://gre/modules/CrashReports.jsm"); michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: Cu.import("resource://gre/modules/Task.jsm"); michael@0: Cu.import("resource://gre/modules/osfile.jsm"); michael@0: michael@0: XPCOMUtils.defineLazyModuleGetter(this, "CrashSubmit", michael@0: "resource://gre/modules/CrashSubmit.jsm"); michael@0: michael@0: const buildID = Services.appinfo.appBuildID; michael@0: michael@0: function submitSuccess(dumpid, ret) { michael@0: let link = document.getElementById(dumpid); michael@0: if (link) { michael@0: link.className = ""; michael@0: // reset the link to point at our new crash report. this way, if the michael@0: // user clicks "Back", the link will be correct. michael@0: let CrashID = ret.CrashID; michael@0: link.firstChild.textContent = CrashID; michael@0: link.setAttribute("id", CrashID); michael@0: link.removeEventListener("click", submitPendingReport, true); michael@0: michael@0: if (reportURL) { michael@0: link.setAttribute("href", reportURL + CrashID); michael@0: // redirect the user to their brand new crash report michael@0: window.location.href = reportURL + CrashID; michael@0: } michael@0: } michael@0: } michael@0: michael@0: function submitError(dumpid) { michael@0: //XXX: do something more useful here michael@0: let link = document.getElementById(dumpid); michael@0: if (link) michael@0: link.className = ""; michael@0: // dispatch an event, useful for testing michael@0: let event = document.createEvent("Events"); michael@0: event.initEvent("CrashSubmitFailed", true, false); michael@0: document.dispatchEvent(event); michael@0: } michael@0: michael@0: function submitPendingReport(event) { michael@0: var link = event.target; michael@0: var id = link.firstChild.textContent; michael@0: if (CrashSubmit.submit(id, { submitSuccess: submitSuccess, michael@0: submitError: submitError, michael@0: noThrottle: true })) { michael@0: link.className = "submitting"; michael@0: } michael@0: event.preventDefault(); michael@0: return false; michael@0: } michael@0: michael@0: function populateReportList() { michael@0: var prefService = Cc["@mozilla.org/preferences-service;1"]. michael@0: getService(Ci.nsIPrefBranch); michael@0: michael@0: try { michael@0: reportURL = prefService.getCharPref("breakpad.reportURL"); michael@0: // Ignore any non http/https urls michael@0: if (!/^https?:/i.test(reportURL)) michael@0: reportURL = null; michael@0: } michael@0: catch (e) { } michael@0: if (!reportURL) { michael@0: document.getElementById("clear-reports").style.display = "none"; michael@0: document.getElementById("reportList").style.display = "none"; michael@0: document.getElementById("noConfig").style.display = "block"; michael@0: return; michael@0: } michael@0: let reports = CrashReports.getReports(); michael@0: michael@0: if (reports.length == 0) { michael@0: document.getElementById("clear-reports").style.display = "none"; michael@0: document.getElementById("reportList").style.display = "none"; michael@0: document.getElementById("noReports").style.display = "block"; michael@0: return; michael@0: } michael@0: michael@0: var formatter = Cc["@mozilla.org/intl/scriptabledateformat;1"]. michael@0: createInstance(Ci.nsIScriptableDateFormat); michael@0: var body = document.getElementById("tbody"); michael@0: var ios = Cc["@mozilla.org/network/io-service;1"]. michael@0: getService(Ci.nsIIOService); michael@0: var reportURI = ios.newURI(reportURL, null, null); michael@0: // resolving this URI relative to /report/index michael@0: var aboutThrottling = ios.newURI("../../about/throttling", null, reportURI); michael@0: michael@0: for (var i = 0; i < reports.length; i++) { michael@0: var row = document.createElement("tr"); michael@0: var cell = document.createElement("td"); michael@0: row.appendChild(cell); michael@0: var link = document.createElement("a"); michael@0: if (reports[i].pending) { michael@0: link.setAttribute("href", aboutThrottling.spec); michael@0: link.addEventListener("click", submitPendingReport, true); michael@0: } michael@0: else { michael@0: link.setAttribute("href", reportURL + reports[i].id); michael@0: } michael@0: link.setAttribute("id", reports[i].id); michael@0: link.appendChild(document.createTextNode(reports[i].id)); michael@0: cell.appendChild(link); michael@0: michael@0: var date = new Date(reports[i].date); michael@0: cell = document.createElement("td"); michael@0: var datestr = formatter.FormatDate("", michael@0: Ci.nsIScriptableDateFormat.dateFormatShort, michael@0: date.getFullYear(), michael@0: date.getMonth() + 1, michael@0: date.getDate()); michael@0: cell.appendChild(document.createTextNode(datestr)); michael@0: row.appendChild(cell); michael@0: cell = document.createElement("td"); michael@0: var timestr = formatter.FormatTime("", michael@0: Ci.nsIScriptableDateFormat.timeFormatNoSeconds, michael@0: date.getHours(), michael@0: date.getMinutes(), michael@0: date.getSeconds()); michael@0: cell.appendChild(document.createTextNode(timestr)); michael@0: row.appendChild(cell); michael@0: body.appendChild(row); michael@0: } michael@0: } michael@0: michael@0: let clearReports = Task.async(function*() { michael@0: let bundle = Services.strings.createBundle("chrome://global/locale/crashes.properties"); michael@0: michael@0: if (!Services. michael@0: prompt.confirm(window, michael@0: bundle.GetStringFromName("deleteconfirm.title"), michael@0: bundle.GetStringFromName("deleteconfirm.description"))) { michael@0: return; michael@0: } michael@0: michael@0: let cleanupFolder = Task.async(function*(path, filter) { michael@0: let iterator = new OS.File.DirectoryIterator(path); michael@0: try { michael@0: yield iterator.forEach(Task.async(function*(aEntry) { michael@0: if (!filter || (yield filter(aEntry))) { michael@0: yield OS.File.remove(aEntry.path); michael@0: } michael@0: })); michael@0: } catch (e if e instanceof OS.File.Error && e.becauseNoSuchFile) { michael@0: } finally { michael@0: iterator.close(); michael@0: } michael@0: }); michael@0: michael@0: yield cleanupFolder(CrashReports.submittedDir.path, function*(aEntry) { michael@0: return aEntry.name.startsWith("bp-") && aEntry.name.endsWith(".txt"); michael@0: }); michael@0: michael@0: let oneYearAgo = Date.now() - 31586000000; michael@0: yield cleanupFolder(CrashReports.reportsDir.path, function*(aEntry) { michael@0: if (!aEntry.name.startsWith("InstallTime") || michael@0: aEntry.name == "InstallTime" + buildID) { michael@0: return false; michael@0: } michael@0: michael@0: let date = aEntry.winLastWriteDate; michael@0: if (!date) { michael@0: let stat = yield OS.File.stat(aEntry.path); michael@0: date = stat.lastModificationDate; michael@0: } michael@0: michael@0: return (date < oneYearAgo); michael@0: }); michael@0: michael@0: yield cleanupFolder(CrashReports.pendingDir.path); michael@0: michael@0: document.getElementById("clear-reports").style.display = "none"; michael@0: document.getElementById("reportList").style.display = "none"; michael@0: document.getElementById("noReports").style.display = "block"; michael@0: });