browser/devtools/framework/toolbox-hosts.js

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:a9d6f40c8e93
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 "use strict";
6
7 const {Cu} = require("chrome");
8 const EventEmitter = require("devtools/toolkit/event-emitter");
9 const {Promise: promise} = require("resource://gre/modules/Promise.jsm");
10 Cu.import("resource://gre/modules/Services.jsm");
11 Cu.import("resource:///modules/devtools/DOMHelpers.jsm");
12
13 /**
14 * A toolbox host represents an object that contains a toolbox (e.g. the
15 * sidebar or a separate window). Any host object should implement the
16 * following functions:
17 *
18 * create() - create the UI and emit a 'ready' event when the UI is ready to use
19 * destroy() - destroy the host's UI
20 */
21
22 exports.Hosts = {
23 "bottom": BottomHost,
24 "side": SidebarHost,
25 "window": WindowHost,
26 "custom": CustomHost
27 };
28
29 /**
30 * Host object for the dock on the bottom of the browser
31 */
32 function BottomHost(hostTab) {
33 this.hostTab = hostTab;
34
35 EventEmitter.decorate(this);
36 }
37
38 BottomHost.prototype = {
39 type: "bottom",
40
41 heightPref: "devtools.toolbox.footer.height",
42
43 /**
44 * Create a box at the bottom of the host tab.
45 */
46 create: function BH_create() {
47 let deferred = promise.defer();
48
49 let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
50 let ownerDocument = gBrowser.ownerDocument;
51
52 this._splitter = ownerDocument.createElement("splitter");
53 this._splitter.setAttribute("class", "devtools-horizontal-splitter");
54
55 this.frame = ownerDocument.createElement("iframe");
56 this.frame.className = "devtools-toolbox-bottom-iframe";
57 this.frame.height = Services.prefs.getIntPref(this.heightPref);
58
59 this._nbox = gBrowser.getNotificationBox(this.hostTab.linkedBrowser);
60 this._nbox.appendChild(this._splitter);
61 this._nbox.appendChild(this.frame);
62
63 let frameLoad = function() {
64 this.emit("ready", this.frame);
65 deferred.resolve(this.frame);
66 }.bind(this);
67
68 this.frame.tooltip = "aHTMLTooltip";
69
70 // we have to load something so we can switch documents if we have to
71 this.frame.setAttribute("src", "about:blank");
72
73 let domHelper = new DOMHelpers(this.frame.contentWindow);
74 domHelper.onceDOMReady(frameLoad);
75
76 focusTab(this.hostTab);
77
78 return deferred.promise;
79 },
80
81 /**
82 * Raise the host.
83 */
84 raise: function BH_raise() {
85 focusTab(this.hostTab);
86 },
87
88 /**
89 * Set the toolbox title.
90 */
91 setTitle: function BH_setTitle(title) {
92 // Nothing to do for this host type.
93 },
94
95 /**
96 * Destroy the bottom dock.
97 */
98 destroy: function BH_destroy() {
99 if (!this._destroyed) {
100 this._destroyed = true;
101
102 Services.prefs.setIntPref(this.heightPref, this.frame.height);
103 this._nbox.removeChild(this._splitter);
104 this._nbox.removeChild(this.frame);
105 }
106
107 return promise.resolve(null);
108 }
109 }
110
111
112 /**
113 * Host object for the in-browser sidebar
114 */
115 function SidebarHost(hostTab) {
116 this.hostTab = hostTab;
117
118 EventEmitter.decorate(this);
119 }
120
121 SidebarHost.prototype = {
122 type: "side",
123
124 widthPref: "devtools.toolbox.sidebar.width",
125
126 /**
127 * Create a box in the sidebar of the host tab.
128 */
129 create: function SH_create() {
130 let deferred = promise.defer();
131
132 let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
133 let ownerDocument = gBrowser.ownerDocument;
134
135 this._splitter = ownerDocument.createElement("splitter");
136 this._splitter.setAttribute("class", "devtools-side-splitter");
137
138 this.frame = ownerDocument.createElement("iframe");
139 this.frame.className = "devtools-toolbox-side-iframe";
140 this.frame.width = Services.prefs.getIntPref(this.widthPref);
141
142 this._sidebar = gBrowser.getSidebarContainer(this.hostTab.linkedBrowser);
143 this._sidebar.appendChild(this._splitter);
144 this._sidebar.appendChild(this.frame);
145
146 let frameLoad = function() {
147 this.emit("ready", this.frame);
148 deferred.resolve(this.frame);
149 }.bind(this);
150
151 this.frame.tooltip = "aHTMLTooltip";
152 this.frame.setAttribute("src", "about:blank");
153
154 let domHelper = new DOMHelpers(this.frame.contentWindow);
155 domHelper.onceDOMReady(frameLoad);
156
157 focusTab(this.hostTab);
158
159 return deferred.promise;
160 },
161
162 /**
163 * Raise the host.
164 */
165 raise: function SH_raise() {
166 focusTab(this.hostTab);
167 },
168
169 /**
170 * Set the toolbox title.
171 */
172 setTitle: function SH_setTitle(title) {
173 // Nothing to do for this host type.
174 },
175
176 /**
177 * Destroy the sidebar.
178 */
179 destroy: function SH_destroy() {
180 if (!this._destroyed) {
181 this._destroyed = true;
182
183 Services.prefs.setIntPref(this.widthPref, this.frame.width);
184 this._sidebar.removeChild(this._splitter);
185 this._sidebar.removeChild(this.frame);
186 }
187
188 return promise.resolve(null);
189 }
190 }
191
192 /**
193 * Host object for the toolbox in a separate window
194 */
195 function WindowHost() {
196 this._boundUnload = this._boundUnload.bind(this);
197
198 EventEmitter.decorate(this);
199 }
200
201 WindowHost.prototype = {
202 type: "window",
203
204 WINDOW_URL: "chrome://browser/content/devtools/framework/toolbox-window.xul",
205
206 /**
207 * Create a new xul window to contain the toolbox.
208 */
209 create: function WH_create() {
210 let deferred = promise.defer();
211
212 let flags = "chrome,centerscreen,resizable,dialog=no";
213 let win = Services.ww.openWindow(null, this.WINDOW_URL, "_blank",
214 flags, null);
215
216 let frameLoad = function(event) {
217 win.removeEventListener("load", frameLoad, true);
218 win.focus();
219 this.frame = win.document.getElementById("toolbox-iframe");
220 this.emit("ready", this.frame);
221
222 deferred.resolve(this.frame);
223 }.bind(this);
224
225 win.addEventListener("load", frameLoad, true);
226 win.addEventListener("unload", this._boundUnload);
227
228 this._window = win;
229
230 return deferred.promise;
231 },
232
233 /**
234 * Catch the user closing the window.
235 */
236 _boundUnload: function(event) {
237 if (event.target.location != this.WINDOW_URL) {
238 return;
239 }
240 this._window.removeEventListener("unload", this._boundUnload);
241
242 this.emit("window-closed");
243 },
244
245 /**
246 * Raise the host.
247 */
248 raise: function RH_raise() {
249 this._window.focus();
250 },
251
252 /**
253 * Set the toolbox title.
254 */
255 setTitle: function WH_setTitle(title) {
256 this._window.document.title = title;
257 },
258
259 /**
260 * Destroy the window.
261 */
262 destroy: function WH_destroy() {
263 if (!this._destroyed) {
264 this._destroyed = true;
265
266 this._window.removeEventListener("unload", this._boundUnload);
267 this._window.close();
268 }
269
270 return promise.resolve(null);
271 }
272 };
273
274 /**
275 * Host object for the toolbox in its own tab
276 */
277 function CustomHost(hostTab, options) {
278 this.frame = options.customIframe;
279 this.uid = options.uid;
280 EventEmitter.decorate(this);
281 }
282
283 CustomHost.prototype = {
284 type: "custom",
285
286 _sendMessageToTopWindow: function CH__sendMessageToTopWindow(msg, data) {
287 // It's up to the custom frame owner (parent window) to honor
288 // "close" or "raise" instructions.
289 let topWindow = this.frame.ownerDocument.defaultView;
290 let json = {name:"toolbox-" + msg, uid: this.uid};
291 if (data) {
292 json.data = data;
293 }
294 topWindow.postMessage(JSON.stringify(json), "*");
295 },
296
297 /**
298 * Create a new xul window to contain the toolbox.
299 */
300 create: function CH_create() {
301 return promise.resolve(this.frame);
302 },
303
304 /**
305 * Raise the host.
306 */
307 raise: function CH_raise() {
308 this._sendMessageToTopWindow("raise");
309 },
310
311 /**
312 * Set the toolbox title.
313 */
314 setTitle: function CH_setTitle(title) {
315 this._sendMessageToTopWindow("title", { value: title });
316 },
317
318 /**
319 * Destroy the window.
320 */
321 destroy: function WH_destroy() {
322 if (!this._destroyed) {
323 this._destroyed = true;
324 this._sendMessageToTopWindow("close");
325 }
326 return promise.resolve(null);
327 }
328 }
329
330 /**
331 * Switch to the given tab in a browser and focus the browser window
332 */
333 function focusTab(tab) {
334 let browserWindow = tab.ownerDocument.defaultView;
335 browserWindow.focus();
336 browserWindow.gBrowser.selectedTab = tab;
337 }

mercurial