From 446b329c0aac4f1e5216e09c5c8d2e2587f2de3b Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Mon, 17 Aug 2009 14:41:57 -0400 Subject: [PATCH] =?UTF-8?q?Backed=20out=20changeset=2021ad4f1ce214=20-=20T?= =?UTF-8?q?ed=20Mielczarek=20=E2=80=93=20bug=20378528=20-=20crash=20report?= =?UTF-8?q?er=20should=20allow=20resubmission=20of=20pending=20reports,=20?= =?UTF-8?q?due=20to=20leaks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/crash-submit-form.xhtml | 9 - toolkit/crashreporter/content/crashes.js | 414 ------------------ toolkit/crashreporter/content/crashes.xhtml | 147 ++++++- toolkit/crashreporter/jar.mn | 4 +- toolkit/crashreporter/test/Makefile.in | 2 - .../test/browser/aboutcrashes_utils.js | 68 +-- .../test/browser/browser_aboutCrashes.js | 2 +- .../browser/browser_aboutCrashesResubmit.js | 144 ------ .../test/browser/crashreport.sjs | 172 -------- 9 files changed, 153 insertions(+), 809 deletions(-) delete mode 100644 toolkit/crashreporter/content/crash-submit-form.xhtml delete mode 100644 toolkit/crashreporter/content/crashes.js delete mode 100644 toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js delete mode 100644 toolkit/crashreporter/test/browser/crashreport.sjs diff --git a/toolkit/crashreporter/content/crash-submit-form.xhtml b/toolkit/crashreporter/content/crash-submit-form.xhtml deleted file mode 100644 index 80ddc90e54a..00000000000 --- a/toolkit/crashreporter/content/crash-submit-form.xhtml +++ /dev/null @@ -1,9 +0,0 @@ - - - - -
- -
- diff --git a/toolkit/crashreporter/content/crashes.js b/toolkit/crashreporter/content/crashes.js deleted file mode 100644 index a6a66061b2c..00000000000 --- a/toolkit/crashreporter/content/crashes.js +++ /dev/null @@ -1,414 +0,0 @@ -const Cc = Components.classes; -const Ci = Components.interfaces; - -var reportURL = null; -var reportsDir, pendingDir; -var strings = null; - -function parseKeyValuePairs(text) { - var lines = text.split('\n'); - var data = {}; - for (let i = 0; i < lines.length; i++) { - if (lines[i] == '') - continue; - - [key, value] = lines[i].split('=', 2); - if (value) - data[key] = value.replace("\\n", "\n", "g").replace("\\\\", "\\", "g"); - } - return data; -} - -function parseKeyValuePairsFromFile(file) { - var fstream = Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(Ci.nsIFileInputStream); - fstream.init(file, -1, 0, 0); - var is = Cc["@mozilla.org/intl/converter-input-stream;1"]. - createInstance(Ci.nsIConverterInputStream); - is.init(fstream, "UTF-8", 1024, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); - var str = {}; - var contents = ''; - while (is.readString(4096, str) != 0) { - contents += str.value; - } - is.close(); - fstream.close(); - return parseKeyValuePairs(contents); -} - -function parseINIStrings(file) { - var factory = Cc["@mozilla.org/xpcom/ini-parser-factory;1"]. - getService(Ci.nsIINIParserFactory); - var parser = factory.createINIParser(file); - var obj = {}; - var en = parser.getKeys("Strings"); - while (en.hasMore()) { - var key = en.getNext(); - obj[key] = parser.getString("Strings", key); - } - return obj; -} - -// Since we're basically re-implementing part of the crashreporter -// client here, we'll just steal the strings we need from crashreporter.ini -function getL10nStrings() { - let dirSvc = Cc["@mozilla.org/file/directory_service;1"]. - getService(Ci.nsIProperties); - let path = dirSvc.get("GreD", Ci.nsIFile); - path.append("crashreporter.ini"); - if (!path.exists()) { - // see if we're on a mac - path = path.parent; - path.append("crashreporter.app"); - path.append("Contents"); - path.append("MacOS"); - path.append("crashreporter.ini"); - if (!path.exists()) { - // very bad, but I don't know how to recover - return; - } - } - let crstrings = parseINIStrings(path); - strings = { - 'crashid': crstrings.CrashID, - 'reporturl': crstrings.CrashDetailsURL - }; - - path = dirSvc.get("XCurProcD", Ci.nsIFile); - path.append("crashreporter-override.ini"); - if (path.exists()) { - crstrings = parseINIStrings(path); - if ('CrashID' in crstrings) - strings['crashid'] = crstrings.CrashID; - if ('CrashDetailsURL' in crstrings) - strings['reporturl'] = crstrings.CrashDetailsURL; - } -} - -function getPendingMinidump(id) { - let directoryService = Cc["@mozilla.org/file/directory_service;1"]. - getService(Ci.nsIProperties); - let dump = pendingDir.clone(); - let extra = pendingDir.clone(); - dump.append(id + ".dmp"); - extra.append(id + ".extra"); - return [dump, extra]; -} - -function addFormEntry(doc, form, name, value) { - var input = doc.createElement("input"); - input.type = "hidden"; - input.name = name; - input.value = value; - form.appendChild(input); -} - -function writeSubmittedReport(crashID, viewURL) { - let reportFile = reportsDir.clone(); - reportFile.append(crashID + ".txt"); - var fstream = Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(Ci.nsIFileOutputStream); - // open, write, truncate - fstream.init(reportFile, -1, -1, 0); - var os = Cc["@mozilla.org/intl/converter-output-stream;1"]. - createInstance(Ci.nsIConverterOutputStream); - os.init(fstream, "UTF-8", 0, 0x0000); - - var data = strings.crashid.replace("%s", crashID); - if (viewURL) - data += "\n" + strings.reporturl.replace("%s", viewURL); - - os.writeString(data); - os.close(); - fstream.close(); -} - -function submitSuccess(ret, link, dump, extra) { - if (!ret.CrashID) - return; - // Write out the details file to submitted/ - writeSubmittedReport(ret.CrashID, ret.ViewURL); - - // Delete from pending dir - try { - dump.remove(false); - extra.remove(false); - } - catch (ex) { - // report an error? not much the user can do here. - } - - // reset the link to point at our new crash report. this way, if the - // user clicks "Back", the link will be correct. - let CrashID = ret.CrashID; - link.firstChild.textContent = CrashID; - link.setAttribute("id", CrashID); - link.removeEventListener("click", submitPendingReport, true); - - if (reportURL) { - link.setAttribute("href", reportURL + CrashID); - // redirect the user to their brand new crash report - window.location.href = reportURL + CrashID; - } -} - -function submitForm(iframe, dump, extra, link) -{ - let reportData = parseKeyValuePairsFromFile(extra); - let form = iframe.contentDocument.forms[0]; - if ('ServerURL' in reportData) { - form.action = reportData.ServerURL; - delete reportData.ServerURL; - } - else { - return false; - } - // add the other data - for (let [name, value] in Iterator(reportData)) { - addFormEntry(iframe.contentDocument, form, name, value); - } - // tell the server not to throttle this, since it was manually submitted - addFormEntry(iframe.contentDocument, form, "Throttleable", "0"); - // add the minidump - iframe.contentDocument.getElementById('minidump').value = dump.path; - - // web progress listener - const STATE_START = Ci.nsIWebProgressListener.STATE_START; - const STATE_STOP = Ci.nsIWebProgressListener.STATE_STOP; - let myListener = { - QueryInterface: function(aIID) { - if (aIID.equals(Ci.nsIWebProgressListener) || - aIID.equals(Ci.nsISupportsWeakReference) || - aIID.equals(Ci.nsISupports)) - return this; - throw Components.results.NS_NOINTERFACE; - }, - - onStateChange: function(aWebProgress, aRequest, aFlag, aStatus) { - if(aFlag & STATE_STOP) { - iframe.docShell.removeProgressListener(myListener); - link.className = ""; - - //XXX: give some indication of failure? - // check general request status first - if (!Components.isSuccessCode(aStatus)) { - document.body.removeChild(iframe); - return 0; - } - // check HTTP status - if (aRequest instanceof Ci.nsIHttpChannel && - aRequest.responseStatus != 200) { - document.body.removeChild(iframe); - return 0; - } - - var ret = parseKeyValuePairs(iframe.contentDocument.documentElement.textContent); - document.body.removeChild(iframe); - submitSuccess(ret, link, dump, extra); - } - return 0; - }, - - onLocationChange: function(aProgress, aRequest, aURI) {return 0;}, - onProgressChange: function() {return 0;}, - onStatusChange: function() {return 0;}, - onSecurityChange: function() {return 0;}, - onLinkIconAvailable: function() {return 0;} - }; - iframe.docShell.QueryInterface(Ci.nsIWebProgress); - iframe.docShell.addProgressListener(myListener, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT); - form.submit(); - return true; -} - -function createAndSubmitForm(id, link) { - let [dump, extra] = getPendingMinidump(id); - if (!dump.exists() || !extra.exists()) - return false; - let iframe = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "iframe"); - iframe.onload = function() { - if (iframe.contentWindow.location == "about:blank") - return; - iframe.onload = null; - submitForm(iframe, dump, extra, link); - }; - document.body.appendChild(iframe); - iframe.webNavigation.loadURI("chrome://global/content/crash-submit-form.xhtml", 0, null, null, null); - return true; -} - -function submitPendingReport(event) { - var link = event.target; - var id = link.firstChild.textContent; - if (createAndSubmitForm(id, link)) - link.className = "submitting"; - event.preventDefault(); - return false; -} - -function findInsertionPoint(reports, date) { - if (reports.length == 0) - return 0; - - var min = 0; - var max = reports.length - 1; - while (min < max) { - var mid = parseInt((min + max) / 2); - if (reports[mid].date < date) - max = mid - 1; - else if (reports[mid].date > date) - min = mid + 1; - else - return mid; - } - if (reports[min].date <= date) - return min; - return min+1; -} - -function populateReportList() { - var prefService = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefBranch); - - try { - reportURL = prefService.getCharPref("breakpad.reportURL"); - // Ignore any non http/https urls - if (!/^https?:/i.test(reportURL)) - reportURL = null; - } - catch (e) { } - if (!reportURL) { - document.getElementById("clear-reports").style.display = "none"; - document.getElementById("reportList").style.display = "none"; - document.getElementById("noConfig").style.display = "block"; - return; - } - var directoryService = Cc["@mozilla.org/file/directory_service;1"]. - getService(Ci.nsIProperties); - - reportsDir = directoryService.get("UAppData", Ci.nsIFile); - reportsDir.append("Crash Reports"); - reportsDir.append("submitted"); - - var reports = []; - if (reportsDir.exists() && reportsDir.isDirectory()) { - var entries = reportsDir.directoryEntries; - while (entries.hasMoreElements()) { - var file = entries.getNext().QueryInterface(Ci.nsIFile); - var leaf = file.leafName; - if (leaf.substr(0, 3) == "bp-" && - leaf.substr(-4) == ".txt") { - var entry = { - id: leaf.slice(0, -4), - date: file.lastModifiedTime, - pending: false - }; - var pos = findInsertionPoint(reports, entry.date); - reports.splice(pos, 0, entry); - } - } - } - - pendingDir = directoryService.get("UAppData", Ci.nsIFile); - pendingDir.append("Crash Reports"); - pendingDir.append("pending"); - - if (pendingDir.exists() && pendingDir.isDirectory()) { - var entries = pendingDir.directoryEntries; - while (entries.hasMoreElements()) { - var file = entries.getNext().QueryInterface(Ci.nsIFile); - var leaf = file.leafName; - if (leaf.substr(-4) == ".dmp") { - var entry = { - id: leaf.slice(0, -4), - date: file.lastModifiedTime, - pending: true - }; - var pos = findInsertionPoint(reports, entry.date); - reports.splice(pos, 0, entry); - } - } - } - - if (reports.length == 0) { - document.getElementById("clear-reports").style.display = "none"; - document.getElementById("reportList").style.display = "none"; - document.getElementById("noReports").style.display = "block"; - return; - } - - var formatter = Cc["@mozilla.org/intl/scriptabledateformat;1"]. - createInstance(Ci.nsIScriptableDateFormat); - var body = document.getElementById("tbody"); - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var reportURI = ios.newURI(reportURL, null, null); - // resolving this URI relative to /report/index - var aboutThrottling = ios.newURI("../../about/throttling", null, reportURI); - - for (var i = 0; i < reports.length; i++) { - var row = document.createElement("tr"); - var cell = document.createElement("td"); - row.appendChild(cell); - var link = document.createElement("a"); - if (reports[i].pending) { - link.setAttribute("href", aboutThrottling.spec); - link.addEventListener("click", submitPendingReport, true); - } - else { - link.setAttribute("href", reportURL + reports[i].id); - } - link.setAttribute("id", reports[i].id); - link.appendChild(document.createTextNode(reports[i].id)); - cell.appendChild(link); - - var date = new Date(reports[i].date); - cell = document.createElement("td"); - var datestr = formatter.FormatDate("", - Ci.nsIScriptableDateFormat.dateFormatShort, - date.getFullYear(), - date.getMonth() + 1, - date.getDate()); - cell.appendChild(document.createTextNode(datestr)); - row.appendChild(cell); - cell = document.createElement("td"); - var timestr = formatter.FormatTime("", - Ci.nsIScriptableDateFormat.timeFormatNoSeconds, - date.getHours(), - date.getMinutes(), - date.getSeconds()); - cell.appendChild(document.createTextNode(timestr)); - row.appendChild(cell); - body.appendChild(row); - } -} - -function clearReports() { - var bundles = Cc["@mozilla.org/intl/stringbundle;1"]. - getService(Ci.nsIStringBundleService); - var bundle = bundles.createBundle("chrome://global/locale/crashes.properties"); - var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"]. - getService(Ci.nsIPromptService); - if (!prompts.confirm(window, - bundle.GetStringFromName("deleteconfirm.title"), - bundle.GetStringFromName("deleteconfirm.description"))) - return; - - var entries = reportsDir.directoryEntries; - while (entries.hasMoreElements()) { - var file = entries.getNext().QueryInterface(Ci.nsIFile); - var leaf = file.leafName; - if (leaf.substr(0, 3) == "bp-" && - leaf.substr(-4) == ".txt") { - file.remove(false); - } - } - document.getElementById("clear-reports").style.display = "none"; - document.getElementById("reportList").style.display = "none"; - document.getElementById("noReports").style.display = "block"; -} - -function init() { - getL10nStrings(); - populateReportList(); -} diff --git a/toolkit/crashreporter/content/crashes.xhtml b/toolkit/crashreporter/content/crashes.xhtml index 74dd29de6cb..62e94941a20 100644 --- a/toolkit/crashreporter/content/crashes.xhtml +++ b/toolkit/crashreporter/content/crashes.xhtml @@ -28,9 +28,8 @@ th[chromedir="rtl"] { th:first-child { -moz-padding-end: 2em; } -:link, :visited { +:link { display: block; - min-height: 17px; } /* date */ td:first-child + td { @@ -50,19 +49,147 @@ td:last-child { #clear-reports[chromedir="rtl"] { float: left; } - -.submitting { - background-image: url(chrome://global/skin/icons/loading_16.png); - background-repeat: no-repeat; - background-position: right; -} - &crashes.title; - +

&crashes.title;

diff --git a/toolkit/crashreporter/jar.mn b/toolkit/crashreporter/jar.mn index 5ccf6b7ea49..e46603f6df3 100644 --- a/toolkit/crashreporter/jar.mn +++ b/toolkit/crashreporter/jar.mn @@ -1,4 +1,2 @@ toolkit.jar: - content/global/crashes.xhtml (content/crashes.xhtml) - content/global/crashes.js (content/crashes.js) - content/global/crash-submit-form.xhtml (content/crash-submit-form.xhtml) + content/global/crashes.xhtml (content/crashes.xhtml) diff --git a/toolkit/crashreporter/test/Makefile.in b/toolkit/crashreporter/test/Makefile.in index da41023b20a..246059b7c6c 100644 --- a/toolkit/crashreporter/test/Makefile.in +++ b/toolkit/crashreporter/test/Makefile.in @@ -50,10 +50,8 @@ include $(topsrcdir)/config/rules.mk _BROWSER_FILES = \ browser/aboutcrashes_utils.js \ - browser/crashreport.sjs \ browser/browser_aboutCrashes.js \ browser/browser_bug471404.js \ - browser/browser_aboutCrashesResubmit.js \ $(NULL) libs:: $(_BROWSER_FILES) diff --git a/toolkit/crashreporter/test/browser/aboutcrashes_utils.js b/toolkit/crashreporter/test/browser/aboutcrashes_utils.js index 9824018a7f8..4d4568eae95 100644 --- a/toolkit/crashreporter/test/browser/aboutcrashes_utils.js +++ b/toolkit/crashreporter/test/browser/aboutcrashes_utils.js @@ -1,13 +1,10 @@ -const Cc = Components.classes; -const Ci = Components.interfaces; - function create_subdir(dir, subdirname) { let subdir = dir.clone(); subdir.append(subdirname); if (subdir.exists()) { subdir.remove(true); } - subdir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755); + subdir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); return subdir; } @@ -18,9 +15,9 @@ function make_fake_appdir() { // Create a directory inside the profile and register it as UAppData, so // we can stick fake crash reports inside there. We put it inside the profile // just because we know that will get cleaned up after the mochitest run. - let dirSvc = Cc["@mozilla.org/file/directory_service;1"] - .getService(Ci.nsIProperties); - let profD = dirSvc.get("ProfD", Ci.nsILocalFile); + let dirSvc = Components.classes["@mozilla.org/file/directory_service;1"] + .getService(Components.interfaces.nsIProperties); + let profD = dirSvc.get("ProfD", Components.interfaces.nsILocalFile); // create a subdir just to keep our files out of the way let appD = create_subdir(profD, "UAppData"); @@ -37,15 +34,15 @@ function make_fake_appdir() { throw Components.results.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { + if (iid.equals(Components.interfaces.nsIDirectoryProvider) || + iid.equals(Components.interfaces.nsISupports)) { return this; } throw Components.results.NS_ERROR_NO_INTERFACE; } }; // register our new provider - dirSvc.QueryInterface(Ci.nsIDirectoryService) + dirSvc.QueryInterface(Components.interfaces.nsIDirectoryService) .registerProvider(_provider); // and undefine the old value try { @@ -55,8 +52,8 @@ function make_fake_appdir() { } function cleanup_fake_appdir() { - let dirSvc = Cc["@mozilla.org/file/directory_service;1"] - .getService(Ci.nsIProperties); + let dirSvc = Components.classes["@mozilla.org/file/directory_service;1"] + .getService(Components.interfaces.nsIProperties); dirSvc.unregisterProvider(_provider); // undefine our value so future calls get the real value try { @@ -68,8 +65,8 @@ function cleanup_fake_appdir() { function add_fake_crashes(crD, count) { let results = []; - let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"] - .getService(Ci.nsIUUIDGenerator); + let uuidGenerator = Components.classes["@mozilla.org/uuid-generator;1"] + .getService(Components.interfaces.nsIUUIDGenerator); let submitdir = crD.clone(); submitdir.append("submitted"); // create them from oldest to newest, to ensure that about:crashes @@ -78,11 +75,11 @@ function add_fake_crashes(crD, count) { for (let i = 0; i < count; i++) { let uuid = uuidGenerator.generateUUID().toString(); // ditch the {} - uuid = "bp-" + uuid.substring(1, uuid.length - 2); - let fn = uuid + ".txt"; + uuid = uuid.substring(1,uuid.length-2); + let fn = "bp-" + uuid + ".txt"; let file = submitdir.clone(); file.append(fn); - file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); + file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666); file.lastModifiedTime = date; results.push({'id': uuid, 'date': date, 'pending': false}); @@ -93,40 +90,3 @@ function add_fake_crashes(crD, count) { results.sort(function(a,b) b.date - a.date); return results; } - -function writeDataToFile(file, data) { - var fstream = Cc["@mozilla.org/network/file-output-stream;1"] - .createInstance(Ci.nsIFileOutputStream); - // open, write, truncate - fstream.init(file, -1, -1, 0); - var os = Cc["@mozilla.org/intl/converter-output-stream;1"] - .createInstance(Ci.nsIConverterOutputStream); - os.init(fstream, "UTF-8", 0, 0x0000); - os.writeString(data); - os.close(); - fstream.close(); -} - -function addPendingCrashreport(crD, extra) { - let pendingdir = crD.clone(); - pendingdir.append("pending"); - let date = Date.now() - Math.round(Math.random() * 10 * 60000); - let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"] - .getService(Ci.nsIUUIDGenerator); - let uuid = uuidGenerator.generateUUID().toString(); - // ditch the {} - uuid = uuid.substring(1, uuid.length - 2); - let dumpfile = pendingdir.clone(); - dumpfile.append(uuid + ".dmp"); - writeDataToFile(dumpfile, "MDMP"); // that's the start of a valid minidump, anyway - let extrafile = pendingdir.clone(); - extrafile.append(uuid + ".extra"); - let extradata = ""; - for (let x in extra) { - extradata += x + "=" + extra[x] + "\n"; - } - writeDataToFile(extrafile, extradata); - dumpfile.lastModifiedTime = date; - extrafile.lastModifiedTime = date; - return {'id': uuid, 'date': date, 'pending': true, 'extra': extra}; -} diff --git a/toolkit/crashreporter/test/browser/browser_aboutCrashes.js b/toolkit/crashreporter/test/browser/browser_aboutCrashes.js index 29603efa59b..5bb5dd4bfcc 100644 --- a/toolkit/crashreporter/test/browser/browser_aboutCrashes.js +++ b/toolkit/crashreporter/test/browser/browser_aboutCrashes.js @@ -8,7 +8,7 @@ function check_crash_list(tab, crashes) { let crashlinks = doc.getElementById("tbody").getElementsByTagName("a"); is(crashlinks.length, crashes.length, "about:crashes lists correct number of crash reports"); for(let i = 0; i < crashes.length; i++) { - is(crashlinks[i].firstChild.textContent, crashes[i].id, i + ": crash ID is correct"); + is(crashlinks[i].firstChild.textContent, "bp-" + crashes[i].id, i + ": crash ID is correct"); } cleanup_fake_appdir(); gBrowser.removeTab(tab); diff --git a/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js b/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js deleted file mode 100644 index 4fc4963f648..00000000000 --- a/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js +++ /dev/null @@ -1,144 +0,0 @@ -// load our utility script -var scriptLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] - .getService(Components.interfaces.mozIJSSubScriptLoader); -scriptLoader.loadSubScript("chrome://mochikit/content/browser/toolkit/crashreporter/test/browser/aboutcrashes_utils.js", this); - -function cleanup_and_finish() { - try { - cleanup_fake_appdir(); - } catch(ex) {} - let prefs = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - prefs.clearUserPref("breakpad.reportURL"); - gBrowser.removeTab(gBrowser.selectedTab); - finish(); -} - -/* - * check_crash_list - * - * Check that the list of crashes displayed by about:crashes matches - * the list of crashes that we placed in the pending+submitted directories. - */ -function check_crash_list(tab, crashes) { - let doc = gBrowser.getBrowserForTab(tab).contentDocument; - let crashlinks = doc.getElementById("tbody").getElementsByTagName("a"); - is(crashlinks.length, crashes.length, - "about:crashes lists correct number of crash reports"); - // no point in checking this if the lists aren't the same length - if (crashlinks.length == crashes.length) { - for(let i=0; i 0) - Array.prototype.push.apply(bytes, body.readByteArray(avail)); - let data = String.fromCharCode.apply(null, bytes); - let formData = {}; - let done = false; - let start = 0; - while (true) { - // read first line - let end = data.indexOf("\r\n", start); - if (end == -1) { - done = true; - end = data.length; - } - - let line = data.substring(start, end); - // look for closing boundary delimiter line - if (line == boundary + "--") { - break; - } - - if (line != boundary) { - dump("expected boundary line but didn't find it!"); - break; - } - - // parse headers - start = end + 2; - let headers = null; - [headers, start] = parseHeaders(data, start); - - // find next boundary string - end = data.indexOf("\r\n" + boundary, start); - if (end == -1) { - dump("couldn't find next boundary string\n"); - break; - } - - // read part data, stick in formData using Content-Disposition header - let part = data.substring(start, end); - start = end + 2; - - if ("Content-Disposition" in headers) { - let bits = headers["Content-Disposition"].split(';'); - if (bits[0] == 'form-data') { - for (let i = 0; i < bits.length; i++) { - let b = bits[i].trimLeft(); - if (b.indexOf('name=') == 0) { - //TODO: handle non-ascii here? - let name = b.substring(6, b.length - 1); - //TODO: handle multiple-value properties? - formData[name] = part; - } - //TODO: handle filename= ? - //TODO: handle multipart/mixed for multi-file uploads? - } - } - } - } - return formData; -} - -function handleRequest(request, response) -{ - if (request.method == "GET") { - let id = null; - for each(p in request.queryString.split('&')) { - let [key, value] = p.split('='); - if (key == 'id') - id = value; - } - if (id == null) { - response.setStatusLine(request.httpVersion, 400, "Bad Request"); - response.write("Missing id parameter"); - } - else { - let data = getState(id); - if (data == "") { - response.setStatusLine(request.httpVersion, 404, "Not Found"); - response.write("Not Found"); - } - else { - response.setHeader("Content-Type", "text/plain", false); - response.write(data); - } - } - } - else if (request.method == "POST") { - let formData = parseMultipartForm(request); - - if ('upload_file_minidump' in formData) { - response.setHeader("Content-Type", "text/plain", false); - - let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"] - .getService(Ci.nsIUUIDGenerator); - let uuid = uuidGenerator.generateUUID().toString(); - // ditch the {}, add bp- prefix - uuid = 'bp-' + uuid.substring(1,uuid.length-2); - - let d = JSON.stringify(formData); - //dump('saving crash report ' + uuid + ': ' + d + '\n'); - setState(uuid, d); - - response.write("CrashID=" + uuid + "\n"); - } - else { - response.setStatusLine(request.httpVersion, 400, "Bad Request"); - response.write("Missing minidump file"); - } - } - else { - response.setStatusLine(request.httpVersion, 405, "Method not allowed"); - response.write("Can't handle HTTP method " + request.method); - } -}