mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-16 20:27:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
27
ipc/testshell/PTestShell.ipdl
Normal file
27
ipc/testshell/PTestShell.ipdl
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PContent;
|
||||
include protocol PTestShellCommand;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
async protocol PTestShell
|
||||
{
|
||||
manager PContent;
|
||||
|
||||
manages PTestShellCommand;
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
|
||||
async ExecuteCommand(nsString aCommand);
|
||||
|
||||
async PTestShellCommand(nsString aCommand);
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
20
ipc/testshell/PTestShellCommand.ipdl
Normal file
20
ipc/testshell/PTestShellCommand.ipdl
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PTestShell;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
protocol PTestShellCommand
|
||||
{
|
||||
manager PTestShell;
|
||||
|
||||
parent:
|
||||
async __delete__(nsString aResponse);
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
56
ipc/testshell/TestShellChild.cpp
Normal file
56
ipc/testshell/TestShellChild.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TestShellChild.h"
|
||||
|
||||
using mozilla::ipc::TestShellChild;
|
||||
using mozilla::ipc::PTestShellCommandChild;
|
||||
using mozilla::ipc::XPCShellEnvironment;
|
||||
|
||||
TestShellChild::TestShellChild()
|
||||
: mXPCShell(XPCShellEnvironment::CreateEnvironment())
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
TestShellChild::RecvExecuteCommand(const nsString& aCommand)
|
||||
{
|
||||
if (mXPCShell->IsQuitting()) {
|
||||
NS_WARNING("Commands sent after quit command issued!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return mXPCShell->EvaluateString(aCommand);
|
||||
}
|
||||
|
||||
PTestShellCommandChild*
|
||||
TestShellChild::AllocPTestShellCommandChild(const nsString& aCommand)
|
||||
{
|
||||
return new PTestShellCommandChild();
|
||||
}
|
||||
|
||||
bool
|
||||
TestShellChild::DeallocPTestShellCommandChild(PTestShellCommandChild* aCommand)
|
||||
{
|
||||
delete aCommand;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestShellChild::RecvPTestShellCommandConstructor(PTestShellCommandChild* aActor,
|
||||
const nsString& aCommand)
|
||||
{
|
||||
if (mXPCShell->IsQuitting()) {
|
||||
NS_WARNING("Commands sent after quit command issued!");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsString response;
|
||||
if (!mXPCShell->EvaluateString(aCommand, &response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return PTestShellCommandChild::Send__delete__(aActor, response);
|
||||
}
|
||||
|
||||
45
ipc/testshell/TestShellChild.h
Normal file
45
ipc/testshell/TestShellChild.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef ipc_testshell_TestShellChild_h
|
||||
#define ipc_testshell_TestShellChild_h 1
|
||||
|
||||
#include "mozilla/ipc/PTestShellChild.h"
|
||||
#include "mozilla/ipc/PTestShellCommandChild.h"
|
||||
#include "mozilla/ipc/XPCShellEnvironment.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
|
||||
class XPCShellEnvironment;
|
||||
|
||||
class TestShellChild : public PTestShellChild
|
||||
{
|
||||
public:
|
||||
TestShellChild();
|
||||
|
||||
bool
|
||||
RecvExecuteCommand(const nsString& aCommand);
|
||||
|
||||
PTestShellCommandChild*
|
||||
AllocPTestShellCommandChild(const nsString& aCommand);
|
||||
|
||||
bool
|
||||
RecvPTestShellCommandConstructor(PTestShellCommandChild* aActor,
|
||||
const nsString& aCommand);
|
||||
|
||||
bool
|
||||
DeallocPTestShellCommandChild(PTestShellCommandChild* aCommand);
|
||||
|
||||
private:
|
||||
nsAutoPtr<XPCShellEnvironment> mXPCShell;
|
||||
};
|
||||
|
||||
} /* namespace ipc */
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* ipc_testshell_TestShellChild_h */
|
||||
109
ipc/testshell/TestShellParent.cpp
Normal file
109
ipc/testshell/TestShellParent.cpp
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TestShellParent.h"
|
||||
|
||||
/* This must occur *after* TestShellParent.h to avoid typedefs conflicts. */
|
||||
#include "jsfriendapi.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
||||
#include "xpcpublic.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using mozilla::ipc::TestShellParent;
|
||||
using mozilla::ipc::TestShellCommandParent;
|
||||
using mozilla::ipc::PTestShellCommandParent;
|
||||
using mozilla::dom::ContentParent;
|
||||
|
||||
void
|
||||
TestShellParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
// Implement me! Bug 1005177
|
||||
}
|
||||
|
||||
PTestShellCommandParent*
|
||||
TestShellParent::AllocPTestShellCommandParent(const nsString& aCommand)
|
||||
{
|
||||
return new TestShellCommandParent();
|
||||
}
|
||||
|
||||
bool
|
||||
TestShellParent::DeallocPTestShellCommandParent(PTestShellCommandParent* aActor)
|
||||
{
|
||||
delete aActor;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestShellParent::CommandDone(TestShellCommandParent* command,
|
||||
const nsString& aResponse)
|
||||
{
|
||||
// XXX what should happen if the callback fails?
|
||||
/*bool ok = */command->RunCallback(aResponse);
|
||||
command->ReleaseCallback();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestShellCommandParent::SetCallback(JSContext* aCx,
|
||||
const JS::Value& aCallback)
|
||||
{
|
||||
if (!mCallback.initialized()) {
|
||||
mCallback.init(aCx, aCallback);
|
||||
return true;
|
||||
}
|
||||
|
||||
mCallback = aCallback;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestShellCommandParent::RunCallback(const nsString& aResponse)
|
||||
{
|
||||
NS_ENSURE_TRUE(mCallback.isObject(), false);
|
||||
|
||||
// We're about to run script via JS_CallFunctionValue, so we need an
|
||||
// AutoEntryScript. This is just for testing and not in any spec.
|
||||
dom::AutoEntryScript aes(&mCallback.toObject(), "TestShellCommand");
|
||||
JSContext* cx = aes.cx();
|
||||
JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
|
||||
|
||||
JSString* str = JS_NewUCStringCopyN(cx, aResponse.get(), aResponse.Length());
|
||||
NS_ENSURE_TRUE(str, false);
|
||||
|
||||
JS::Rooted<JS::Value> strVal(cx, JS::StringValue(str));
|
||||
|
||||
JS::Rooted<JS::Value> rval(cx);
|
||||
JS::Rooted<JS::Value> callback(cx, mCallback);
|
||||
bool ok = JS_CallFunctionValue(cx, global, callback, JS::HandleValueArray(strVal), &rval);
|
||||
NS_ENSURE_TRUE(ok, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestShellCommandParent::ReleaseCallback()
|
||||
{
|
||||
mCallback.reset();
|
||||
}
|
||||
|
||||
bool
|
||||
TestShellCommandParent::ExecuteCallback(const nsString& aResponse)
|
||||
{
|
||||
return static_cast<TestShellParent*>(Manager())->CommandDone(
|
||||
this, aResponse);
|
||||
}
|
||||
|
||||
void
|
||||
TestShellCommandParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (why == AbnormalShutdown) {
|
||||
ExecuteCallback(EmptyString());
|
||||
}
|
||||
}
|
||||
68
ipc/testshell/TestShellParent.h
Normal file
68
ipc/testshell/TestShellParent.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef ipc_testshell_TestShellParent_h
|
||||
#define ipc_testshell_TestShellParent_h 1
|
||||
|
||||
#include "mozilla/ipc/PTestShellParent.h"
|
||||
#include "mozilla/ipc/PTestShellCommandParent.h"
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
|
||||
class TestShellCommandParent;
|
||||
|
||||
class TestShellParent : public PTestShellParent
|
||||
{
|
||||
public:
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
PTestShellCommandParent*
|
||||
AllocPTestShellCommandParent(const nsString& aCommand) override;
|
||||
|
||||
bool
|
||||
DeallocPTestShellCommandParent(PTestShellCommandParent* aActor) override;
|
||||
|
||||
bool
|
||||
CommandDone(TestShellCommandParent* aActor, const nsString& aResponse);
|
||||
};
|
||||
|
||||
|
||||
class TestShellCommandParent : public PTestShellCommandParent
|
||||
{
|
||||
public:
|
||||
TestShellCommandParent() {}
|
||||
|
||||
bool SetCallback(JSContext* aCx, const JS::Value& aCallback);
|
||||
|
||||
bool RunCallback(const nsString& aResponse);
|
||||
|
||||
void ReleaseCallback();
|
||||
|
||||
protected:
|
||||
bool ExecuteCallback(const nsString& aResponse);
|
||||
|
||||
void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
bool Recv__delete__(const nsString& aResponse) {
|
||||
return ExecuteCallback(aResponse);
|
||||
}
|
||||
|
||||
private:
|
||||
JS::PersistentRooted<JS::Value> mCallback;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace ipc */
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* ipc_testshell_TestShellParent_h */
|
||||
541
ipc/testshell/XPCShellEnvironment.cpp
Normal file
541
ipc/testshell/XPCShellEnvironment.cpp
Normal file
|
|
@ -0,0 +1,541 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=80:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_IO_H
|
||||
#include <io.h> /* for isatty() */
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h> /* for isatty() */
|
||||
#endif
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "xpcpublic.h"
|
||||
|
||||
#include "XPCShellEnvironment.h"
|
||||
|
||||
#include "mozilla/XPCOM.h"
|
||||
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIDirectoryService.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIXPCScriptable.h"
|
||||
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#include "BackstagePass.h"
|
||||
|
||||
#include "TestShellChild.h"
|
||||
#include "TestShellParent.h"
|
||||
|
||||
using mozilla::ipc::XPCShellEnvironment;
|
||||
using mozilla::ipc::TestShellChild;
|
||||
using mozilla::ipc::TestShellParent;
|
||||
using mozilla::AutoSafeJSContext;
|
||||
using mozilla::dom::AutoJSAPI;
|
||||
using mozilla::dom::AutoEntryScript;
|
||||
using namespace JS;
|
||||
|
||||
namespace {
|
||||
|
||||
static const char kDefaultRuntimeScriptFilename[] = "xpcshell.js";
|
||||
|
||||
inline XPCShellEnvironment*
|
||||
Environment(Handle<JSObject*> global)
|
||||
{
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(global)) {
|
||||
return nullptr;
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
Rooted<Value> v(cx);
|
||||
if (!JS_GetProperty(cx, global, "__XPCShellEnvironment", &v) ||
|
||||
!v.get().isDouble())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<XPCShellEnvironment*>(v.get().toPrivate());
|
||||
}
|
||||
|
||||
static bool
|
||||
Print(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
|
||||
for (unsigned i = 0; i < args.length(); i++) {
|
||||
JSString *str = JS::ToString(cx, args[i]);
|
||||
if (!str)
|
||||
return false;
|
||||
JSAutoByteString bytes(cx, str);
|
||||
if (!bytes)
|
||||
return false;
|
||||
fprintf(stdout, "%s%s", i ? " " : "", bytes.ptr());
|
||||
fflush(stdout);
|
||||
}
|
||||
fputc('\n', stdout);
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetLine(char *bufp,
|
||||
FILE *file,
|
||||
const char *prompt)
|
||||
{
|
||||
char line[256];
|
||||
fputs(prompt, stdout);
|
||||
fflush(stdout);
|
||||
if (!fgets(line, sizeof line, file))
|
||||
return false;
|
||||
strcpy(bufp, line);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
Dump(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
|
||||
if (!args.length())
|
||||
return true;
|
||||
|
||||
JSString *str = JS::ToString(cx, args[0]);
|
||||
if (!str)
|
||||
return false;
|
||||
JSAutoByteString bytes(cx, str);
|
||||
if (!bytes)
|
||||
return false;
|
||||
|
||||
fputs(bytes.ptr(), stdout);
|
||||
fflush(stdout);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
Load(JSContext *cx,
|
||||
unsigned argc,
|
||||
JS::Value *vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
|
||||
JS::Rooted<JSObject*> obj(cx, JS_THIS_OBJECT(cx, vp));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
if (!JS_IsGlobalObject(obj)) {
|
||||
JS_ReportErrorASCII(cx, "Trying to load() into a non-global object");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < args.length(); i++) {
|
||||
JS::Rooted<JSString*> str(cx, JS::ToString(cx, args[i]));
|
||||
if (!str)
|
||||
return false;
|
||||
JSAutoByteString filename(cx, str);
|
||||
if (!filename)
|
||||
return false;
|
||||
FILE *file = fopen(filename.ptr(), "r");
|
||||
if (!file) {
|
||||
filename.clear();
|
||||
if (!filename.encodeUtf8(cx, str))
|
||||
return false;
|
||||
JS_ReportErrorUTF8(cx, "cannot open file '%s' for reading", filename.ptr());
|
||||
return false;
|
||||
}
|
||||
JS::CompileOptions options(cx);
|
||||
options.setUTF8(true)
|
||||
.setFileAndLine(filename.ptr(), 1);
|
||||
JS::Rooted<JSScript*> script(cx);
|
||||
bool ok = JS::Compile(cx, options, file, &script);
|
||||
fclose(file);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
if (!JS_ExecuteScript(cx, script)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
Version(JSContext *cx,
|
||||
unsigned argc,
|
||||
JS::Value *vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
args.rval().setInt32(JS_GetVersion(cx));
|
||||
if (args.get(0).isInt32())
|
||||
JS_SetVersionForCompartment(js::GetContextCompartment(cx),
|
||||
JSVersion(args[0].toInt32()));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
Quit(JSContext *cx,
|
||||
unsigned argc,
|
||||
JS::Value *vp)
|
||||
{
|
||||
Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
|
||||
XPCShellEnvironment* env = Environment(global);
|
||||
env->SetIsQuitting();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
DumpXPC(JSContext *cx,
|
||||
unsigned argc,
|
||||
JS::Value *vp)
|
||||
{
|
||||
JS::CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
uint16_t depth = 2;
|
||||
if (args.length() > 0) {
|
||||
if (!JS::ToUint16(cx, args[0], &depth))
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
|
||||
if (xpc)
|
||||
xpc->DebugDump(int16_t(depth));
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
GC(JSContext *cx,
|
||||
unsigned argc,
|
||||
JS::Value *vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
|
||||
JS_GC(cx);
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
static bool
|
||||
GCZeal(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
uint32_t zeal;
|
||||
if (!ToUint32(cx, args.get(0), &zeal))
|
||||
return false;
|
||||
|
||||
JS_SetGCZeal(cx, uint8_t(zeal), JS_DEFAULT_ZEAL_FREQ);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
const JSFunctionSpec gGlobalFunctions[] =
|
||||
{
|
||||
JS_FS("print", Print, 0,0),
|
||||
JS_FS("load", Load, 1,0),
|
||||
JS_FS("quit", Quit, 0,0),
|
||||
JS_FS("version", Version, 1,0),
|
||||
JS_FS("dumpXPC", DumpXPC, 1,0),
|
||||
JS_FS("dump", Dump, 1,0),
|
||||
JS_FS("gc", GC, 0,0),
|
||||
#ifdef JS_GC_ZEAL
|
||||
JS_FS("gczeal", GCZeal, 1,0),
|
||||
#endif
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
typedef enum JSShellErrNum
|
||||
{
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
name = number,
|
||||
#include "jsshell.msg"
|
||||
#undef MSG_DEF
|
||||
JSShellErr_Limit
|
||||
#undef MSGDEF
|
||||
} JSShellErrNum;
|
||||
|
||||
} /* anonymous namespace */
|
||||
|
||||
void
|
||||
XPCShellEnvironment::ProcessFile(JSContext *cx,
|
||||
const char *filename,
|
||||
FILE *file,
|
||||
bool forceTTY)
|
||||
{
|
||||
XPCShellEnvironment* env = this;
|
||||
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
int lineno, startline;
|
||||
bool ok, hitEOF;
|
||||
char *bufp, buffer[4096];
|
||||
JSString *str;
|
||||
|
||||
JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
|
||||
MOZ_ASSERT(global);
|
||||
|
||||
if (forceTTY) {
|
||||
file = stdin;
|
||||
}
|
||||
else if (!isatty(fileno(file)))
|
||||
{
|
||||
/*
|
||||
* It's not interactive - just execute it.
|
||||
*
|
||||
* Support the UNIX #! shell hack; gobble the first line if it starts
|
||||
* with '#'. TODO - this isn't quite compatible with sharp variables,
|
||||
* as a legal js program (using sharp variables) might start with '#'.
|
||||
* But that would require multi-character lookahead.
|
||||
*/
|
||||
int ch = fgetc(file);
|
||||
if (ch == '#') {
|
||||
while((ch = fgetc(file)) != EOF) {
|
||||
if(ch == '\n' || ch == '\r')
|
||||
break;
|
||||
}
|
||||
}
|
||||
ungetc(ch, file);
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
options.setUTF8(true)
|
||||
.setFileAndLine(filename, 1);
|
||||
JS::Rooted<JSScript*> script(cx);
|
||||
if (JS::Compile(cx, options, file, &script))
|
||||
(void)JS_ExecuteScript(cx, script, &result);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* It's an interactive filehandle; drop into read-eval-print loop. */
|
||||
lineno = 1;
|
||||
hitEOF = false;
|
||||
do {
|
||||
bufp = buffer;
|
||||
*bufp = '\0';
|
||||
|
||||
/*
|
||||
* Accumulate lines until we get a 'compilable unit' - one that either
|
||||
* generates an error (before running out of source) or that compiles
|
||||
* cleanly. This should be whenever we get a complete statement that
|
||||
* coincides with the end of a line.
|
||||
*/
|
||||
startline = lineno;
|
||||
do {
|
||||
if (!GetLine(bufp, file, startline == lineno ? "js> " : "")) {
|
||||
hitEOF = true;
|
||||
break;
|
||||
}
|
||||
bufp += strlen(bufp);
|
||||
lineno++;
|
||||
} while (!JS_BufferIsCompilableUnit(cx, global, buffer, strlen(buffer)));
|
||||
|
||||
/* Clear any pending exception from previous failed compiles. */
|
||||
JS_ClearPendingException(cx);
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine("typein", startline);
|
||||
JS::Rooted<JSScript*> script(cx);
|
||||
if (JS_CompileScript(cx, buffer, strlen(buffer), options, &script)) {
|
||||
JS::WarningReporter older;
|
||||
|
||||
ok = JS_ExecuteScript(cx, script, &result);
|
||||
if (ok && !result.isUndefined()) {
|
||||
/* Suppress warnings from JS::ToString(). */
|
||||
older = JS::SetWarningReporter(cx, nullptr);
|
||||
str = JS::ToString(cx, result);
|
||||
JSAutoByteString bytes;
|
||||
if (str)
|
||||
bytes.encodeLatin1(cx, str);
|
||||
JS::SetWarningReporter(cx, older);
|
||||
|
||||
if (!!bytes)
|
||||
fprintf(stdout, "%s\n", bytes.ptr());
|
||||
else
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
} while (!hitEOF && !env->IsQuitting());
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
// static
|
||||
XPCShellEnvironment*
|
||||
XPCShellEnvironment::CreateEnvironment()
|
||||
{
|
||||
XPCShellEnvironment* env = new XPCShellEnvironment();
|
||||
if (env && !env->Init()) {
|
||||
delete env;
|
||||
env = nullptr;
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
XPCShellEnvironment::XPCShellEnvironment()
|
||||
: mQuitting(false)
|
||||
{
|
||||
}
|
||||
|
||||
XPCShellEnvironment::~XPCShellEnvironment()
|
||||
{
|
||||
if (GetGlobalObject()) {
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(GetGlobalObject())) {
|
||||
return;
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
Rooted<JSObject*> global(cx, GetGlobalObject());
|
||||
|
||||
{
|
||||
JSAutoCompartment ac(cx, global);
|
||||
JS_SetAllNonReservedSlotsToUndefined(cx, global);
|
||||
}
|
||||
mGlobalHolder.reset();
|
||||
|
||||
JS_GC(cx);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
XPCShellEnvironment::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// unbuffer stdout so that output is in the correct order; note that stderr
|
||||
// is unbuffered by default
|
||||
setbuf(stdout, 0);
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
|
||||
mGlobalHolder.init(cx);
|
||||
|
||||
nsCOMPtr<nsIXPConnect> xpc =
|
||||
do_GetService(nsIXPConnect::GetCID());
|
||||
if (!xpc) {
|
||||
NS_ERROR("failed to get nsXPConnect service!");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv) && securityManager) {
|
||||
rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
|
||||
if (NS_FAILED(rv)) {
|
||||
fprintf(stderr, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "+++ Failed to get ScriptSecurityManager service, running without principals");
|
||||
}
|
||||
|
||||
RefPtr<BackstagePass> backstagePass;
|
||||
rv = NS_NewBackstagePass(getter_AddRefs(backstagePass));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Failed to create backstage pass!");
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::CompartmentOptions options;
|
||||
options.creationOptions().setZone(JS::SystemZone);
|
||||
options.behaviors().setVersion(JSVERSION_LATEST);
|
||||
if (xpc::SharedMemoryEnabled())
|
||||
options.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = xpc->InitClassesWithNewWrappedGlobal(cx,
|
||||
static_cast<nsIGlobalObject *>(backstagePass),
|
||||
principal, 0,
|
||||
options,
|
||||
getter_AddRefs(holder));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("InitClassesWithNewWrappedGlobal failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> globalObj(cx, holder->GetJSObject());
|
||||
if (!globalObj) {
|
||||
NS_ERROR("Failed to get global JSObject!");
|
||||
return false;
|
||||
}
|
||||
JSAutoCompartment ac(cx, globalObj);
|
||||
|
||||
backstagePass->SetGlobalObject(globalObj);
|
||||
|
||||
JS::Rooted<Value> privateVal(cx, PrivateValue(this));
|
||||
if (!JS_DefineProperty(cx, globalObj, "__XPCShellEnvironment",
|
||||
privateVal,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT,
|
||||
JS_STUBGETTER, JS_STUBSETTER) ||
|
||||
!JS_DefineFunctions(cx, globalObj, gGlobalFunctions) ||
|
||||
!JS_DefineProfilingFunctions(cx, globalObj))
|
||||
{
|
||||
NS_ERROR("JS_DefineFunctions failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
mGlobalHolder = globalObj;
|
||||
|
||||
FILE* runtimeScriptFile = fopen(kDefaultRuntimeScriptFilename, "r");
|
||||
if (runtimeScriptFile) {
|
||||
fprintf(stdout, "[loading '%s'...]\n", kDefaultRuntimeScriptFilename);
|
||||
ProcessFile(cx, kDefaultRuntimeScriptFilename,
|
||||
runtimeScriptFile, false);
|
||||
fclose(runtimeScriptFile);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
XPCShellEnvironment::EvaluateString(const nsString& aString,
|
||||
nsString* aResult)
|
||||
{
|
||||
AutoEntryScript aes(GetGlobalObject(),
|
||||
"ipc XPCShellEnvironment::EvaluateString");
|
||||
JSContext* cx = aes.cx();
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine("typein", 0);
|
||||
JS::Rooted<JSScript*> script(cx);
|
||||
if (!JS_CompileUCScript(cx, aString.get(), aString.Length(), options,
|
||||
&script))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aResult) {
|
||||
aResult->Truncate();
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
bool ok = JS_ExecuteScript(cx, script, &result);
|
||||
if (ok && !result.isUndefined()) {
|
||||
JS::WarningReporter old = JS::SetWarningReporter(cx, nullptr);
|
||||
JSString* str = JS::ToString(cx, result);
|
||||
nsAutoJSString autoStr;
|
||||
if (str)
|
||||
autoStr.init(cx, str);
|
||||
JS::SetWarningReporter(cx, old);
|
||||
|
||||
if (!autoStr.IsEmpty() && aResult) {
|
||||
aResult->Assign(autoStr);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
64
ipc/testshell/XPCShellEnvironment.h
Normal file
64
ipc/testshell/XPCShellEnvironment.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _IPC_TESTSHELL_XPCSHELLENVIRONMENT_H_
|
||||
#define _IPC_TESTSHELL_XPCSHELLENVIRONMENT_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsString.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
struct JSPrincipals;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class XPCShellEnvironment
|
||||
{
|
||||
public:
|
||||
static XPCShellEnvironment* CreateEnvironment();
|
||||
~XPCShellEnvironment();
|
||||
|
||||
void ProcessFile(JSContext *cx, const char *filename, FILE *file, bool forceTTY);
|
||||
bool EvaluateString(const nsString& aString,
|
||||
nsString* aResult = nullptr);
|
||||
|
||||
JSPrincipals* GetPrincipal() {
|
||||
return nsJSPrincipals::get(nsContentUtils::GetSystemPrincipal());
|
||||
}
|
||||
|
||||
JSObject* GetGlobalObject() {
|
||||
return mGlobalHolder;
|
||||
}
|
||||
|
||||
void SetIsQuitting() {
|
||||
mQuitting = true;
|
||||
}
|
||||
bool IsQuitting() {
|
||||
return mQuitting;
|
||||
}
|
||||
|
||||
protected:
|
||||
XPCShellEnvironment();
|
||||
bool Init();
|
||||
|
||||
private:
|
||||
JS::PersistentRooted<JSObject *> mGlobalHolder;
|
||||
|
||||
bool mQuitting;
|
||||
};
|
||||
|
||||
} /* namespace ipc */
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* _IPC_TESTSHELL_XPCSHELLENVIRONMENT_H_ */
|
||||
37
ipc/testshell/moz.build
Normal file
37
ipc/testshell/moz.build
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS.mozilla.ipc += [
|
||||
'TestShellChild.h',
|
||||
'TestShellParent.h',
|
||||
'XPCShellEnvironment.h',
|
||||
]
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell.ini']
|
||||
|
||||
SOURCES += [
|
||||
'TestShellChild.cpp',
|
||||
'TestShellParent.cpp',
|
||||
'XPCShellEnvironment.cpp',
|
||||
]
|
||||
|
||||
IPDL_SOURCES = [
|
||||
'PTestShell.ipdl',
|
||||
'PTestShellCommand.ipdl',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
# For xpcshell error messages and nsAutoJSString
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
'/js/xpconnect/src',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
28
ipc/testshell/tests/test_ipcshell.js
Normal file
28
ipc/testshell/tests/test_ipcshell.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
function callback(result) {
|
||||
do_check_eq(result, Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT);
|
||||
do_test_finished();
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
do_check_eq(runtime.processType, Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
|
||||
|
||||
sendCommand("load('test_ipcshell_child.js');");
|
||||
|
||||
sendCommand("runtime.processType;", callback);
|
||||
|
||||
[ [ "C", "D" ], [ "D", "C" ], [ "\u010C", "D" ], [ "D", "\u010C" ] ].forEach(
|
||||
function (pair) {
|
||||
do_test_pending();
|
||||
var cmp = pair[0].localeCompare(pair[1]);
|
||||
sendCommand(
|
||||
"'"+ pair[0] +"'.localeCompare('"+ pair[1] +"');",
|
||||
function (result) {
|
||||
do_check_eq(cmp, result);
|
||||
do_test_finished();
|
||||
});
|
||||
})
|
||||
}
|
||||
load('test_ipcshell_child.js');
|
||||
|
||||
9
ipc/testshell/tests/test_ipcshell_child.js
Normal file
9
ipc/testshell/tests/test_ipcshell_child.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
|
||||
const runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
|
||||
|
||||
if (typeof(run_test) == "undefined") {
|
||||
run_test = function() {
|
||||
do_check_eq(runtime.processType, Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
|
||||
}
}
|
||||
9
ipc/testshell/tests/xpcshell.ini
Normal file
9
ipc/testshell/tests/xpcshell.ini
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[DEFAULT]
|
||||
head =
|
||||
tail =
|
||||
skip-if = toolkit == 'android'
|
||||
|
||||
[test_ipcshell.js]
|
||||
# Bug 676963: test fails consistently on Android
|
||||
fail-if = os == "android"
|
||||
[test_ipcshell_child.js]
|
||||
Loading…
Add table
Add a link
Reference in a new issue