michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const Cu = Components.utils; michael@0: const Ci = Components.interfaces; michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Cu.import("resource:///modules/devtools/gDevTools.jsm"); michael@0: michael@0: const {Simulator} = Cu.import("resource://gre/modules/devtools/Simulator.jsm") michael@0: const {Devices} = Cu.import("resource://gre/modules/devtools/Devices.jsm"); michael@0: const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}); michael@0: const {require} = devtools; michael@0: michael@0: const {ConnectionManager, Connection} = require("devtools/client/connection-manager"); michael@0: const {getDeviceFront} = require("devtools/server/actors/device"); michael@0: const ConnectionStore = require("devtools/app-manager/connection-store"); michael@0: const DeviceStore = require("devtools/app-manager/device-store"); michael@0: const simulatorsStore = require("devtools/app-manager/simulators-store"); michael@0: const adbStore = require("devtools/app-manager/builtin-adb-store"); michael@0: michael@0: window.addEventListener("unload", function onUnload() { michael@0: window.removeEventListener("unload", onUnload); michael@0: UI.destroy(); michael@0: }); michael@0: michael@0: let UI = { michael@0: init: function() { michael@0: this.useFloatingScrollbarsIfNeeded(); michael@0: let connections = ConnectionManager.connections; michael@0: if (connections.length > 0) { michael@0: let hash = window.location.hash; michael@0: if (hash) { michael@0: let res = (/cid=([^&]+)/).exec(hash) michael@0: if (res) { michael@0: let [,cid] = res; michael@0: this.connection = connections.filter((({uid}) => uid == cid))[0]; michael@0: } michael@0: } michael@0: if (!this.connection) { michael@0: // We take the first connection available. michael@0: this.connection = connections[0]; michael@0: } michael@0: } else { michael@0: let host = Services.prefs.getCharPref("devtools.debugger.remote-host"); michael@0: let port = Services.prefs.getIntPref("devtools.debugger.remote-port"); michael@0: this.connection = ConnectionManager.createConnection(host, port); michael@0: } michael@0: michael@0: window.location.hash = "cid=" + this.connection.uid; michael@0: window.parent.postMessage(JSON.stringify({name:"connection",cid:this.connection.uid}), "*"); michael@0: michael@0: this.store = Utils.mergeStores({ michael@0: "device": new DeviceStore(this.connection), michael@0: "connection": new ConnectionStore(this.connection), michael@0: "simulators": simulatorsStore, michael@0: "adb": adbStore michael@0: }); michael@0: michael@0: let pre = document.querySelector("#logs > pre"); michael@0: pre.textContent = this.connection.logs; michael@0: pre.scrollTop = pre.scrollTopMax; michael@0: this.connection.on(Connection.Events.NEW_LOG, this._onNewLog); michael@0: michael@0: this.template = new Template(document.body, this.store, Utils.l10n); michael@0: this.template.start(); michael@0: michael@0: this._onSimulatorConnected = this._onSimulatorConnected.bind(this); michael@0: this._onSimulatorDisconnected = this._onSimulatorDisconnected.bind(this); michael@0: }, michael@0: michael@0: destroy: function() { michael@0: this.store.destroy(); michael@0: this.connection.off(Connection.Events.NEW_LOG, this._onNewLog); michael@0: this.template.destroy(); michael@0: }, michael@0: michael@0: _onNewLog: function(event, str) { michael@0: let pre = document.querySelector("#logs > pre"); michael@0: pre.textContent += "\n" + str; michael@0: pre.scrollTop = pre.scrollTopMax; michael@0: }, michael@0: michael@0: useFloatingScrollbarsIfNeeded: function() { michael@0: if (Services.appinfo.OS == "Darwin") { michael@0: return; michael@0: } michael@0: let scrollbarsUrl = Services.io.newURI("chrome://browser/skin/devtools/floating-scrollbars-light.css", null, null); michael@0: let winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); michael@0: winUtils.loadSheet(scrollbarsUrl, winUtils.AGENT_SHEET); michael@0: let computedStyle = window.getComputedStyle(document.documentElement); michael@0: if (computedStyle) { // Force a reflow to take the new css into account michael@0: let display = computedStyle.display; // Save display value michael@0: document.documentElement.style.display = "none"; michael@0: window.getComputedStyle(document.documentElement).display; // Flush michael@0: document.documentElement.style.display = display; // Restore michael@0: } michael@0: }, michael@0: michael@0: disconnect: function() { michael@0: this.connection.disconnect(); michael@0: }, michael@0: michael@0: connect: function() { michael@0: this.connection.connect(); michael@0: }, michael@0: michael@0: editConnectionParameters: function() { michael@0: document.body.classList.add("edit-connection"); michael@0: document.querySelector("input.host").focus(); michael@0: }, michael@0: michael@0: saveConnectionInfo: function() { michael@0: document.body.classList.remove("edit-connection"); michael@0: document.querySelector("#connect-button").focus(); michael@0: let host = document.querySelector("input.host").value; michael@0: let port = document.querySelector("input.port").value; michael@0: this.connection.port = port; michael@0: this.connection.host = host; michael@0: Services.prefs.setCharPref("devtools.debugger.remote-host", host); michael@0: Services.prefs.setIntPref("devtools.debugger.remote-port", port); michael@0: }, michael@0: michael@0: showSimulatorList: function() { michael@0: document.body.classList.add("show-simulators"); michael@0: }, michael@0: michael@0: cancelShowSimulatorList: function() { michael@0: document.body.classList.remove("show-simulators"); michael@0: }, michael@0: michael@0: installSimulator: function() { michael@0: let url = "https://developer.mozilla.org/docs/Mozilla/Firefox_OS/Using_the_App_Manager#Simulator"; michael@0: window.open(url); michael@0: }, michael@0: michael@0: startSimulator: function(version) { michael@0: this._portBeforeSimulatorStarted = this.connection.port; michael@0: let port = ConnectionManager.getFreeTCPPort(); michael@0: let simulator = Simulator.getByVersion(version); michael@0: if (!simulator) { michael@0: this.connection.log("Error: can't find simulator: " + version); michael@0: return; michael@0: } michael@0: if (!simulator.launch) { michael@0: this.connection.log("Error: invalid simulator: " + version); michael@0: return; michael@0: } michael@0: this.connection.log("Found simulator: " + version); michael@0: this.connection.log("Starting simulator..."); michael@0: michael@0: this.simulator = simulator; michael@0: this.simulator.launch({ port: port }) michael@0: .then(() => { michael@0: this.connection.log("Simulator ready. Connecting."); michael@0: this.connection.port = port; michael@0: this.connection.host = "localhost"; michael@0: this.connection.once("connected", michael@0: this._onSimulatorConnected); michael@0: this.connection.once("disconnected", michael@0: this._onSimulatorDisconnected); michael@0: this.connection.keepConnecting = true; michael@0: this.connection.connect(); michael@0: }); michael@0: document.body.classList.remove("show-simulators"); michael@0: }, michael@0: michael@0: _onSimulatorConnected: function() { michael@0: this.connection.log("Connected to simulator."); michael@0: this.connection.keepConnecting = false; michael@0: michael@0: // This doesn't change the current (successful) connection, michael@0: // but makes sure that when the simulator is disconnected, the michael@0: // connection doesn't end up with a random port number (from michael@0: // getFreeTCPPort). michael@0: this.connection.port = this._portBeforeSimulatorStarted; michael@0: }, michael@0: michael@0: _onSimulatorDisconnected: function() { michael@0: this.connection.off("connected", this._onSimulatorConnected); michael@0: }, michael@0: michael@0: connectToAdbDevice: function(name) { michael@0: let device = Devices.getByName(name); michael@0: device.connect().then((port) => { michael@0: this.connection.host = "localhost"; michael@0: this.connection.port = port; michael@0: this.connect(); michael@0: }); michael@0: }, michael@0: michael@0: screenshot: function() { michael@0: this.connection.client.listTabs( michael@0: response => { michael@0: let front = getDeviceFront(this.connection.client, response); michael@0: front.screenshotToBlob().then(blob => { michael@0: let topWindow = Services.wm.getMostRecentWindow("navigator:browser"); michael@0: let gBrowser = topWindow.gBrowser; michael@0: let url = topWindow.URL.createObjectURL(blob); michael@0: let tab = gBrowser.selectedTab = gBrowser.addTab(url); michael@0: tab.addEventListener("TabClose", function onTabClose() { michael@0: tab.removeEventListener("TabClose", onTabClose, false); michael@0: topWindow.URL.revokeObjectURL(url); michael@0: }, false); michael@0: }).then(null, console.error); michael@0: } michael@0: ); michael@0: }, michael@0: }