1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/test/test_child_process_shutdown_message.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,177 @@ 1.4 +<!DOCTYPE html> 1.5 +<html> 1.6 +<head> 1.7 + <meta charset="utf-8"> 1.8 + <title>Test that processes that are shutdown send a 'process-shutdown' 1.9 + message to their process message manager.</title> 1.10 + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> 1.11 + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 1.12 +</head> 1.13 +<body onload="runTests();"> 1.14 +<p id="display"> 1.15 +</p> 1.16 +<div id="content" style="display: none"> 1.17 + 1.18 +</div> 1.19 +<pre id="test"> 1.20 +<script class="testbody" type="application/javascript;version=1.8"> 1.21 + 1.22 +const APP_URL = "http://example.org"; 1.23 +const APP_MANIFEST = "http://example.org/manifest.webapp"; 1.24 +const CHILD_PROCESS_SHUTDOWN_MESSAGE = "child-process-shutdown"; 1.25 + 1.26 +let ppmm = SpecialPowers.Cc["@mozilla.org/parentprocessmessagemanager;1"] 1.27 + .getService(SpecialPowers.Ci.nsIMessageBroadcaster); 1.28 +let obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"] 1.29 + .getService(SpecialPowers.Ci.nsIObserverService); 1.30 + 1.31 +/** 1.32 + * Load the example.org site in an <iframe mozbrowser> 1.33 + * 1.34 + * @param isApp 1.35 + * If true, the example.org site will be loaded as an app. 1.36 + */ 1.37 +function loadBrowser(isApp, callback) { 1.38 + let iframe = document.createElement("iframe"); 1.39 + if (isApp) { 1.40 + iframe.setAttribute("mozapp", APP_MANIFEST); 1.41 + } 1.42 + SpecialPowers.wrap(iframe).mozbrowser = true; 1.43 + iframe.src = APP_URL; 1.44 + document.getElementById("content").appendChild(iframe); 1.45 + 1.46 + iframe.addEventListener("mozbrowserloadend", function onloadend() { 1.47 + iframe.removeEventListener("mozbrowserloadend", onloadend); 1.48 + callback(iframe); 1.49 + }); 1.50 +} 1.51 + 1.52 +/** 1.53 + * Prepare the child process for an intentional crash. This is to keep 1.54 + * the leak automation tools happy. 1.55 + * 1.56 + * This also allows us to acquire the process message manaager that 1.57 + * corresponds to the process by sending a message to a frame script 1.58 + * in the content process and having it reply to us via the child 1.59 + * process message manager. 1.60 + */ 1.61 +function prepareProcess(frameMM, callback) { 1.62 + let frameScript = 'data:,\ 1.63 + privateNoteIntentionalCrash();\ 1.64 + var cpmm = Components.classes["@mozilla.org/childprocessmessagemanager;1"]\ 1.65 + .getService(Components.interfaces.nsISyncMessageSender);\ 1.66 + addMessageListener("TestChild:Ohai", function receiveMessage(msg) {\ 1.67 + cpmm.sendAsyncMessage("TestChild:Ohai");\ 1.68 + });'; 1.69 + frameMM.loadFrameScript(frameScript, false); 1.70 + frameMM.sendAsyncMessage("TestChild:Ohai"); 1.71 + ppmm.addMessageListener("TestChild:Ohai", function receiveMessage(msg) { 1.72 + ppmm.removeMessageListener("TestChild:Ohai", receiveMessage); 1.73 + msg = SpecialPowers.wrap(msg); 1.74 + callback(msg.target); 1.75 + }); 1.76 +} 1.77 + 1.78 +/** 1.79 + * Expects an OOP frame's process to shut down and report four 1.80 + * events/messages: an error event on the browser element, and a 1.81 + * 'child-process-shutdown' message on both the frame and process 1.82 + * message managers. 1.83 + */ 1.84 +function expectFrameProcessShutdown(iframe, frameMM, processMM, callback) { 1.85 + let msgCount = 0; 1.86 + function countMessage() { 1.87 + msgCount += 1; 1.88 + if (msgCount == 4) { 1.89 + ok(true, "Observed all four expected events."); 1.90 + callback(); 1.91 + } 1.92 + }; 1.93 + 1.94 + iframe.addEventListener("mozbrowsererror", function onerror(event) { 1.95 + iframe.removeEventListener("mozbrowsererror", onerror); 1.96 + is(event.detail.type, "fatal", "Observed expected event."); 1.97 + countMessage(); 1.98 + }); 1.99 + 1.100 + processMM.addMessageListener(CHILD_PROCESS_SHUTDOWN_MESSAGE, function receiveMessage() { 1.101 + processMM.removeMessageListener(CHILD_PROCESS_SHUTDOWN_MESSAGE, receiveMessage); 1.102 + ok(true, "Received 'child-process-shutdown' message from process message manager."); 1.103 + countMessage(); 1.104 + }); 1.105 + 1.106 + frameMM.addMessageListener(CHILD_PROCESS_SHUTDOWN_MESSAGE, function receiveMessage() { 1.107 + frameMM.removeMessageListener(CHILD_PROCESS_SHUTDOWN_MESSAGE, receiveMessage); 1.108 + ok(true, "Received 'child-process-shutdown' message from frame message manager."); 1.109 + countMessage(); 1.110 + }); 1.111 + 1.112 + obs.addObserver(function observe(subject, type, data) { 1.113 + if (subject == SpecialPowers.unwrap(processMM)) { 1.114 + obs.removeObserver(observe, "message-manager-disconnect"); 1.115 + ok(true, "Received 'message-manager-disconnect' notification with " + 1.116 + "frame message manager"); 1.117 + countMessage(); 1.118 + } 1.119 + }, "message-manager-disconnect", false); 1.120 +} 1.121 + 1.122 +function setUp() { 1.123 + SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true); 1.124 + SpecialPowers.setBoolPref("dom.ipc.browser_frames.oop_by_default", true); 1.125 + SpecialPowers.addPermission("browser", true, window.document); 1.126 + SpecialPowers.addPermission("embed-apps", true, window.document); 1.127 + 1.128 + // TODO: remove in bug 820712 1.129 + SpecialPowers.setBoolPref("network.disable.ipc.security", true); 1.130 + 1.131 + runNextTest(); 1.132 +} 1.133 + 1.134 +function makeKillTest(isApp) function testKill() { 1.135 + loadBrowser(isApp, function (iframe) { 1.136 + // We want to make sure we get notified on both the frame and 1.137 + // process message managers. 1.138 + let frameMM = SpecialPowers.getBrowserFrameMessageManager(iframe); 1.139 + prepareProcess(frameMM, function (processMM) { 1.140 + // Let's kill the content process by asking for a permission 1.141 + // that it doesn't have. 1.142 + ok(!processMM.assertPermission("frobnaz"), 1.143 + "Content child should not have this permission"); 1.144 + expectFrameProcessShutdown(iframe, frameMM, processMM, function () { 1.145 + iframe.parentNode.removeChild(iframe); 1.146 + runNextTest(); 1.147 + }); 1.148 + }); 1.149 + }); 1.150 +} 1.151 + 1.152 +function tearDown() { 1.153 + SpecialPowers.clearUserPref("dom.mozBrowserFramesEnabled"); 1.154 + SpecialPowers.clearUserPref("dom.ipc.browser_frames.oop_by_default"); 1.155 + 1.156 + // TODO: remove in bug 820712 1.157 + SpecialPowers.clearUserPref("network.disable.ipc.security"); 1.158 + 1.159 + SimpleTest.finish(); 1.160 +} 1.161 + 1.162 +let _tests = [ 1.163 + setUp, 1.164 + makeKillTest(false), 1.165 + makeKillTest(true), 1.166 + tearDown 1.167 +] 1.168 +function runNextTest() { 1.169 + SimpleTest.executeSoon(_tests.shift()); 1.170 +} 1.171 + 1.172 +function runTests() { 1.173 + SimpleTest.waitForExplicitFinish(); 1.174 + runNextTest(); 1.175 +} 1.176 + 1.177 +</script> 1.178 +</pre> 1.179 +</body> 1.180 +</html>