1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 * @extends {WebInspector.VBox}
9 WebInspector.DevicesView = function()
11 WebInspector.VBox.call(this, true);
12 this.registerRequiredCSS("devices/devicesView.css");
14 this._tabbedPane = new WebInspector.TabbedPane();
15 var titleElement = createElementWithClass("div", "devices-view-title");
16 titleElement.createTextChild(WebInspector.UIString("Devices"));
18 this._tabbedPane.insertBeforeTabStrip(titleElement);
19 this._tabbedPane.setShrinkableTabs(false);
20 this._tabbedPane.setVerticalTabLayout(true);
22 this._discoveryView = new WebInspector.DevicesView.DiscoveryView();
23 this._tabbedPane.appendTab("discovery", WebInspector.UIString("Settings"), this._discoveryView);
25 /** @type {!Map<string, !WebInspector.DevicesView.DeviceView>} */
26 this._viewById = new Map();
27 /** @type {!Array<!Adb.Device>} */
30 this._tabbedPane.show(this.contentElement);
32 var discoveryFooter = this.contentElement.createChild("div", "devices-footer");
33 this._deviceCountSpan = discoveryFooter.createChild("span");
34 discoveryFooter.createChild("span").textContent = WebInspector.UIString(" Read ");
35 discoveryFooter.appendChild(WebInspector.linkifyURLAsNode("https://developers.google.com/chrome-developer-tools/docs/remote-debugging", WebInspector.UIString("remote debugging documentation"), undefined, true));
36 discoveryFooter.createChild("span").textContent = WebInspector.UIString(" for more information.");
39 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.DevicesUpdated, this._devicesUpdated, this);
40 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this);
43 WebInspector.DevicesView.prototype = {
45 * @param {!WebInspector.Event} event
47 _devicesUpdated: function(event)
49 this._devices = /** @type {!Array.<!Adb.Device>} */ (event.data).slice();
52 for (var device of this._devices)
55 for (var deviceId of this._viewById.keys()) {
56 if (!ids.has(deviceId)) {
57 this._tabbedPane.closeTab(deviceId);
58 this._viewById.remove(deviceId);
62 for (var device of this._devices) {
63 var view = this._viewById.get(device.id);
65 view = new WebInspector.DevicesView.DeviceView();
66 this._viewById.set(device.id, view);
67 this._tabbedPane.appendTab(device.id, device.adbModel, view);
69 this._tabbedPane.changeTabTitle(device.id, device.adbModel);
77 * @param {!WebInspector.Event} event
79 _devicesDiscoveryConfigChanged: function(event)
81 var discoverUsbDevices = /** @type {boolean} */ (event.data["discoverUsbDevices"]);
82 var portForwardingEnabled = /** @type {boolean} */ (event.data["portForwardingEnabled"]);
83 var portForwardingConfig = /** @type {!Adb.PortForwardingConfig} */ (event.data["portForwardingConfig"]);
84 this._discoveryView.discoveryConfigChanged(discoverUsbDevices, portForwardingEnabled, portForwardingConfig);
87 _updateFooter: function()
89 this._deviceCountSpan.textContent =
90 !this._devices.length ? WebInspector.UIString("No devices detected.") :
91 this._devices.length === 1 ? WebInspector.UIString("1 device detected.") : WebInspector.UIString("%d devices detected.", this._devices.length);
99 WebInspector.PanelWithSidebar.prototype.wasShown.call(this);
100 InspectorFrontendHost.setDevicesUpdatesEnabled(true);
108 WebInspector.PanelWithSidebar.prototype.wasShown.call(this);
109 InspectorFrontendHost.setDevicesUpdatesEnabled(false);
112 __proto__: WebInspector.VBox.prototype
116 * @return {!WebInspector.DevicesView}
118 WebInspector.DevicesView._instance = function()
120 if (!WebInspector.DevicesView._instanceObject)
121 WebInspector.DevicesView._instanceObject = new WebInspector.DevicesView();
122 return WebInspector.DevicesView._instanceObject;
128 * @extends {WebInspector.VBox}
130 WebInspector.DevicesView.DiscoveryView = function()
132 WebInspector.VBox.call(this);
133 this.setMinimumSize(100, 100);
134 this.element.classList.add("discovery-view");
136 this.contentElement.createChild("div", "hbox device-text-row").createChild("div", "view-title").textContent = WebInspector.UIString("Settings");
138 var discoverUsbDevicesCheckbox = createCheckboxLabel(WebInspector.UIString("Discover USB devices"));
139 discoverUsbDevicesCheckbox.classList.add("usb-checkbox");
140 this.element.appendChild(discoverUsbDevicesCheckbox);
141 this._discoverUsbDevicesCheckbox = discoverUsbDevicesCheckbox.checkboxElement;
142 this._discoverUsbDevicesCheckbox.addEventListener("click", this._updateDiscoveryConfig.bind(this), false);
144 var portForwardingEnabledCheckbox = createCheckboxLabel(WebInspector.UIString("Port forwarding"));
145 portForwardingEnabledCheckbox.classList.add("port-forwarding-checkbox");
146 this.element.appendChild(portForwardingEnabledCheckbox);
147 this._portForwardingEnabledCheckbox = portForwardingEnabledCheckbox.checkboxElement;
148 this._portForwardingEnabledCheckbox.addEventListener("click", this._updateDiscoveryConfig.bind(this), false);
150 this._portForwardingList = this.element.createChild("div", "port-forwarding-list");
152 var portForwardingFooter = this.element.createChild("div", "port-forwarding-footer");
153 portForwardingFooter.createChild("span").textContent = WebInspector.UIString("Define the listening port on your device that maps to a port accessible from your development machine. ");
154 portForwardingFooter.appendChild(WebInspector.linkifyURLAsNode("https://developer.chrome.com/devtools/docs/remote-debugging#reverse-port-forwarding", WebInspector.UIString("Learn more"), undefined, true));
157 WebInspector.DevicesView.DiscoveryView.prototype = {
159 * @param {boolean} discoverUsbDevices
160 * @param {boolean} portForwardingEnabled
161 * @param {!Adb.PortForwardingConfig} portForwardingConfig
163 discoveryConfigChanged: function(discoverUsbDevices, portForwardingEnabled, portForwardingConfig)
165 this._discoverUsbDevicesCheckbox.checked = discoverUsbDevices;
166 this._portForwardingEnabledCheckbox.checked = portForwardingEnabled;
169 _updateDiscoveryConfig: function()
171 InspectorFrontendHost.setDevicesDiscoveryConfig(this._discoverUsbDevicesCheckbox.checked, this._portForwardingEnabledCheckbox.checked, {"8080": "localhost:8080"});
174 __proto__: WebInspector.VBox.prototype
180 * @extends {WebInspector.VBox}
182 WebInspector.DevicesView.DeviceView = function()
184 WebInspector.VBox.call(this);
185 this.setMinimumSize(100, 100);
186 this.contentElement.classList.add("device-view");
188 var topRow = this.contentElement.createChild("div", "hbox device-text-row");
189 this._deviceTitle = topRow.createChild("div", "view-title");
190 this._deviceSerial = topRow.createChild("div", "device-serial");
192 this._deviceOffline = this.contentElement.createChild("div");
193 this._deviceOffline.textContent = WebInspector.UIString("Pending authentication: please accept debugging session on the device.");
195 this._noBrowsers = this.contentElement.createChild("div");
196 this._noBrowsers.textContent = WebInspector.UIString("No browsers detected.");
198 this._browsers = this.contentElement.createChild("div", "device-browser-list vbox");
200 /** @type {!Map<string, !WebInspector.DevicesView.BrowserSection>} */
201 this._browserById = new Map();
206 /** @typedef {!{browser: ?Adb.Browser, element: !Element, title: !Element, pages: !Element, pageSections: !Map<string, !WebInspector.DevicesView.PageSection>}} */
207 WebInspector.DevicesView.BrowserSection;
209 /** @typedef {!{page: ?Adb.Page, element: !Element, title: !Element, url: !Element, inspect: !Element}} */
210 WebInspector.DevicesView.PageSection;
212 WebInspector.DevicesView.DeviceView.prototype = {
214 * @param {!Adb.Device} device
216 update: function(device)
218 if (!this._device || this._device.adbModel !== device.adbModel)
219 this._deviceTitle.textContent = device.adbModel;
221 if (!this._device || this._device.adbSerial !== device.adbSerial)
222 this._deviceSerial.textContent = "#" + device.adbSerial;
224 this._deviceOffline.classList.toggle("hidden", device.adbConnected);
225 this._noBrowsers.classList.toggle("hidden", !device.adbConnected || device.browsers.length);
226 this._browsers.classList.toggle("hidden", !device.adbConnected || !device.browsers.length);
228 var browserIds = new Set();
229 for (var browser of device.browsers)
230 browserIds.add(browser.id);
232 for (var browserId of this._browserById.keys()) {
233 if (!browserIds.has(browserId)) {
234 this._browserById.get(browserId).element.remove();
235 this._browserById.remove(browserId);
239 for (var browser of device.browsers) {
240 var section = this._browserById.get(browser.id);
242 section = this._createBrowserSection();
243 this._browserById.set(browser.id, section);
244 this._browsers.appendChild(section.element);
246 this._updateBrowserSection(section, browser);
249 this._device = device;
253 * @return {!WebInspector.DevicesView.BrowserSection}
255 _createBrowserSection: function()
257 var element = createElementWithClass("div", "vbox flex-none");
258 var topRow = element.createChild("div", "");
259 var title = topRow.createChild("div", "device-browser-title");
260 var pages = element.createChild("div", "device-page-list vbox");
261 return {browser: null, element: element, title: title, pages: pages, pageSections: new Map()};
265 * @param {!WebInspector.DevicesView.BrowserSection} section
266 * @param {!Adb.Browser} browser
268 _updateBrowserSection: function(section, browser)
270 if (!section.browser || section.browser.adbBrowserName !== browser.adbBrowserName || section.browser.adbBrowserVersion !== browser.adbBrowserVersion) {
271 if (browser.adbBrowserVersion)
272 section.title.textContent = String.sprintf("%s (%s)", browser.adbBrowserName, browser.adbBrowserVersion);
274 section.title.textContent = browser.adbBrowserName;
277 var pageIds = new Set();
278 for (var page of browser.pages)
279 pageIds.add(page.id);
281 for (var pageId of section.pageSections.keys()) {
282 if (!pageIds.has(pageId)) {
283 section.pageSections.get(pageId).element.remove();
284 section.pageSections.remove(pageId);
288 for (var page of browser.pages) {
289 var pageSection = section.pageSections.get(page.id);
291 pageSection = this._createPageSection();
292 section.pageSections.set(page.id, pageSection);
293 section.pages.appendChild(pageSection.element);
295 this._updatePageSection(pageSection, page);
298 section.browser = browser;
302 * @return {!WebInspector.DevicesView.PageSection}
304 _createPageSection: function()
306 var element = createElementWithClass("div", "vbox");
307 var title = element.createChild("div", "device-page-title");
308 var url = element.createChild("div", "device-page-url");
309 var actions = element.createChild("div", "device-page-actions hbox");
310 var section = /** @type {!WebInspector.DevicesView.PageSection} */ ({page: null, element: element, title: title, url: url});
311 section.inspect = this._createAction(actions, WebInspector.UIString("inspect"), "inspect", section);
312 this._createAction(actions, WebInspector.UIString("reload"), "reload", section);
313 this._createAction(actions, WebInspector.UIString("activate"), "activate", section);
314 this._createAction(actions, WebInspector.UIString("close"), "close", section);
319 * @param {!Element} container
320 * @param {string} title
321 * @param {string} action
322 * @param {!WebInspector.DevicesView.PageSection} section
325 _createAction: function(container, title, action, section)
327 var element = container.createChild("div", "link");
328 element.textContent = title;
329 element.addEventListener("click", onClick, false);
335 InspectorFrontendHost.performActionOnRemotePage(section.page.id, action);
340 * @param {!WebInspector.DevicesView.PageSection} section
341 * @param {!Adb.Page} page
343 _updatePageSection: function(section, page)
345 if (!section.page || section.page.name !== page.name)
346 section.title.textContent = page.name;
347 if (!section.page || section.page.url !== page.url) {
348 section.url.textContent = "";
349 section.url.appendChild(WebInspector.linkifyURLAsNode(page.url, undefined, undefined, true));
351 section.inspect.disabled = page.adbAttachedForeign;
356 __proto__: WebInspector.VBox.prototype