mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
Bug 898559 - Add metadata API for add-on globals. r=bholley
This commit is contained in:
parent
b8058c2b43
commit
7d44f15b4a
@ -120,7 +120,7 @@ interface ScheduledGCCallback : nsISupports
|
||||
/**
|
||||
* interface of Components.utils
|
||||
*/
|
||||
[scriptable, uuid(35d5b0e5-9b29-48de-9f79-d2534b497435)]
|
||||
[scriptable, uuid(c9ccec7a-726c-4479-9438-6f51f6ef4170)]
|
||||
interface nsIXPCComponents_Utils : nsISupports
|
||||
{
|
||||
|
||||
@ -172,6 +172,32 @@ interface nsIXPCComponents_Utils : nsISupports
|
||||
[optional] in jsval filename,
|
||||
[optional] in long lineNo);
|
||||
|
||||
/*
|
||||
* getSandboxMetadata is designed to be called from JavaScript only.
|
||||
*
|
||||
* getSandboxMetadata retrieves the metadata associated with
|
||||
* a sandbox object. It will return undefined if there
|
||||
* is no metadata attached to the sandbox.
|
||||
*
|
||||
* var s = C.u.Sandbox(..., { metadata: "metadata" });
|
||||
* var metadata = C.u.getSandboxMetadata(s);
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
jsval getSandboxMetadata(in jsval sandbox);
|
||||
|
||||
/*
|
||||
* setSandboxMetadata is designed to be called from JavaScript only.
|
||||
*
|
||||
* setSandboxMetadata sets the metadata associated with
|
||||
* a sandbox object.
|
||||
*
|
||||
* Note that the metadata object will be copied before being used.
|
||||
* The copy will be performed using the structured clone algorithm.
|
||||
* Note that this algorithm does not support reflectors and
|
||||
* it will throw if it encounters them.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void setSandboxMetadata(in jsval sandbox, in jsval metadata);
|
||||
|
||||
/*
|
||||
* import is designed to be called from JavaScript only.
|
||||
|
@ -585,9 +585,11 @@ sandbox_convert(JSContext *cx, HandleObject obj, JSType type, MutableHandleValue
|
||||
return JS_ConvertStub(cx, obj, type, vp);
|
||||
}
|
||||
|
||||
#define XPCONNECT_SANDBOX_CLASS_METADATA_SLOT (XPCONNECT_GLOBAL_EXTRA_SLOT_OFFSET)
|
||||
|
||||
static JSClass SandboxClass = {
|
||||
"Sandbox",
|
||||
XPCONNECT_GLOBAL_FLAGS,
|
||||
XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(1),
|
||||
JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
|
||||
sandbox_enumerate, sandbox_resolve, sandbox_convert, sandbox_finalize,
|
||||
NULL, NULL, NULL, NULL, TraceXPCGlobal
|
||||
@ -1041,6 +1043,8 @@ xpc::CreateSandboxObject(JSContext *cx, jsval *vp, nsISupports *prinOrSop, Sandb
|
||||
// about:memory may use that information
|
||||
xpc::SetLocationForGlobal(sandbox, options.sandboxName);
|
||||
|
||||
xpc::SetSandboxMetadata(cx, sandbox, options.metadata);
|
||||
|
||||
JS_FireOnNewGlobalObject(cx, sandbox);
|
||||
|
||||
return NS_OK;
|
||||
@ -1338,6 +1342,10 @@ ParseOptionsObject(JSContext *cx, jsval from, SandboxOptions &options)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = GetDOMConstructorsFromOptions(cx, optionsObject, options);
|
||||
|
||||
bool found;
|
||||
rv = GetPropFromOptions(cx, optionsObject,
|
||||
"metadata", &options.metadata, &found);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
@ -1650,3 +1658,40 @@ xpc::NewFunctionForwarder(JSContext *cx, HandleId id, HandleObject callable, boo
|
||||
vp.setObject(*funobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
xpc::GetSandboxMetadata(JSContext *cx, HandleObject sandbox, MutableHandleValue rval)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(IsSandbox(sandbox));
|
||||
|
||||
RootedValue metadata(cx);
|
||||
{
|
||||
JSAutoCompartment ac(cx, sandbox);
|
||||
metadata = JS_GetReservedSlot(sandbox, XPCONNECT_SANDBOX_CLASS_METADATA_SLOT);
|
||||
}
|
||||
|
||||
if (!JS_WrapValue(cx, metadata.address()))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rval.set(metadata);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpc::SetSandboxMetadata(JSContext *cx, HandleObject sandbox, HandleValue metadataArg)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(IsSandbox(sandbox));
|
||||
|
||||
RootedValue metadata(cx);
|
||||
|
||||
JSAutoCompartment ac(cx, sandbox);
|
||||
if (!JS_StructuredClone(cx, metadataArg, metadata.address(), NULL, NULL))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
JS_SetReservedSlot(sandbox, XPCONNECT_SANDBOX_CLASS_METADATA_SLOT, metadata);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2830,6 +2830,46 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString& source,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::GetSandboxMetadata(const JS::Value &sandboxVal,
|
||||
JSContext *cx, JS::Value *rval)
|
||||
{
|
||||
if (!sandboxVal.isObject())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
RootedObject sandbox(cx, &sandboxVal.toObject());
|
||||
sandbox = js::CheckedUnwrap(sandbox);
|
||||
if (!sandbox || !xpc::IsSandbox(sandbox))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
RootedValue metadata(cx);
|
||||
nsresult rv = xpc::GetSandboxMetadata(cx, sandbox, &metadata);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
*rval = metadata;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::SetSandboxMetadata(const JS::Value &sandboxVal,
|
||||
const JS::Value &metadataVal,
|
||||
JSContext *cx)
|
||||
{
|
||||
if (!sandboxVal.isObject())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
RootedObject sandbox(cx, &sandboxVal.toObject());
|
||||
sandbox = js::CheckedUnwrap(sandbox);
|
||||
if (!sandbox || !xpc::IsSandbox(sandbox))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
RootedValue metadata(cx, metadataVal);
|
||||
nsresult rv = xpc::SetSandboxMetadata(cx, sandbox, metadata);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* JSObject import (in AUTF8String registryLocation,
|
||||
* [optional] in JSObject targetObj);
|
||||
*/
|
||||
|
@ -3604,6 +3604,7 @@ struct SandboxOptions {
|
||||
, wantExportHelpers(false)
|
||||
, proto(xpc_GetSafeJSContext())
|
||||
, sameZoneAs(xpc_GetSafeJSContext())
|
||||
, metadata(xpc_GetSafeJSContext())
|
||||
{ }
|
||||
|
||||
bool wantXrays;
|
||||
@ -3613,6 +3614,7 @@ struct SandboxOptions {
|
||||
nsCString sandboxName;
|
||||
JS::RootedObject sameZoneAs;
|
||||
DOMConstructors DOMConstructors;
|
||||
JS::RootedValue metadata;
|
||||
};
|
||||
|
||||
JSObject *
|
||||
@ -3647,8 +3649,19 @@ EvalInSandbox(JSContext *cx, JS::HandleObject sandbox, const nsAString& source,
|
||||
JSVersion jsVersion, bool returnStringOnly,
|
||||
JS::MutableHandleValue rval);
|
||||
|
||||
// Helper for retrieving metadata stored in a reserved slot. The metadata
|
||||
// is set during the sandbox creation using the "metadata" option.
|
||||
nsresult
|
||||
GetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg,
|
||||
JS::MutableHandleValue rval);
|
||||
|
||||
nsresult
|
||||
SetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg,
|
||||
JS::HandleValue metadata);
|
||||
|
||||
} /* namespace xpc */
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
// Inlined utilities.
|
||||
|
||||
|
45
js/xpconnect/tests/unit/test_sandbox_metadata.js
Normal file
45
js/xpconnect/tests/unit/test_sandbox_metadata.js
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/. */
|
||||
|
||||
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=898559 */
|
||||
|
||||
function run_test()
|
||||
{
|
||||
let sandbox = Components.utils.Sandbox("http://www.blah.com", {
|
||||
metadata: "test metadata"
|
||||
});
|
||||
|
||||
do_check_eq(Components.utils.getSandboxMetadata(sandbox), "test metadata");
|
||||
|
||||
let sandbox = Components.utils.Sandbox("http://www.blah.com", {
|
||||
metadata: { foopy: { bar: 2 }, baz: "hi" }
|
||||
});
|
||||
|
||||
let metadata = Components.utils.getSandboxMetadata(sandbox);
|
||||
do_check_eq(metadata.baz, "hi");
|
||||
do_check_eq(metadata.foopy.bar, 2);
|
||||
metadata.baz = "foo";
|
||||
|
||||
metadata = Components.utils.getSandboxMetadata(sandbox);
|
||||
do_check_eq(metadata.baz, "foo");
|
||||
|
||||
metadata = { foo: "bar" };
|
||||
Components.utils.setSandboxMetadata(sandbox, metadata);
|
||||
metadata.foo = "baz";
|
||||
metadata = Components.utils.getSandboxMetadata(sandbox);
|
||||
do_check_eq(metadata.foo, "bar");
|
||||
|
||||
let thrown = false;
|
||||
let reflector = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Components.interfaces.nsIXMLHttpRequest);
|
||||
|
||||
try {
|
||||
Components.utils.setSandboxMetadata(sandbox, { foo: reflector });
|
||||
} catch(e) {
|
||||
thrown = true;
|
||||
}
|
||||
|
||||
do_check_eq(thrown, true);
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ fail-if = os == "android"
|
||||
[test_allowedDomains.js]
|
||||
[test_allowedDomainsXHR.js]
|
||||
[test_nuke_sandbox.js]
|
||||
[test_sandbox_metadata.js]
|
||||
[test_exportFunction.js]
|
||||
[test_textDecoder.js]
|
||||
[test_watchdog_enable.js]
|
||||
|
Loading…
Reference in New Issue
Block a user