<?xml version="1.0"?> <?xml-stylesheet href="chrome://global/skin" type="text/css"?> <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?> <window title="Basic Plugin Tests" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js" /> <script type="application/javascript" src="plugin-utils.js"></script> <script type="application/javascript"> setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); </script> <body xmlns="http://www.w3.org/1999/xhtml" onload="runTests()"> <embed id="plugin1" type="application/x-test" width="200" height="200"></embed> </body> <script class="testbody" type="application/javascript"> <![CDATA[ SimpleTest.waitForExplicitFinish(); SimpleTest.ignoreAllUncaughtExceptions(); Components.utils.import("resource://gre/modules/NetUtil.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Task.jsm"); var Cc = Components.classes; var Ci = Components.interfaces; const crashReporter = Cc["@mozilla.org/toolkit/crash-reporter;1"].getService(Ci.nsICrashReporter); const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs"; var oldServerURL = crashReporter.serverURL; const oldTimeoutPref = Services.prefs.getIntPref("dom.ipc.plugins.timeoutSecs"); var testObserver = { observe: function(subject, topic, data) { if (data == "submitting") // not done yet return; is(data, "success", "report should have been submitted successfully"); is(topic, "crash-report-status", "Checking correct topic"); ok(subject instanceof Ci.nsIPropertyBag2, "Subject should be a property bag"); ok(subject.hasKey("minidumpID"), "Should have a local crash ID"); let crashID = subject.getPropertyAsAString("minidumpID"); isnot(crashID, "", "Local crash ID should not be an empty string"); ok(subject.hasKey("serverCrashID"), "Should have a server crash ID"); let remoteID = subject.getPropertyAsAString("serverCrashID"); isnot(remoteID, "", "Server crash ID should not be an empty string"); // Verify the data. The SJS script will return the data that was POSTed let req = new XMLHttpRequest(); req.open("GET", SERVER_URL + "?id=" + remoteID, false); req.send(null); is(req.status, 200, "Server response should be 200 OK"); let submitted = JSON.parse(req.responseText); ok(!("Throttleable" in submitted), "Submit request should not be Throttleable"); is(submitted.ProcessType, "plugin", "Should specify ProcessType=plugin"); ok("PluginHang" in submitted, "Request should contain PluginHang field"); ok("additional_minidumps" in submitted, "Request should contain additional_minidumps field"); let dumpNames = submitted.additional_minidumps.split(','); ok(dumpNames.indexOf("browser") != -1, "additional_minidumps should contain browser"); info("additional_minidumps="+submitted.additional_minidumps); ok("upload_file_minidump" in submitted, "Request should contain upload_file_minidump field"); ok("upload_file_minidump_browser" in submitted, "Request should contain upload_file_minidump_browser field"); // Cleanup // First remove our fake submitted report let file = Services.dirsvc.get("UAppData", Ci.nsILocalFile); file.append("Crash Reports"); file.append("submitted"); file.append(remoteID + ".txt"); file.remove(false); // Next unregister our observer Services.obs.removeObserver(testObserver, "crash-report-status"); // Finally re-set prefs crashReporter.serverURL = oldServerURL; Services.prefs.setIntPref("dom.ipc.plugins.timeoutSecs", oldTimeoutPref); // Check and cleanup CrashManager. Task.spawn(function* () { let cm = Services.crashmanager; let store = yield cm._getStore(); is(store.crashesCount, 1, "Store should have only 1 item"); let crash = store.getCrash(crashID); ok(!!crash, "Store should have the crash record"); ok(crash.isOfType(cm.PROCESS_TYPE_PLUGIN, cm.CRASH_TYPE_HANG), "Crash type should be plugin-hang"); is(crash.remoteID, remoteID, "Crash remoteID should match"); is(crash.submissions.size, 1, "Crash should have a submission"); let submission = crash.submissions.values().next().value; is(submission.result, cm.SUBMISSION_RESULT_OK, "Submission should be successful"); store.reset(); SimpleTest.finish(); }); }, QueryInterface: function(iid) { if (iid.equals(Ci.nsIObserver) || iid.equals(Ci.nsISupportsWeakReference) || iid.equals(Ci.nsISupports)) return this; throw Components.results.NS_NOINTERFACE; } }; function onPluginCrashed(aEvent) { ok(true, "Plugin crashed notification received"); is(aEvent.type, "PluginCrashed", "event is correct type"); let submitButton = document.getAnonymousElementByAttribute(aEvent.target, "class", "submitButton"); // try to submit this report sendMouseEvent({type:'click'}, submitButton, window); } function runTests() { // Default plugin hang timeout is too high for mochitests Services.prefs.setIntPref("dom.ipc.plugins.timeoutSecs", 1); // Override the crash reporter URL to send to our fake server crashReporter.serverURL = NetUtil.newURI(SERVER_URL); // Hook into plugin crash events Services.obs.addObserver(testObserver, "crash-report-status", true); document.addEventListener("PluginCrashed", onPluginCrashed, false); var pluginElement = document.getElementById("plugin1"); try { Task.spawn(function* () { // Clear data in CrashManager in case previous tests caused something // to be added. let store = yield Services.crashmanager._getStore(); store.reset(); pluginElement.hang(); }); } catch (e) { } } ]]> </script> </window>