Bug 1268845. Make sure to set up an XPCWrappedNativeScope for SimpleGlobalObject globals on the main thread. r=bholley,ttaubert,ejpbruel

This commit is contained in:
Boris Zbarsky 2016-05-10 20:57:29 -04:00
Родитель 72f9bd44e0
Коммит 20a2c90769
4 изменённых файлов: 76 добавлений и 22 удалений

Просмотреть файл

@ -96,15 +96,19 @@ SimpleGlobalObject::Create(GlobalType globalType, JS::Handle<JS::Value> proto)
JS::CompartmentOptions options;
options.creationOptions().setInvisibleToDebugger(true);
nsCOMPtr<nsIPrincipal> principal;
if (NS_IsMainThread()) {
principal = nsNullPrincipal::Create();
}
JS::Rooted<JSObject*> global(cx);
JS::Rooted<JSObject*> global(cx,
JS_NewGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
nsJSPrincipals::get(principal),
JS::DontFireOnNewGlobalHook, options));
if (NS_IsMainThread()) {
nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
options.creationOptions().setTrace(xpc::TraceXPCGlobal);
global = xpc::CreateGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
nsJSPrincipals::get(principal),
options);
} else {
global = JS_NewGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
nullptr,
JS::DontFireOnNewGlobalHook, options);
}
if (!global) {
JS_ClearPendingException(cx);
@ -130,7 +134,7 @@ SimpleGlobalObject::Create(GlobalType globalType, JS::Handle<JS::Value> proto)
return nullptr;
}
if (!JS_SetPrototype(cx, global, protoObj)) {
if (!JS_SplicePrototype(cx, global, protoObj)) {
JS_ClearPendingException(cx);
return nullptr;
}

Просмотреть файл

@ -307,6 +307,38 @@ TestArray.addTest(
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"JWK unwrap attempt on bogus data should error out",
function () {
// Largely cribbed from the "JWK wrap/unwrap round-trip, with AES-GCM" test
var that = this;
var wrapAlg = { name: "AES-GCM", iv: tv.aes_gcm_enc.iv };
var wrapKey;
function doBogusWrap() {
var abv = new TextEncoder("utf-8").encode("I am so not JSON");
return crypto.subtle.encrypt(wrapAlg, wrapKey, abv);
}
function doUnwrap(wrappedKey) {
return crypto.subtle.unwrapKey("jwk", wrappedKey, wrapKey, wrapAlg,
{name: "HMAC", hash: "SHA-384"},
true, ['sign', 'verify']);
}
crypto.subtle.importKey("jwk", tv.aes_gcm_enc.key_jwk,
"AES-GCM", false, ['encrypt','unwrapKey'])
.then(function(x) { wrapKey = x; })
.then(doBogusWrap, error(that))
.then(doUnwrap, error(that))
.then(
error(that),
complete(that)
);
}
);
/*]]>*/</script>
</head>

Просмотреть файл

@ -59,6 +59,7 @@
#include "mozilla/dom/PMessagePort.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseDebugging.h"
#include "mozilla/dom/SimpleGlobalObject.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/StructuredCloneHolder.h"
#include "mozilla/dom/TabChild.h"
@ -1058,6 +1059,11 @@ public:
// Now fire an event at the global object, but don't do that if the error
// code is too much recursion and this is the same script threw the error.
// XXXbz the interaction of this with worker errors seems kinda broken.
// An overrecursion in the debugger or debugger sandbox will get turned
// into an error event on our parent worker!
// https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks making this
// better.
if (aFireAtScope && (aTarget || aErrorNumber != JSMSG_OVER_RECURSED)) {
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
NS_ASSERTION(global, "This should never be null!");
@ -1074,10 +1080,19 @@ public:
UNWRAP_OBJECT(WorkerDebuggerGlobalScope, global, globalScope);
MOZ_ASSERT_IF(globalScope, globalScope->GetWrapperPreserveColor() == global);
MOZ_ASSERT_IF(!globalScope, IsDebuggerSandbox(global));
if (globalScope || IsDebuggerSandbox(global)) {
aWorkerPrivate->ReportErrorToDebugger(aFilename, aLineNumber,
aMessage);
return;
}
aWorkerPrivate->ReportErrorToDebugger(aFilename, aLineNumber,
aMessage);
MOZ_ASSERT(SimpleGlobalObject::SimpleGlobalType(global) ==
SimpleGlobalObject::GlobalType::BindingDetail);
// XXXbz We should really log this to console, but unwinding out of
// this stuff without ending up firing any events is ... hard. Just
// return for now.
// https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks
// making this better.
return;
}

Просмотреть файл

@ -402,19 +402,22 @@ CreateGlobalObject(JSContext* cx, const JSClass* clasp, nsIPrincipal* principal,
// of |global|.
(void) new XPCWrappedNativeScope(cx, global);
if (clasp->flags & JSCLASS_DOM_GLOBAL) {
#ifdef DEBUG
// Verify that the right trace hook is called. Note that this doesn't
// work right for wrapped globals, since the tracing situation there is
// more complicated. Manual inspection shows that they do the right thing.
if (!((const js::Class*)clasp)->isWrappedNative())
{
VerifyTraceProtoAndIfaceCacheCalledTracer trc(JS_GetRuntime(cx));
TraceChildren(&trc, GCCellPtr(global.get()));
MOZ_ASSERT(trc.ok, "Trace hook on global needs to call TraceXPCGlobal for XPConnect compartments.");
}
// Verify that the right trace hook is called. Note that this doesn't
// work right for wrapped globals, since the tracing situation there is
// more complicated. Manual inspection shows that they do the right
// thing. Also note that we only check this for JSCLASS_DOM_GLOBAL
// classes because xpc::TraceXPCGlobal won't call
// TraceProtoAndIfaceCache unless that flag is set.
if (!((const js::Class*)clasp)->isWrappedNative())
{
VerifyTraceProtoAndIfaceCacheCalledTracer trc(JS_GetRuntime(cx));
TraceChildren(&trc, GCCellPtr(global.get()));
MOZ_ASSERT(trc.ok, "Trace hook on global needs to call TraceXPCGlobal for XPConnect compartments.");
}
#endif
if (clasp->flags & JSCLASS_DOM_GLOBAL) {
const char* className = clasp->name;
AllocateProtoAndIfaceCache(global,
(strcmp(className, "Window") == 0 ||