/** * This module allows specific messages of interest to be directed from the * outer browser to the inner browser (and vice versa) in a targetted fashion * without having to touch the original code paths that use them. */ function MessageManagerTunnel(outer, inner) { if (outer.isRemoteBrowser) { throw new Error("The outer browser must be non-remote."); } this.outerRef = Cu.getWeakReference(outer); this.innerRef = Cu.getWeakReference(inner); this.tunneledMessageNames = new Set(); this.init(); }
initialize: function(conn, [window, global, caller, type, name, stack, args, result]) { protocol.Actor.prototype.initialize.call(this, conn); this.details = { type: type, name: name, stack: stack, }; // Store a weak reference to all objects so we don't // prevent natural GC if `holdWeak` was passed into // setup as truthy. Used in the Web Audio Editor. if (this._holdWeak) { let weakRefs = { window: Cu.getWeakReference(window), caller: Cu.getWeakReference(caller), result: Cu.getWeakReference(result), args: Cu.getWeakReference(args) }; Object.defineProperties(this.details, { window: { get: () => weakRefs.window.get() }, caller: { get: () => weakRefs.caller.get() }, result: { get: () => weakRefs.result.get() }, args: { get: () => weakRefs.args.get() } }); } // Otherwise, hold strong references to the objects. else { this.details.window = window; this.details.caller = caller; this.details.result = result; this.details.args = args; } this.meta = { global: -1, previews: { caller: "", args: "" } }; if (global == "WebGLRenderingContext") { this.meta.global = CallWatcherFront.CANVAS_WEBGL_CONTEXT; } else if (global == "CanvasRenderingContext2D") { this.meta.global = CallWatcherFront.CANVAS_2D_CONTEXT; } else if (global == "window") { this.meta.global = CallWatcherFront.UNKNOWN_SCOPE; } else { this.meta.global = CallWatcherFront.GLOBAL_SCOPE; } this.meta.previews.caller = this._generateCallerPreview(); this.meta.previews.args = this._generateArgsPreview(); },
initialize: function ( conn, [window, global, caller, type, name, stack, timestamp, args, result], holdWeak ) { protocol.Actor.prototype.initialize.call(this, conn); this.details = { global: global, type: type, name: name, stack: stack, timestamp: timestamp }; // Store a weak reference to all objects so we don't // prevent natural GC if `holdWeak` was passed into // setup as truthy. if (holdWeak) { let weakRefs = { window: Cu.getWeakReference(window), caller: Cu.getWeakReference(caller), args: Cu.getWeakReference(args), result: Cu.getWeakReference(result), }; Object.defineProperties(this.details, { window: { get: () => weakRefs.window.get() }, caller: { get: () => weakRefs.caller.get() }, args: { get: () => weakRefs.args.get() }, result: { get: () => weakRefs.result.get() }, }); } else { // Otherwise, hold strong references to the objects. this.details.window = window; this.details.caller = caller; this.details.args = args; this.details.result = result; } // The caller, args and results are string names for now. It would // certainly be nicer if they were Object actors. Make this smarter, so // that the frontend can inspect each argument, be it object or primitive. // Bug 978960. this.details.previews = { caller: this._generateStringPreview(caller), args: this._generateArgsPreview(args), result: this._generateStringPreview(result) }; },
initialize: function (conn, node) { protocol.Actor.prototype.initialize.call(this, conn); // Store ChromeOnly property `id` to identify AudioNode, // rather than storing a strong reference, and store a weak // ref to underlying node for controlling. this.nativeID = node.id; this.node = Cu.getWeakReference(node); // Stores the AutomationTimelines for this node's AudioParams. this.automation = {}; try { this.type = getConstructorName(node); } catch (e) { this.type = ""; } this.source = !!AUDIO_NODE_DEFINITION[this.type].source; this.bypassable = !AUDIO_NODE_DEFINITION[this.type].unbypassable; // Create automation timelines for all AudioParams Object.keys(AUDIO_NODE_DEFINITION[this.type].properties || {}) .filter(isAudioParam.bind(null, node)) .forEach(paramName => { this.automation[paramName] = new AutomationTimeline(node[paramName].defaultValue); }); },
notifyPanelCanOpen: function(panel, callback) { let view = viewFor(panel); // Can't pass an arrow function as the event handler because we need to be // able to call |removeEventListener| later. view.addEventListener("popuphidden", SinglePanelManager.onVisiblePanelHidden, true); view.addEventListener("popupshown", SinglePanelManager.onVisiblePanelShown, false); SinglePanelManager.enqueuedPanel = null; SinglePanelManager.enqueuedPanelCallback = null; SinglePanelManager.visiblePanel = Cu.getWeakReference(panel); callback(); },
requestOpen: function(panelToOpen, callback) { let currentPanel = getPanelFromWeakRef(SinglePanelManager.visiblePanel); if (currentPanel || SinglePanelManager.enqueuedPanel) { SinglePanelManager.enqueuedPanel = Cu.getWeakReference(panelToOpen); SinglePanelManager.enqueuedPanelCallback = callback; if (currentPanel && currentPanel.isShowing) { currentPanel.hide(); } } else { SinglePanelManager.notifyPanelCanOpen(panelToOpen, callback); } },
initialize: function (conn, node) { protocol.Actor.prototype.initialize.call(this, conn); // Store ChromeOnly property `id` to identify AudioNode, // rather than storing a strong reference, and store a weak // ref to underlying node for controlling. this.nativeID = node.id; this.node = Cu.getWeakReference(node); try { this.type = getConstructorName(node); } catch (e) { this.type = ""; } },
set: function(v) { if (v && typeof v === "object") { try { // Try to set a weak reference. This can throw for some values. // For example, if the value is a native object that does not // implement nsISupportsWeakReference. this._weakValue = Cu.getWeakReference(v) this._simpleValue = undefined; return; } catch (e) { // Do nothing. Fall through to setting _simpleValue below. } } this._simpleValue = v; this._weakValue = undefined; },
function on(type, listener, strong) { // Unless last optional argument is `true` we use a weak reference to a // listener. let weak = !strong; // Take list of observers associated with given `listener` function. let observers = subscribers(listener); // If `observer` for the given `type` is not registered yet, then // associate an `observer` and register it. if (!(type in observers)) { let observer = Observer(listener); observers[type] = observer; addObserver(observer, type, weak); // WeakRef gymnastics to remove all alive observers on unload let ref = Cu.getWeakReference(observer); weakRefs.set(observer, ref); stillAlive.set(ref, type); } }
var track = exports.track = function track(object, bin, stackFrameNumber) { var frame = components.stack.caller; var weakref = Cu.getWeakReference(object); if (!bin) bin = object.constructor.name; if (bin == "Object") bin = frame.name; if (!bin) bin = "generic"; if (!(bin in trackedObjects)) trackedObjects[bin] = []; if (stackFrameNumber > 0) for (var i = 0; i < stackFrameNumber; i++) frame = frame.caller; trackedObjects[bin].push({weakref: weakref, created: new Date(), filename: frame.filename, lineNo: frame.lineNumber, bin: bin}); };
function windowObserver(subject, topic) { let supportsWeak = subject.QueryInterface(Ci.nsISupportsWeakReference); if (supportsWeak) { weakWindows.push(Cu.getWeakReference(supportsWeak)); } }
function makeStrictDocumentFilter(window) { // Note: Do not define a closure within this function. Otherwise // you may leak the window argument. let weak = Cu.getWeakReference(window); return documentMatches.bind(null, weak); }
onTrack: function(window){ if (!isBrowser(window) || isPrivate(window)) return; let warn = function(element){ require('./logger').logMissingElement({ type: "extra-missing", message: "Extra listener could not select an element.", info: {element: element} }); } // burger button let f = function(){ event('burger-button', {type: 'extra'}); } let button = Cu.getWeakReference(window.document.getElementById("PanelUI-menu-button")); if (button.get()){ button.get().addEventListener("click", f); unload(function(){ if (button.get()) button.get().removeEventListener("click", f); }) } else warn('burger-button'); f = function(){ event('searchbar', {type: 'extra'}); } // search bar if (!window.document.getElementById("searchbar")) warn('searchbar') else { let bar = Cu.getWeakReference(window.document .getAnonymousElementByAttribute( window.document.getElementById("searchbar") , "anonid", "searchbar-textbox")); if (bar.get()){ bar.get().addEventListener("focus", f) unload(function(){ if (bar.get()) bar.get().removeEventListener("focus", f); }); } else warn('searchbar-textbox'); } // home button f = function(){ event('home-button', {type: 'extra'}); } button = Cu.getWeakReference(window.document.getElementById("home-button")); if (button.get()){ button.get().addEventListener("click", f); unload(function(){ if (button.get()) button.get().removeEventListener("click", f); }); } else warn('home-button'); // loop button f = function(){ event('loop-button', {type: 'extra'}); } button = Cu.getWeakReference(window.document.getElementById("loop-button")); if (button.get()){ button.get().addEventListener("click", f); unload(function(){ if (button.get()) button.get().removeEventListener("click", f); }); } else warn('loop-button'); // pocket button f = function(){ event('pocket-button', {type: 'extra'}); } button = Cu.getWeakReference(window.document.getElementById("pocket-button")); if (button.get()){ button.get().addEventListener("click", f); unload(function(){ if (button.get()) button.get().removeEventListener("click", f); }) } else warn('pocket-button'); // downloads button f = function(){ event('downloads-button', {type: 'extra'}); } button = Cu.getWeakReference(window.document.getElementById("downloads-button")); if (button.get()){ button.get().addEventListener("click", f); unload(function(){ if (button.get()) button.get().removeEventListener("click", f); }) } else warn('downloads-button'); // show history f = function(){ event('show-history', {type: 'extra'}); } let historyCmd = Cu.getWeakReference(window.document.getElementById("Browser:ShowAllHistory")); if (historyCmd.get()){ historyCmd.get().addEventListener("command", f); unload(function(){ if (historyCmd.get()) historyCmd.get().removeEventListener("command", f); }); } else warn('show-history'); }