1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/devtools/server/actors/common.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,168 @@ 1.4 +/* -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +"use strict"; 1.11 + 1.12 +/** 1.13 + * Methods shared between RootActor and BrowserTabActor. 1.14 + */ 1.15 + 1.16 +/** 1.17 + * Populate |this._extraActors| as specified by |aFactories|, reusing whatever 1.18 + * actors are already there. Add all actors in the final extra actors table to 1.19 + * |aPool|. 1.20 + * 1.21 + * The root actor and the tab actor use this to instantiate actors that other 1.22 + * parts of the browser have specified with DebuggerServer.addTabActor antd 1.23 + * DebuggerServer.addGlobalActor. 1.24 + * 1.25 + * @param aFactories 1.26 + * An object whose own property names are the names of properties to add to 1.27 + * some reply packet (say, a tab actor grip or the "listTabs" response 1.28 + * form), and whose own property values are actor constructor functions, as 1.29 + * documented for addTabActor and addGlobalActor. 1.30 + * 1.31 + * @param this 1.32 + * The BrowserRootActor or BrowserTabActor with which the new actors will 1.33 + * be associated. It should support whatever API the |aFactories| 1.34 + * constructor functions might be interested in, as it is passed to them. 1.35 + * For the sake of CommonCreateExtraActors itself, it should have at least 1.36 + * the following properties: 1.37 + * 1.38 + * - _extraActors 1.39 + * An object whose own property names are factory table (and packet) 1.40 + * property names, and whose values are no-argument actor constructors, 1.41 + * of the sort that one can add to an ActorPool. 1.42 + * 1.43 + * - conn 1.44 + * The DebuggerServerConnection in which the new actors will participate. 1.45 + * 1.46 + * - actorID 1.47 + * The actor's name, for use as the new actors' parentID. 1.48 + */ 1.49 +exports.createExtraActors = function createExtraActors(aFactories, aPool) { 1.50 + // Walk over global actors added by extensions. 1.51 + for (let name in aFactories) { 1.52 + let actor = this._extraActors[name]; 1.53 + if (!actor) { 1.54 + actor = aFactories[name].bind(null, this.conn, this); 1.55 + actor.prototype = aFactories[name].prototype; 1.56 + actor.parentID = this.actorID; 1.57 + this._extraActors[name] = actor; 1.58 + } 1.59 + aPool.addActor(actor); 1.60 + } 1.61 +} 1.62 + 1.63 +/** 1.64 + * Append the extra actors in |this._extraActors|, constructed by a prior call 1.65 + * to CommonCreateExtraActors, to |aObject|. 1.66 + * 1.67 + * @param aObject 1.68 + * The object to which the extra actors should be added, under the 1.69 + * property names given in the |aFactories| table passed to 1.70 + * CommonCreateExtraActors. 1.71 + * 1.72 + * @param this 1.73 + * The BrowserRootActor or BrowserTabActor whose |_extraActors| table we 1.74 + * should use; see above. 1.75 + */ 1.76 +exports.appendExtraActors = function appendExtraActors(aObject) { 1.77 + for (let name in this._extraActors) { 1.78 + let actor = this._extraActors[name]; 1.79 + aObject[name] = actor.actorID; 1.80 + } 1.81 +} 1.82 + 1.83 +/** 1.84 + * Construct an ActorPool. 1.85 + * 1.86 + * ActorPools are actorID -> actor mapping and storage. These are 1.87 + * used to accumulate and quickly dispose of groups of actors that 1.88 + * share a lifetime. 1.89 + */ 1.90 +function ActorPool(aConnection) 1.91 +{ 1.92 + this.conn = aConnection; 1.93 + this._cleanups = {}; 1.94 + this._actors = {}; 1.95 +} 1.96 + 1.97 +ActorPool.prototype = { 1.98 + /** 1.99 + * Add an actor to the actor pool. If the actor doesn't have an ID, 1.100 + * allocate one from the connection. 1.101 + * 1.102 + * @param aActor object 1.103 + * The actor implementation. If the object has a 1.104 + * 'disconnect' property, it will be called when the actor 1.105 + * pool is cleaned up. 1.106 + */ 1.107 + addActor: function AP_addActor(aActor) { 1.108 + aActor.conn = this.conn; 1.109 + if (!aActor.actorID) { 1.110 + let prefix = aActor.actorPrefix; 1.111 + if (typeof aActor == "function") { 1.112 + // typeName is a convention used with protocol.js-based actors 1.113 + prefix = aActor.prototype.actorPrefix || aActor.prototype.typeName; 1.114 + } 1.115 + aActor.actorID = this.conn.allocID(prefix || undefined); 1.116 + } 1.117 + 1.118 + if (aActor.registeredPool) { 1.119 + aActor.registeredPool.removeActor(aActor); 1.120 + } 1.121 + aActor.registeredPool = this; 1.122 + 1.123 + this._actors[aActor.actorID] = aActor; 1.124 + if (aActor.disconnect) { 1.125 + this._cleanups[aActor.actorID] = aActor; 1.126 + } 1.127 + }, 1.128 + 1.129 + get: function AP_get(aActorID) { 1.130 + return this._actors[aActorID]; 1.131 + }, 1.132 + 1.133 + has: function AP_has(aActorID) { 1.134 + return aActorID in this._actors; 1.135 + }, 1.136 + 1.137 + /** 1.138 + * Returns true if the pool is empty. 1.139 + */ 1.140 + isEmpty: function AP_isEmpty() { 1.141 + return Object.keys(this._actors).length == 0; 1.142 + }, 1.143 + 1.144 + /** 1.145 + * Remove an actor from the actor pool. 1.146 + */ 1.147 + removeActor: function AP_remove(aActor) { 1.148 + delete this._actors[aActor.actorID]; 1.149 + delete this._cleanups[aActor.actorID]; 1.150 + }, 1.151 + 1.152 + /** 1.153 + * Match the api expected by the protocol library. 1.154 + */ 1.155 + unmanage: function(aActor) { 1.156 + return this.removeActor(aActor); 1.157 + }, 1.158 + 1.159 + /** 1.160 + * Run all actor cleanups. 1.161 + */ 1.162 + cleanup: function AP_cleanup() { 1.163 + for each (let actor in this._cleanups) { 1.164 + actor.disconnect(); 1.165 + } 1.166 + this._cleanups = {}; 1.167 + } 1.168 +} 1.169 + 1.170 +exports.ActorPool = ActorPool; 1.171 +