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;
 | |
| }
 | 
