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: "use strict"; michael@0: michael@0: const {Cc, Ci, Cu, Cr} = require("chrome"); michael@0: const {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); michael@0: michael@0: const events = require("sdk/event/core"); michael@0: const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {}); michael@0: michael@0: /** michael@0: * Handles adding an observer for the creation of content document globals, michael@0: * event sent immediately after a web content document window has been set up, michael@0: * but before any script code has been executed. michael@0: */ michael@0: function ContentObserver(tabActor) { michael@0: this._contentWindow = tabActor.window; michael@0: this._onContentGlobalCreated = this._onContentGlobalCreated.bind(this); michael@0: this._onInnerWindowDestroyed = this._onInnerWindowDestroyed.bind(this); michael@0: this.startListening(); michael@0: } michael@0: michael@0: module.exports.ContentObserver = ContentObserver; michael@0: michael@0: ContentObserver.prototype = { michael@0: /** michael@0: * Starts listening for the required observer messages. michael@0: */ michael@0: startListening: function() { michael@0: Services.obs.addObserver( michael@0: this._onContentGlobalCreated, "content-document-global-created", false); michael@0: Services.obs.addObserver( michael@0: this._onInnerWindowDestroyed, "inner-window-destroyed", false); michael@0: }, michael@0: michael@0: /** michael@0: * Stops listening for the required observer messages. michael@0: */ michael@0: stopListening: function() { michael@0: Services.obs.removeObserver( michael@0: this._onContentGlobalCreated, "content-document-global-created", false); michael@0: Services.obs.removeObserver( michael@0: this._onInnerWindowDestroyed, "inner-window-destroyed", false); michael@0: }, michael@0: michael@0: /** michael@0: * Fired immediately after a web content document window has been set up. michael@0: */ michael@0: _onContentGlobalCreated: function(subject, topic, data) { michael@0: if (subject == this._contentWindow) { michael@0: events.emit(this, "global-created", subject); michael@0: } michael@0: }, michael@0: michael@0: /** michael@0: * Fired when an inner window is removed from the backward/forward cache. michael@0: */ michael@0: _onInnerWindowDestroyed: function(subject, topic, data) { michael@0: let id = subject.QueryInterface(Ci.nsISupportsPRUint64).data; michael@0: events.emit(this, "global-destroyed", id); michael@0: } michael@0: }; michael@0: michael@0: // Utility functions. michael@0: michael@0: ContentObserver.GetInnerWindowID = function(window) { michael@0: return window michael@0: .QueryInterface(Ci.nsIInterfaceRequestor) michael@0: .getInterface(Ci.nsIDOMWindowUtils) michael@0: .currentInnerWindowID; michael@0: };