Bug 1274708 Add BaseContext.jsonStringify() r=kmag
MozReview-Commit-ID: E4F1e8hDA5a
This commit is contained in:
@@ -148,6 +148,7 @@ class BaseContext {
|
||||
this.contextId = ++gContextId;
|
||||
this.unloaded = false;
|
||||
this.extensionId = extensionId;
|
||||
this.jsonSandbox = null;
|
||||
}
|
||||
|
||||
get cloneScope() {
|
||||
@@ -196,6 +197,24 @@ class BaseContext {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely call JSON.stringify() on an object that comes from an
|
||||
* extension.
|
||||
*
|
||||
* @param {array<any>} args Arguments for JSON.stringify()
|
||||
* @returns {string} The stringified representation of obj
|
||||
*/
|
||||
jsonStringify(...args) {
|
||||
if (!this.jsonSandbox) {
|
||||
this.jsonSandbox = Cu.Sandbox(this.principal, {
|
||||
sameZoneAs: this.cloneScope,
|
||||
wantXrays: false,
|
||||
});
|
||||
}
|
||||
|
||||
return Cu.waiveXrays(this.jsonSandbox.JSON).stringify(...args);
|
||||
}
|
||||
|
||||
callOnClose(obj) {
|
||||
this.onClose.add(obj);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ var {
|
||||
class StubContext extends BaseContext {
|
||||
constructor() {
|
||||
super();
|
||||
this.sandbox = new Cu.Sandbox(global);
|
||||
this.sandbox = Cu.Sandbox(global);
|
||||
}
|
||||
|
||||
get cloneScope() {
|
||||
@@ -127,3 +127,62 @@ add_task(function* test_post_unload_listeners() {
|
||||
// any micro-tasks that get enqueued by the resolution handlers above.
|
||||
yield new Promise(resolve => setTimeout(resolve, 0));
|
||||
});
|
||||
|
||||
class Context extends BaseContext {
|
||||
constructor(principal) {
|
||||
super();
|
||||
Object.defineProperty(this, "principal", {
|
||||
value: principal,
|
||||
configurable: true,
|
||||
});
|
||||
this.sandbox = Cu.Sandbox(principal, {wantXrays: false});
|
||||
this.extension = {id: "test@web.extension"};
|
||||
}
|
||||
|
||||
get cloneScope() {
|
||||
return this.sandbox;
|
||||
}
|
||||
}
|
||||
|
||||
let ssm = Services.scriptSecurityManager;
|
||||
const PRINCIPAL1 = ssm.createCodebasePrincipalFromOrigin("http://www.example.org");
|
||||
const PRINCIPAL2 = ssm.createCodebasePrincipalFromOrigin("http://www.somethingelse.org");
|
||||
|
||||
// Test that toJSON() works in the json sandbox
|
||||
add_task(function* test_stringify_toJSON() {
|
||||
let context = new Context(PRINCIPAL1);
|
||||
let obj = Cu.evalInSandbox("({hidden: true, toJSON() { return {visible: true}; } })", context.sandbox);
|
||||
|
||||
let stringified = context.jsonStringify(obj);
|
||||
let expected = JSON.stringify({visible: true});
|
||||
equal(stringified, expected, "Stringified object with toJSON() method is as expected");
|
||||
});
|
||||
|
||||
// Test that stringifying in inaccessible property throws
|
||||
add_task(function* test_stringify_inaccessible() {
|
||||
let context = new Context(PRINCIPAL1);
|
||||
let sandbox = context.sandbox;
|
||||
let sandbox2 = Cu.Sandbox(PRINCIPAL2);
|
||||
|
||||
Cu.waiveXrays(sandbox).subobj = Cu.evalInSandbox("({ subobject: true })", sandbox2);
|
||||
let obj = Cu.evalInSandbox("({ local: true, nested: subobj })", sandbox);
|
||||
Assert.throws(() => {
|
||||
context.jsonStringify(obj);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_stringify_accessible() {
|
||||
// Test that an accessible property from another global is included
|
||||
let principal = ssm.createExpandedPrincipal([PRINCIPAL1, PRINCIPAL2]);
|
||||
let context = new Context(principal);
|
||||
let sandbox = context.sandbox;
|
||||
let sandbox2 = Cu.Sandbox(PRINCIPAL2);
|
||||
|
||||
Cu.waiveXrays(sandbox).subobj = Cu.evalInSandbox("({ subobject: true })", sandbox2);
|
||||
let obj = Cu.evalInSandbox("({ local: true, nested: subobj })", sandbox);
|
||||
let stringified = context.jsonStringify(obj);
|
||||
|
||||
let expected = JSON.stringify({local: true, nested: {subobject: true}});
|
||||
equal(stringified, expected, "Stringified object with accessible property is as expected");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user