browser/devtools/framework/toolbox-hosts.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial