michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: /* This code is loaded in every child process that is started by mochitest in michael@0: * order to be used as a replacement for UniversalXPConnect michael@0: */ michael@0: michael@0: function SpecialPowers(window) { michael@0: this.window = Components.utils.getWeakReference(window); michael@0: this._encounteredCrashDumpFiles = []; michael@0: this._unexpectedCrashDumpFiles = { }; michael@0: this._crashDumpDir = null; michael@0: this.DOMWindowUtils = bindDOMWindowUtils(window); michael@0: Object.defineProperty(this, 'Components', { michael@0: configurable: true, enumerable: true, get: function() { michael@0: var win = this.window.get(); michael@0: if (!win) michael@0: return null; michael@0: return getRawComponents(win); michael@0: }}); michael@0: this._pongHandlers = []; michael@0: this._messageListener = this._messageReceived.bind(this); michael@0: addMessageListener("SPPingService", this._messageListener); michael@0: } michael@0: michael@0: SpecialPowers.prototype = new SpecialPowersAPI(); michael@0: michael@0: SpecialPowers.prototype.toString = function() { return "[SpecialPowers]"; }; michael@0: SpecialPowers.prototype.sanityCheck = function() { return "foo"; }; michael@0: michael@0: // This gets filled in in the constructor. michael@0: SpecialPowers.prototype.DOMWindowUtils = undefined; michael@0: SpecialPowers.prototype.Components = undefined; michael@0: michael@0: SpecialPowers.prototype._sendSyncMessage = function(msgname, msg) { michael@0: return sendSyncMessage(msgname, msg); michael@0: }; michael@0: michael@0: SpecialPowers.prototype._sendAsyncMessage = function(msgname, msg) { michael@0: sendAsyncMessage(msgname, msg); michael@0: }; michael@0: michael@0: SpecialPowers.prototype._addMessageListener = function(msgname, listener) { michael@0: addMessageListener(msgname, listener); michael@0: }; michael@0: michael@0: SpecialPowers.prototype._removeMessageListener = function(msgname, listener) { michael@0: removeMessageListener(msgname, listener); michael@0: }; michael@0: michael@0: SpecialPowers.prototype.registerProcessCrashObservers = function() { michael@0: addMessageListener("SPProcessCrashService", this._messageListener); michael@0: sendSyncMessage("SPProcessCrashService", { op: "register-observer" }); michael@0: }; michael@0: michael@0: SpecialPowers.prototype.unregisterProcessCrashObservers = function() { michael@0: addMessageListener("SPProcessCrashService", this._messageListener); michael@0: sendSyncMessage("SPProcessCrashService", { op: "unregister-observer" }); michael@0: }; michael@0: michael@0: SpecialPowers.prototype._messageReceived = function(aMessage) { michael@0: switch (aMessage.name) { michael@0: case "SPProcessCrashService": michael@0: if (aMessage.json.type == "crash-observed") { michael@0: for (let e of aMessage.json.dumpIDs) { michael@0: this._encounteredCrashDumpFiles.push(e.id + "." + e.extension); michael@0: } michael@0: } michael@0: break; michael@0: michael@0: case "SPPingService": michael@0: if (aMessage.json.op == "pong") { michael@0: var handler = this._pongHandlers.shift(); michael@0: if (handler) { michael@0: handler(); michael@0: } michael@0: } michael@0: break; michael@0: } michael@0: return true; michael@0: }; michael@0: michael@0: SpecialPowers.prototype.quit = function() { michael@0: sendAsyncMessage("SpecialPowers.Quit", {}); michael@0: }; michael@0: michael@0: SpecialPowers.prototype.executeAfterFlushingMessageQueue = function(aCallback) { michael@0: this._pongHandlers.push(aCallback); michael@0: sendAsyncMessage("SPPingService", { op: "ping" }); michael@0: }; michael@0: michael@0: // Expose everything but internal APIs (starting with underscores) to michael@0: // web content. We cannot use Object.keys to view SpecialPowers.prototype since michael@0: // we are using the functions from SpecialPowersAPI.prototype michael@0: SpecialPowers.prototype.__exposedProps__ = {}; michael@0: for (var i in SpecialPowers.prototype) { michael@0: if (i.charAt(0) != "_") michael@0: SpecialPowers.prototype.__exposedProps__[i] = "r"; michael@0: } michael@0: michael@0: // Attach our API to the window. michael@0: function attachSpecialPowersToWindow(aWindow) { michael@0: try { michael@0: if ((aWindow !== null) && michael@0: (aWindow !== undefined) && michael@0: (aWindow.wrappedJSObject) && michael@0: !(aWindow.wrappedJSObject.SpecialPowers)) { michael@0: aWindow.wrappedJSObject.SpecialPowers = new SpecialPowers(aWindow); michael@0: } michael@0: } catch(ex) { michael@0: dump("TEST-INFO | specialpowers.js | Failed to attach specialpowers to window exception: " + ex + "\n"); michael@0: } michael@0: } michael@0: michael@0: // This is a frame script, so it may be running in a content process. michael@0: // In any event, it is targeted at a specific "tab", so we listen for michael@0: // the DOMWindowCreated event to be notified about content windows michael@0: // being created in this context. michael@0: michael@0: function SpecialPowersManager() { michael@0: addEventListener("DOMWindowCreated", this, false); michael@0: } michael@0: michael@0: SpecialPowersManager.prototype = { michael@0: handleEvent: function handleEvent(aEvent) { michael@0: var window = aEvent.target.defaultView; michael@0: attachSpecialPowersToWindow(window); michael@0: } michael@0: }; michael@0: michael@0: var specialpowersmanager = new SpecialPowersManager(); michael@0: michael@0: this.SpecialPowers = SpecialPowers; michael@0: this.attachSpecialPowersToWindow = attachSpecialPowersToWindow;