michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "TestShellParent.h" michael@0: michael@0: /* This must occur *after* TestShellParent.h to avoid typedefs conflicts. */ michael@0: #include "mozilla/ArrayUtils.h" michael@0: michael@0: #include "mozilla/dom/ContentParent.h" michael@0: michael@0: #include "nsAutoPtr.h" michael@0: #include "nsCxPusher.h" michael@0: michael@0: using namespace mozilla; michael@0: using mozilla::ipc::TestShellParent; michael@0: using mozilla::ipc::TestShellCommandParent; michael@0: using mozilla::ipc::PTestShellCommandParent; michael@0: using mozilla::dom::ContentParent; michael@0: michael@0: PTestShellCommandParent* michael@0: TestShellParent::AllocPTestShellCommandParent(const nsString& aCommand) michael@0: { michael@0: return new TestShellCommandParent(); michael@0: } michael@0: michael@0: bool michael@0: TestShellParent::DeallocPTestShellCommandParent(PTestShellCommandParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TestShellParent::CommandDone(TestShellCommandParent* command, michael@0: const nsString& aResponse) michael@0: { michael@0: // XXX what should happen if the callback fails? michael@0: /*bool ok = */command->RunCallback(aResponse); michael@0: command->ReleaseCallback(); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TestShellCommandParent::SetCallback(JSContext* aCx, michael@0: JS::Value aCallback) michael@0: { michael@0: if (!mCallback.Hold(aCx)) { michael@0: return false; michael@0: } michael@0: michael@0: mCallback = aCallback; michael@0: mCx = aCx; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TestShellCommandParent::RunCallback(const nsString& aResponse) michael@0: { michael@0: NS_ENSURE_TRUE(!mCallback.get().isNull() && mCx, false); michael@0: michael@0: // We're pulling a cx off the heap, so make sure it's stack-top. michael@0: AutoCxPusher pusher(mCx); michael@0: NS_ENSURE_TRUE(mCallback.ToJSObject(), false); michael@0: JSAutoCompartment ac(mCx, mCallback.ToJSObject()); michael@0: JS::Rooted global(mCx, JS::CurrentGlobalOrNull(mCx)); michael@0: michael@0: JSString* str = JS_NewUCStringCopyN(mCx, aResponse.get(), aResponse.Length()); michael@0: NS_ENSURE_TRUE(str, false); michael@0: michael@0: JS::Rooted strVal(mCx, JS::StringValue(str)); michael@0: michael@0: JS::Rooted rval(mCx); michael@0: JS::Rooted callback(mCx, mCallback); michael@0: bool ok = JS_CallFunctionValue(mCx, global, callback, strVal, &rval); michael@0: NS_ENSURE_TRUE(ok, false); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: TestShellCommandParent::ReleaseCallback() michael@0: { michael@0: mCallback.Release(); michael@0: } michael@0: michael@0: bool michael@0: TestShellCommandParent::ExecuteCallback(const nsString& aResponse) michael@0: { michael@0: return static_cast(Manager())->CommandDone( michael@0: this, aResponse); michael@0: } michael@0: michael@0: void michael@0: TestShellCommandParent::ActorDestroy(ActorDestroyReason why) michael@0: { michael@0: if (why == AbnormalShutdown) { michael@0: ExecuteCallback(EmptyString()); michael@0: } michael@0: }