forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			247 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			247 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* global gBrowser */
 | 
						|
ChromeUtils.import("resource://gre/modules/CrashSubmit.jsm", this);
 | 
						|
 | 
						|
const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs";
 | 
						|
 | 
						|
var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
 | 
						|
var gTestBrowser = null;
 | 
						|
var config = {};
 | 
						|
 | 
						|
add_task(async function() {
 | 
						|
  // The test harness sets MOZ_CRASHREPORTER_NO_REPORT, which disables plugin
 | 
						|
  // crash reports.  This test needs them enabled.  The test also needs a mock
 | 
						|
  // report server, and fortunately one is already set up by toolkit/
 | 
						|
  // crashreporter/test/Makefile.in.  Assign its URL to MOZ_CRASHREPORTER_URL,
 | 
						|
  // which CrashSubmit.jsm uses as a server override.
 | 
						|
  let env = Cc["@mozilla.org/process/environment;1"]
 | 
						|
              .getService(Ci.nsIEnvironment);
 | 
						|
  let noReport = env.get("MOZ_CRASHREPORTER_NO_REPORT");
 | 
						|
  let serverUrl = env.get("MOZ_CRASHREPORTER_URL");
 | 
						|
  env.set("MOZ_CRASHREPORTER_NO_REPORT", "");
 | 
						|
  env.set("MOZ_CRASHREPORTER_URL", SERVER_URL);
 | 
						|
 | 
						|
  gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
 | 
						|
  gTestBrowser = gBrowser.selectedBrowser;
 | 
						|
 | 
						|
  // Crash immediately
 | 
						|
  Services.prefs.setIntPref("dom.ipc.plugins.timeoutSecs", 0);
 | 
						|
 | 
						|
  registerCleanupFunction(async function() {
 | 
						|
    Services.prefs.clearUserPref("dom.ipc.plugins.timeoutSecs");
 | 
						|
    env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport);
 | 
						|
    env.set("MOZ_CRASHREPORTER_URL", serverUrl);
 | 
						|
    env = null;
 | 
						|
    config = null;
 | 
						|
    gTestBrowser = null;
 | 
						|
    gBrowser.removeCurrentTab();
 | 
						|
    window.focus();
 | 
						|
  });
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function() {
 | 
						|
  config = {
 | 
						|
    shouldSubmissionUIBeVisible: true,
 | 
						|
    comment: "",
 | 
						|
    urlOptIn: false
 | 
						|
  };
 | 
						|
 | 
						|
  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
 | 
						|
 | 
						|
  let pluginCrashed = promisePluginCrashed();
 | 
						|
 | 
						|
  await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_crashCommentAndURL.html");
 | 
						|
 | 
						|
  // Work around for delayed PluginBindingAttached
 | 
						|
  await promiseUpdatePluginBindings(gTestBrowser);
 | 
						|
 | 
						|
  // Wait for the plugin to crash
 | 
						|
  await pluginCrashed;
 | 
						|
 | 
						|
  let crashReportStatus = TestUtils.topicObserved("crash-report-status", onSubmitStatus);
 | 
						|
 | 
						|
  // Test that the crash submission UI is actually visible and submit the crash report.
 | 
						|
  await ContentTask.spawn(gTestBrowser, config, async function(aConfig) {
 | 
						|
    let doc = content.document;
 | 
						|
    let plugin = doc.getElementById("plugin");
 | 
						|
    let pleaseSubmit = doc.getAnonymousElementByAttribute(plugin, "anonid", "pleaseSubmit");
 | 
						|
    let submitButton = doc.getAnonymousElementByAttribute(plugin, "anonid", "submitButton");
 | 
						|
    // Test that we don't send the URL when urlOptIn is false.
 | 
						|
    doc.getAnonymousElementByAttribute(plugin, "anonid", "submitURLOptIn").checked = aConfig.urlOptIn;
 | 
						|
    submitButton.click();
 | 
						|
    Assert.equal(content.getComputedStyle(pleaseSubmit).display == "block",
 | 
						|
      aConfig.shouldSubmissionUIBeVisible, "The crash UI should be visible");
 | 
						|
  });
 | 
						|
 | 
						|
  await crashReportStatus;
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function() {
 | 
						|
  config = {
 | 
						|
    shouldSubmissionUIBeVisible: true,
 | 
						|
    comment: "a test comment",
 | 
						|
    urlOptIn: true
 | 
						|
  };
 | 
						|
 | 
						|
  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
 | 
						|
 | 
						|
  let pluginCrashed = promisePluginCrashed();
 | 
						|
 | 
						|
  await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_crashCommentAndURL.html");
 | 
						|
 | 
						|
  // Work around for delayed PluginBindingAttached
 | 
						|
  await promiseUpdatePluginBindings(gTestBrowser);
 | 
						|
 | 
						|
  // Wait for the plugin to crash
 | 
						|
  await pluginCrashed;
 | 
						|
 | 
						|
  let crashReportStatus = TestUtils.topicObserved("crash-report-status", onSubmitStatus);
 | 
						|
 | 
						|
  // Test that the crash submission UI is actually visible and submit the crash report.
 | 
						|
  await ContentTask.spawn(gTestBrowser, config, async function(aConfig) {
 | 
						|
    let doc = content.document;
 | 
						|
    let plugin = doc.getElementById("plugin");
 | 
						|
    let pleaseSubmit = doc.getAnonymousElementByAttribute(plugin, "anonid", "pleaseSubmit");
 | 
						|
    let submitButton = doc.getAnonymousElementByAttribute(plugin, "anonid", "submitButton");
 | 
						|
    // Test that we send the URL when urlOptIn is true.
 | 
						|
    doc.getAnonymousElementByAttribute(plugin, "anonid", "submitURLOptIn").checked = aConfig.urlOptIn;
 | 
						|
    doc.getAnonymousElementByAttribute(plugin, "anonid", "submitComment").value = aConfig.comment;
 | 
						|
    submitButton.click();
 | 
						|
    Assert.equal(content.getComputedStyle(pleaseSubmit).display == "block",
 | 
						|
      aConfig.shouldSubmissionUIBeVisible, "The crash UI should be visible");
 | 
						|
  });
 | 
						|
 | 
						|
  await crashReportStatus;
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function() {
 | 
						|
  config = {
 | 
						|
    shouldSubmissionUIBeVisible: false,
 | 
						|
    comment: "",
 | 
						|
    urlOptIn: true
 | 
						|
  };
 | 
						|
 | 
						|
  // Deferred promise object used by the test to wait for the crash handler
 | 
						|
  let crashDeferred = PromiseUtils.defer();
 | 
						|
 | 
						|
  // Clear out any minidumps we create from plugin crashes, this is needed
 | 
						|
  // because we do not submit the crash otherwise the submission process would
 | 
						|
  // have deleted the crash dump files for us.
 | 
						|
  let crashObserver = (subject, topic, data) => {
 | 
						|
    if (topic != "plugin-crashed") {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    let propBag = subject.QueryInterface(Ci.nsIPropertyBag2);
 | 
						|
    let minidumpID = propBag.getPropertyAsAString("pluginDumpID");
 | 
						|
 | 
						|
    Services.crashmanager.ensureCrashIsPresent(minidumpID).then(() => {
 | 
						|
      let minidumpDir = Services.dirsvc.get("UAppData", Ci.nsIFile);
 | 
						|
      minidumpDir.append("Crash Reports");
 | 
						|
      minidumpDir.append("pending");
 | 
						|
 | 
						|
      let pluginDumpFile = minidumpDir.clone();
 | 
						|
      pluginDumpFile.append(minidumpID + ".dmp");
 | 
						|
 | 
						|
      let extraFile = minidumpDir.clone();
 | 
						|
      extraFile.append(minidumpID + ".extra");
 | 
						|
 | 
						|
      pluginDumpFile.remove(false);
 | 
						|
      extraFile.remove(false);
 | 
						|
      crashDeferred.resolve();
 | 
						|
    });
 | 
						|
  };
 | 
						|
 | 
						|
  Services.obs.addObserver(crashObserver, "plugin-crashed");
 | 
						|
 | 
						|
  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
 | 
						|
 | 
						|
  let pluginCrashed = promisePluginCrashed();
 | 
						|
 | 
						|
  // Make sure that the plugin container is too small to display the crash submission UI
 | 
						|
  await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_crashCommentAndURL.html?" +
 | 
						|
                            encodeURIComponent(JSON.stringify({width: 300, height: 300})));
 | 
						|
 | 
						|
  // Work around for delayed PluginBindingAttached
 | 
						|
  await promiseUpdatePluginBindings(gTestBrowser);
 | 
						|
 | 
						|
  // Wait for the plugin to crash
 | 
						|
  await pluginCrashed;
 | 
						|
 | 
						|
  // Test that the crash submission UI is not visible and do not submit a crash report.
 | 
						|
  await ContentTask.spawn(gTestBrowser, config, async function(aConfig) {
 | 
						|
    let doc = content.document;
 | 
						|
    let plugin = doc.getElementById("plugin");
 | 
						|
    let pleaseSubmit = doc.getAnonymousElementByAttribute(plugin, "anonid", "pleaseSubmit");
 | 
						|
    Assert.equal(!!pleaseSubmit && content.getComputedStyle(pleaseSubmit).display == "block",
 | 
						|
      aConfig.shouldSubmissionUIBeVisible, "Plugin crash UI should not be visible");
 | 
						|
  });
 | 
						|
 | 
						|
  await crashDeferred.promise;
 | 
						|
  Services.obs.removeObserver(crashObserver, "plugin-crashed");
 | 
						|
});
 | 
						|
 | 
						|
function promisePluginCrashed() {
 | 
						|
  return new ContentTask.spawn(gTestBrowser, {}, async function() {
 | 
						|
    await new Promise((resolve) => {
 | 
						|
      addEventListener("PluginCrashReporterDisplayed", function onPluginCrashed() {
 | 
						|
        removeEventListener("PluginCrashReporterDisplayed", onPluginCrashed);
 | 
						|
        resolve();
 | 
						|
      });
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function onSubmitStatus(aSubject, aData) {
 | 
						|
  if (aData === "submitting") {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  is(aData, "success", "The crash report should be submitted successfully");
 | 
						|
 | 
						|
  let propBag = aSubject.QueryInterface(Ci.nsIPropertyBag);
 | 
						|
  if (aData == "success") {
 | 
						|
    let remoteID = getPropertyBagValue(propBag, "serverCrashID");
 | 
						|
    ok(!!remoteID, "serverCrashID should be set");
 | 
						|
 | 
						|
    // Remove the submitted report file.
 | 
						|
    let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
 | 
						|
    file.initWithPath(Services.crashmanager._submittedDumpsDir);
 | 
						|
    file.append(remoteID + ".txt");
 | 
						|
    ok(file.exists(), "Submitted report file should exist");
 | 
						|
    file.remove(false);
 | 
						|
  }
 | 
						|
 | 
						|
  let extra = getPropertyBagValue(propBag, "extra");
 | 
						|
  ok(extra instanceof Ci.nsIPropertyBag, "Extra data should be property bag");
 | 
						|
 | 
						|
  let val = getPropertyBagValue(extra, "PluginUserComment");
 | 
						|
  if (config.comment) {
 | 
						|
    is(val, config.comment,
 | 
						|
       "Comment in extra data should match comment in textbox");
 | 
						|
  } else {
 | 
						|
    ok(val === undefined,
 | 
						|
       "Comment should be absent from extra data when textbox is empty");
 | 
						|
  }
 | 
						|
 | 
						|
  val = getPropertyBagValue(extra, "PluginContentURL");
 | 
						|
  if (config.urlOptIn) {
 | 
						|
    is(val, gBrowser.currentURI.spec,
 | 
						|
       "URL in extra data should match browser URL when opt-in checked");
 | 
						|
  } else {
 | 
						|
    ok(val === undefined,
 | 
						|
       "URL should be absent from extra data when opt-in not checked");
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
function getPropertyBagValue(bag, key) {
 | 
						|
  try {
 | 
						|
    var val = bag.getProperty(key);
 | 
						|
  } catch (e) {
 | 
						|
    if (e.result != Cr.NS_ERROR_FAILURE) {
 | 
						|
      throw e;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return val;
 | 
						|
}
 |