From 3056ce6dfe4900416980896381e487c902946c12 Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Thu, 27 Sep 2012 22:43:24 -0700 Subject: [PATCH] Bug 777508 - Notify parent if child processes are terminated through message manager. r=cjones --- content/base/test/Makefile.in | 1 + .../test_child_process_shutdown_message.html | 136 ++++++++++++++++++ .../test_messagemanager_assertpermission.html | 52 +++++-- dom/ipc/ContentParent.cpp | 6 + dom/ipc/ContentParent.h | 2 + dom/ipc/TabParent.cpp | 1 + 6 files changed, 184 insertions(+), 14 deletions(-) create mode 100644 content/base/test/test_child_process_shutdown_message.html diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index 094727682ff4..ee4321327751 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -577,6 +577,7 @@ ifneq ($(OS_ARCH),WINNT) ifndef MOZ_JAVA_COMPOSITOR MOCHITEST_FILES_B += \ test_messagemanager_assertpermission.html \ + test_child_process_shutdown_message.html \ $(NULL) endif endif diff --git a/content/base/test/test_child_process_shutdown_message.html b/content/base/test/test_child_process_shutdown_message.html new file mode 100644 index 000000000000..75b4abbb5f14 --- /dev/null +++ b/content/base/test/test_child_process_shutdown_message.html @@ -0,0 +1,136 @@ + + + + + Test that processes that are shutdown send a 'process-shutdown' + message to their process message manager. + + + + +

+

+ +
+
+
+ + diff --git a/content/base/test/test_messagemanager_assertpermission.html b/content/base/test/test_messagemanager_assertpermission.html index 1b497b62e067..022b5fed2f14 100644 --- a/content/base/test/test_messagemanager_assertpermission.html +++ b/content/base/test/test_messagemanager_assertpermission.html @@ -19,6 +19,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = SpecialPowers.wrap const APP_URL = "http://example.org"; const APP_MANIFEST = "http://example.org/manifest.webapp"; +const CHILD_PROCESS_SHUTDOWN_MESSAGE = "child-process-shutdown"; let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"] .getService(Ci.nsIMessageBroadcaster); @@ -81,6 +82,41 @@ function prepareProcess(frameMM, callback) { }); } +/** + * Expects an OOP frame's process to shut down and report three + * events/messages: an error event on the browser element, and a + * 'child-process-shutdown' message on both the frame and process + * message managers. + */ +function expectFrameProcessShutdown(iframe, frameMM, processMM, callback) { + let msgCount = 0; + function countMessage() { + msgCount += 1; + if (msgCount == 3) { + ok(true, "Observed all three expected events."); + callback(); + } + }; + + iframe.addEventListener("mozbrowsererror", function onerror(event) { + iframe.removeEventListener("mozbrowsererror", onerror); + is(event.detail.type, "fatal", "Observed expected event."); + countMessage(); + }); + + processMM.addMessageListener(CHILD_PROCESS_SHUTDOWN_MESSAGE, function receiveMessage() { + processMM.removeMessageListener(CHILD_PROCESS_SHUTDOWN_MESSAGE, receiveMessage); + ok(true, "Received 'child-process-shutdown' message from process message manager."); + countMessage(); + }); + + frameMM.addMessageListener(CHILD_PROCESS_SHUTDOWN_MESSAGE, function receiveMessage() { + frameMM.removeMessageListener(CHILD_PROCESS_SHUTDOWN_MESSAGE, receiveMessage); + ok(true, "Received 'child-process-shutdown' message from frame message manager."); + countMessage(); + }); +} + function testSameProcess() { // Assert permissions on the in-process child process message manager. // It always has all permissions, including ones that were never @@ -106,13 +142,7 @@ function testFrameMessageManager() { "Frame mm has assigned permission."); ok(!frameMM.assertPermission("frobnaz"), "Frame mm doesn't have non-existing permission."); - - // The last permission check will result in the content process - // being killed. - iframe.addEventListener("mozbrowsererror", function onerror(event) { - iframe.removeEventListener("mozbrowsererror", onerror); - is(event.detail.type, "fatal", "Observed expected event."); - + expectFrameProcessShutdown(iframe, frameMM, processMM, function () { iframe.parentNode.removeChild(iframe); runNextTest(); }); @@ -130,13 +160,7 @@ function testChildProcessMessageManager() { "Process mm has assigned permission."); ok(!processMM.assertPermission("frobnaz"), "Process mm doesn't have non-existing permission."); - - // The last permission check will result in the content process - // being killed. - iframe.addEventListener("mozbrowsererror", function onerror(event) { - iframe.removeEventListener("mozbrowsererror", onerror); - is(event.detail.type, "fatal", "Observed expected event."); - + expectFrameProcessShutdown(iframe, frameMM, processMM, function () { iframe.parentNode.removeChild(iframe); runNextTest(); }); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index ded1545bf557..cb74018234ef 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -573,6 +573,12 @@ struct DelayedDeleteContentParentTask : public nsRunnable void ContentParent::ActorDestroy(ActorDestroyReason why) { + nsRefPtr ppm = mMessageManager; + if (ppm) { + ppm->ReceiveMessage(static_cast(ppm.get()), + CHILD_PROCESS_SHUTDOWN_MESSAGE, false, + nullptr, nullptr, nullptr); + } nsCOMPtr kungFuDeathGrip(static_cast(this)); nsCOMPtr obs = mozilla::services::GetObserverService(); diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index b4ba0b5925ae..5df7b6b4d239 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -26,6 +26,8 @@ #include "nsDataHashtable.h" #include "nsHashKeys.h" +#define CHILD_PROCESS_SHUTDOWN_MESSAGE NS_LITERAL_STRING("child-process-shutdown") + class mozIApplication; class nsIDOMBlob; diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 38148ee917b7..578566942e87 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -132,6 +132,7 @@ TabParent::ActorDestroy(ActorDestroyReason why) } nsRefPtr frameLoader = GetFrameLoader(); if (frameLoader) { + ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr); frameLoader->DestroyChild(); if (why == AbnormalShutdown) {