2 * Copyright 2014 The Chromium Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
9 * @extends {WebInspector.VBox}
11 WebInspector.DevicesView = function()
13 WebInspector.VBox.call(this);
14 this.registerRequiredCSS("devicesView.css");
15 this.element.classList.add("devices");
16 this._devicesHelp = this.element.createChild("div");
17 this._devicesHelp.innerHTML = WebInspector.UIString("No devices detected. \
18 Please read the <a href=\"https://developers.google.com/chrome-developer\
19 -tools/docs/remote-debugging\"> remote debugging documentation</a> to \
20 verify your device is enabled for USB debugging.");
21 this.element.createChild("div", "devices-info").innerHTML = WebInspector.UIString("Click \"Try here\" button, to open the current page in the selected remote browser.");
22 this._devicesList = this.element.createChild("div");
23 this._devicesList.cellSpacing = 0;
24 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.DevicesUpdated, this._onDevicesUpdated, this);
27 WebInspector.DevicesView.MinVersionNewTab = 29;
33 * @typedef {{id: string, adbBrowserChromeVersion: string, compatibleVersion: boolean, adbBrowserName: string, source: string, adbBrowserVersion: string}}
38 * @typedef {{id: string, adbModel: string, adbSerial: string, browsers: !Array.<!Adb.Browser>, adbPortStatus: !Array.<number>, adbConnected: boolean}}
42 WebInspector.DevicesView.Events = {
43 DevicesChanged: "DevicesChanged"
46 WebInspector.DevicesView.prototype = {
47 _onDevicesUpdated: function(event)
49 this._updateDeviceList(/** @type {!Array.<!Adb.Device>} */(event.data));
53 * @param {!Array.<!Adb.Device>} devices
55 _updateDeviceList: function(devices)
61 function sanitizeForId(id)
63 return id.replace(/[.:/\/ ]/g, "-");
67 * @param {!Element} element
68 * @param {!Object} data
71 function alreadyDisplayed(element, data)
73 var json = JSON.stringify(data);
74 if (element.__cachedJSON === json)
76 element.__cachedJSON = json;
81 * @param {!Element} parent
82 * @param {!Element} child
84 function insertChildSortedById(parent, child)
86 for (var sibling = parent.firstElementChild; sibling; sibling = sibling.nextElementSibling) {
87 if (sibling.id && sibling.id > child.id) {
88 parent.insertBefore(child, sibling);
92 parent.appendChild(child);
97 * @param {!Array.<string>} validIds
98 * @param {!Element} section
100 function removeObsolete(validIds, section)
102 if (validIds.indexOf(section.id) < 0)
106 if (alreadyDisplayed(this._devicesList, devices))
109 var newDeviceIds = devices.map(function(device) { return device.id; });
111 Array.prototype.forEach.call(
112 this._devicesList.querySelectorAll(".device"),
113 removeObsolete.bind(null, newDeviceIds));
115 this._devicesHelp.hidden = !!devices.length;
117 for (var d = 0; d < devices.length; d++) {
118 // FIXME: Try to use shadow DOM.
119 var device = devices[d];
121 var deviceSection = this._devicesList.querySelector("#" + sanitizeForId(device.id));
122 if (!deviceSection) {
123 deviceSection = this._devicesList.createChild("div", "device");
124 deviceSection.id = sanitizeForId(device.id);
125 var deviceHeader = deviceSection.createChild("div", "device-header");
126 deviceHeader.createChild("div", "device-name");
127 var deviceSerial = deviceHeader.createChild("div", "device-serial");
128 deviceSerial.textContent = "#" + device.adbSerial.toUpperCase();
129 deviceSection.createChild("div", "device-auth");
132 if (alreadyDisplayed(deviceSection, device))
135 deviceSection.querySelector(".device-name").textContent = device.adbModel;
136 deviceSection.querySelector(".device-auth").textContent =
137 device.adbConnected ? ""
138 : WebInspector.UIString("Pending authentication: please accept debugging session on the device.");
140 var browsers = device.browsers.filter(function(browser) { return browser.adbBrowserChromeVersion; });
142 var newBrowserIds = browsers.map(function(browser) { return browser.id });
143 Array.prototype.forEach.call(deviceSection.querySelectorAll(".browser"), removeObsolete.bind(null, newBrowserIds));
145 for (var b = 0; b < browsers.length; b++) {
146 var browser = browsers[b];
147 var incompatibleVersion = browser.hasOwnProperty("compatibleVersion") && !browser.compatibleVersion;
148 var browserSection = deviceSection.querySelector("#" + sanitizeForId(browser.id));
149 if (!browserSection) {
150 browserSection = document.createElementWithClass("div", "browser");
151 browserSection.id = sanitizeForId(browser.id);
152 insertChildSortedById(deviceSection, browserSection);
154 var browserName = browserSection.createChild("div", "browser-name");
155 browserName.textContent = browser.adbBrowserName;
156 if (browser.adbBrowserVersion)
157 browserName.textContent += " (" + browser.adbBrowserVersion + ")";
159 if (incompatibleVersion || browser.adbBrowserChromeVersion < WebInspector.DevicesView.MinVersionNewTab) {
160 var warningSection = browserSection.createChild("div", "warning");
161 warningSection.textContent = incompatibleVersion
162 ? WebInspector.UIString("You may need a newer version of desktop Chrome. Please try Chrome %s or later.", browser.adbBrowserVersion)
163 : WebInspector.UIString("You may need a newer version of Chrome on your device. Please try Chrome %s or later.", WebInspector.DevicesView.MinVersionNewTab);
165 var newPageButton = browserSection.createChild("button", "text-button");
166 newPageButton.textContent = WebInspector.UIString("Try here");
167 newPageButton.title = WebInspector.UIString("Inspect current page in this browser.");
168 newPageButton.addEventListener("click", InspectorFrontendHost.openUrlOnRemoteDeviceAndInspect.bind(null, browser.id, WebInspector.targetManager.inspectedPageURL()), true);
178 InspectorFrontendHost.setDevicesUpdatesEnabled(false);
183 InspectorFrontendHost.setDevicesUpdatesEnabled(true);
186 __proto__: WebInspector.VBox.prototype