--- a/ipc/glue/GeckoThread.cpp
+++ b/ipc/glue/GeckoThread.cpp
@@ -70,21 +70,16 @@ GeckoThread::Init()
mXREEmbed.Start();
}
void
GeckoThread::CleanUp()
{
mXREEmbed.Stop();
NS_LogTerm();
-
- // Maybe kill process?
-
- // Call this last according to chrome source comments.
- ChildThread::CleanUp();
}
//
// BrowserProcessSubThread
//
// Friendly names for the well-known threads.
static const char* kBrowserThreadNames[BrowserProcessSubThread::ID_COUNT] = {
--- a/ipc/testshell/TestShell.ipdl
+++ b/ipc/testshell/TestShell.ipdl
@@ -32,16 +32,17 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
namespace mozilla {
namespace ipc {
-rpc protocol TestShell
+sync protocol TestShell
{
child:
- rpc SendCommand(String aCommand);
+ async SendCommand(String aCommand);
+ sync SendCommandWithResponse(String aCommand) returns (String aResponse);
};
} // namespace ipc
} // namespace mozilla
--- a/ipc/testshell/TestShellChild.cpp
+++ b/ipc/testshell/TestShellChild.cpp
@@ -48,18 +48,31 @@ TestShellChild::TestShellChild()
}
TestShellChild::~TestShellChild()
{
}
nsresult
-TestShellChild::AnswerSendCommand(const String& aCommand)
+TestShellChild::RecvSendCommand(const String& aCommand)
{
- nsresult rv = mXPCShell->EvaluateString(aCommand) ? NS_OK : NS_ERROR_FAILURE;
-
if (mXPCShell->IsQuitting()) {
- MessageLoop::current()->Quit();
+ NS_WARNING("Commands sent after quit command issued!");
+ return NS_ERROR_UNEXPECTED;
}
- return rv;
+ return mXPCShell->EvaluateString(aCommand) ? NS_OK : NS_ERROR_FAILURE;
}
+
+nsresult
+TestShellChild::RecvSendCommandWithResponse(const String& aCommand,
+ String* aResponse)
+{
+ if (mXPCShell->IsQuitting()) {
+ NS_WARNING("Commands sent after quit command issued!");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return mXPCShell->EvaluateString(aCommand, aResponse) ?
+ NS_OK :
+ NS_ERROR_FAILURE;
+}
--- a/ipc/testshell/TestShellChild.h
+++ b/ipc/testshell/TestShellChild.h
@@ -47,17 +47,19 @@ class XPCShellEnvironment;
class TestShellChild : public TestShellProtocolChild
{
public:
typedef mozilla::ipc::String String;
TestShellChild();
virtual ~TestShellChild();
- virtual nsresult AnswerSendCommand(const String& aCommand);
+ virtual nsresult RecvSendCommand(const String& aCommand);
+ virtual nsresult RecvSendCommandWithResponse(const String& aCommand,
+ String* aResponse);
void SetXPCShell(XPCShellEnvironment* aXPCShell) {
mXPCShell = aXPCShell;
}
private:
XPCShellEnvironment* mXPCShell;
};
--- a/ipc/testshell/TestShellThread.cpp
+++ b/ipc/testshell/TestShellThread.cpp
@@ -54,24 +54,24 @@ TestShellThread::~TestShellThread()
}
void
TestShellThread::Init()
{
GeckoThread::Init();
mXPCShell = XPCShellEnvironment::CreateEnvironment();
- if (mXPCShell) {
+ if (mXPCShell && mXPCShell->DefineIPCCommands(&mTestShellChild)) {
if (mTestShellChild.Open(channel(), owner_loop())) {
mTestShellChild.SetXPCShell(mXPCShell);
}
}
}
void
TestShellThread::CleanUp()
{
- GeckoThread::CleanUp();
if (mXPCShell) {
XPCShellEnvironment::DestroyEnvironment(mXPCShell);
mTestShellChild.Close();
}
+ GeckoThread::CleanUp();
}
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -40,20 +40,16 @@
#include <errno.h>
#ifdef HAVE_IO_H
#include <io.h> /* for isatty() */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for isatty() */
#endif
-#if defined(XP_MACOSX)
-#include <Foundation/Foundation.h>
-#endif
-
#include "jsapi.h"
#include "jscntxt.h"
#include "jsdbgapi.h"
#include "jsprf.h"
#include "mozilla/XPCOM.h"
#include "nsIChannel.h"
@@ -64,22 +60,24 @@
#include "nsIPrincipal.h"
#include "nsIScriptSecurityManager.h"
#include "nsIURI.h"
#include "nsIXPConnect.h"
#include "nsIXPCScriptable.h"
#include "nsXULAppAPI.h"
+#include "TestShellChild.h"
#include "TestShellParent.h"
#define EXITCODE_RUNTIME_ERROR 3
#define EXITCODE_FILE_NOT_FOUND 4
using mozilla::ipc::XPCShellEnvironment;
+using mozilla::ipc::TestShellChild;
using mozilla::ipc::TestShellParent;
namespace {
static const char kDefaultRuntimeScriptFilename[] = "xpcshell.js";
class FullTrustSecMan : public nsIScriptSecurityManager
{
@@ -1432,74 +1430,148 @@ SendCommand(JSContext *cx,
}
JSString* str = JS_ValueToString(cx, argv[0]);
if (!str) {
JS_ReportError(cx, "Could not convert argument to string!");
return JS_FALSE;
}
- return Environment(cx)->DoSendCommand(str);
+ mozilla::ipc::String command(JS_GetStringBytes(str));
+
+ if (!Environment(cx)->DoSendCommand(command)) {
+ JS_ReportError(cx, "Failed to send command!");
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+SendCommandWithResponse(JSContext *cx,
+ JSObject *obj,
+ uintN argc,
+ jsval *argv,
+ jsval *rval)
+{
+ if (argc != 1) {
+ JS_ReportError(cx, "Function takes only one argument!");
+ return JS_FALSE;
+ }
+
+ JSString* str = JS_ValueToString(cx, argv[0]);
+ if (!str) {
+ JS_ReportError(cx, "Could not convert argument to string!");
+ return JS_FALSE;
+ }
+
+ mozilla::ipc::String command(JS_GetStringBytes(str));
+ mozilla::ipc::String result;
+
+ if (!Environment(cx)->DoSendCommand(command, &result)) {
+ JS_ReportError(cx, "Failed to send command!");
+ return JS_FALSE;
+ }
+
+ JSString* resultStr = JS_NewStringCopyN(cx, result.c_str(), result.length());
+ if (!resultStr) {
+ JS_ReportError(cx, "Failed to convert response to string!");
+ return JS_FALSE;
+ }
+
+ *rval = STRING_TO_JSVAL(resultStr);
+ return JS_TRUE;
}
} /* anonymous namespace */
bool
-XPCShellEnvironment::DefineSendCommand(TestShellParent* aParent)
+XPCShellEnvironment::DefineIPCCommands(TestShellChild* aChild)
{
+ NS_ASSERTION(aChild, "Don't hand me null!");
+
+ // XXXbent Nothing here yet, soon though!
+ return true;
+}
+
+bool
+XPCShellEnvironment::DefineIPCCommands(TestShellParent* aParent)
+{
+ NS_ASSERTION(aParent, "Don't hand me null!");
+
mParent = aParent;
+ JSObject* global = GetGlobalObject();
+
JSAutoRequest ar(mCx);
- JSFunction* fun = JS_DefineFunction(mCx, GetGlobalObject(), "sendCommand",
+ JSFunction* fun = JS_DefineFunction(mCx, global, "sendCommand",
SendCommand, 1, JSPROP_ENUMERATE);
if (!fun) {
NS_WARNING("Failed to define sendCommand function!");
return false;
}
+ fun = JS_DefineFunction(mCx, global, "sendCommandWithResponse",
+ SendCommandWithResponse, 1, JSPROP_ENUMERATE);
+ if (!fun) {
+ NS_WARNING("Failed to define sendCommandWithResponse function!");
+ return false;
+ }
+
return true;
}
JSBool
-XPCShellEnvironment::DoSendCommand(JSString* aCommand)
+XPCShellEnvironment::DoSendCommand(const mozilla::ipc::String& aCommand,
+ mozilla::ipc::String* aResult)
{
- String str(JS_GetStringBytes(aCommand));
+ nsresult rv = aResult ?
+ mParent->SendSendCommandWithResponse(aCommand, aResult) :
+ mParent->SendSendCommand(aCommand);
- nsresult rv = mParent->CallSendCommand(str);
return NS_SUCCEEDED(rv) ? JS_TRUE : JS_FALSE;
}
bool
-XPCShellEnvironment::EvaluateString(const std::string& aString)
+XPCShellEnvironment::EvaluateString(const mozilla::ipc::String& aString,
+ mozilla::ipc::String* aResult)
{
JSAutoRequest ar(mCx);
JS_ClearPendingException(mCx);
JSObject* global = GetGlobalObject();
JSScript* script =
JS_CompileScriptForPrincipals(mCx, global, GetPrincipal(),
aString.c_str(), aString.length(),
"typein", 0);
if (!script) {
return false;
}
if (!ShouldCompileOnly()) {
+ if (aResult) {
+ aResult->clear();
+ }
+
jsval result;
JSBool ok = JS_ExecuteScript(mCx, global, script, &result);
if (ok && result != JSVAL_VOID) {
JSErrorReporter old = JS_SetErrorReporter(mCx, NULL);
JSString* str = JS_ValueToString(mCx, result);
JS_SetErrorReporter(mCx, old);
if (str) {
- fprintf(stdout, "%s\n", JS_GetStringBytes(str));
+ const char* bytes = JS_GetStringBytes(str);
+ fprintf(stdout, "%s\n", bytes);
+ if (aResult) {
+ aResult->assign(bytes);
+ }
}
}
}
JS_DestroyScript(mCx, script);
return true;
}
--- a/ipc/testshell/XPCShellEnvironment.h
+++ b/ipc/testshell/XPCShellEnvironment.h
@@ -40,41 +40,47 @@
#include "base/basictypes.h"
#include <string>
#include <stdio.h>
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsAutoJSValHolder.h"
+#include "mozilla/ipc/TestShellProtocol.h"
+
struct JSContext;
struct JSObject;
struct JSPrincipals;
class nsIJSContextStack;
namespace mozilla {
namespace ipc {
+class TestShellChild;
class TestShellParent;
class XPCShellEnvironment
{
public:
static XPCShellEnvironment* CreateEnvironment();
static void DestroyEnvironment(XPCShellEnvironment* aEnv);
void Process(const char* aFilename = nsnull,
JSBool aIsInteractive = JS_FALSE);
- bool DefineSendCommand(TestShellParent* aParent);
+ bool DefineIPCCommands(TestShellChild* aChild);
+ bool DefineIPCCommands(TestShellParent* aParent);
- JSBool DoSendCommand(JSString* aCommand);
+ JSBool DoSendCommand(const mozilla::ipc::String& aCommand,
+ mozilla::ipc::String* aResult = nsnull);
- bool EvaluateString(const std::string& aString);
+ bool EvaluateString(const mozilla::ipc::String& aString,
+ mozilla::ipc::String* aResult = nsnull);
JSPrincipals* GetPrincipal() {
return mJSPrincipals;
}
JSObject* GetGlobalObject() {
return mGlobalHolder.ToJSObject();
}
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -430,17 +430,17 @@ TestShellMain(int argc, char** argv)
NS_ENSURE_TRUE(channel, 1);
TestShellParent testShellParent;
if (!testShellParent.Open(channel)) {
NS_WARNING("Failed to open channel!");
return 1;
}
- if (!env->DefineSendCommand(&testShellParent)) {
+ if (!env->DefineIPCCommands(&testShellParent)) {
NS_WARNING("DefineChildObject failed!");
return 1;
}
const char* filename = argc > 1 ? argv[1] : nsnull;
env->Process(filename);
return env->ExitCode();