test_ChildCrashHandler.js (3405B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 "use strict"; 4 5 const lazy = {}; 6 ChromeUtils.defineESModuleGetters(lazy, { 7 ChildCrashHandler: "resource://gre/modules/ChildCrashHandler.sys.mjs", 8 EventDispatcher: "resource://gre/modules/Messaging.sys.mjs", 9 }); 10 11 const { makeFakeAppDir } = ChromeUtils.importESModule( 12 "resource://testing-common/AppData.sys.mjs" 13 ); 14 15 add_setup(async function () { 16 await makeFakeAppDir(); 17 // The test harness sets MOZ_CRASHREPORTER_NO_REPORT, which disables 18 // reporting crashes to the user. This test needs them enabled. 19 const noReport = Services.env.get("MOZ_CRASHREPORTER_NO_REPORT"); 20 Services.env.set("MOZ_CRASHREPORTER_NO_REPORT", ""); 21 22 registerCleanupFunction(function () { 23 Services.env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport); 24 }); 25 }); 26 27 add_task(async function test_remoteType() { 28 const childID = 123; 29 const remoteType = "webIsolated=https://example.com"; 30 // Force-set a remote type for the process that we are going to "crash" next. 31 lazy.ChildCrashHandler.childMap.set(childID, remoteType); 32 33 // Mock a process crash being notified. 34 const propertyBag = Cc["@mozilla.org/hash-property-bag;1"].createInstance( 35 Ci.nsIWritablePropertyBag2 36 ); 37 propertyBag.setPropertyAsBool("abnormal", true); 38 propertyBag.setPropertyAsAString("dumpID", "a-dump-id"); 39 40 // Set up a listener to receive the crash report event emitted by the handler. 41 let listener; 42 const crashReportPromise = new Promise(resolve => { 43 listener = { 44 onEvent(aEvent, aData) { 45 resolve([aEvent, aData]); 46 }, 47 }; 48 }); 49 lazy.EventDispatcher.instance.registerListener(listener, [ 50 "GeckoView:ChildCrashReport", 51 ]); 52 53 // Simulate a crash. 54 lazy.ChildCrashHandler.observe(propertyBag, "ipc:content-shutdown", childID); 55 56 const [aEvent, aData] = await crashReportPromise; 57 Assert.equal( 58 "GeckoView:ChildCrashReport", 59 aEvent, 60 "expected a child crash report" 61 ); 62 Assert.equal("webIsolated", aData?.remoteType, "expected remote type prefix"); 63 }); 64 65 add_task(async function test_extensions_process_crash() { 66 const childID = 123; 67 const remoteType = "extension"; 68 // Force-set a remote type for the process that we are going to "crash" next. 69 lazy.ChildCrashHandler.childMap.set(childID, remoteType); 70 71 // Mock a process crash being notified. 72 const propertyBag = Cc["@mozilla.org/hash-property-bag;1"].createInstance( 73 Ci.nsIWritablePropertyBag2 74 ); 75 propertyBag.setPropertyAsBool("abnormal", true); 76 propertyBag.setPropertyAsAString("dumpID", "a-dump-id"); 77 78 // Set up a listener to receive the crash report event emitted by the handler. 79 let listener; 80 const crashReportPromise = new Promise(resolve => { 81 listener = { 82 onEvent(aEvent, aData) { 83 resolve([aEvent, aData]); 84 }, 85 }; 86 }); 87 lazy.EventDispatcher.instance.registerListener(listener, [ 88 "GeckoView:ChildCrashReport", 89 ]); 90 91 // Simulate a crash. 92 lazy.ChildCrashHandler.observe(propertyBag, "ipc:content-shutdown", childID); 93 94 const [aEvent, aData] = await crashReportPromise; 95 Assert.equal( 96 "GeckoView:ChildCrashReport", 97 aEvent, 98 "expected a child crash report" 99 ); 100 Assert.equal("extension", aData?.remoteType, "expected remote type"); 101 Assert.equal( 102 "BACKGROUND_CHILD", 103 aData?.processVisibility, 104 "expected process type" 105 ); 106 });