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 file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: 'use strict'; michael@0: michael@0: const { Promise } = Cu.import("resource://gre/modules/Promise.jsm", {}); michael@0: michael@0: /** michael@0: * WebappRT-specific actors. michael@0: */ michael@0: michael@0: /** michael@0: * Construct a root actor appropriate for use in a server running in the webapp michael@0: * runtime. The returned root actor: michael@0: * - respects the factories registered with DebuggerServer.addGlobalActor, michael@0: * - uses a WebappTabList to supply tab actors, michael@0: * - sends all webapprt:webapp window documents a Debugger:Shutdown event michael@0: * when it exits. michael@0: * michael@0: * * @param connection DebuggerServerConnection michael@0: * The conection to the client. michael@0: */ michael@0: function createRootActor(connection) michael@0: { michael@0: let parameters = { michael@0: tabList: new WebappTabList(connection), michael@0: globalActorFactories: DebuggerServer.globalActorFactories, michael@0: onShutdown: sendShutdownEvent michael@0: }; michael@0: return new RootActor(connection, parameters); michael@0: } michael@0: michael@0: /** michael@0: * A live list of BrowserTabActors representing the current webapp windows, michael@0: * to be provided to the root actor to answer 'listTabs' requests. In the michael@0: * webapp runtime, only a single tab per window is ever present. michael@0: * michael@0: * @param connection DebuggerServerConnection michael@0: * The connection in which this list's tab actors may participate. michael@0: * michael@0: * @see BrowserTabList for more a extensive description of how tab list objects michael@0: * work. michael@0: */ michael@0: function WebappTabList(connection) michael@0: { michael@0: BrowserTabList.call(this, connection); michael@0: } michael@0: michael@0: WebappTabList.prototype = Object.create(BrowserTabList.prototype); michael@0: michael@0: WebappTabList.prototype.constructor = WebappTabList; michael@0: michael@0: WebappTabList.prototype.getList = function() { michael@0: let topXULWindow = Services.wm.getMostRecentWindow(this._windowType); michael@0: michael@0: // As a sanity check, make sure all the actors presently in our map get michael@0: // picked up when we iterate over all windows. michael@0: let initialMapSize = this._actorByBrowser.size; michael@0: let foundCount = 0; michael@0: michael@0: // To avoid mysterious behavior if windows are closed or opened mid-iteration, michael@0: // we update the map first, and then make a second pass over it to yield michael@0: // the actors. Thus, the sequence yielded is always a snapshot of the michael@0: // actors that were live when we began the iteration. michael@0: michael@0: // Iterate over all webapprt:webapp XUL windows. michael@0: for (let win of allAppShellDOMWindows(this._windowType)) { michael@0: let browser = win.document.getElementById("content"); michael@0: if (!browser) { michael@0: continue; michael@0: } michael@0: michael@0: // Do we have an existing actor for this browser? If not, create one. michael@0: let actor = this._actorByBrowser.get(browser); michael@0: if (actor) { michael@0: foundCount++; michael@0: } else { michael@0: actor = new WebappTabActor(this._connection, browser); michael@0: this._actorByBrowser.set(browser, actor); michael@0: } michael@0: michael@0: actor.selected = (win == topXULWindow); michael@0: } michael@0: michael@0: if (this._testing && initialMapSize !== foundCount) { michael@0: throw Error("_actorByBrowser map contained actors for dead tabs"); michael@0: } michael@0: michael@0: this._mustNotify = true; michael@0: this._checkListening(); michael@0: michael@0: return Promise.resolve([actor for ([_, actor] of this._actorByBrowser)]); michael@0: }; michael@0: michael@0: /** michael@0: * Creates a tab actor for handling requests to the single tab, like michael@0: * attaching and detaching. WebappTabActor respects the actor factories michael@0: * registered with DebuggerServer.addTabActor. michael@0: * michael@0: * We override the title of the XUL window in content/webapp.js so here michael@0: * we need to override the title property to avoid confusion to the user. michael@0: * We won't return the title of the contained browser, but the title of michael@0: * the webapp window. michael@0: * michael@0: * @param connection DebuggerServerConnection michael@0: * The conection to the client. michael@0: * @param browser browser michael@0: * The browser instance that contains this tab. michael@0: */ michael@0: function WebappTabActor(connection, browser) michael@0: { michael@0: BrowserTabActor.call(this, connection, browser); michael@0: } michael@0: michael@0: WebappTabActor.prototype.constructor = WebappTabActor; michael@0: michael@0: WebappTabActor.prototype = Object.create(BrowserTabActor.prototype); michael@0: michael@0: Object.defineProperty(WebappTabActor.prototype, "title", { michael@0: get: function() { michael@0: return this.browser.ownerDocument.defaultView.document.title; michael@0: }, michael@0: enumerable: true, michael@0: configurable: false michael@0: });