diff -r 000000000000 -r 6474c204b198 b2g/chrome/content/devtools.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/b2g/chrome/content/devtools.js Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,596 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +'use strict'; + +const DEVELOPER_HUD_LOG_PREFIX = 'DeveloperHUD'; + +XPCOMUtils.defineLazyGetter(this, 'devtools', function() { + const {devtools} = Cu.import('resource://gre/modules/devtools/Loader.jsm', {}); + return devtools; +}); + +XPCOMUtils.defineLazyGetter(this, 'DebuggerClient', function() { + return Cu.import('resource://gre/modules/devtools/dbg-client.jsm', {}).DebuggerClient; +}); + +XPCOMUtils.defineLazyGetter(this, 'WebConsoleUtils', function() { + return devtools.require('devtools/toolkit/webconsole/utils').Utils; +}); + +XPCOMUtils.defineLazyGetter(this, 'EventLoopLagFront', function() { + return devtools.require('devtools/server/actors/eventlooplag').EventLoopLagFront; +}); + +XPCOMUtils.defineLazyGetter(this, 'MemoryFront', function() { + return devtools.require('devtools/server/actors/memory').MemoryFront; +}); + + +/** + * The Developer HUD is an on-device developer tool that displays widgets, + * showing visual debug information about apps. Each widget corresponds to a + * metric as tracked by a metric watcher (e.g. consoleWatcher). + */ +let developerHUD = { + + _targets: new Map(), + _frames: new Map(), + _client: null, + _conn: null, + _watchers: [], + _logging: true, + + /** + * This method registers a metric watcher that will watch one or more metrics + * on app frames that are being tracked. A watcher must implement the + * `trackTarget(target)` and `untrackTarget(target)` methods, register + * observed metrics with `target.register(metric)`, and keep them up-to-date + * with `target.update(metric, message)` when necessary. + */ + registerWatcher: function dwp_registerWatcher(watcher) { + this._watchers.unshift(watcher); + }, + + init: function dwp_init() { + if (this._client) + return; + + if (!DebuggerServer.initialized) { + RemoteDebugger.start(); + } + + // We instantiate a local debugger connection so that watchers can use our + // DebuggerClient to send requests to tab actors (e.g. the consoleActor). + // Note the special usage of the private _serverConnection, which we need + // to call connectToChild and set up child process actors on a frame we + // intend to track. These actors will use the connection to communicate with + // our DebuggerServer in the parent process. + let transport = DebuggerServer.connectPipe(); + this._conn = transport._serverConnection; + this._client = new DebuggerClient(transport); + + for (let w of this._watchers) { + if (w.init) { + w.init(this._client); + } + } + + Services.obs.addObserver(this, 'remote-browser-shown', false); + Services.obs.addObserver(this, 'inprocess-browser-shown', false); + Services.obs.addObserver(this, 'message-manager-disconnect', false); + + let systemapp = document.querySelector('#systemapp'); + this.trackFrame(systemapp); + + let frames = systemapp.contentWindow.document.querySelectorAll('iframe[mozapp]'); + for (let frame of frames) { + this.trackFrame(frame); + } + + SettingsListener.observe('hud.logging', this._logging, enabled => { + this._logging = enabled; + }); + }, + + uninit: function dwp_uninit() { + if (!this._client) + return; + + for (let frame of this._targets.keys()) { + this.untrackFrame(frame); + } + + Services.obs.removeObserver(this, 'remote-browser-shown'); + Services.obs.removeObserver(this, 'inprocess-browser-shown'); + Services.obs.removeObserver(this, 'message-manager-disconnect'); + + this._client.close(); + delete this._client; + }, + + /** + * This method will ask all registered watchers to track and update metrics + * on an app frame. + */ + trackFrame: function dwp_trackFrame(frame) { + if (this._targets.has(frame)) + return; + + DebuggerServer.connectToChild(this._conn, frame).then(actor => { + let target = new Target(frame, actor); + this._targets.set(frame, target); + + for (let w of this._watchers) { + w.trackTarget(target); + } + }); + }, + + untrackFrame: function dwp_untrackFrame(frame) { + let target = this._targets.get(frame); + if (target) { + for (let w of this._watchers) { + w.untrackTarget(target); + } + + target.destroy(); + this._targets.delete(frame); + } + }, + + observe: function dwp_observe(subject, topic, data) { + if (!this._client) + return; + + let frame; + + switch(topic) { + + // listen for frame creation in OOP (device) as well as in parent process (b2g desktop) + case 'remote-browser-shown': + case 'inprocess-browser-shown': + let frameLoader = subject; + // get a ref to the app