Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | /* This code is loaded in every child process that is started by mochitest in |
michael@0 | 5 | * order to be used as a replacement for UniversalXPConnect |
michael@0 | 6 | */ |
michael@0 | 7 | |
michael@0 | 8 | function SpecialPowers(window) { |
michael@0 | 9 | this.window = Components.utils.getWeakReference(window); |
michael@0 | 10 | this._encounteredCrashDumpFiles = []; |
michael@0 | 11 | this._unexpectedCrashDumpFiles = { }; |
michael@0 | 12 | this._crashDumpDir = null; |
michael@0 | 13 | this.DOMWindowUtils = bindDOMWindowUtils(window); |
michael@0 | 14 | Object.defineProperty(this, 'Components', { |
michael@0 | 15 | configurable: true, enumerable: true, get: function() { |
michael@0 | 16 | var win = this.window.get(); |
michael@0 | 17 | if (!win) |
michael@0 | 18 | return null; |
michael@0 | 19 | return getRawComponents(win); |
michael@0 | 20 | }}); |
michael@0 | 21 | this._pongHandlers = []; |
michael@0 | 22 | this._messageListener = this._messageReceived.bind(this); |
michael@0 | 23 | addMessageListener("SPPingService", this._messageListener); |
michael@0 | 24 | } |
michael@0 | 25 | |
michael@0 | 26 | SpecialPowers.prototype = new SpecialPowersAPI(); |
michael@0 | 27 | |
michael@0 | 28 | SpecialPowers.prototype.toString = function() { return "[SpecialPowers]"; }; |
michael@0 | 29 | SpecialPowers.prototype.sanityCheck = function() { return "foo"; }; |
michael@0 | 30 | |
michael@0 | 31 | // This gets filled in in the constructor. |
michael@0 | 32 | SpecialPowers.prototype.DOMWindowUtils = undefined; |
michael@0 | 33 | SpecialPowers.prototype.Components = undefined; |
michael@0 | 34 | |
michael@0 | 35 | SpecialPowers.prototype._sendSyncMessage = function(msgname, msg) { |
michael@0 | 36 | return sendSyncMessage(msgname, msg); |
michael@0 | 37 | }; |
michael@0 | 38 | |
michael@0 | 39 | SpecialPowers.prototype._sendAsyncMessage = function(msgname, msg) { |
michael@0 | 40 | sendAsyncMessage(msgname, msg); |
michael@0 | 41 | }; |
michael@0 | 42 | |
michael@0 | 43 | SpecialPowers.prototype._addMessageListener = function(msgname, listener) { |
michael@0 | 44 | addMessageListener(msgname, listener); |
michael@0 | 45 | }; |
michael@0 | 46 | |
michael@0 | 47 | SpecialPowers.prototype._removeMessageListener = function(msgname, listener) { |
michael@0 | 48 | removeMessageListener(msgname, listener); |
michael@0 | 49 | }; |
michael@0 | 50 | |
michael@0 | 51 | SpecialPowers.prototype.registerProcessCrashObservers = function() { |
michael@0 | 52 | addMessageListener("SPProcessCrashService", this._messageListener); |
michael@0 | 53 | sendSyncMessage("SPProcessCrashService", { op: "register-observer" }); |
michael@0 | 54 | }; |
michael@0 | 55 | |
michael@0 | 56 | SpecialPowers.prototype.unregisterProcessCrashObservers = function() { |
michael@0 | 57 | addMessageListener("SPProcessCrashService", this._messageListener); |
michael@0 | 58 | sendSyncMessage("SPProcessCrashService", { op: "unregister-observer" }); |
michael@0 | 59 | }; |
michael@0 | 60 | |
michael@0 | 61 | SpecialPowers.prototype._messageReceived = function(aMessage) { |
michael@0 | 62 | switch (aMessage.name) { |
michael@0 | 63 | case "SPProcessCrashService": |
michael@0 | 64 | if (aMessage.json.type == "crash-observed") { |
michael@0 | 65 | for (let e of aMessage.json.dumpIDs) { |
michael@0 | 66 | this._encounteredCrashDumpFiles.push(e.id + "." + e.extension); |
michael@0 | 67 | } |
michael@0 | 68 | } |
michael@0 | 69 | break; |
michael@0 | 70 | |
michael@0 | 71 | case "SPPingService": |
michael@0 | 72 | if (aMessage.json.op == "pong") { |
michael@0 | 73 | var handler = this._pongHandlers.shift(); |
michael@0 | 74 | if (handler) { |
michael@0 | 75 | handler(); |
michael@0 | 76 | } |
michael@0 | 77 | } |
michael@0 | 78 | break; |
michael@0 | 79 | } |
michael@0 | 80 | return true; |
michael@0 | 81 | }; |
michael@0 | 82 | |
michael@0 | 83 | SpecialPowers.prototype.quit = function() { |
michael@0 | 84 | sendAsyncMessage("SpecialPowers.Quit", {}); |
michael@0 | 85 | }; |
michael@0 | 86 | |
michael@0 | 87 | SpecialPowers.prototype.executeAfterFlushingMessageQueue = function(aCallback) { |
michael@0 | 88 | this._pongHandlers.push(aCallback); |
michael@0 | 89 | sendAsyncMessage("SPPingService", { op: "ping" }); |
michael@0 | 90 | }; |
michael@0 | 91 | |
michael@0 | 92 | // Expose everything but internal APIs (starting with underscores) to |
michael@0 | 93 | // web content. We cannot use Object.keys to view SpecialPowers.prototype since |
michael@0 | 94 | // we are using the functions from SpecialPowersAPI.prototype |
michael@0 | 95 | SpecialPowers.prototype.__exposedProps__ = {}; |
michael@0 | 96 | for (var i in SpecialPowers.prototype) { |
michael@0 | 97 | if (i.charAt(0) != "_") |
michael@0 | 98 | SpecialPowers.prototype.__exposedProps__[i] = "r"; |
michael@0 | 99 | } |
michael@0 | 100 | |
michael@0 | 101 | // Attach our API to the window. |
michael@0 | 102 | function attachSpecialPowersToWindow(aWindow) { |
michael@0 | 103 | try { |
michael@0 | 104 | if ((aWindow !== null) && |
michael@0 | 105 | (aWindow !== undefined) && |
michael@0 | 106 | (aWindow.wrappedJSObject) && |
michael@0 | 107 | !(aWindow.wrappedJSObject.SpecialPowers)) { |
michael@0 | 108 | aWindow.wrappedJSObject.SpecialPowers = new SpecialPowers(aWindow); |
michael@0 | 109 | } |
michael@0 | 110 | } catch(ex) { |
michael@0 | 111 | dump("TEST-INFO | specialpowers.js | Failed to attach specialpowers to window exception: " + ex + "\n"); |
michael@0 | 112 | } |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | // This is a frame script, so it may be running in a content process. |
michael@0 | 116 | // In any event, it is targeted at a specific "tab", so we listen for |
michael@0 | 117 | // the DOMWindowCreated event to be notified about content windows |
michael@0 | 118 | // being created in this context. |
michael@0 | 119 | |
michael@0 | 120 | function SpecialPowersManager() { |
michael@0 | 121 | addEventListener("DOMWindowCreated", this, false); |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | SpecialPowersManager.prototype = { |
michael@0 | 125 | handleEvent: function handleEvent(aEvent) { |
michael@0 | 126 | var window = aEvent.target.defaultView; |
michael@0 | 127 | attachSpecialPowersToWindow(window); |
michael@0 | 128 | } |
michael@0 | 129 | }; |
michael@0 | 130 | |
michael@0 | 131 | var specialpowersmanager = new SpecialPowersManager(); |
michael@0 | 132 | |
michael@0 | 133 | this.SpecialPowers = SpecialPowers; |
michael@0 | 134 | this.attachSpecialPowersToWindow = attachSpecialPowersToWindow; |