|
1 /* -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 "use strict"; |
|
8 |
|
9 /** |
|
10 * Methods shared between RootActor and BrowserTabActor. |
|
11 */ |
|
12 |
|
13 /** |
|
14 * Populate |this._extraActors| as specified by |aFactories|, reusing whatever |
|
15 * actors are already there. Add all actors in the final extra actors table to |
|
16 * |aPool|. |
|
17 * |
|
18 * The root actor and the tab actor use this to instantiate actors that other |
|
19 * parts of the browser have specified with DebuggerServer.addTabActor antd |
|
20 * DebuggerServer.addGlobalActor. |
|
21 * |
|
22 * @param aFactories |
|
23 * An object whose own property names are the names of properties to add to |
|
24 * some reply packet (say, a tab actor grip or the "listTabs" response |
|
25 * form), and whose own property values are actor constructor functions, as |
|
26 * documented for addTabActor and addGlobalActor. |
|
27 * |
|
28 * @param this |
|
29 * The BrowserRootActor or BrowserTabActor with which the new actors will |
|
30 * be associated. It should support whatever API the |aFactories| |
|
31 * constructor functions might be interested in, as it is passed to them. |
|
32 * For the sake of CommonCreateExtraActors itself, it should have at least |
|
33 * the following properties: |
|
34 * |
|
35 * - _extraActors |
|
36 * An object whose own property names are factory table (and packet) |
|
37 * property names, and whose values are no-argument actor constructors, |
|
38 * of the sort that one can add to an ActorPool. |
|
39 * |
|
40 * - conn |
|
41 * The DebuggerServerConnection in which the new actors will participate. |
|
42 * |
|
43 * - actorID |
|
44 * The actor's name, for use as the new actors' parentID. |
|
45 */ |
|
46 exports.createExtraActors = function createExtraActors(aFactories, aPool) { |
|
47 // Walk over global actors added by extensions. |
|
48 for (let name in aFactories) { |
|
49 let actor = this._extraActors[name]; |
|
50 if (!actor) { |
|
51 actor = aFactories[name].bind(null, this.conn, this); |
|
52 actor.prototype = aFactories[name].prototype; |
|
53 actor.parentID = this.actorID; |
|
54 this._extraActors[name] = actor; |
|
55 } |
|
56 aPool.addActor(actor); |
|
57 } |
|
58 } |
|
59 |
|
60 /** |
|
61 * Append the extra actors in |this._extraActors|, constructed by a prior call |
|
62 * to CommonCreateExtraActors, to |aObject|. |
|
63 * |
|
64 * @param aObject |
|
65 * The object to which the extra actors should be added, under the |
|
66 * property names given in the |aFactories| table passed to |
|
67 * CommonCreateExtraActors. |
|
68 * |
|
69 * @param this |
|
70 * The BrowserRootActor or BrowserTabActor whose |_extraActors| table we |
|
71 * should use; see above. |
|
72 */ |
|
73 exports.appendExtraActors = function appendExtraActors(aObject) { |
|
74 for (let name in this._extraActors) { |
|
75 let actor = this._extraActors[name]; |
|
76 aObject[name] = actor.actorID; |
|
77 } |
|
78 } |
|
79 |
|
80 /** |
|
81 * Construct an ActorPool. |
|
82 * |
|
83 * ActorPools are actorID -> actor mapping and storage. These are |
|
84 * used to accumulate and quickly dispose of groups of actors that |
|
85 * share a lifetime. |
|
86 */ |
|
87 function ActorPool(aConnection) |
|
88 { |
|
89 this.conn = aConnection; |
|
90 this._cleanups = {}; |
|
91 this._actors = {}; |
|
92 } |
|
93 |
|
94 ActorPool.prototype = { |
|
95 /** |
|
96 * Add an actor to the actor pool. If the actor doesn't have an ID, |
|
97 * allocate one from the connection. |
|
98 * |
|
99 * @param aActor object |
|
100 * The actor implementation. If the object has a |
|
101 * 'disconnect' property, it will be called when the actor |
|
102 * pool is cleaned up. |
|
103 */ |
|
104 addActor: function AP_addActor(aActor) { |
|
105 aActor.conn = this.conn; |
|
106 if (!aActor.actorID) { |
|
107 let prefix = aActor.actorPrefix; |
|
108 if (typeof aActor == "function") { |
|
109 // typeName is a convention used with protocol.js-based actors |
|
110 prefix = aActor.prototype.actorPrefix || aActor.prototype.typeName; |
|
111 } |
|
112 aActor.actorID = this.conn.allocID(prefix || undefined); |
|
113 } |
|
114 |
|
115 if (aActor.registeredPool) { |
|
116 aActor.registeredPool.removeActor(aActor); |
|
117 } |
|
118 aActor.registeredPool = this; |
|
119 |
|
120 this._actors[aActor.actorID] = aActor; |
|
121 if (aActor.disconnect) { |
|
122 this._cleanups[aActor.actorID] = aActor; |
|
123 } |
|
124 }, |
|
125 |
|
126 get: function AP_get(aActorID) { |
|
127 return this._actors[aActorID]; |
|
128 }, |
|
129 |
|
130 has: function AP_has(aActorID) { |
|
131 return aActorID in this._actors; |
|
132 }, |
|
133 |
|
134 /** |
|
135 * Returns true if the pool is empty. |
|
136 */ |
|
137 isEmpty: function AP_isEmpty() { |
|
138 return Object.keys(this._actors).length == 0; |
|
139 }, |
|
140 |
|
141 /** |
|
142 * Remove an actor from the actor pool. |
|
143 */ |
|
144 removeActor: function AP_remove(aActor) { |
|
145 delete this._actors[aActor.actorID]; |
|
146 delete this._cleanups[aActor.actorID]; |
|
147 }, |
|
148 |
|
149 /** |
|
150 * Match the api expected by the protocol library. |
|
151 */ |
|
152 unmanage: function(aActor) { |
|
153 return this.removeActor(aActor); |
|
154 }, |
|
155 |
|
156 /** |
|
157 * Run all actor cleanups. |
|
158 */ |
|
159 cleanup: function AP_cleanup() { |
|
160 for each (let actor in this._cleanups) { |
|
161 actor.disconnect(); |
|
162 } |
|
163 this._cleanups = {}; |
|
164 } |
|
165 } |
|
166 |
|
167 exports.ActorPool = ActorPool; |
|
168 |