Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | Components.utils.import("resource://gre/modules/Services.jsm"); |
michael@0 | 6 | Components.utils.import("resource://gre/modules/KeyValueParser.jsm"); |
michael@0 | 7 | |
michael@0 | 8 | this.EXPORTED_SYMBOLS = [ |
michael@0 | 9 | "CrashSubmit" |
michael@0 | 10 | ]; |
michael@0 | 11 | |
michael@0 | 12 | const Cc = Components.classes; |
michael@0 | 13 | const Ci = Components.interfaces; |
michael@0 | 14 | const STATE_START = Ci.nsIWebProgressListener.STATE_START; |
michael@0 | 15 | const STATE_STOP = Ci.nsIWebProgressListener.STATE_STOP; |
michael@0 | 16 | |
michael@0 | 17 | const SUCCESS = "success"; |
michael@0 | 18 | const FAILED = "failed"; |
michael@0 | 19 | const SUBMITTING = "submitting"; |
michael@0 | 20 | |
michael@0 | 21 | let reportURL = null; |
michael@0 | 22 | let strings = null; |
michael@0 | 23 | let myListener = null; |
michael@0 | 24 | |
michael@0 | 25 | function parseINIStrings(file) { |
michael@0 | 26 | var factory = Cc["@mozilla.org/xpcom/ini-parser-factory;1"]. |
michael@0 | 27 | getService(Ci.nsIINIParserFactory); |
michael@0 | 28 | var parser = factory.createINIParser(file); |
michael@0 | 29 | var obj = {}; |
michael@0 | 30 | var en = parser.getKeys("Strings"); |
michael@0 | 31 | while (en.hasMore()) { |
michael@0 | 32 | var key = en.getNext(); |
michael@0 | 33 | obj[key] = parser.getString("Strings", key); |
michael@0 | 34 | } |
michael@0 | 35 | return obj; |
michael@0 | 36 | } |
michael@0 | 37 | |
michael@0 | 38 | // Since we're basically re-implementing part of the crashreporter |
michael@0 | 39 | // client here, we'll just steal the strings we need from crashreporter.ini |
michael@0 | 40 | function getL10nStrings() { |
michael@0 | 41 | let dirSvc = Cc["@mozilla.org/file/directory_service;1"]. |
michael@0 | 42 | getService(Ci.nsIProperties); |
michael@0 | 43 | let path = dirSvc.get("GreD", Ci.nsIFile); |
michael@0 | 44 | path.append("crashreporter.ini"); |
michael@0 | 45 | if (!path.exists()) { |
michael@0 | 46 | // see if we're on a mac |
michael@0 | 47 | path = path.parent; |
michael@0 | 48 | path.append("crashreporter.app"); |
michael@0 | 49 | path.append("Contents"); |
michael@0 | 50 | path.append("MacOS"); |
michael@0 | 51 | path.append("crashreporter.ini"); |
michael@0 | 52 | if (!path.exists()) { |
michael@0 | 53 | // very bad, but I don't know how to recover |
michael@0 | 54 | return; |
michael@0 | 55 | } |
michael@0 | 56 | } |
michael@0 | 57 | let crstrings = parseINIStrings(path); |
michael@0 | 58 | strings = { |
michael@0 | 59 | 'crashid': crstrings.CrashID, |
michael@0 | 60 | 'reporturl': crstrings.CrashDetailsURL |
michael@0 | 61 | }; |
michael@0 | 62 | |
michael@0 | 63 | path = dirSvc.get("XCurProcD", Ci.nsIFile); |
michael@0 | 64 | path.append("crashreporter-override.ini"); |
michael@0 | 65 | if (path.exists()) { |
michael@0 | 66 | crstrings = parseINIStrings(path); |
michael@0 | 67 | if ('CrashID' in crstrings) |
michael@0 | 68 | strings['crashid'] = crstrings.CrashID; |
michael@0 | 69 | if ('CrashDetailsURL' in crstrings) |
michael@0 | 70 | strings['reporturl'] = crstrings.CrashDetailsURL; |
michael@0 | 71 | } |
michael@0 | 72 | } |
michael@0 | 73 | |
michael@0 | 74 | function getPendingDir() { |
michael@0 | 75 | let directoryService = Cc["@mozilla.org/file/directory_service;1"]. |
michael@0 | 76 | getService(Ci.nsIProperties); |
michael@0 | 77 | let pendingDir = directoryService.get("UAppData", Ci.nsIFile); |
michael@0 | 78 | pendingDir.append("Crash Reports"); |
michael@0 | 79 | pendingDir.append("pending"); |
michael@0 | 80 | return pendingDir; |
michael@0 | 81 | } |
michael@0 | 82 | |
michael@0 | 83 | function getPendingMinidump(id) { |
michael@0 | 84 | let pendingDir = getPendingDir(); |
michael@0 | 85 | let dump = pendingDir.clone(); |
michael@0 | 86 | let extra = pendingDir.clone(); |
michael@0 | 87 | dump.append(id + ".dmp"); |
michael@0 | 88 | extra.append(id + ".extra"); |
michael@0 | 89 | return [dump, extra]; |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | function getAllPendingMinidumpsIDs() { |
michael@0 | 93 | let minidumps = []; |
michael@0 | 94 | let pendingDir = getPendingDir(); |
michael@0 | 95 | |
michael@0 | 96 | if (!(pendingDir.exists() && pendingDir.isDirectory())) |
michael@0 | 97 | return []; |
michael@0 | 98 | let entries = pendingDir.directoryEntries; |
michael@0 | 99 | |
michael@0 | 100 | while (entries.hasMoreElements()) { |
michael@0 | 101 | let entry = entries.getNext().QueryInterface(Ci.nsIFile); |
michael@0 | 102 | if (entry.isFile()) { |
michael@0 | 103 | let matches = entry.leafName.match(/(.+)\.extra$/); |
michael@0 | 104 | if (matches) |
michael@0 | 105 | minidumps.push(matches[1]); |
michael@0 | 106 | } |
michael@0 | 107 | } |
michael@0 | 108 | |
michael@0 | 109 | return minidumps; |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | function pruneSavedDumps() { |
michael@0 | 113 | const KEEP = 10; |
michael@0 | 114 | |
michael@0 | 115 | let pendingDir = getPendingDir(); |
michael@0 | 116 | if (!(pendingDir.exists() && pendingDir.isDirectory())) |
michael@0 | 117 | return; |
michael@0 | 118 | let entries = pendingDir.directoryEntries; |
michael@0 | 119 | let entriesArray = []; |
michael@0 | 120 | |
michael@0 | 121 | while (entries.hasMoreElements()) { |
michael@0 | 122 | let entry = entries.getNext().QueryInterface(Ci.nsIFile); |
michael@0 | 123 | if (entry.isFile()) { |
michael@0 | 124 | let matches = entry.leafName.match(/(.+)\.extra$/); |
michael@0 | 125 | if (matches) |
michael@0 | 126 | entriesArray.push(entry); |
michael@0 | 127 | } |
michael@0 | 128 | } |
michael@0 | 129 | |
michael@0 | 130 | entriesArray.sort(function(a,b) { |
michael@0 | 131 | let dateA = a.lastModifiedTime; |
michael@0 | 132 | let dateB = b.lastModifiedTime; |
michael@0 | 133 | if (dateA < dateB) |
michael@0 | 134 | return -1; |
michael@0 | 135 | if (dateB < dateA) |
michael@0 | 136 | return 1; |
michael@0 | 137 | return 0; |
michael@0 | 138 | }); |
michael@0 | 139 | |
michael@0 | 140 | if (entriesArray.length > KEEP) { |
michael@0 | 141 | for (let i = 0; i < entriesArray.length - KEEP; ++i) { |
michael@0 | 142 | let extra = entriesArray[i]; |
michael@0 | 143 | let matches = extra.leafName.match(/(.+)\.extra$/); |
michael@0 | 144 | if (matches) { |
michael@0 | 145 | let dump = extra.clone(); |
michael@0 | 146 | dump.leafName = matches[1] + '.dmp'; |
michael@0 | 147 | dump.remove(false); |
michael@0 | 148 | extra.remove(false); |
michael@0 | 149 | } |
michael@0 | 150 | } |
michael@0 | 151 | } |
michael@0 | 152 | } |
michael@0 | 153 | |
michael@0 | 154 | function addFormEntry(doc, form, name, value) { |
michael@0 | 155 | var input = doc.createElement("input"); |
michael@0 | 156 | input.type = "hidden"; |
michael@0 | 157 | input.name = name; |
michael@0 | 158 | input.value = value; |
michael@0 | 159 | form.appendChild(input); |
michael@0 | 160 | } |
michael@0 | 161 | |
michael@0 | 162 | function writeSubmittedReport(crashID, viewURL) { |
michael@0 | 163 | let directoryService = Cc["@mozilla.org/file/directory_service;1"]. |
michael@0 | 164 | getService(Ci.nsIProperties); |
michael@0 | 165 | let reportFile = directoryService.get("UAppData", Ci.nsIFile); |
michael@0 | 166 | reportFile.append("Crash Reports"); |
michael@0 | 167 | reportFile.append("submitted"); |
michael@0 | 168 | if (!reportFile.exists()) |
michael@0 | 169 | reportFile.create(Ci.nsIFile.DIRECTORY_TYPE, 0700); |
michael@0 | 170 | reportFile.append(crashID + ".txt"); |
michael@0 | 171 | var fstream = Cc["@mozilla.org/network/file-output-stream;1"]. |
michael@0 | 172 | createInstance(Ci.nsIFileOutputStream); |
michael@0 | 173 | // open, write, truncate |
michael@0 | 174 | fstream.init(reportFile, -1, -1, 0); |
michael@0 | 175 | var os = Cc["@mozilla.org/intl/converter-output-stream;1"]. |
michael@0 | 176 | createInstance(Ci.nsIConverterOutputStream); |
michael@0 | 177 | os.init(fstream, "UTF-8", 0, 0x0000); |
michael@0 | 178 | |
michael@0 | 179 | var data = strings.crashid.replace("%s", crashID); |
michael@0 | 180 | if (viewURL) |
michael@0 | 181 | data += "\n" + strings.reporturl.replace("%s", viewURL); |
michael@0 | 182 | |
michael@0 | 183 | os.writeString(data); |
michael@0 | 184 | os.close(); |
michael@0 | 185 | fstream.close(); |
michael@0 | 186 | } |
michael@0 | 187 | |
michael@0 | 188 | // the Submitter class represents an individual submission. |
michael@0 | 189 | function Submitter(id, submitSuccess, submitError, noThrottle, |
michael@0 | 190 | extraExtraKeyVals) { |
michael@0 | 191 | this.id = id; |
michael@0 | 192 | this.successCallback = submitSuccess; |
michael@0 | 193 | this.errorCallback = submitError; |
michael@0 | 194 | this.noThrottle = noThrottle; |
michael@0 | 195 | this.additionalDumps = []; |
michael@0 | 196 | this.extraKeyVals = extraExtraKeyVals || {}; |
michael@0 | 197 | } |
michael@0 | 198 | |
michael@0 | 199 | Submitter.prototype = { |
michael@0 | 200 | submitSuccess: function Submitter_submitSuccess(ret) |
michael@0 | 201 | { |
michael@0 | 202 | if (!ret.CrashID) { |
michael@0 | 203 | this.notifyStatus(FAILED); |
michael@0 | 204 | this.cleanup(); |
michael@0 | 205 | return; |
michael@0 | 206 | } |
michael@0 | 207 | |
michael@0 | 208 | // Write out the details file to submitted/ |
michael@0 | 209 | writeSubmittedReport(ret.CrashID, ret.ViewURL); |
michael@0 | 210 | |
michael@0 | 211 | // Delete from pending dir |
michael@0 | 212 | try { |
michael@0 | 213 | this.dump.remove(false); |
michael@0 | 214 | this.extra.remove(false); |
michael@0 | 215 | for (let i of this.additionalDumps) { |
michael@0 | 216 | i.dump.remove(false); |
michael@0 | 217 | } |
michael@0 | 218 | } |
michael@0 | 219 | catch (ex) { |
michael@0 | 220 | // report an error? not much the user can do here. |
michael@0 | 221 | } |
michael@0 | 222 | |
michael@0 | 223 | this.notifyStatus(SUCCESS, ret); |
michael@0 | 224 | this.cleanup(); |
michael@0 | 225 | }, |
michael@0 | 226 | |
michael@0 | 227 | cleanup: function Submitter_cleanup() { |
michael@0 | 228 | // drop some references just to be nice |
michael@0 | 229 | this.successCallback = null; |
michael@0 | 230 | this.errorCallback = null; |
michael@0 | 231 | this.iframe = null; |
michael@0 | 232 | this.dump = null; |
michael@0 | 233 | this.extra = null; |
michael@0 | 234 | this.additionalDumps = null; |
michael@0 | 235 | // remove this object from the list of active submissions |
michael@0 | 236 | let idx = CrashSubmit._activeSubmissions.indexOf(this); |
michael@0 | 237 | if (idx != -1) |
michael@0 | 238 | CrashSubmit._activeSubmissions.splice(idx, 1); |
michael@0 | 239 | }, |
michael@0 | 240 | |
michael@0 | 241 | submitForm: function Submitter_submitForm() |
michael@0 | 242 | { |
michael@0 | 243 | if (!('ServerURL' in this.extraKeyVals)) { |
michael@0 | 244 | return false; |
michael@0 | 245 | } |
michael@0 | 246 | let serverURL = this.extraKeyVals.ServerURL; |
michael@0 | 247 | |
michael@0 | 248 | // Override the submission URL from the environment or prefs. |
michael@0 | 249 | |
michael@0 | 250 | var envOverride = Cc['@mozilla.org/process/environment;1']. |
michael@0 | 251 | getService(Ci.nsIEnvironment).get("MOZ_CRASHREPORTER_URL"); |
michael@0 | 252 | if (envOverride != '') { |
michael@0 | 253 | serverURL = envOverride; |
michael@0 | 254 | } |
michael@0 | 255 | else if ('PluginHang' in this.extraKeyVals) { |
michael@0 | 256 | try { |
michael@0 | 257 | serverURL = Services.prefs. |
michael@0 | 258 | getCharPref("toolkit.crashreporter.pluginHangSubmitURL"); |
michael@0 | 259 | } catch(e) { } |
michael@0 | 260 | } |
michael@0 | 261 | |
michael@0 | 262 | let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] |
michael@0 | 263 | .createInstance(Ci.nsIXMLHttpRequest); |
michael@0 | 264 | xhr.open("POST", serverURL, true); |
michael@0 | 265 | |
michael@0 | 266 | let formData = Cc["@mozilla.org/files/formdata;1"] |
michael@0 | 267 | .createInstance(Ci.nsIDOMFormData); |
michael@0 | 268 | // add the data |
michael@0 | 269 | for (let [name, value] in Iterator(this.extraKeyVals)) { |
michael@0 | 270 | if (name != "ServerURL") { |
michael@0 | 271 | formData.append(name, value); |
michael@0 | 272 | } |
michael@0 | 273 | } |
michael@0 | 274 | if (this.noThrottle) { |
michael@0 | 275 | // tell the server not to throttle this, since it was manually submitted |
michael@0 | 276 | formData.append("Throttleable", "0"); |
michael@0 | 277 | } |
michael@0 | 278 | // add the minidumps |
michael@0 | 279 | formData.append("upload_file_minidump", File(this.dump.path)); |
michael@0 | 280 | if (this.additionalDumps.length > 0) { |
michael@0 | 281 | let names = []; |
michael@0 | 282 | for (let i of this.additionalDumps) { |
michael@0 | 283 | names.push(i.name); |
michael@0 | 284 | formData.append("upload_file_minidump_"+i.name, |
michael@0 | 285 | File(i.dump.path)); |
michael@0 | 286 | } |
michael@0 | 287 | } |
michael@0 | 288 | |
michael@0 | 289 | let self = this; |
michael@0 | 290 | xhr.addEventListener("readystatechange", function (aEvt) { |
michael@0 | 291 | if (xhr.readyState == 4) { |
michael@0 | 292 | if (xhr.status != 200) { |
michael@0 | 293 | self.notifyStatus(FAILED); |
michael@0 | 294 | self.cleanup(); |
michael@0 | 295 | } else { |
michael@0 | 296 | let ret = parseKeyValuePairs(xhr.responseText); |
michael@0 | 297 | self.submitSuccess(ret); |
michael@0 | 298 | } |
michael@0 | 299 | } |
michael@0 | 300 | }, false); |
michael@0 | 301 | |
michael@0 | 302 | xhr.send(formData); |
michael@0 | 303 | return true; |
michael@0 | 304 | }, |
michael@0 | 305 | |
michael@0 | 306 | notifyStatus: function Submitter_notify(status, ret) |
michael@0 | 307 | { |
michael@0 | 308 | let propBag = Cc["@mozilla.org/hash-property-bag;1"]. |
michael@0 | 309 | createInstance(Ci.nsIWritablePropertyBag2); |
michael@0 | 310 | propBag.setPropertyAsAString("minidumpID", this.id); |
michael@0 | 311 | if (status == SUCCESS) { |
michael@0 | 312 | propBag.setPropertyAsAString("serverCrashID", ret.CrashID); |
michael@0 | 313 | } |
michael@0 | 314 | |
michael@0 | 315 | let extraKeyValsBag = Cc["@mozilla.org/hash-property-bag;1"]. |
michael@0 | 316 | createInstance(Ci.nsIWritablePropertyBag2); |
michael@0 | 317 | for (let key in this.extraKeyVals) { |
michael@0 | 318 | extraKeyValsBag.setPropertyAsAString(key, this.extraKeyVals[key]); |
michael@0 | 319 | } |
michael@0 | 320 | propBag.setPropertyAsInterface("extra", extraKeyValsBag); |
michael@0 | 321 | |
michael@0 | 322 | Services.obs.notifyObservers(propBag, "crash-report-status", status); |
michael@0 | 323 | |
michael@0 | 324 | switch (status) { |
michael@0 | 325 | case SUCCESS: |
michael@0 | 326 | if (this.successCallback) |
michael@0 | 327 | this.successCallback(this.id, ret); |
michael@0 | 328 | break; |
michael@0 | 329 | case FAILED: |
michael@0 | 330 | if (this.errorCallback) |
michael@0 | 331 | this.errorCallback(this.id); |
michael@0 | 332 | break; |
michael@0 | 333 | default: |
michael@0 | 334 | // no callbacks invoked. |
michael@0 | 335 | } |
michael@0 | 336 | }, |
michael@0 | 337 | |
michael@0 | 338 | submit: function Submitter_submit() |
michael@0 | 339 | { |
michael@0 | 340 | let [dump, extra] = getPendingMinidump(this.id); |
michael@0 | 341 | if (!dump.exists() || !extra.exists()) { |
michael@0 | 342 | this.notifyStatus(FAILED); |
michael@0 | 343 | this.cleanup(); |
michael@0 | 344 | return false; |
michael@0 | 345 | } |
michael@0 | 346 | |
michael@0 | 347 | let extraKeyVals = parseKeyValuePairsFromFile(extra); |
michael@0 | 348 | for (let key in extraKeyVals) { |
michael@0 | 349 | if (!(key in this.extraKeyVals)) { |
michael@0 | 350 | this.extraKeyVals[key] = extraKeyVals[key]; |
michael@0 | 351 | } |
michael@0 | 352 | } |
michael@0 | 353 | |
michael@0 | 354 | let additionalDumps = []; |
michael@0 | 355 | if ("additional_minidumps" in this.extraKeyVals) { |
michael@0 | 356 | let names = this.extraKeyVals.additional_minidumps.split(','); |
michael@0 | 357 | for (let name of names) { |
michael@0 | 358 | let [dump, extra] = getPendingMinidump(this.id + "-" + name); |
michael@0 | 359 | if (!dump.exists()) { |
michael@0 | 360 | this.notifyStatus(FAILED); |
michael@0 | 361 | this.cleanup(); |
michael@0 | 362 | return false; |
michael@0 | 363 | } |
michael@0 | 364 | additionalDumps.push({'name': name, 'dump': dump}); |
michael@0 | 365 | } |
michael@0 | 366 | } |
michael@0 | 367 | |
michael@0 | 368 | this.notifyStatus(SUBMITTING); |
michael@0 | 369 | |
michael@0 | 370 | this.dump = dump; |
michael@0 | 371 | this.extra = extra; |
michael@0 | 372 | this.additionalDumps = additionalDumps; |
michael@0 | 373 | |
michael@0 | 374 | if (!this.submitForm()) { |
michael@0 | 375 | this.notifyStatus(FAILED); |
michael@0 | 376 | this.cleanup(); |
michael@0 | 377 | return false; |
michael@0 | 378 | } |
michael@0 | 379 | return true; |
michael@0 | 380 | } |
michael@0 | 381 | }; |
michael@0 | 382 | |
michael@0 | 383 | //=================================== |
michael@0 | 384 | // External API goes here |
michael@0 | 385 | this.CrashSubmit = { |
michael@0 | 386 | /** |
michael@0 | 387 | * Submit the crash report named id.dmp from the "pending" directory. |
michael@0 | 388 | * |
michael@0 | 389 | * @param id |
michael@0 | 390 | * Filename (minus .dmp extension) of the minidump to submit. |
michael@0 | 391 | * @param params |
michael@0 | 392 | * An object containing any of the following optional parameters: |
michael@0 | 393 | * - submitSuccess |
michael@0 | 394 | * A function that will be called if the report is submitted |
michael@0 | 395 | * successfully with two parameters: the id that was passed |
michael@0 | 396 | * to this function, and an object containing the key/value |
michael@0 | 397 | * data returned from the server in its properties. |
michael@0 | 398 | * - submitError |
michael@0 | 399 | * A function that will be called with one parameter if the |
michael@0 | 400 | * report fails to submit: the id that was passed to this |
michael@0 | 401 | * function. |
michael@0 | 402 | * - noThrottle |
michael@0 | 403 | * If true, this crash report should be submitted with |
michael@0 | 404 | * an extra parameter of "Throttleable=0" indicating that |
michael@0 | 405 | * it should be processed right away. This should be set |
michael@0 | 406 | * when the report is being submitted and the user expects |
michael@0 | 407 | * to see the results immediately. Defaults to false. |
michael@0 | 408 | * - extraExtraKeyVals |
michael@0 | 409 | * An object whose key-value pairs will be merged with the data from |
michael@0 | 410 | * the ".extra" file submitted with the report. The properties of |
michael@0 | 411 | * this object will override properties of the same name in the |
michael@0 | 412 | * .extra file. |
michael@0 | 413 | * |
michael@0 | 414 | * @return true if the submission began successfully, or false if |
michael@0 | 415 | * it failed for some reason. (If the dump file does not |
michael@0 | 416 | * exist, for example.) |
michael@0 | 417 | */ |
michael@0 | 418 | submit: function CrashSubmit_submit(id, params) |
michael@0 | 419 | { |
michael@0 | 420 | params = params || {}; |
michael@0 | 421 | let submitSuccess = null; |
michael@0 | 422 | let submitError = null; |
michael@0 | 423 | let noThrottle = false; |
michael@0 | 424 | let extraExtraKeyVals = null; |
michael@0 | 425 | |
michael@0 | 426 | if ('submitSuccess' in params) |
michael@0 | 427 | submitSuccess = params.submitSuccess; |
michael@0 | 428 | if ('submitError' in params) |
michael@0 | 429 | submitError = params.submitError; |
michael@0 | 430 | if ('noThrottle' in params) |
michael@0 | 431 | noThrottle = params.noThrottle; |
michael@0 | 432 | if ('extraExtraKeyVals' in params) |
michael@0 | 433 | extraExtraKeyVals = params.extraExtraKeyVals; |
michael@0 | 434 | |
michael@0 | 435 | let submitter = new Submitter(id, |
michael@0 | 436 | submitSuccess, |
michael@0 | 437 | submitError, |
michael@0 | 438 | noThrottle, |
michael@0 | 439 | extraExtraKeyVals); |
michael@0 | 440 | CrashSubmit._activeSubmissions.push(submitter); |
michael@0 | 441 | return submitter.submit(); |
michael@0 | 442 | }, |
michael@0 | 443 | |
michael@0 | 444 | /** |
michael@0 | 445 | * Delete the minidup from the "pending" directory. |
michael@0 | 446 | * |
michael@0 | 447 | * @param id |
michael@0 | 448 | * Filename (minus .dmp extension) of the minidump to delete. |
michael@0 | 449 | */ |
michael@0 | 450 | delete: function CrashSubmit_delete(id) { |
michael@0 | 451 | let [dump, extra] = getPendingMinidump(id); |
michael@0 | 452 | dump.QueryInterface(Ci.nsIFile).remove(false); |
michael@0 | 453 | extra.QueryInterface(Ci.nsIFile).remove(false); |
michael@0 | 454 | }, |
michael@0 | 455 | |
michael@0 | 456 | /** |
michael@0 | 457 | * Get the list of pending crash IDs. |
michael@0 | 458 | * |
michael@0 | 459 | * @return an array of string, each being an ID as |
michael@0 | 460 | * expected to be passed to submit() |
michael@0 | 461 | */ |
michael@0 | 462 | pendingIDs: function CrashSubmit_pendingIDs() { |
michael@0 | 463 | return getAllPendingMinidumpsIDs(); |
michael@0 | 464 | }, |
michael@0 | 465 | |
michael@0 | 466 | /** |
michael@0 | 467 | * Prune the saved dumps. |
michael@0 | 468 | */ |
michael@0 | 469 | pruneSavedDumps: function CrashSubmit_pruneSavedDumps() { |
michael@0 | 470 | pruneSavedDumps(); |
michael@0 | 471 | }, |
michael@0 | 472 | |
michael@0 | 473 | // List of currently active submit objects |
michael@0 | 474 | _activeSubmissions: [] |
michael@0 | 475 | }; |
michael@0 | 476 | |
michael@0 | 477 | // Run this when first loaded |
michael@0 | 478 | getL10nStrings(); |