Commit 30de4722 authored by Victor Porof's avatar Victor Porof
Browse files

Bug 1561435 - Format toolkit/crashreporter/, a=automatic-formatting

# ignore-this-changeset

Differential Revision: https://phabricator.services.mozilla.com/D36054

--HG--
extra : source : 0b29c27eb14e47c44674fc7aa8e90f74e4430233
parent 07737959
Loading
Loading
Loading
Loading
+7 −9
Original line number Diff line number Diff line
@@ -4,9 +4,7 @@

const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");

var EXPORTED_SYMBOLS = [
  "CrashReports",
];
var EXPORTED_SYMBOLS = ["CrashReports"];

var CrashReports = {
  pendingDir: null,
@@ -17,8 +15,9 @@ var CrashReports = {

    try {
      // Ignore any non http/https urls
      if (!/^https?:/i.test(Services.prefs.getCharPref("breakpad.reportURL")))
      if (!/^https?:/i.test(Services.prefs.getCharPref("breakpad.reportURL"))) {
        return reports;
      }
    } catch (e) {}

    if (this.submittedDir.exists() && this.submittedDir.isDirectory()) {
@@ -26,8 +25,7 @@ var CrashReports = {
      while (entries.hasMoreElements()) {
        let file = entries.nextFile;
        let leaf = file.leafName;
        if (leaf.startsWith("bp-") &&
            leaf.endsWith(".txt")) {
        if (leaf.startsWith("bp-") && leaf.endsWith(".txt")) {
          let entry = {
            id: leaf.slice(0, -4),
            date: file.lastModifiedTime,
+117 −67
Original line number Diff line number Diff line
@@ -3,17 +3,25 @@
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {FileUtils} = ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const {parseKeyValuePairs, parseKeyValuePairsFromFileAsync} = ChromeUtils.import("resource://gre/modules/KeyValueParser.jsm");
XPCOMUtils.defineLazyGlobalGetters(this, ["File", "FormData", "XMLHttpRequest"]);
const { FileUtils } = ChromeUtils.import(
  "resource://gre/modules/FileUtils.jsm"
);
const { XPCOMUtils } = ChromeUtils.import(
  "resource://gre/modules/XPCOMUtils.jsm"
);
const {
  parseKeyValuePairs,
  parseKeyValuePairsFromFileAsync,
} = ChromeUtils.import("resource://gre/modules/KeyValueParser.jsm");
XPCOMUtils.defineLazyGlobalGetters(this, [
  "File",
  "FormData",
  "XMLHttpRequest",
]);

ChromeUtils.defineModuleGetter(this, "OS",
                               "resource://gre/modules/osfile.jsm");
ChromeUtils.defineModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");

var EXPORTED_SYMBOLS = [
  "CrashSubmit",
];
var EXPORTED_SYMBOLS = ["CrashSubmit"];

const SUCCESS = "success";
const FAILED = "failed";
@@ -24,8 +32,9 @@ const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12
// TODO: this is still synchronous; need an async INI parser to make it async
function parseINIStrings(path) {
  let file = new FileUtils.File(path);
  let factory = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].
                getService(Ci.nsIINIParserFactory);
  let factory = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].getService(
    Ci.nsIINIParserFactory
  );
  let parser = factory.createINIParser(file);
  let obj = {};
  for (let key of parser.getKeys("Strings")) {
@@ -37,15 +46,23 @@ function parseINIStrings(path) {
// Since we're basically re-implementing (with async) part of the crashreporter
// client here, we'll just steal the strings we need from crashreporter.ini
async function getL10nStrings() {
  let path = OS.Path.join(Services.dirsvc.get("GreD", Ci.nsIFile).path,
                          "crashreporter.ini");
  let path = OS.Path.join(
    Services.dirsvc.get("GreD", Ci.nsIFile).path,
    "crashreporter.ini"
  );
  let pathExists = await OS.File.exists(path);

  if (!pathExists) {
    // we if we're on a mac
    let parentDir = OS.Path.dirname(path);
    path = OS.Path.join(parentDir, "MacOS", "crashreporter.app", "Contents",
                        "Resources", "crashreporter.ini");
    path = OS.Path.join(
      parentDir,
      "MacOS",
      "crashreporter.app",
      "Contents",
      "Resources",
      "crashreporter.ini"
    );

    let pathExists = await OS.File.exists(path);

@@ -54,20 +71,22 @@ async function getL10nStrings() {
      // Android users can't see the contents of the submitted files
      // anyway, so just hardcode some fallback strings.
      return {
        "crashid": "Crash ID: %s",
        "reporturl": "You can view details of this crash at %s",
        crashid: "Crash ID: %s",
        reporturl: "You can view details of this crash at %s",
      };
    }
  }

  let crstrings = parseINIStrings(path);
  let strings = {
    "crashid": crstrings.CrashID,
    "reporturl": crstrings.CrashDetailsURL,
    crashid: crstrings.CrashID,
    reporturl: crstrings.CrashDetailsURL,
  };

  path = OS.Path.join(Services.dirsvc.get("XCurProcD", Ci.nsIFile).path,
                      "crashreporter-override.ini");
  path = OS.Path.join(
    Services.dirsvc.get("XCurProcD", Ci.nsIFile).path,
    "crashreporter-override.ini"
  );
  pathExists = await OS.File.exists(path);

  if (pathExists) {
@@ -147,9 +166,11 @@ Submitter.prototype = {
        toDelete.push(dump);
      }

      await Promise.all(toDelete.map(path => {
      await Promise.all(
        toDelete.map(path => {
          return OS.File.remove(path, { ignoreAbsent: true });
      }));
        })
      );
    } catch (ex) {
      Cu.reportError(ex);
    }
@@ -180,8 +201,9 @@ Submitter.prototype = {

    // Override the submission URL from the environment

    let envOverride = Cc["@mozilla.org/process/environment;1"].
      getService(Ci.nsIEnvironment).get("MOZ_CRASHREPORTER_URL");
    let envOverride = Cc["@mozilla.org/process/environment;1"]
      .getService(Ci.nsIEnvironment)
      .get("MOZ_CRASHREPORTER_URL");
    if (envOverride != "") {
      serverURL = envOverride;
    }
@@ -209,25 +231,29 @@ Submitter.prototype = {
    ];

    if (this.memory) {
      promises.push(File.createFromFileName(this.memory).then(file => {
      promises.push(
        File.createFromFileName(this.memory).then(file => {
          formData.append("memory_report", file);
      }));
        })
      );
    }

    if (this.additionalDumps.length > 0) {
      let names = [];
      for (let i of this.additionalDumps) {
        names.push(i.name);
        promises.push(File.createFromFileName(i.dump).then(file => {
        promises.push(
          File.createFromFileName(i.dump).then(file => {
            formData.append("upload_file_minidump_" + i.name, file);
        }));
          })
        );
      }
    }

    let manager = Services.crashmanager;
    let submissionID = manager.generateSubmissionID();

    xhr.addEventListener("readystatechange", (evt) => {
    xhr.addEventListener("readystatechange", evt => {
      if (xhr.readyState == 4) {
        let ret =
          xhr.status === 200 ? parseKeyValuePairs(xhr.responseText) : {};
@@ -235,10 +261,15 @@ Submitter.prototype = {
        let p = Promise.resolve();

        if (this.recordSubmission) {
          let result = submitted ? manager.SUBMISSION_RESULT_OK :
                                   manager.SUBMISSION_RESULT_FAILED;
          p = manager.addSubmissionResult(this.id, submissionID, new Date(),
                                          result);
          let result = submitted
            ? manager.SUBMISSION_RESULT_OK
            : manager.SUBMISSION_RESULT_FAILED;
          p = manager.addSubmissionResult(
            this.id,
            submissionID,
            new Date(),
            result
          );
          if (submitted) {
            manager.setRemoteCrashID(this.id, ret.CrashID);
          }
@@ -259,25 +290,32 @@ Submitter.prototype = {
    let id = this.id;

    if (this.recordSubmission) {
      p = p.then(() => { return manager.ensureCrashIsPresent(id); })
      p = p
        .then(() => {
          return manager.ensureCrashIsPresent(id);
        })
        .then(() => {
          return manager.addSubmissionAttempt(id, submissionID, new Date());
        });
    }
    p.then(() => { xhr.send(formData); });
    p.then(() => {
      xhr.send(formData);
    });
    return true;
  },

  notifyStatus: function Submitter_notify(status, ret) {
    let propBag = Cc["@mozilla.org/hash-property-bag;1"].
                  createInstance(Ci.nsIWritablePropertyBag2);
    let propBag = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
      Ci.nsIWritablePropertyBag2
    );
    propBag.setPropertyAsAString("minidumpID", this.id);
    if (status == SUCCESS) {
      propBag.setPropertyAsAString("serverCrashID", ret.CrashID);
    }

    let extraKeyValsBag = Cc["@mozilla.org/hash-property-bag;1"].
                          createInstance(Ci.nsIWritablePropertyBag2);
    let extraKeyValsBag = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
      Ci.nsIWritablePropertyBag2
    );
    for (let key in this.extraKeyVals) {
      extraKeyValsBag.setPropertyAsAString(key, this.extraKeyVals[key]);
    }
@@ -330,7 +368,9 @@ Submitter.prototype = {
      let names = this.extraKeyVals.additional_minidumps.split(",");

      for (let name of names) {
        let [dump /* , extra, memory */] = getPendingMinidump(this.id + "-" + name);
        let [dump /* , extra, memory */] = getPendingMinidump(
          this.id + "-" + name
        );

        dumpsExistsPromises.push(OS.File.exists(dump));
        additionalDumps.push({ name, dump });
@@ -403,8 +443,12 @@ var CrashSubmit = {
      extraExtraKeyVals = params.extraExtraKeyVals;
    }

    let submitter = new Submitter(id, recordSubmission,
                                  noThrottle, extraExtraKeyVals);
    let submitter = new Submitter(
      id,
      recordSubmission,
      noThrottle,
      extraExtraKeyVals
    );
    CrashSubmit._activeSubmissions.push(submitter);
    return submitter.submit();
  },
@@ -419,9 +463,11 @@ var CrashSubmit = {
   *         rejected otherwise
   */
  delete: async function CrashSubmit_delete(id) {
    await Promise.all(getPendingMinidump(id).map(path => {
    await Promise.all(
      getPendingMinidump(id).map(path => {
        return OS.File.remove(path, { ignoreAbsent: true });
    }));
      })
    );
  },

  /**
@@ -436,8 +482,11 @@ var CrashSubmit = {
   */
  ignore: async function CrashSubmit_ignore(id) {
    let [dump /* , extra, memory */] = getPendingMinidump(id);
    let file = await OS.File.open(`${dump}.ignore`, { create: true },
                                  { unixFlags: OS.Constants.libc.O_CREAT });
    let file = await OS.File.open(
      `${dump}.ignore`,
      { create: true },
      { unixFlags: OS.Constants.libc.O_CREAT }
    );
    await file.close();
  },

@@ -498,8 +547,7 @@ var CrashSubmit = {
      for (let entry in entries) {
        let entryInfo = await entries[entry];

        if (!(entry in ignored) &&
            entryInfo.lastAccessDate > minFileDate) {
        if (!(entry in ignored) && entryInfo.lastAccessDate > minFileDate) {
          ids.push(entry);
        }
      }
@@ -589,9 +637,11 @@ var CrashSubmit = {
        }
      }

      await Promise.all(toDelete.map(path => {
      await Promise.all(
        toDelete.map(path => {
          return OS.File.remove(path, { ignoreAbsent: true });
      }));
        })
      );
    }
  },

+18 −11
Original line number Diff line number Diff line
@@ -2,8 +2,7 @@
 * 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/. */

ChromeUtils.defineModuleGetter(this, "OS",
                               "resource://gre/modules/osfile.jsm");
ChromeUtils.defineModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");

var EXPORTED_SYMBOLS = [
  "parseKeyValuePairsFromLines",
@@ -15,18 +14,19 @@ var EXPORTED_SYMBOLS = [
var parseKeyValuePairsFromLines = function(lines) {
  let data = {};
  for (let line of lines) {
    if (line == "")
    if (line == "") {
      continue;
    }

    // can't just .split() because the value might contain = characters
    let eq = line.indexOf("=");
    if (eq != -1) {
      let [key, value] = [line.substring(0, eq),
                          line.substring(eq + 1)];
      if (key && value)
      let [key, value] = [line.substring(0, eq), line.substring(eq + 1)];
      if (key && value) {
        data[key] = value.replace(/\\n/g, "\n").replace(/\\\\/g, "\\");
      }
    }
  }
  return data;
};

@@ -37,12 +37,19 @@ function parseKeyValuePairs(text) {

// some test setup still uses this sync version
function parseKeyValuePairsFromFile(file) {
  let fstream = Cc["@mozilla.org/network/file-input-stream;1"].
                createInstance(Ci.nsIFileInputStream);
  let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
    Ci.nsIFileInputStream
  );
  fstream.init(file, -1, 0, 0);
  let is = Cc["@mozilla.org/intl/converter-input-stream;1"].
           createInstance(Ci.nsIConverterInputStream);
  is.init(fstream, "UTF-8", 1024, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
  let is = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(
    Ci.nsIConverterInputStream
  );
  is.init(
    fstream,
    "UTF-8",
    1024,
    Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER
  );
  let str = {};
  let contents = "";
  while (is.readString(4096, str) != 0) {
+65 −30
Original line number Diff line number Diff line
@@ -4,18 +4,28 @@

let reportURL;

const {CrashReports} = ChromeUtils.import("resource://gre/modules/CrashReports.jsm");
const { CrashReports } = ChromeUtils.import(
  "resource://gre/modules/CrashReports.jsm"
);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");

ChromeUtils.defineModuleGetter(this, "CrashSubmit", "resource://gre/modules/CrashSubmit.jsm");
ChromeUtils.defineModuleGetter(
  this,
  "CrashSubmit",
  "resource://gre/modules/CrashSubmit.jsm"
);

document.addEventListener("DOMContentLoaded", () => {
  populateReportLists();
  document.getElementById("clearUnsubmittedReports").addEventListener("click", () => {
  document
    .getElementById("clearUnsubmittedReports")
    .addEventListener("click", () => {
      clearUnsubmittedReports().catch(Cu.reportError);
    });
  document.getElementById("clearSubmittedReports").addEventListener("click", () => {
  document
    .getElementById("clearSubmittedReports")
    .addEventListener("click", () => {
      clearSubmittedReports().catch(Cu.reportError);
    });
});
@@ -48,7 +58,9 @@ function populateReportLists() {
    timeStyle: "short",
    dateStyle: "short",
  });
  reports.forEach(report => addReportRow(report.pending, report.id, report.date, dateFormatter));
  reports.forEach(report =>
    addReportRow(report.pending, report.id, report.date, dateFormatter)
  );
  showAppropriateSections();
}

@@ -64,7 +76,9 @@ function populateReportLists() {
 */
function addReportRow(isPending, id, date, dateFormatter) {
  const rowTemplate = document.getElementById("crashReportRow");
  const row = document.importNode(rowTemplate.content, true).querySelector("tr");
  const row = document
    .importNode(rowTemplate.content, true)
    .querySelector("tr");
  row.id = id;

  const cells = row.querySelectorAll("td");
@@ -73,15 +87,20 @@ function addReportRow(isPending, id, date, dateFormatter) {

  if (isPending) {
    const buttonTemplate = document.getElementById("crashSubmitButton");
    const button = document.importNode(buttonTemplate.content, true).querySelector("button");
    const button = document
      .importNode(buttonTemplate.content, true)
      .querySelector("button");
    const buttonText = button.querySelector("span");
    button.addEventListener("click",
      () => submitPendingReport(id, row, button, buttonText, dateFormatter));
    button.addEventListener("click", () =>
      submitPendingReport(id, row, button, buttonText, dateFormatter)
    );
    cells[2].appendChild(button);
    document.getElementById("unsubmitted").appendChild(row);
  } else {
    const linkTemplate = document.getElementById("viewCrashLink");
    const link = document.importNode(linkTemplate.content, true).querySelector("a");
    const link = document
      .importNode(linkTemplate.content, true)
      .querySelector("a");
    link.href = `${reportURL}${id}`;
    cells[2].appendChild(link);
    document.getElementById("submitted").appendChild(row);
@@ -95,12 +114,19 @@ function addReportRow(isPending, id, date, dateFormatter) {
 * indicating that no crash reports have been submitted.
 */
function showAppropriateSections() {
  let hasUnsubmitted = document.getElementById("unsubmitted").childElementCount > 0;
  document.getElementById("reportListUnsubmitted").classList.toggle("hidden", !hasUnsubmitted);
  let hasUnsubmitted =
    document.getElementById("unsubmitted").childElementCount > 0;
  document
    .getElementById("reportListUnsubmitted")
    .classList.toggle("hidden", !hasUnsubmitted);

  let hasSubmitted = document.getElementById("submitted").childElementCount > 0;
  document.getElementById("reportListSubmitted").classList.toggle("hidden", !hasSubmitted);
  document.getElementById("noSubmittedReports").classList.toggle("hidden", hasSubmitted);
  document
    .getElementById("reportListSubmitted")
    .classList.toggle("hidden", !hasSubmitted);
  document
    .getElementById("noSubmittedReports")
    .classList.toggle("hidden", hasSubmitted);
}

/**
@@ -118,9 +144,12 @@ function showAppropriateSections() {
 */
function submitPendingReport(reportId, row, button, buttonText, dateFormatter) {
  button.classList.add("submitting");
  CrashSubmit.submit(reportId, { noThrottle: true }).then(remoteCrashID => {
  CrashSubmit.submit(reportId, { noThrottle: true }).then(
    remoteCrashID => {
      document.getElementById("unsubmitted").removeChild(row);
      const report = CrashReports.getReports().filter(report => report.id === remoteCrashID);
      const report = CrashReports.getReports().filter(
        report => report.id === remoteCrashID
      );
      addReportRow(false, remoteCrashID, report.date, dateFormatter);
      showAppropriateSections();
      dispatchEvent("CrashSubmitSucceeded");
@@ -128,9 +157,12 @@ function submitPendingReport(reportId, row, button, buttonText, dateFormatter) {
    () => {
      button.classList.remove("submitting");
      button.classList.add("failed-to-submit");
      document.l10n.setAttributes(buttonText, "submit-crash-button-failure-label");
      document.l10n.setAttributes(
        buttonText,
        "submit-crash-button-failure-label"
      );
      dispatchEvent("CrashSubmitFailed");
    },
    }
  );
}

@@ -167,7 +199,7 @@ async function clearSubmittedReports() {

  await cleanupFolder(
    CrashReports.submittedDir.path,
    async entry => entry.name.startsWith("bp-") && entry.name.endsWith(".txt"),
    async entry => entry.name.startsWith("bp-") && entry.name.endsWith(".txt")
  );
  await clearOldReports();
  document.getElementById("reportListSubmitted").classList.add("hidden");
@@ -180,7 +212,10 @@ async function clearSubmittedReports() {
async function clearOldReports() {
  const oneYearAgo = Date.now() - 31586000000;
  await cleanupFolder(CrashReports.reportsDir.path, async entry => {
    if (!entry.name.startsWith("InstallTime") || entry.name == "InstallTime" + buildID) {
    if (
      !entry.name.startsWith("InstallTime") ||
      entry.name == "InstallTime" + buildID
    ) {
      return false;
    }

+60 −48
Original line number Diff line number Diff line
@@ -46,39 +46,51 @@ var file = dir.clone();
file = file.parent;
file.append(ctypes.libraryName("testcrasher"));
var lib = ctypes.open(file.path);
CrashTestUtils.crash = lib.declare("Crash",
CrashTestUtils.crash = lib.declare(
  "Crash",
  ctypes.default_abi,
  ctypes.void_t,
                                   ctypes.int16_t);
CrashTestUtils.saveAppMemory = lib.declare("SaveAppMemory",
  ctypes.int16_t
);
CrashTestUtils.saveAppMemory = lib.declare(
  "SaveAppMemory",
  ctypes.default_abi,
                                           ctypes.uint64_t);
  ctypes.uint64_t
);

try {
  CrashTestUtils.TryOverrideExceptionHandler = lib.declare("TryOverrideExceptionHandler",
  CrashTestUtils.TryOverrideExceptionHandler = lib.declare(
    "TryOverrideExceptionHandler",
    ctypes.default_abi,
                                                           ctypes.void_t);
    ctypes.void_t
  );
} catch (ex) {}

CrashTestUtils.dumpHasStream = lib.declare("DumpHasStream",
CrashTestUtils.dumpHasStream = lib.declare(
  "DumpHasStream",
  ctypes.default_abi,
  ctypes.bool,
  ctypes.char.ptr,
                                           ctypes.uint32_t);
  ctypes.uint32_t
);

CrashTestUtils.dumpHasInstructionPointerMemory =
  lib.declare("DumpHasInstructionPointerMemory",
CrashTestUtils.dumpHasInstructionPointerMemory = lib.declare(
  "DumpHasInstructionPointerMemory",
  ctypes.default_abi,
  ctypes.bool,
              ctypes.char.ptr);
  ctypes.char.ptr
);

CrashTestUtils.dumpCheckMemory = lib.declare("DumpCheckMemory",
CrashTestUtils.dumpCheckMemory = lib.declare(
  "DumpCheckMemory",
  ctypes.default_abi,
  ctypes.bool,
                                             ctypes.char.ptr);
  ctypes.char.ptr
);

CrashTestUtils.getWin64CFITestFnAddrOffset =
  lib.declare("GetWin64CFITestFnAddrOffset",
CrashTestUtils.getWin64CFITestFnAddrOffset = lib.declare(
  "GetWin64CFITestFnAddrOffset",
  ctypes.default_abi,
  ctypes.int32_t,
    ctypes.int16_t);
  ctypes.int16_t
);
Loading