1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/devtools/app-manager/content/device.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,229 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +const Cu = Components.utils; 1.9 +Cu.import("resource://gre/modules/Services.jsm"); 1.10 +Cu.import("resource://gre/modules/devtools/dbg-client.jsm"); 1.11 +const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {}); 1.12 + 1.13 +const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}); 1.14 +const {require} = devtools; 1.15 + 1.16 +const {ConnectionManager, Connection} 1.17 + = require("devtools/client/connection-manager"); 1.18 +const {getDeviceFront} = require("devtools/server/actors/device"); 1.19 +const {getTargetForApp, launchApp, closeApp} 1.20 + = require("devtools/app-actor-front"); 1.21 +const DeviceStore = require("devtools/app-manager/device-store"); 1.22 +const WebappsStore = require("devtools/app-manager/webapps-store"); 1.23 +const promise = require("devtools/toolkit/deprecated-sync-thenables"); 1.24 +const DEFAULT_APP_ICON = "chrome://browser/skin/devtools/app-manager/default-app-icon.png"; 1.25 + 1.26 +window.addEventListener("message", function(event) { 1.27 + try { 1.28 + let message = JSON.parse(event.data); 1.29 + if (message.name == "connection") { 1.30 + let cid = parseInt(message.cid); 1.31 + for (let c of ConnectionManager.connections) { 1.32 + if (c.uid == cid) { 1.33 + UI.connection = c; 1.34 + UI.onNewConnection(); 1.35 + break; 1.36 + } 1.37 + } 1.38 + } 1.39 + } catch(e) { 1.40 + Cu.reportError(e); 1.41 + } 1.42 +}); 1.43 + 1.44 +window.addEventListener("unload", function onUnload() { 1.45 + window.removeEventListener("unload", onUnload); 1.46 + UI.destroy(); 1.47 +}); 1.48 + 1.49 +let UI = { 1.50 + init: function() { 1.51 + this.showFooterIfNeeded(); 1.52 + this.setTab("apps"); 1.53 + if (this.connection) { 1.54 + this.onNewConnection(); 1.55 + } else { 1.56 + this.hide(); 1.57 + } 1.58 + }, 1.59 + 1.60 + destroy: function() { 1.61 + if (this.connection) { 1.62 + this.connection.off(Connection.Events.STATUS_CHANGED, this._onConnectionStatusChange); 1.63 + } 1.64 + if (this.store) { 1.65 + this.store.destroy(); 1.66 + } 1.67 + if (this.template) { 1.68 + this.template.destroy(); 1.69 + } 1.70 + }, 1.71 + 1.72 + showFooterIfNeeded: function() { 1.73 + let footer = document.querySelector("#connection-footer"); 1.74 + if (window.parent == window) { 1.75 + // We're alone. Let's add a footer. 1.76 + footer.removeAttribute("hidden"); 1.77 + footer.src = "chrome://browser/content/devtools/app-manager/connection-footer.xhtml"; 1.78 + } else { 1.79 + footer.setAttribute("hidden", "true"); 1.80 + } 1.81 + }, 1.82 + 1.83 + hide: function() { 1.84 + document.body.classList.add("notconnected"); 1.85 + }, 1.86 + 1.87 + show: function() { 1.88 + document.body.classList.remove("notconnected"); 1.89 + }, 1.90 + 1.91 + onNewConnection: function() { 1.92 + this.connection.on(Connection.Events.STATUS_CHANGED, this._onConnectionStatusChange); 1.93 + 1.94 + this.store = Utils.mergeStores({ 1.95 + "device": new DeviceStore(this.connection), 1.96 + "apps": new WebappsStore(this.connection), 1.97 + }); 1.98 + 1.99 + if (this.template) { 1.100 + this.template.destroy(); 1.101 + } 1.102 + this.template = new Template(document.body, this.store, Utils.l10n); 1.103 + 1.104 + this.template.start(); 1.105 + this._onConnectionStatusChange(); 1.106 + }, 1.107 + 1.108 + setWallpaper: function(dataurl) { 1.109 + document.getElementById("meta").style.backgroundImage = "url(" + dataurl + ")"; 1.110 + }, 1.111 + 1.112 + _onConnectionStatusChange: function() { 1.113 + if (this.connection.status != Connection.Status.CONNECTED) { 1.114 + this.hide(); 1.115 + this.listTabsResponse = null; 1.116 + } else { 1.117 + this.show(); 1.118 + this.connection.client.listTabs( 1.119 + response => { 1.120 + this.listTabsResponse = response; 1.121 + let front = getDeviceFront(this.connection.client, this.listTabsResponse); 1.122 + front.getWallpaper().then(longstr => { 1.123 + longstr.string().then(dataURL => { 1.124 + longstr.release().then(null, Cu.reportError); 1.125 + this.setWallpaper(dataURL); 1.126 + }); 1.127 + }); 1.128 + if (Services.prefs.getBoolPref("devtools.chrome.enabled")) { 1.129 + let rootButton = document.getElementById("root-actor-debug"); 1.130 + if (response.consoleActor) { 1.131 + rootButton.removeAttribute("hidden"); 1.132 + } else { 1.133 + rootButton.setAttribute("hidden", "true"); 1.134 + } 1.135 + } 1.136 + } 1.137 + ); 1.138 + } 1.139 + }, 1.140 + 1.141 + get connected() { return !!this.listTabsResponse; }, 1.142 + 1.143 + setTab: function(name) { 1.144 + var tab = document.querySelector(".tab.selected"); 1.145 + var panel = document.querySelector(".tabpanel.selected"); 1.146 + 1.147 + if (tab) tab.classList.remove("selected"); 1.148 + if (panel) panel.classList.remove("selected"); 1.149 + 1.150 + var tab = document.querySelector(".tab." + name); 1.151 + var panel = document.querySelector(".tabpanel." + name); 1.152 + 1.153 + if (tab) tab.classList.add("selected"); 1.154 + if (panel) panel.classList.add("selected"); 1.155 + }, 1.156 + 1.157 + openToolboxForRootActor: function() { 1.158 + if (!this.connected) { 1.159 + return; 1.160 + } 1.161 + 1.162 + let options = { 1.163 + form: this.listTabsResponse, 1.164 + client: this.connection.client, 1.165 + chrome: true 1.166 + }; 1.167 + devtools.TargetFactory.forRemoteTab(options).then((target) => { 1.168 + top.UI.openAndShowToolboxForTarget(target, "Main process", null); 1.169 + }); 1.170 + }, 1.171 + 1.172 + openToolboxForApp: function(manifest) { 1.173 + if (!this.connected) { 1.174 + return; 1.175 + } 1.176 + 1.177 + let app = this.store.object.apps.all.filter(a => a.manifestURL == manifest)[0]; 1.178 + getTargetForApp(this.connection.client, 1.179 + this.listTabsResponse.webappsActor, 1.180 + manifest).then((target) => { 1.181 + 1.182 + top.UI.openAndShowToolboxForTarget(target, app.name, app.iconURL); 1.183 + }, console.error); 1.184 + }, 1.185 + 1.186 + _getTargetForTab: function (form) { 1.187 + let options = { 1.188 + form: form, 1.189 + client: this.connection.client, 1.190 + chrome: false 1.191 + }; 1.192 + let deferred = promise.defer(); 1.193 + return devtools.TargetFactory.forRemoteTab(options); 1.194 + }, 1.195 + 1.196 + openToolboxForTab: function (aNode) { 1.197 + let index = Array.prototype.indexOf.apply( 1.198 + aNode.parentNode.parentNode.parentNode.children, 1.199 + [aNode.parentNode.parentNode]); 1.200 + this.connection.client.listTabs( 1.201 + response => { 1.202 + let tab = response.tabs[index]; 1.203 + this._getTargetForTab(tab).then(target => { 1.204 + top.UI.openAndShowToolboxForTarget( 1.205 + target, tab.title, DEFAULT_APP_ICON); 1.206 + }, console.error); 1.207 + } 1.208 + ); 1.209 + }, 1.210 + 1.211 + startApp: function(manifest) { 1.212 + if (!this.connected) { 1.213 + return promise.reject(); 1.214 + } 1.215 + return launchApp(this.connection.client, 1.216 + this.listTabsResponse.webappsActor, 1.217 + manifest); 1.218 + }, 1.219 + 1.220 + stopApp: function(manifest) { 1.221 + if (!this.connected) { 1.222 + return promise.reject(); 1.223 + } 1.224 + return closeApp(this.connection.client, 1.225 + this.listTabsResponse.webappsActor, 1.226 + manifest); 1.227 + }, 1.228 +} 1.229 + 1.230 +// This must be bound immediately, as it might be used via the message listener 1.231 +// before UI.init() has been called. 1.232 +UI._onConnectionStatusChange = UI._onConnectionStatusChange.bind(UI);