Bug 568698 - Instead of fixing two globals in the jetpack process, allow jetpack to create sandboxes in which to load user code and implementation modules, r=bent
This commit is contained in:
@@ -71,7 +71,7 @@ public:
|
|||||||
> MapType;
|
> MapType;
|
||||||
|
|
||||||
OpaqueSeenType() {
|
OpaqueSeenType() {
|
||||||
NS_ASSERTION(map.init(1), "Failed to initialize map");
|
(void) map.init(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok() { return map.initialized(); }
|
bool ok() { return map.initialized(); }
|
||||||
@@ -452,24 +452,18 @@ JetpackActorCommon::RecvMessage(JSContext* cx,
|
|||||||
JSObject* implGlobal = JS_GetGlobalObject(cx);
|
JSObject* implGlobal = JS_GetGlobalObject(cx);
|
||||||
js::AutoValueRooter rval(cx);
|
js::AutoValueRooter rval(cx);
|
||||||
|
|
||||||
const uint32 savedOptions =
|
|
||||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT);
|
|
||||||
|
|
||||||
for (PRUint32 i = 0; i < snapshot.Length(); ++i) {
|
for (PRUint32 i = 0; i < snapshot.Length(); ++i) {
|
||||||
Variant* vp = results ? results->AppendElement() : NULL;
|
Variant* vp = results ? results->AppendElement() : NULL;
|
||||||
rval.set(JSVAL_VOID);
|
rval.set(JSVAL_VOID);
|
||||||
if (!JS_CallFunctionValue(cx, implGlobal, snapshot[i], argc, argv,
|
if (!JS_CallFunctionValue(cx, implGlobal, snapshot[i], argc, argv,
|
||||||
rval.addr())) {
|
rval.addr())) {
|
||||||
// If a receiver throws, we drop the exception on the floor.
|
(void) JS_ReportPendingException(cx);
|
||||||
JS_ClearPendingException(cx);
|
|
||||||
if (vp)
|
if (vp)
|
||||||
*vp = void_t();
|
*vp = void_t();
|
||||||
} else if (vp && !jsval_to_Variant(cx, rval.value(), vp))
|
} else if (vp && !jsval_to_Variant(cx, rval.value(), vp))
|
||||||
*vp = void_t();
|
*vp = void_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_SetOptions(cx, savedOptions);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,8 @@
|
|||||||
|
|
||||||
#include "jsarray.h"
|
#include "jsarray.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace jetpack {
|
namespace jetpack {
|
||||||
|
|
||||||
@@ -55,18 +57,6 @@ JetpackChild::~JetpackChild()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IMPL_PROP_FLAGS (JSPROP_SHARED | \
|
|
||||||
JSPROP_ENUMERATE | \
|
|
||||||
JSPROP_READONLY | \
|
|
||||||
JSPROP_PERMANENT)
|
|
||||||
const JSPropertySpec
|
|
||||||
JetpackChild::sImplProperties[] = {
|
|
||||||
{ "jetpack", 0, IMPL_PROP_FLAGS, UserJetpackGetter, NULL },
|
|
||||||
{ 0, 0, 0, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef IMPL_PROP_FLAGS
|
|
||||||
|
|
||||||
#define IMPL_METHOD_FLAGS (JSFUN_FAST_NATIVE | \
|
#define IMPL_METHOD_FLAGS (JSFUN_FAST_NATIVE | \
|
||||||
JSPROP_ENUMERATE | \
|
JSPROP_ENUMERATE | \
|
||||||
JSPROP_READONLY | \
|
JSPROP_READONLY | \
|
||||||
@@ -80,6 +70,8 @@ JetpackChild::sImplMethods[] = {
|
|||||||
JS_FN("unregisterReceivers", UnregisterReceivers, 1, IMPL_METHOD_FLAGS),
|
JS_FN("unregisterReceivers", UnregisterReceivers, 1, IMPL_METHOD_FLAGS),
|
||||||
JS_FN("wrap", Wrap, 1, IMPL_METHOD_FLAGS),
|
JS_FN("wrap", Wrap, 1, IMPL_METHOD_FLAGS),
|
||||||
JS_FN("createHandle", CreateHandle, 0, IMPL_METHOD_FLAGS),
|
JS_FN("createHandle", CreateHandle, 0, IMPL_METHOD_FLAGS),
|
||||||
|
JS_FN("createSandbox", CreateSandbox, 0, IMPL_METHOD_FLAGS),
|
||||||
|
JS_FN("evalInSandbox", EvalInSandbox, 2, IMPL_METHOD_FLAGS),
|
||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -92,7 +84,21 @@ JetpackChild::sGlobalClass = {
|
|||||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
|
||||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
ReportJetpackErrors(JSContext* cx, const char* message, JSErrorReport* report)
|
||||||
|
{
|
||||||
|
const char* filename = "<unknown>";
|
||||||
|
if (report && report->filename)
|
||||||
|
filename = report->filename;
|
||||||
|
int lineno = -1;
|
||||||
|
if (report)
|
||||||
|
lineno = report->lineno;
|
||||||
|
|
||||||
|
fprintf(stderr, "Jetpack JavaScript Error: %s:%i, %s\n",
|
||||||
|
filename, lineno, message);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JetpackChild::Init(base::ProcessHandle aParentProcessHandle,
|
JetpackChild::Init(base::ProcessHandle aParentProcessHandle,
|
||||||
MessageLoop* aIOLoop,
|
MessageLoop* aIOLoop,
|
||||||
@@ -102,31 +108,20 @@ JetpackChild::Init(base::ProcessHandle aParentProcessHandle,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!(mRuntime = JS_NewRuntime(32L * 1024L * 1024L)) ||
|
if (!(mRuntime = JS_NewRuntime(32L * 1024L * 1024L)) ||
|
||||||
!(mImplCx = JS_NewContext(mRuntime, 8192)) ||
|
!(mCx = JS_NewContext(mRuntime, 8192)))
|
||||||
!(mUserCx = JS_NewContext(mRuntime, 8192)))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
{
|
JS_SetErrorReporter(mCx, ReportJetpackErrors);
|
||||||
JSAutoRequest request(mImplCx);
|
|
||||||
JS_SetContextPrivate(mImplCx, this);
|
|
||||||
JSObject* implGlobal =
|
|
||||||
JS_NewGlobalObject(mImplCx, const_cast<JSClass*>(&sGlobalClass));
|
|
||||||
if (!implGlobal ||
|
|
||||||
!JS_InitStandardClasses(mImplCx, implGlobal) ||
|
|
||||||
!JS_DefineProperties(mImplCx, implGlobal,
|
|
||||||
const_cast<JSPropertySpec*>(sImplProperties)) ||
|
|
||||||
!JS_DefineFunctions(mImplCx, implGlobal,
|
|
||||||
const_cast<JSFunctionSpec*>(sImplMethods)))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
JSAutoRequest request(mUserCx);
|
JSAutoRequest request(mCx);
|
||||||
JS_SetContextPrivate(mUserCx, this);
|
JS_SetContextPrivate(mCx, this);
|
||||||
JSObject* userGlobal =
|
JSObject* implGlobal =
|
||||||
JS_NewGlobalObject(mUserCx, const_cast<JSClass*>(&sGlobalClass));
|
JS_NewGlobalObject(mCx, const_cast<JSClass*>(&sGlobalClass));
|
||||||
if (!userGlobal ||
|
if (!implGlobal ||
|
||||||
!JS_InitStandardClasses(mUserCx, userGlobal))
|
!JS_InitStandardClasses(mCx, implGlobal) ||
|
||||||
|
!JS_DefineFunctions(mCx, implGlobal,
|
||||||
|
const_cast<JSFunctionSpec*>(sImplMethods)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,8 +132,7 @@ void
|
|||||||
JetpackChild::CleanUp()
|
JetpackChild::CleanUp()
|
||||||
{
|
{
|
||||||
ClearReceivers();
|
ClearReceivers();
|
||||||
JS_DestroyContext(mUserCx);
|
JS_DestroyContext(mCx);
|
||||||
JS_DestroyContext(mImplCx);
|
|
||||||
JS_DestroyRuntime(mRuntime);
|
JS_DestroyRuntime(mRuntime);
|
||||||
JS_ShutDown();
|
JS_ShutDown();
|
||||||
}
|
}
|
||||||
@@ -153,32 +147,21 @@ bool
|
|||||||
JetpackChild::RecvSendMessage(const nsString& messageName,
|
JetpackChild::RecvSendMessage(const nsString& messageName,
|
||||||
const nsTArray<Variant>& data)
|
const nsTArray<Variant>& data)
|
||||||
{
|
{
|
||||||
JSAutoRequest request(mImplCx);
|
JSAutoRequest request(mCx);
|
||||||
return JetpackActorCommon::RecvMessage(mImplCx, messageName, data, NULL);
|
return JetpackActorCommon::RecvMessage(mCx, messageName, data, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
Evaluate(JSContext* cx, const nsCString& code)
|
JetpackChild::RecvEvalScript(const nsString& code)
|
||||||
{
|
{
|
||||||
JSAutoRequest request(cx);
|
JSAutoRequest request(mCx);
|
||||||
js::AutoValueRooter ignored(cx);
|
|
||||||
JS_EvaluateScript(cx, JS_GetGlobalObject(cx), code.get(),
|
js::AutoValueRooter ignored(mCx);
|
||||||
code.Length(), "", 1, ignored.addr());
|
(void) JS_EvaluateUCScript(mCx, JS_GetGlobalObject(mCx), code.get(),
|
||||||
|
code.Length(), "", 1, ignored.addr());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
JetpackChild::RecvLoadImplementation(const nsCString& code)
|
|
||||||
{
|
|
||||||
return Evaluate(mImplCx, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JetpackChild::RecvLoadUserScript(const nsCString& code)
|
|
||||||
{
|
|
||||||
return Evaluate(mUserCx, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
PHandleChild*
|
PHandleChild*
|
||||||
JetpackChild::AllocPHandle()
|
JetpackChild::AllocPHandle()
|
||||||
{
|
{
|
||||||
@@ -197,20 +180,10 @@ JetpackChild::GetThis(JSContext* cx)
|
|||||||
{
|
{
|
||||||
JetpackChild* self =
|
JetpackChild* self =
|
||||||
static_cast<JetpackChild*>(JS_GetContextPrivate(cx));
|
static_cast<JetpackChild*>(JS_GetContextPrivate(cx));
|
||||||
JS_ASSERT(cx == self->mImplCx ||
|
JS_ASSERT(cx == self->mCx);
|
||||||
cx == self->mUserCx);
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
|
||||||
JetpackChild::UserJetpackGetter(JSContext* cx, JSObject* obj, jsval id,
|
|
||||||
jsval* vp)
|
|
||||||
{
|
|
||||||
JSObject* userGlobal = JS_GetGlobalObject(GetThis(cx)->mUserCx);
|
|
||||||
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(userGlobal));
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MessageResult {
|
struct MessageResult {
|
||||||
nsString msgName;
|
nsString msgName;
|
||||||
nsTArray<Variant> data;
|
nsTArray<Variant> data;
|
||||||
@@ -428,5 +401,49 @@ JetpackChild::CreateHandle(JSContext* cx, uintN argc, jsval* vp)
|
|||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
JetpackChild::CreateSandbox(JSContext* cx, uintN argc, jsval* vp)
|
||||||
|
{
|
||||||
|
if (argc > 0) {
|
||||||
|
JS_ReportError(cx, "createSandbox takes zero arguments");
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject* obj = JS_NewGlobalObject(cx, const_cast<JSClass*>(&sGlobalClass));
|
||||||
|
if (!obj)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
|
||||||
|
return JS_InitStandardClasses(cx, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
JetpackChild::EvalInSandbox(JSContext* cx, uintN argc, jsval* vp)
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
JS_ReportError(cx, "evalInSandbox takes two arguments");
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
jsval* argv = JS_ARGV(cx, vp);
|
||||||
|
|
||||||
|
JSObject* obj;
|
||||||
|
if (!JSVAL_IS_OBJECT(argv[0]) ||
|
||||||
|
!(obj = JSVAL_TO_OBJECT(argv[0])) ||
|
||||||
|
&sGlobalClass != JS_GetClass(cx, obj) ||
|
||||||
|
obj == JS_GetGlobalObject(cx)) {
|
||||||
|
JS_ReportError(cx, "The first argument to evalInSandbox must be a global object created using createSandbox.");
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSString* str = JS_ValueToString(cx, argv[1]);
|
||||||
|
if (!str)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
js::AutoValueRooter ignored(cx);
|
||||||
|
return JS_EvaluateUCScript(cx, obj, JS_GetStringChars(str), JS_GetStringLength(str), "", 1,
|
||||||
|
ignored.addr());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace jetpack
|
} // namespace jetpack
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -69,22 +69,17 @@ protected:
|
|||||||
|
|
||||||
NS_OVERRIDE virtual bool RecvSendMessage(const nsString& messageName,
|
NS_OVERRIDE virtual bool RecvSendMessage(const nsString& messageName,
|
||||||
const nsTArray<Variant>& data);
|
const nsTArray<Variant>& data);
|
||||||
NS_OVERRIDE virtual bool RecvLoadImplementation(const nsCString& code);
|
NS_OVERRIDE virtual bool RecvEvalScript(const nsString& script);
|
||||||
NS_OVERRIDE virtual bool RecvLoadUserScript(const nsCString& code);
|
|
||||||
|
|
||||||
NS_OVERRIDE virtual PHandleChild* AllocPHandle();
|
NS_OVERRIDE virtual PHandleChild* AllocPHandle();
|
||||||
NS_OVERRIDE virtual bool DeallocPHandle(PHandleChild* actor);
|
NS_OVERRIDE virtual bool DeallocPHandle(PHandleChild* actor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSRuntime* mRuntime;
|
JSRuntime* mRuntime;
|
||||||
JSContext *mImplCx, *mUserCx;
|
JSContext *mCx;
|
||||||
|
|
||||||
static JetpackChild* GetThis(JSContext* cx);
|
static JetpackChild* GetThis(JSContext* cx);
|
||||||
|
|
||||||
static const JSPropertySpec sImplProperties[];
|
|
||||||
static JSBool UserJetpackGetter(JSContext* cx, JSObject* obj, jsval idval,
|
|
||||||
jsval* vp);
|
|
||||||
|
|
||||||
static const JSFunctionSpec sImplMethods[];
|
static const JSFunctionSpec sImplMethods[];
|
||||||
static JSBool SendMessage(JSContext* cx, uintN argc, jsval *vp);
|
static JSBool SendMessage(JSContext* cx, uintN argc, jsval *vp);
|
||||||
static JSBool CallMessage(JSContext* cx, uintN argc, jsval *vp);
|
static JSBool CallMessage(JSContext* cx, uintN argc, jsval *vp);
|
||||||
@@ -93,6 +88,8 @@ private:
|
|||||||
static JSBool UnregisterReceivers(JSContext* cx, uintN argc, jsval *vp);
|
static JSBool UnregisterReceivers(JSContext* cx, uintN argc, jsval *vp);
|
||||||
static JSBool Wrap(JSContext* cx, uintN argc, jsval *vp);
|
static JSBool Wrap(JSContext* cx, uintN argc, jsval *vp);
|
||||||
static JSBool CreateHandle(JSContext* cx, uintN argc, jsval *vp);
|
static JSBool CreateHandle(JSContext* cx, uintN argc, jsval *vp);
|
||||||
|
static JSBool CreateSandbox(JSContext* cx, uintN argc, jsval *vp);
|
||||||
|
static JSBool EvalInSandbox(JSContext* cx, uintN argc, jsval *vp);
|
||||||
|
|
||||||
static const JSClass sGlobalClass;
|
static const JSClass sGlobalClass;
|
||||||
|
|
||||||
|
|||||||
@@ -63,38 +63,6 @@ JetpackParent::~JetpackParent()
|
|||||||
|
|
||||||
NS_IMPL_ISUPPORTS1(JetpackParent, nsIJetpack)
|
NS_IMPL_ISUPPORTS1(JetpackParent, nsIJetpack)
|
||||||
|
|
||||||
static nsresult
|
|
||||||
ReadFromURI(const nsAString& aURI,
|
|
||||||
nsCString* content)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIURI> uri;
|
|
||||||
nsresult rv = NS_NewURI(getter_AddRefs(uri),
|
|
||||||
NS_ConvertUTF16toUTF8(aURI));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIChannel> channel;
|
|
||||||
NS_NewChannel(getter_AddRefs(channel), uri);
|
|
||||||
NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> input;
|
|
||||||
rv = channel->Open(getter_AddRefs(input));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
NS_ASSERTION(input, "Channel opened successfully but stream was null?");
|
|
||||||
|
|
||||||
char buffer[256];
|
|
||||||
PRUint32 avail = 0;
|
|
||||||
input->Available(&avail);
|
|
||||||
if (avail) {
|
|
||||||
PRUint32 read = 0;
|
|
||||||
while (NS_SUCCEEDED(input->Read(buffer, sizeof(buffer), &read)) && read) {
|
|
||||||
content->Append(buffer, read);
|
|
||||||
read = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
JetpackParent::SendMessage(const nsAString& aMessageName)
|
JetpackParent::SendMessage(const nsAString& aMessageName)
|
||||||
{
|
{
|
||||||
@@ -159,31 +127,12 @@ JetpackParent::UnregisterReceivers(const nsAString& aMessageName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
JetpackParent::LoadImplementation(const nsAString& aURI)
|
JetpackParent::EvalScript(const nsAString& aScript)
|
||||||
{
|
{
|
||||||
nsCString code;
|
if (!SendEvalScript(nsString(aScript)))
|
||||||
nsresult rv = ReadFromURI(aURI, &code);
|
return NS_ERROR_FAILURE;
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (!code.IsEmpty() &&
|
return NS_OK;
|
||||||
!SendLoadImplementation(code))
|
|
||||||
rv = NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
JetpackParent::LoadUserScript(const nsAString& aURI)
|
|
||||||
{
|
|
||||||
nsCString code;
|
|
||||||
nsresult rv = ReadFromURI(aURI, &code);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (!code.IsEmpty() &&
|
|
||||||
!SendLoadUserScript(code))
|
|
||||||
rv = NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -78,8 +78,7 @@ both:
|
|||||||
async PHandle();
|
async PHandle();
|
||||||
|
|
||||||
child:
|
child:
|
||||||
async LoadImplementation(nsCString code);
|
async EvalScript(nsString code);
|
||||||
async LoadUserScript(nsCString code);
|
|
||||||
|
|
||||||
parent:
|
parent:
|
||||||
sync CallMessage(nsString messageName,
|
sync CallMessage(nsString messageName,
|
||||||
|
|||||||
@@ -53,8 +53,7 @@ interface nsIJetpack : nsISupports
|
|||||||
in jsval aReceiver);
|
in jsval aReceiver);
|
||||||
void unregisterReceivers(in AString aMessageName);
|
void unregisterReceivers(in AString aMessageName);
|
||||||
|
|
||||||
void loadImplementation(in AString aURI);
|
void evalScript(in AString aScript);
|
||||||
void loadUserScript(in AString aURI);
|
|
||||||
|
|
||||||
nsIVariant createHandle();
|
nsIVariant createHandle();
|
||||||
|
|
||||||
|
|||||||
@@ -41,3 +41,43 @@ registerReceiver("drop methods", echo);
|
|||||||
registerReceiver("exception coping", echo);
|
registerReceiver("exception coping", echo);
|
||||||
|
|
||||||
registerReceiver("duplicate receivers", echo);
|
registerReceiver("duplicate receivers", echo);
|
||||||
|
|
||||||
|
function ok(c, msg)
|
||||||
|
{
|
||||||
|
sendMessage("test result", c, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerReceiver("test sandbox", function() {
|
||||||
|
var addon = createSandbox();
|
||||||
|
ok(typeof(addon) == "object", "typeof(addon)");
|
||||||
|
ok("Date" in addon, "addon.Date exists");
|
||||||
|
ok(addon.Date !== Date, "Date objects are different");
|
||||||
|
|
||||||
|
var fn = "var x; var c = 3; function doit() { x = 12; return 4; }";
|
||||||
|
evalInSandbox(addon, fn);
|
||||||
|
|
||||||
|
ok(addon.x === undefined, "x is undefined");
|
||||||
|
ok(addon.c == 3, "c is 3");
|
||||||
|
ok(addon.doit() == 4, "doit called successfully");
|
||||||
|
ok(addon.x == 12, "x is now 12");
|
||||||
|
|
||||||
|
var fn2 = "let function barbar{}";
|
||||||
|
try {
|
||||||
|
evalInSandbox(addon, fn2);
|
||||||
|
ok(false, "bad syntax should throw");
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
ok(true, "bad syntax should throw");
|
||||||
|
}
|
||||||
|
|
||||||
|
var fn3 = "throw new Error('just kidding')";
|
||||||
|
try {
|
||||||
|
evalInSandbox(addon, fn3);
|
||||||
|
ok(false, "thrown error should be caught");
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
ok(true, "thrown error should be caught");
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage("sandbox done");
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
|
||||||
var jps = Components.classes["@mozilla.org/jetpack/service;1"]
|
var jps = Components.classes["@mozilla.org/jetpack/service;1"]
|
||||||
.getService(Components.interfaces.nsIJetpackService);
|
.getService(Components.interfaces.nsIJetpackService);
|
||||||
var jetpack = null;
|
var jetpack = null;
|
||||||
@@ -7,11 +10,32 @@ function createHandle() {
|
|||||||
return jetpack.createHandle();
|
return jetpack.createHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PR_RDONLY = 0x1;
|
||||||
|
|
||||||
|
function read_file(f)
|
||||||
|
{
|
||||||
|
var fis = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||||
|
.createInstance(Ci.nsIFileInputStream);
|
||||||
|
fis.init(f, PR_RDONLY, 0444, Ci.nsIFileInputStream.CLOSE_ON_EOF);
|
||||||
|
|
||||||
|
var lis = Cc["@mozilla.org/intl/converter-input-stream;1"]
|
||||||
|
.createInstance(Ci.nsIConverterInputStream);
|
||||||
|
lis.init(fis, "UTF-8", 1024, 0);
|
||||||
|
|
||||||
|
var data = "";
|
||||||
|
|
||||||
|
var r = {};
|
||||||
|
while (lis.readString(0x0FFFFFFF, r))
|
||||||
|
data += r.value;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
jetpack = jps.createJetpack();
|
jetpack = jps.createJetpack();
|
||||||
run_handle_tests();
|
run_handle_tests();
|
||||||
|
|
||||||
jetpack.loadImplementation("file://" + do_get_file("impl.js").path);
|
jetpack.evalScript(read_file(do_get_file("impl.js")));
|
||||||
|
|
||||||
var circ1 = {},
|
var circ1 = {},
|
||||||
circ2 = {},
|
circ2 = {},
|
||||||
@@ -162,6 +186,13 @@ function run_test() {
|
|||||||
jetpack.registerReceiver("duplicate receivers",
|
jetpack.registerReceiver("duplicate receivers",
|
||||||
function() { do_test_finished() });
|
function() { do_test_finished() });
|
||||||
|
|
||||||
|
jetpack.registerReceiver("test result", function(name, c, msg) {
|
||||||
|
dump("TEST-INFO | test_jetpack.js | remote check '" + msg + "' result: " + c + "\n");
|
||||||
|
do_check_true(c);
|
||||||
|
});
|
||||||
|
jetpack.registerReceiver("sandbox done", do_test_finished);
|
||||||
|
|
||||||
|
do_test_pending();
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
@@ -183,8 +214,11 @@ function run_test() {
|
|||||||
undefined, null, true, false, 1, 2, 999, 1/4, "oyez");
|
undefined, null, true, false, 1, 2, 999, 1/4, "oyez");
|
||||||
jetpack.sendMessage("drop methods", drop);
|
jetpack.sendMessage("drop methods", drop);
|
||||||
jetpack.sendMessage("exception coping");
|
jetpack.sendMessage("exception coping");
|
||||||
|
|
||||||
jetpack.sendMessage("duplicate receivers");
|
jetpack.sendMessage("duplicate receivers");
|
||||||
|
|
||||||
|
jetpack.sendMessage("test sandbox");
|
||||||
|
|
||||||
do_register_cleanup(function() {
|
do_register_cleanup(function() {
|
||||||
jetpack.destroy();
|
jetpack.destroy();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ class XPCShellTests(object):
|
|||||||
'-e', 'print("To start the test, type |_execute_test();|.");',
|
'-e', 'print("To start the test, type |_execute_test();|.");',
|
||||||
'-i']
|
'-i']
|
||||||
else:
|
else:
|
||||||
self.xpcsRunArgs = ['-e', '_execute_test();']
|
self.xpcsRunArgs = ['-e', '_execute_test(); quit(0);']
|
||||||
|
|
||||||
def getPipes(self):
|
def getPipes(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user