Bug 581341 - Part 4: Always run the IPC testshell callback, regardless of execution success or failure. r=bent
--- 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();
}