Bug 581341 - Part 4: Always run the IPC testshell callback, regardless of execution success or failure. r=bent
authorJosh Matthews <josh@joshmatthews.net>
Thu, 23 Jun 2011 19:31:58 -0400
changeset 72285 f64afb604e05f003f9a2835c4af783e28470871d
parent 72284 f70d110ad2c9cf19ade31c2a56a6049516ee3424
child 72286 461d34f67036ae3744c01d7aa2e66348ddaddeaa
push idunknown
push userunknown
push dateunknown
reviewersbent
bugs581341
milestone7.0a1
Bug 581341 - Part 4: Always run the IPC testshell callback, regardless of execution success or failure. r=bent
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
ipc/testshell/TestShellParent.cpp
ipc/testshell/TestShellParent.h
toolkit/xre/nsEmbedFunctions.cpp
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -322,16 +322,24 @@ ContentParent::CreateTestShell()
 }
 
 bool
 ContentParent::DestroyTestShell(TestShellParent* aTestShell)
 {
     return PTestShellParent::Send__delete__(aTestShell);
 }
 
+TestShellParent*
+ContentParent::GetTestShellSingleton()
+{
+    if (!ManagedPTestShellParent().Length())
+        return nsnull;
+    return static_cast<TestShellParent*>(ManagedPTestShellParent()[0]);
+}
+
 ContentParent::ContentParent()
     : mGeolocationWatchID(-1)
     , mRunToCompletionDepth(0)
     , mShouldCallUnblockChild(false)
     , mIsAlive(true)
 {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content);
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -89,16 +89,17 @@ public:
     NS_DECL_NSITHREADOBSERVER
     NS_DECL_NSIDOMGEOPOSITIONCALLBACK
     NS_DECL_NSIDEVICEMOTIONLISTENER
 
     TabParent* CreateTab(PRUint32 aChromeFlags);
 
     TestShellParent* CreateTestShell();
     bool DestroyTestShell(TestShellParent* aTestShell);
+    TestShellParent* GetTestShellSingleton();
 
     void ReportChildAlreadyBlocked();
     bool RequestRunToCompletion();
 
     bool IsAlive();
 
     void SetChildMemoryReporters(const InfallibleTArray<MemoryReport>& report);
 
--- a/ipc/testshell/TestShellParent.cpp
+++ b/ipc/testshell/TestShellParent.cpp
@@ -141,8 +141,23 @@ TestShellCommandParent::RunCallback(cons
   return JS_TRUE;
 }
 
 void
 TestShellCommandParent::ReleaseCallback()
 {
   mCallback.Release();
 }
+
+bool
+TestShellCommandParent::ExecuteCallback(const nsString& aResponse)
+{
+  return static_cast<TestShellParent*>(Manager())->CommandDone(
+      this, aResponse);
+}
+
+void
+TestShellCommandParent::ActorDestroy(ActorDestroyReason why)
+{
+  if (why == AbnormalShutdown) {
+    ExecuteCallback(EmptyString());
+  }
+}
--- a/ipc/testshell/TestShellParent.h
+++ b/ipc/testshell/TestShellParent.h
@@ -87,19 +87,22 @@ public:
   JSBool SetCallback(JSContext* aCx,
                      jsval aCallback);
 
   JSBool RunCallback(const nsString& aResponse);
 
   void ReleaseCallback();
 
 protected:
+  bool ExecuteCallback(const nsString& aResponse);
+
+  void ActorDestroy(ActorDestroyReason why);
+  
   bool Recv__delete__(const nsString& aResponse) {
-    return static_cast<TestShellParent*>(Manager())->CommandDone(
-      this, aResponse);
+    return ExecuteCallback(aResponse);
   }
 
 private:
   JSContext* mCx;
   nsAutoJSValHolder mCallback;
 };
 
 
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -701,26 +701,28 @@ XRE_ShutdownChildProcess()
       // that case, we fire off an Exit() here.  If we were indeed
       // above MessagePump::Run(), this Exit() is just superfluous.
       appShell->Exit();
   }
 #endif // XP_MACOSX
 }
 
 namespace {
-TestShellParent* gTestShellParent = nsnull;
 TestShellParent* GetOrCreateTestShellParent()
 {
-    if (!gTestShellParent) {
-        ContentParent* parent = ContentParent::GetSingleton();
-        NS_ENSURE_TRUE(parent, nsnull);
-        gTestShellParent = parent->CreateTestShell();
-        NS_ENSURE_TRUE(gTestShellParent, nsnull);
+    ContentParent* parent = ContentParent::GetSingleton();
+    if (!parent) {
+      return nsnull;
     }
-    return gTestShellParent;
+    TestShellParent* testShell = parent->GetTestShellSingleton();
+    if (testShell) {
+      return testShell;
+    }
+    testShell = parent->CreateTestShell();
+    return testShell;
 }
 }
 
 bool
 XRE_SendTestShellCommand(JSContext* aCx,
                          JSString* aCommand,
                          void* aCallback)
 {
@@ -749,19 +751,21 @@ XRE_GetChildGlobalObject(JSContext* aCx,
 {
     TestShellParent* tsp = GetOrCreateTestShellParent();
     return tsp && tsp->GetGlobalJSObject(aCx, aGlobalP);
 }
 
 bool
 XRE_ShutdownTestShell()
 {
-  if (!gTestShellParent)
+  ContentParent* cp = ContentParent::GetSingleton(PR_FALSE);
+  TestShellParent* tsp = cp ? cp->GetTestShellSingleton() : nsnull;
+  if (!tsp)
     return true;
-  return ContentParent::GetSingleton()->DestroyTestShell(gTestShellParent);
+  return cp->DestroyTestShell(tsp);
 }
 
 #ifdef MOZ_X11
 void
 XRE_InstallX11ErrorHandler()
 {
   InstallX11ErrorHandler();
 }