observe: DevToolsUtils.makeInfallible(function(subject, topic, data) { // Create JSON objects suitable for transportation across the RDP, // by breaking cycles and making a copy of the `subject` and `data` via // JSON.stringifying those values with a replacer that omits properties // known to introduce cycles, and then JSON.parsing the result. // This spends some CPU cycles, but it's simple. subject = (subject && !Cu.isXrayWrapper(subject) && subject.wrappedJSObject) || subject; subject = JSON.parse(JSON.stringify(subject, cycleBreaker)); data = (data && !Cu.isXrayWrapper(data) && data.wrappedJSObject) || data; data = JSON.parse(JSON.stringify(data, cycleBreaker)); // Sends actor, type and other additional information over the remote // debugging protocol to any profiler clients. let reply = details => { this.conn.send({ from: this.actorID, type: "eventNotification", subject: subject, topic: topic, data: data, details: details }); }; switch (topic) { case "console-api-profiler": return void reply(this._handleConsoleEvent(subject, data)); case "profiler-started": case "profiler-stopped": default: return void reply(); } }, "ProfilerActor.prototype.observe"),
return DevToolsUtils.makeInfallible(function(subject, topic, data) { subject = (subject && !Cu.isXrayWrapper(subject) && subject.wrappedJSObject) || subject; subject = JSON.parse(JSON.stringify(subject, cycleBreaker)); data = (data && !Cu.isXrayWrapper(data) && data.wrappedJSObject) || data; data = JSON.parse(JSON.stringify(data, cycleBreaker)); // Pass in clean data to the underlying handler return handler.call(this, subject, topic, data); }, identifier);
/** * Creates a TraceActor. TraceActor provides a stream of function * call/return packets to a remote client gathering a full trace. */ function TraceActor(aConn, aParentActor) { this._attached = false; this._activeTraces = new MapStack(); this._totalTraces = 0; this._startTime = 0; // Keep track of how many different trace requests have requested what kind of // tracing info. This way we can minimize the amount of data we are collecting // at any given time. this._requestsForTraceType = Object.create(null); for (let type of TRACE_TYPES) { this._requestsForTraceType[type] = 0; } this._sequence = 0; this._bufferSendTimer = null; this._buffer = []; this.onExitFrame = this.onExitFrame.bind(this); // aParentActor.window might be an Xray for a window, but it might also be a // double-wrapper for a Sandbox. We want to unwrap the latter but not the // former. this.global = aParentActor.window; if (!Cu.isXrayWrapper(this.global)) { this.global = this.global.wrappedJSObject; } }
exports.isSafeJSObject = function isSafeJSObject(aObj) { if (Cu.getGlobalForObject(aObj) == Cu.getGlobalForObject(exports.isSafeJSObject)) { return true; // aObj is not a cross-compartment wrapper. } let principal = Services.scriptSecurityManager.getObjectPrincipal(aObj); if (Services.scriptSecurityManager.isSystemPrincipal(principal)) { return true; // allow chrome objects } return Cu.isXrayWrapper(aObj); };
exports.isSafeJSObject = function isSafeJSObject(aObj) { // If we are running on a worker thread, Cu is not available. In this case, // we always return false, just to be on the safe side. if (isWorker) { return false; } if (Cu.getGlobalForObject(aObj) == Cu.getGlobalForObject(exports.isSafeJSObject)) { return true; // aObj is not a cross-compartment wrapper. } let principal = Cu.getObjectPrincipal(aObj); if (Services.scriptSecurityManager.isSystemPrincipal(principal)) { return true; // allow chrome objects } return Cu.isXrayWrapper(aObj); };
exports.isSafeJSObject = function(obj) { // If we are running on a worker thread, Cu is not available. In this case, // we always return false, just to be on the safe side. if (isWorker) { return false; } if (Cu.getGlobalForObject(obj) == Cu.getGlobalForObject(exports.isSafeJSObject)) { // obj is not a cross-compartment wrapper. return true; } // Xray wrappers protect against unintended code execution. if (Cu.isXrayWrapper(obj)) { return true; } // If there aren't Xrays, only allow chrome objects. const principal = Cu.getObjectPrincipal(obj); if (!Services.scriptSecurityManager.isSystemPrincipal(principal)) { return false; } // Scripted proxy objects without Xrays can run their proxy traps. if (Cu.isProxy(obj)) { return false; } // Even if `obj` looks safe, an unsafe object in its prototype chain may still // run unintended code, e.g. when using the `instanceof` operator. const proto = Object.getPrototypeOf(obj); if (proto && !exports.isSafeJSObject(proto)) { return false; } // Allow non-problematic chrome objects. return true; };
unwrap(obj) { return Cu.isXrayWrapper(obj) ? obj.wrappedJSObject : obj; }