OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 /** |
| 5 * @unrestricted |
| 6 */ |
| 7 WebInspector.DevicesView = class extends WebInspector.VBox { |
| 8 constructor() { |
| 9 super(true); |
| 10 this.registerRequiredCSS('devices/devicesView.css'); |
| 11 this.contentElement.classList.add('devices-view'); |
4 | 12 |
5 /** | 13 var hbox = this.contentElement.createChild('div', 'hbox devices-container'); |
6 * @constructor | 14 var sidebar = hbox.createChild('div', 'devices-sidebar'); |
7 * @extends {WebInspector.VBox} | 15 sidebar.createChild('div', 'devices-view-title').createTextChild(WebInspecto
r.UIString('Devices')); |
8 */ | 16 this._sidebarList = sidebar.createChild('div', 'devices-sidebar-list'); |
9 WebInspector.DevicesView = function() | |
10 { | |
11 WebInspector.VBox.call(this, true); | |
12 this.registerRequiredCSS("devices/devicesView.css"); | |
13 this.contentElement.classList.add("devices-view"); | |
14 | |
15 var hbox = this.contentElement.createChild("div", "hbox devices-container"); | |
16 var sidebar = hbox.createChild("div", "devices-sidebar"); | |
17 sidebar.createChild("div", "devices-view-title").createTextChild(WebInspecto
r.UIString("Devices")); | |
18 this._sidebarList = sidebar.createChild("div", "devices-sidebar-list"); | |
19 | 17 |
20 this._discoveryView = new WebInspector.DevicesView.DiscoveryView(); | 18 this._discoveryView = new WebInspector.DevicesView.DiscoveryView(); |
21 this._sidebarListSpacer = this._sidebarList.createChild("div", "devices-side
bar-spacer"); | 19 this._sidebarListSpacer = this._sidebarList.createChild('div', 'devices-side
bar-spacer'); |
22 this._discoveryListItem = this._sidebarList.createChild("div", "devices-side
bar-item"); | 20 this._discoveryListItem = this._sidebarList.createChild('div', 'devices-side
bar-item'); |
23 this._discoveryListItem.textContent = WebInspector.UIString("Settings"); | 21 this._discoveryListItem.textContent = WebInspector.UIString('Settings'); |
24 this._discoveryListItem.addEventListener("click", this._selectSidebarListIte
m.bind(this, this._discoveryListItem, this._discoveryView)); | 22 this._discoveryListItem.addEventListener( |
| 23 'click', this._selectSidebarListItem.bind(this, this._discoveryListItem,
this._discoveryView)); |
25 | 24 |
26 /** @type {!Map<string, !WebInspector.DevicesView.DeviceView>} */ | 25 /** @type {!Map<string, !WebInspector.DevicesView.DeviceView>} */ |
27 this._viewById = new Map(); | 26 this._viewById = new Map(); |
28 /** @type {!Array<!Adb.Device>} */ | 27 /** @type {!Array<!Adb.Device>} */ |
29 this._devices = []; | 28 this._devices = []; |
30 /** @type {!Map<string, !Element>} */ | 29 /** @type {!Map<string, !Element>} */ |
31 this._listItemById = new Map(); | 30 this._listItemById = new Map(); |
32 | 31 |
33 this._viewContainer = hbox.createChild("div", "flex-auto vbox"); | 32 this._viewContainer = hbox.createChild('div', 'flex-auto vbox'); |
34 | 33 |
35 var discoveryFooter = this.contentElement.createChild("div", "devices-footer
"); | 34 var discoveryFooter = this.contentElement.createChild('div', 'devices-footer
'); |
36 this._deviceCountSpan = discoveryFooter.createChild("span"); | 35 this._deviceCountSpan = discoveryFooter.createChild('span'); |
37 discoveryFooter.createChild("span").textContent = WebInspector.UIString(" Re
ad "); | 36 discoveryFooter.createChild('span').textContent = WebInspector.UIString(' Re
ad '); |
38 discoveryFooter.appendChild(WebInspector.linkifyURLAsNode("https://developer
s.google.com/chrome-developer-tools/docs/remote-debugging", WebInspector.UIStrin
g("remote debugging documentation"), undefined, true)); | 37 discoveryFooter.appendChild(WebInspector.linkifyURLAsNode( |
39 discoveryFooter.createChild("span").textContent = WebInspector.UIString(" fo
r more information."); | 38 'https://developers.google.com/chrome-developer-tools/docs/remote-debugg
ing', |
| 39 WebInspector.UIString('remote debugging documentation'), undefined, true
)); |
| 40 discoveryFooter.createChild('span').textContent = WebInspector.UIString(' fo
r more information.'); |
40 this._updateFooter(); | 41 this._updateFooter(); |
41 this._selectSidebarListItem(this._discoveryListItem, this._discoveryView); | 42 this._selectSidebarListItem(this._discoveryListItem, this._discoveryView); |
42 | 43 |
43 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Event
s.DevicesUpdated, this._devicesUpdated, this); | 44 InspectorFrontendHost.events.addEventListener( |
44 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Event
s.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this); | 45 InspectorFrontendHostAPI.Events.DevicesUpdated, this._devicesUpdated, th
is); |
45 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Event
s.DevicesPortForwardingStatusChanged, this._devicesPortForwardingStatusChanged,
this); | 46 InspectorFrontendHost.events.addEventListener( |
| 47 InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._dev
icesDiscoveryConfigChanged, this); |
| 48 InspectorFrontendHost.events.addEventListener( |
| 49 InspectorFrontendHostAPI.Events.DevicesPortForwardingStatusChanged, this
._devicesPortForwardingStatusChanged, |
| 50 this); |
46 | 51 |
47 this.contentElement.tabIndex = 0; | 52 this.contentElement.tabIndex = 0; |
48 this.setDefaultFocusedElement(this.contentElement); | 53 this.setDefaultFocusedElement(this.contentElement); |
| 54 } |
| 55 |
| 56 /** |
| 57 * @return {!WebInspector.DevicesView} |
| 58 */ |
| 59 static _instance() { |
| 60 if (!WebInspector.DevicesView._instanceObject) |
| 61 WebInspector.DevicesView._instanceObject = new WebInspector.DevicesView(); |
| 62 return WebInspector.DevicesView._instanceObject; |
| 63 } |
| 64 |
| 65 /** |
| 66 * @param {!Element} listItem |
| 67 * @param {!WebInspector.Widget} view |
| 68 */ |
| 69 _selectSidebarListItem(listItem, view) { |
| 70 if (this._selectedListItem === listItem) |
| 71 return; |
| 72 |
| 73 if (this._selectedListItem) { |
| 74 this._selectedListItem.classList.remove('selected'); |
| 75 this._visibleView.detach(); |
| 76 } |
| 77 |
| 78 this._visibleView = view; |
| 79 this._selectedListItem = listItem; |
| 80 this._visibleView.show(this._viewContainer); |
| 81 this._selectedListItem.classList.add('selected'); |
| 82 } |
| 83 |
| 84 /** |
| 85 * @param {!WebInspector.Event} event |
| 86 */ |
| 87 _devicesUpdated(event) { |
| 88 this._devices = |
| 89 /** @type {!Array.<!Adb.Device>} */ (event.data).slice().filter(d => d.a
dbSerial.toUpperCase() !== 'WEBRTC'); |
| 90 for (var device of this._devices) { |
| 91 if (!device.adbConnected) |
| 92 device.adbModel = WebInspector.UIString('Unknown'); |
| 93 } |
| 94 |
| 95 var ids = new Set(); |
| 96 for (var device of this._devices) |
| 97 ids.add(device.id); |
| 98 |
| 99 var selectedRemoved = false; |
| 100 for (var deviceId of this._viewById.keys()) { |
| 101 if (!ids.has(deviceId)) { |
| 102 var listItem = /** @type {!Element} */ (this._listItemById.get(deviceId)
); |
| 103 this._listItemById.remove(deviceId); |
| 104 this._viewById.remove(deviceId); |
| 105 listItem.remove(); |
| 106 if (listItem === this._selectedListItem) |
| 107 selectedRemoved = true; |
| 108 } |
| 109 } |
| 110 |
| 111 for (var device of this._devices) { |
| 112 var view = this._viewById.get(device.id); |
| 113 var listItem = this._listItemById.get(device.id); |
| 114 |
| 115 if (!view) { |
| 116 view = new WebInspector.DevicesView.DeviceView(); |
| 117 this._viewById.set(device.id, view); |
| 118 listItem = this._createSidebarListItem(view); |
| 119 this._listItemById.set(device.id, listItem); |
| 120 this._sidebarList.insertBefore(listItem, this._sidebarListSpacer); |
| 121 } |
| 122 |
| 123 listItem._title.textContent = device.adbModel; |
| 124 listItem._status.textContent = |
| 125 device.adbConnected ? WebInspector.UIString('Connected') : WebInspecto
r.UIString('Pending Authorization'); |
| 126 listItem.classList.toggle('device-connected', device.adbConnected); |
| 127 view.update(device); |
| 128 } |
| 129 |
| 130 if (selectedRemoved) |
| 131 this._selectSidebarListItem(this._discoveryListItem, this._discoveryView); |
| 132 |
| 133 this._updateFooter(); |
| 134 } |
| 135 |
| 136 /** |
| 137 * @param {!WebInspector.Widget} view |
| 138 * @return {!Element} |
| 139 */ |
| 140 _createSidebarListItem(view) { |
| 141 var listItem = createElementWithClass('div', 'devices-sidebar-item'); |
| 142 listItem.addEventListener('click', this._selectSidebarListItem.bind(this, li
stItem, view)); |
| 143 listItem._title = listItem.createChild('div', 'devices-sidebar-item-title'); |
| 144 listItem._status = listItem.createChild('div', 'devices-sidebar-item-status'
); |
| 145 return listItem; |
| 146 } |
| 147 |
| 148 /** |
| 149 * @param {!WebInspector.Event} event |
| 150 */ |
| 151 _devicesDiscoveryConfigChanged(event) { |
| 152 var discoverUsbDevices = /** @type {boolean} */ (event.data['discoverUsbDevi
ces']); |
| 153 var portForwardingEnabled = /** @type {boolean} */ (event.data['portForwardi
ngEnabled']); |
| 154 var portForwardingConfig = /** @type {!Adb.PortForwardingConfig} */ (event.d
ata['portForwardingConfig']); |
| 155 this._discoveryView.discoveryConfigChanged(discoverUsbDevices, portForwardin
gEnabled, portForwardingConfig); |
| 156 } |
| 157 |
| 158 /** |
| 159 * @param {!WebInspector.Event} event |
| 160 */ |
| 161 _devicesPortForwardingStatusChanged(event) { |
| 162 var status = /** @type {!Adb.PortForwardingStatus} */ (event.data); |
| 163 for (var deviceId in status) { |
| 164 var view = this._viewById.get(deviceId); |
| 165 if (view) |
| 166 view.portForwardingStatusChanged(status[deviceId]); |
| 167 } |
| 168 for (var deviceId of this._viewById.keys()) { |
| 169 var view = this._viewById.get(deviceId); |
| 170 if (view && !(deviceId in status)) |
| 171 view.portForwardingStatusChanged({ports: {}, browserId: ''}); |
| 172 } |
| 173 } |
| 174 |
| 175 _updateFooter() { |
| 176 this._deviceCountSpan.textContent = !this._devices.length ? |
| 177 WebInspector.UIString('No devices detected.') : |
| 178 this._devices.length === 1 ? WebInspector.UIString('1 device detected.')
: |
| 179 WebInspector.UIString('%d devices detected.
', this._devices.length); |
| 180 } |
| 181 |
| 182 /** |
| 183 * @override |
| 184 */ |
| 185 wasShown() { |
| 186 super.wasShown(); |
| 187 InspectorFrontendHost.setDevicesUpdatesEnabled(true); |
| 188 } |
| 189 |
| 190 /** |
| 191 * @override |
| 192 */ |
| 193 willHide() { |
| 194 super.wasShown(); |
| 195 InspectorFrontendHost.setDevicesUpdatesEnabled(false); |
| 196 } |
49 }; | 197 }; |
50 | 198 |
51 WebInspector.DevicesView.prototype = { | |
52 /** | |
53 * @param {!Element} listItem | |
54 * @param {!WebInspector.Widget} view | |
55 */ | |
56 _selectSidebarListItem: function(listItem, view) | |
57 { | |
58 if (this._selectedListItem === listItem) | |
59 return; | |
60 | |
61 if (this._selectedListItem) { | |
62 this._selectedListItem.classList.remove("selected"); | |
63 this._visibleView.detach(); | |
64 } | |
65 | |
66 this._visibleView = view; | |
67 this._selectedListItem = listItem; | |
68 this._visibleView.show(this._viewContainer); | |
69 this._selectedListItem.classList.add("selected"); | |
70 }, | |
71 | |
72 /** | |
73 * @param {!WebInspector.Event} event | |
74 */ | |
75 _devicesUpdated: function(event) | |
76 { | |
77 this._devices = /** @type {!Array.<!Adb.Device>} */ (event.data).slice()
.filter(d => d.adbSerial.toUpperCase() !== "WEBRTC"); | |
78 for (var device of this._devices) { | |
79 if (!device.adbConnected) | |
80 device.adbModel = WebInspector.UIString("Unknown"); | |
81 } | |
82 | |
83 var ids = new Set(); | |
84 for (var device of this._devices) | |
85 ids.add(device.id); | |
86 | |
87 var selectedRemoved = false; | |
88 for (var deviceId of this._viewById.keys()) { | |
89 if (!ids.has(deviceId)) { | |
90 var listItem = /** @type {!Element} */ (this._listItemById.get(d
eviceId)); | |
91 this._listItemById.remove(deviceId); | |
92 this._viewById.remove(deviceId); | |
93 listItem.remove(); | |
94 if (listItem === this._selectedListItem) | |
95 selectedRemoved = true; | |
96 } | |
97 } | |
98 | |
99 for (var device of this._devices) { | |
100 var view = this._viewById.get(device.id); | |
101 var listItem = this._listItemById.get(device.id); | |
102 | |
103 if (!view) { | |
104 view = new WebInspector.DevicesView.DeviceView(); | |
105 this._viewById.set(device.id, view); | |
106 listItem = this._createSidebarListItem(view); | |
107 this._listItemById.set(device.id, listItem); | |
108 this._sidebarList.insertBefore(listItem, this._sidebarListSpacer
); | |
109 } | |
110 | |
111 listItem._title.textContent = device.adbModel; | |
112 listItem._status.textContent = device.adbConnected ? WebInspector.UI
String("Connected") : WebInspector.UIString("Pending Authorization"); | |
113 listItem.classList.toggle("device-connected", device.adbConnected); | |
114 view.update(device); | |
115 } | |
116 | |
117 if (selectedRemoved) | |
118 this._selectSidebarListItem(this._discoveryListItem, this._discovery
View); | |
119 | |
120 this._updateFooter(); | |
121 }, | |
122 | |
123 /** | |
124 * @param {!WebInspector.Widget} view | |
125 * @return {!Element} | |
126 */ | |
127 _createSidebarListItem: function(view) | |
128 { | |
129 var listItem = createElementWithClass("div", "devices-sidebar-item"); | |
130 listItem.addEventListener("click", this._selectSidebarListItem.bind(this
, listItem, view)); | |
131 listItem._title = listItem.createChild("div", "devices-sidebar-item-titl
e"); | |
132 listItem._status = listItem.createChild("div", "devices-sidebar-item-sta
tus"); | |
133 return listItem; | |
134 }, | |
135 | |
136 /** | |
137 * @param {!WebInspector.Event} event | |
138 */ | |
139 _devicesDiscoveryConfigChanged: function(event) | |
140 { | |
141 var discoverUsbDevices = /** @type {boolean} */ (event.data["discoverUsb
Devices"]); | |
142 var portForwardingEnabled = /** @type {boolean} */ (event.data["portForw
ardingEnabled"]); | |
143 var portForwardingConfig = /** @type {!Adb.PortForwardingConfig} */ (eve
nt.data["portForwardingConfig"]); | |
144 this._discoveryView.discoveryConfigChanged(discoverUsbDevices, portForwa
rdingEnabled, portForwardingConfig); | |
145 }, | |
146 | |
147 /** | |
148 * @param {!WebInspector.Event} event | |
149 */ | |
150 _devicesPortForwardingStatusChanged: function(event) | |
151 { | |
152 var status = /** @type {!Adb.PortForwardingStatus} */ (event.data); | |
153 for (var deviceId in status) { | |
154 var view = this._viewById.get(deviceId); | |
155 if (view) | |
156 view.portForwardingStatusChanged(status[deviceId]); | |
157 } | |
158 for (var deviceId of this._viewById.keys()) { | |
159 var view = this._viewById.get(deviceId); | |
160 if (view && !(deviceId in status)) | |
161 view.portForwardingStatusChanged({ports: {}, browserId: ""}); | |
162 } | |
163 }, | |
164 | |
165 _updateFooter: function() | |
166 { | |
167 this._deviceCountSpan.textContent = | |
168 !this._devices.length ? WebInspector.UIString("No devices detected."
) : | |
169 this._devices.length === 1 ? WebInspector.UIString("1 device det
ected.") : WebInspector.UIString("%d devices detected.", this._devices.length); | |
170 }, | |
171 | |
172 /** | |
173 * @override | |
174 */ | |
175 wasShown: function() | |
176 { | |
177 WebInspector.PanelWithSidebar.prototype.wasShown.call(this); | |
178 InspectorFrontendHost.setDevicesUpdatesEnabled(true); | |
179 }, | |
180 | |
181 /** | |
182 * @override | |
183 */ | |
184 willHide: function() | |
185 { | |
186 WebInspector.PanelWithSidebar.prototype.wasShown.call(this); | |
187 InspectorFrontendHost.setDevicesUpdatesEnabled(false); | |
188 }, | |
189 | |
190 __proto__: WebInspector.VBox.prototype | |
191 }; | |
192 | 199 |
193 /** | 200 /** |
194 * @return {!WebInspector.DevicesView} | 201 * @implements {WebInspector.ListWidget.Delegate} |
| 202 * @unrestricted |
195 */ | 203 */ |
196 WebInspector.DevicesView._instance = function() | 204 WebInspector.DevicesView.DiscoveryView = class extends WebInspector.VBox { |
197 { | 205 constructor() { |
198 if (!WebInspector.DevicesView._instanceObject) | 206 super(); |
199 WebInspector.DevicesView._instanceObject = new WebInspector.DevicesView(
); | |
200 return WebInspector.DevicesView._instanceObject; | |
201 }; | |
202 | |
203 | |
204 /** | |
205 * @constructor | |
206 * @extends {WebInspector.VBox} | |
207 * @implements {WebInspector.ListWidget.Delegate} | |
208 */ | |
209 WebInspector.DevicesView.DiscoveryView = function() | |
210 { | |
211 WebInspector.VBox.call(this); | |
212 this.setMinimumSize(100, 100); | 207 this.setMinimumSize(100, 100); |
213 this.element.classList.add("discovery-view"); | 208 this.element.classList.add('discovery-view'); |
214 | 209 |
215 this.contentElement.createChild("div", "hbox device-text-row").createChild("
div", "view-title").textContent = WebInspector.UIString("Settings"); | 210 this.contentElement.createChild('div', 'hbox device-text-row').createChild('
div', 'view-title').textContent = |
216 | 211 WebInspector.UIString('Settings'); |
217 var discoverUsbDevicesCheckbox = createCheckboxLabel(WebInspector.UIString("
Discover USB devices")); | 212 |
218 discoverUsbDevicesCheckbox.classList.add("usb-checkbox"); | 213 var discoverUsbDevicesCheckbox = createCheckboxLabel(WebInspector.UIString('
Discover USB devices')); |
| 214 discoverUsbDevicesCheckbox.classList.add('usb-checkbox'); |
219 this.element.appendChild(discoverUsbDevicesCheckbox); | 215 this.element.appendChild(discoverUsbDevicesCheckbox); |
220 this._discoverUsbDevicesCheckbox = discoverUsbDevicesCheckbox.checkboxElemen
t; | 216 this._discoverUsbDevicesCheckbox = discoverUsbDevicesCheckbox.checkboxElemen
t; |
221 this._discoverUsbDevicesCheckbox.addEventListener("click", this._updateDisco
veryConfig.bind(this), false); | 217 this._discoverUsbDevicesCheckbox.addEventListener('click', this._updateDisco
veryConfig.bind(this), false); |
222 | 218 |
223 var help = this.element.createChild("div", "discovery-help"); | 219 var help = this.element.createChild('div', 'discovery-help'); |
224 help.createChild("span").textContent = WebInspector.UIString("Need help? Rea
d Chrome "); | 220 help.createChild('span').textContent = WebInspector.UIString('Need help? Rea
d Chrome '); |
225 help.appendChild(WebInspector.linkifyURLAsNode("https://developers.google.co
m/chrome-developer-tools/docs/remote-debugging", WebInspector.UIString("remote d
ebugging documentation."), undefined, true)); | 221 help.appendChild(WebInspector.linkifyURLAsNode( |
226 | 222 'https://developers.google.com/chrome-developer-tools/docs/remote-debugg
ing', |
227 var portForwardingHeader = this.element.createChild("div", "port-forwarding-
header"); | 223 WebInspector.UIString('remote debugging documentation.'), undefined, tru
e)); |
228 var portForwardingEnabledCheckbox = createCheckboxLabel(WebInspector.UIStrin
g("Port forwarding")); | 224 |
229 portForwardingEnabledCheckbox.classList.add("port-forwarding-checkbox"); | 225 var portForwardingHeader = this.element.createChild('div', 'port-forwarding-
header'); |
| 226 var portForwardingEnabledCheckbox = createCheckboxLabel(WebInspector.UIStrin
g('Port forwarding')); |
| 227 portForwardingEnabledCheckbox.classList.add('port-forwarding-checkbox'); |
230 portForwardingHeader.appendChild(portForwardingEnabledCheckbox); | 228 portForwardingHeader.appendChild(portForwardingEnabledCheckbox); |
231 this._portForwardingEnabledCheckbox = portForwardingEnabledCheckbox.checkbox
Element; | 229 this._portForwardingEnabledCheckbox = portForwardingEnabledCheckbox.checkbox
Element; |
232 this._portForwardingEnabledCheckbox.addEventListener("click", this._updateDi
scoveryConfig.bind(this), false); | 230 this._portForwardingEnabledCheckbox.addEventListener('click', this._updateDi
scoveryConfig.bind(this), false); |
233 | 231 |
234 var portForwardingFooter = this.element.createChild("div", "port-forwarding-
footer"); | 232 var portForwardingFooter = this.element.createChild('div', 'port-forwarding-
footer'); |
235 portForwardingFooter.createChild("span").textContent = WebInspector.UIString
("Define the listening port on your device that maps to a port accessible from y
our development machine. "); | 233 portForwardingFooter.createChild('span').textContent = WebInspector.UIString
( |
236 portForwardingFooter.appendChild(WebInspector.linkifyURLAsNode("https://deve
loper.chrome.com/devtools/docs/remote-debugging#port-forwarding", WebInspector.U
IString("Learn more"), undefined, true)); | 234 'Define the listening port on your device that maps to a port accessible
from your development machine. '); |
| 235 portForwardingFooter.appendChild(WebInspector.linkifyURLAsNode( |
| 236 'https://developer.chrome.com/devtools/docs/remote-debugging#port-forwar
ding', |
| 237 WebInspector.UIString('Learn more'), undefined, true)); |
237 | 238 |
238 this._list = new WebInspector.ListWidget(this); | 239 this._list = new WebInspector.ListWidget(this); |
239 this._list.registerRequiredCSS("devices/devicesView.css"); | 240 this._list.registerRequiredCSS('devices/devicesView.css'); |
240 this._list.element.classList.add("port-forwarding-list"); | 241 this._list.element.classList.add('port-forwarding-list'); |
241 var placeholder = createElementWithClass("div", "port-forwarding-list-empty"
); | 242 var placeholder = createElementWithClass('div', 'port-forwarding-list-empty'
); |
242 placeholder.textContent = WebInspector.UIString("No rules"); | 243 placeholder.textContent = WebInspector.UIString('No rules'); |
243 this._list.setEmptyPlaceholder(placeholder); | 244 this._list.setEmptyPlaceholder(placeholder); |
244 this._list.show(this.element); | 245 this._list.show(this.element); |
245 | 246 |
246 this.element.appendChild(createTextButton(WebInspector.UIString("Add rule"),
this._addRuleButtonClicked.bind(this), "add-rule-button")); | 247 this.element.appendChild( |
| 248 createTextButton(WebInspector.UIString('Add rule'), this._addRuleButtonC
licked.bind(this), 'add-rule-button')); |
247 | 249 |
248 /** @type {!Array<!Adb.PortForwardingRule>} */ | 250 /** @type {!Array<!Adb.PortForwardingRule>} */ |
249 this._portForwardingConfig = []; | 251 this._portForwardingConfig = []; |
250 }; | 252 } |
251 | 253 |
252 WebInspector.DevicesView.DiscoveryView.prototype = { | 254 _addRuleButtonClicked() { |
253 _addRuleButtonClicked: function() | 255 this._list.addNewItem(this._portForwardingConfig.length, {port: '', address:
''}); |
254 { | 256 } |
255 this._list.addNewItem(this._portForwardingConfig.length, {port: "", addr
ess: ""}); | 257 |
256 }, | 258 /** |
| 259 * @param {boolean} discoverUsbDevices |
| 260 * @param {boolean} portForwardingEnabled |
| 261 * @param {!Adb.PortForwardingConfig} portForwardingConfig |
| 262 */ |
| 263 discoveryConfigChanged(discoverUsbDevices, portForwardingEnabled, portForwardi
ngConfig) { |
| 264 this._discoverUsbDevicesCheckbox.checked = discoverUsbDevices; |
| 265 this._portForwardingEnabledCheckbox.checked = portForwardingEnabled; |
| 266 |
| 267 this._portForwardingConfig = []; |
| 268 this._list.clear(); |
| 269 for (var key of Object.keys(portForwardingConfig)) { |
| 270 var rule = /** @type {!Adb.PortForwardingRule} */ ({port: key, address: po
rtForwardingConfig[key]}); |
| 271 this._portForwardingConfig.push(rule); |
| 272 this._list.appendItem(rule, true); |
| 273 } |
| 274 } |
| 275 |
| 276 /** |
| 277 * @override |
| 278 * @param {*} item |
| 279 * @param {boolean} editable |
| 280 * @return {!Element} |
| 281 */ |
| 282 renderItem(item, editable) { |
| 283 var rule = /** @type {!Adb.PortForwardingRule} */ (item); |
| 284 var element = createElementWithClass('div', 'port-forwarding-list-item'); |
| 285 var port = element.createChild('div', 'port-forwarding-value port-forwarding
-port'); |
| 286 port.createChild('span', 'port-localhost').textContent = WebInspector.UIStri
ng('localhost:'); |
| 287 port.createTextChild(rule.port); |
| 288 element.createChild('div', 'port-forwarding-separator'); |
| 289 element.createChild('div', 'port-forwarding-value').textContent = rule.addre
ss; |
| 290 return element; |
| 291 } |
| 292 |
| 293 /** |
| 294 * @override |
| 295 * @param {*} item |
| 296 * @param {number} index |
| 297 */ |
| 298 removeItemRequested(item, index) { |
| 299 this._portForwardingConfig.splice(index, 1); |
| 300 this._list.removeItem(index); |
| 301 this._updateDiscoveryConfig(); |
| 302 } |
| 303 |
| 304 /** |
| 305 * @override |
| 306 * @param {*} item |
| 307 * @param {!WebInspector.ListWidget.Editor} editor |
| 308 * @param {boolean} isNew |
| 309 */ |
| 310 commitEdit(item, editor, isNew) { |
| 311 var rule = /** @type {!Adb.PortForwardingRule} */ (item); |
| 312 rule.port = editor.control('port').value.trim(); |
| 313 rule.address = editor.control('address').value.trim(); |
| 314 if (isNew) |
| 315 this._portForwardingConfig.push(rule); |
| 316 this._updateDiscoveryConfig(); |
| 317 } |
| 318 |
| 319 /** |
| 320 * @override |
| 321 * @param {*} item |
| 322 * @return {!WebInspector.ListWidget.Editor} |
| 323 */ |
| 324 beginEdit(item) { |
| 325 var rule = /** @type {!Adb.PortForwardingRule} */ (item); |
| 326 var editor = this._createEditor(); |
| 327 editor.control('port').value = rule.port; |
| 328 editor.control('address').value = rule.address; |
| 329 return editor; |
| 330 } |
| 331 |
| 332 /** |
| 333 * @return {!WebInspector.ListWidget.Editor} |
| 334 */ |
| 335 _createEditor() { |
| 336 if (this._editor) |
| 337 return this._editor; |
| 338 |
| 339 var editor = new WebInspector.ListWidget.Editor(); |
| 340 this._editor = editor; |
| 341 var content = editor.contentElement(); |
| 342 var fields = content.createChild('div', 'port-forwarding-edit-row'); |
| 343 fields.createChild('div', 'port-forwarding-value port-forwarding-port') |
| 344 .appendChild(editor.createInput('port', 'text', 'Device port (3333)', po
rtValidator.bind(this))); |
| 345 fields.createChild('div', 'port-forwarding-separator port-forwarding-separat
or-invisible'); |
| 346 fields.createChild('div', 'port-forwarding-value') |
| 347 .appendChild(editor.createInput('address', 'text', 'Local address (dev.e
xample.corp:3333)', addressValidator)); |
| 348 return editor; |
257 | 349 |
258 /** | 350 /** |
259 * @param {boolean} discoverUsbDevices | |
260 * @param {boolean} portForwardingEnabled | |
261 * @param {!Adb.PortForwardingConfig} portForwardingConfig | |
262 */ | |
263 discoveryConfigChanged: function(discoverUsbDevices, portForwardingEnabled,
portForwardingConfig) | |
264 { | |
265 this._discoverUsbDevicesCheckbox.checked = discoverUsbDevices; | |
266 this._portForwardingEnabledCheckbox.checked = portForwardingEnabled; | |
267 | |
268 this._portForwardingConfig = []; | |
269 this._list.clear(); | |
270 for (var key of Object.keys(portForwardingConfig)) { | |
271 var rule = /** @type {!Adb.PortForwardingRule} */ ({port: key, addre
ss: portForwardingConfig[key]}); | |
272 this._portForwardingConfig.push(rule); | |
273 this._list.appendItem(rule, true); | |
274 } | |
275 }, | |
276 | |
277 /** | |
278 * @override | |
279 * @param {*} item | |
280 * @param {boolean} editable | |
281 * @return {!Element} | |
282 */ | |
283 renderItem: function(item, editable) | |
284 { | |
285 var rule = /** @type {!Adb.PortForwardingRule} */ (item); | |
286 var element = createElementWithClass("div", "port-forwarding-list-item")
; | |
287 var port = element.createChild("div", "port-forwarding-value port-forwar
ding-port"); | |
288 port.createChild("span", "port-localhost").textContent = WebInspector.UI
String("localhost:"); | |
289 port.createTextChild(rule.port); | |
290 element.createChild("div", "port-forwarding-separator"); | |
291 element.createChild("div", "port-forwarding-value").textContent = rule.a
ddress; | |
292 return element; | |
293 }, | |
294 | |
295 /** | |
296 * @override | |
297 * @param {*} item | 351 * @param {*} item |
298 * @param {number} index | 352 * @param {number} index |
| 353 * @param {!HTMLInputElement|!HTMLSelectElement} input |
| 354 * @this {WebInspector.DevicesView.DiscoveryView} |
| 355 * @return {boolean} |
299 */ | 356 */ |
300 removeItemRequested: function(item, index) | 357 function portValidator(item, index, input) { |
301 { | 358 var value = input.value.trim(); |
302 this._portForwardingConfig.splice(index, 1); | 359 var match = value.match(/^(\d+)$/); |
303 this._list.removeItem(index); | 360 if (!match) |
304 this._updateDiscoveryConfig(); | 361 return false; |
305 }, | 362 var port = parseInt(match[1], 10); |
| 363 if (port < 1024 || port > 65535) |
| 364 return false; |
| 365 for (var i = 0; i < this._portForwardingConfig.length; ++i) { |
| 366 if (i !== index && this._portForwardingConfig[i].port === value) |
| 367 return false; |
| 368 } |
| 369 return true; |
| 370 } |
306 | 371 |
307 /** | 372 /** |
308 * @override | |
309 * @param {*} item | 373 * @param {*} item |
310 * @param {!WebInspector.ListWidget.Editor} editor | 374 * @param {number} index |
311 * @param {boolean} isNew | 375 * @param {!HTMLInputElement|!HTMLSelectElement} input |
| 376 * @return {boolean} |
312 */ | 377 */ |
313 commitEdit: function(item, editor, isNew) | 378 function addressValidator(item, index, input) { |
314 { | 379 var match = input.value.trim().match(/^([a-zA-Z0-9\.\-_]+):(\d+)$/); |
315 var rule = /** @type {!Adb.PortForwardingRule} */ (item); | 380 if (!match) |
316 rule.port = editor.control("port").value.trim(); | 381 return false; |
317 rule.address = editor.control("address").value.trim(); | 382 var port = parseInt(match[2], 10); |
318 if (isNew) | 383 return port <= 65535; |
319 this._portForwardingConfig.push(rule); | 384 } |
320 this._updateDiscoveryConfig(); | 385 } |
321 }, | 386 |
322 | 387 _updateDiscoveryConfig() { |
323 /** | 388 var configMap = /** @type {!Adb.PortForwardingConfig} */ ({}); |
324 * @override | 389 for (var rule of this._portForwardingConfig) |
325 * @param {*} item | 390 configMap[rule.port] = rule.address; |
326 * @return {!WebInspector.ListWidget.Editor} | 391 InspectorFrontendHost.setDevicesDiscoveryConfig( |
327 */ | 392 this._discoverUsbDevicesCheckbox.checked, this._portForwardingEnabledChe
ckbox.checked, configMap); |
328 beginEdit: function(item) | 393 } |
329 { | |
330 var rule = /** @type {!Adb.PortForwardingRule} */ (item); | |
331 var editor = this._createEditor(); | |
332 editor.control("port").value = rule.port; | |
333 editor.control("address").value = rule.address; | |
334 return editor; | |
335 }, | |
336 | |
337 /** | |
338 * @return {!WebInspector.ListWidget.Editor} | |
339 */ | |
340 _createEditor: function() | |
341 { | |
342 if (this._editor) | |
343 return this._editor; | |
344 | |
345 var editor = new WebInspector.ListWidget.Editor(); | |
346 this._editor = editor; | |
347 var content = editor.contentElement(); | |
348 var fields = content.createChild("div", "port-forwarding-edit-row"); | |
349 fields.createChild("div", "port-forwarding-value port-forwarding-port").
appendChild(editor.createInput("port", "text", "Device port (3333)", portValidat
or.bind(this))); | |
350 fields.createChild("div", "port-forwarding-separator port-forwarding-sep
arator-invisible"); | |
351 fields.createChild("div", "port-forwarding-value").appendChild(editor.cr
eateInput("address", "text", "Local address (dev.example.corp:3333)", addressVal
idator)); | |
352 return editor; | |
353 | |
354 /** | |
355 * @param {*} item | |
356 * @param {number} index | |
357 * @param {!HTMLInputElement|!HTMLSelectElement} input | |
358 * @this {WebInspector.DevicesView.DiscoveryView} | |
359 * @return {boolean} | |
360 */ | |
361 function portValidator(item, index, input) | |
362 { | |
363 var value = input.value.trim(); | |
364 var match = value.match(/^(\d+)$/); | |
365 if (!match) | |
366 return false; | |
367 var port = parseInt(match[1], 10); | |
368 if (port < 1024 || port > 65535) | |
369 return false; | |
370 for (var i = 0; i < this._portForwardingConfig.length; ++i) { | |
371 if (i !== index && this._portForwardingConfig[i].port === value) | |
372 return false; | |
373 } | |
374 return true; | |
375 } | |
376 | |
377 /** | |
378 * @param {*} item | |
379 * @param {number} index | |
380 * @param {!HTMLInputElement|!HTMLSelectElement} input | |
381 * @return {boolean} | |
382 */ | |
383 function addressValidator(item, index, input) | |
384 { | |
385 var match = input.value.trim().match(/^([a-zA-Z0-9\.\-_]+):(\d+)$/); | |
386 if (!match) | |
387 return false; | |
388 var port = parseInt(match[2], 10); | |
389 return port <= 65535; | |
390 } | |
391 }, | |
392 | |
393 _updateDiscoveryConfig: function() | |
394 { | |
395 var configMap = /** @type {!Adb.PortForwardingConfig} */ ({}); | |
396 for (var rule of this._portForwardingConfig) | |
397 configMap[rule.port] = rule.address; | |
398 InspectorFrontendHost.setDevicesDiscoveryConfig(this._discoverUsbDevices
Checkbox.checked, this._portForwardingEnabledCheckbox.checked, configMap); | |
399 }, | |
400 | |
401 __proto__: WebInspector.VBox.prototype | |
402 }; | 394 }; |
403 | 395 |
404 | |
405 /** | 396 /** |
406 * @constructor | 397 * @unrestricted |
407 * @extends {WebInspector.VBox} | |
408 */ | 398 */ |
409 WebInspector.DevicesView.DeviceView = function() | 399 WebInspector.DevicesView.DeviceView = class extends WebInspector.VBox { |
410 { | 400 constructor() { |
411 WebInspector.VBox.call(this); | 401 super(); |
412 this.setMinimumSize(100, 100); | 402 this.setMinimumSize(100, 100); |
413 this.contentElement.classList.add("device-view"); | 403 this.contentElement.classList.add('device-view'); |
414 | 404 |
415 var topRow = this.contentElement.createChild("div", "hbox device-text-row"); | 405 var topRow = this.contentElement.createChild('div', 'hbox device-text-row'); |
416 this._deviceTitle = topRow.createChild("div", "view-title"); | 406 this._deviceTitle = topRow.createChild('div', 'view-title'); |
417 this._deviceSerial = topRow.createChild("div", "device-serial"); | 407 this._deviceSerial = topRow.createChild('div', 'device-serial'); |
418 this._portStatus = this.contentElement.createChild("div", "device-port-statu
s hidden"); | 408 this._portStatus = this.contentElement.createChild('div', 'device-port-statu
s hidden'); |
419 | 409 |
420 this._deviceOffline = this.contentElement.createChild("div"); | 410 this._deviceOffline = this.contentElement.createChild('div'); |
421 this._deviceOffline.textContent = WebInspector.UIString("Pending authenticat
ion: please accept debugging session on the device."); | 411 this._deviceOffline.textContent = |
422 | 412 WebInspector.UIString('Pending authentication: please accept debugging s
ession on the device.'); |
423 this._noBrowsers = this.contentElement.createChild("div"); | 413 |
424 this._noBrowsers.textContent = WebInspector.UIString("No browsers detected."
); | 414 this._noBrowsers = this.contentElement.createChild('div'); |
425 | 415 this._noBrowsers.textContent = WebInspector.UIString('No browsers detected.'
); |
426 this._browsers = this.contentElement.createChild("div", "device-browser-list
vbox"); | 416 |
| 417 this._browsers = this.contentElement.createChild('div', 'device-browser-list
vbox'); |
427 | 418 |
428 /** @type {!Map<string, !WebInspector.DevicesView.BrowserSection>} */ | 419 /** @type {!Map<string, !WebInspector.DevicesView.BrowserSection>} */ |
429 this._browserById = new Map(); | 420 this._browserById = new Map(); |
430 | 421 |
431 this._device = null; | 422 this._device = null; |
| 423 } |
| 424 |
| 425 /** |
| 426 * @param {!Adb.Device} device |
| 427 */ |
| 428 update(device) { |
| 429 if (!this._device || this._device.adbModel !== device.adbModel) |
| 430 this._deviceTitle.textContent = device.adbModel; |
| 431 |
| 432 if (!this._device || this._device.adbSerial !== device.adbSerial) |
| 433 this._deviceSerial.textContent = '#' + device.adbSerial; |
| 434 |
| 435 this._deviceOffline.classList.toggle('hidden', device.adbConnected); |
| 436 this._noBrowsers.classList.toggle('hidden', !device.adbConnected || !!device
.browsers.length); |
| 437 this._browsers.classList.toggle('hidden', !device.adbConnected || !device.br
owsers.length); |
| 438 |
| 439 var browserIds = new Set(); |
| 440 for (var browser of device.browsers) |
| 441 browserIds.add(browser.id); |
| 442 |
| 443 for (var browserId of this._browserById.keys()) { |
| 444 if (!browserIds.has(browserId)) { |
| 445 this._browserById.get(browserId).element.remove(); |
| 446 this._browserById.remove(browserId); |
| 447 } |
| 448 } |
| 449 |
| 450 for (var browser of device.browsers) { |
| 451 var section = this._browserById.get(browser.id); |
| 452 if (!section) { |
| 453 section = this._createBrowserSection(); |
| 454 this._browserById.set(browser.id, section); |
| 455 this._browsers.appendChild(section.element); |
| 456 } |
| 457 this._updateBrowserSection(section, browser); |
| 458 } |
| 459 |
| 460 this._device = device; |
| 461 } |
| 462 |
| 463 /** |
| 464 * @return {!WebInspector.DevicesView.BrowserSection} |
| 465 */ |
| 466 _createBrowserSection() { |
| 467 var element = createElementWithClass('div', 'vbox flex-none'); |
| 468 var topRow = element.createChild('div', ''); |
| 469 var title = topRow.createChild('div', 'device-browser-title'); |
| 470 |
| 471 var newTabRow = element.createChild('div', 'device-browser-new-tab'); |
| 472 newTabRow.createChild('div', '').textContent = WebInspector.UIString('New ta
b:'); |
| 473 var newTabInput = newTabRow.createChild('input', ''); |
| 474 newTabInput.type = 'text'; |
| 475 newTabInput.placeholder = WebInspector.UIString('Enter URL'); |
| 476 newTabInput.addEventListener('keydown', newTabKeyDown, false); |
| 477 var newTabButton = createTextButton(WebInspector.UIString('Open'), openNewTa
b); |
| 478 newTabRow.appendChild(newTabButton); |
| 479 |
| 480 var pages = element.createChild('div', 'device-page-list vbox'); |
| 481 |
| 482 var viewMore = element.createChild('div', 'device-view-more'); |
| 483 viewMore.addEventListener('click', viewMoreClick, false); |
| 484 updateViewMoreTitle(); |
| 485 |
| 486 var section = { |
| 487 browser: null, |
| 488 element: element, |
| 489 title: title, |
| 490 pages: pages, |
| 491 viewMore: viewMore, |
| 492 newTab: newTabRow, |
| 493 pageSections: new Map() |
| 494 }; |
| 495 return section; |
| 496 |
| 497 function viewMoreClick() { |
| 498 pages.classList.toggle('device-view-more-toggled'); |
| 499 updateViewMoreTitle(); |
| 500 } |
| 501 |
| 502 function updateViewMoreTitle() { |
| 503 viewMore.textContent = pages.classList.contains('device-view-more-toggled'
) ? |
| 504 WebInspector.UIString('View less tabs\u2026') : |
| 505 WebInspector.UIString('View more tabs\u2026'); |
| 506 } |
| 507 |
| 508 /** |
| 509 * @param {!Event} event |
| 510 */ |
| 511 function newTabKeyDown(event) { |
| 512 if (event.key === 'Enter') { |
| 513 event.consume(true); |
| 514 openNewTab(); |
| 515 } |
| 516 } |
| 517 |
| 518 function openNewTab() { |
| 519 if (section.browser) { |
| 520 InspectorFrontendHost.openRemotePage(section.browser.id, newTabInput.val
ue.trim() || 'about:blank'); |
| 521 newTabInput.value = ''; |
| 522 } |
| 523 } |
| 524 } |
| 525 |
| 526 /** |
| 527 * @param {!WebInspector.DevicesView.BrowserSection} section |
| 528 * @param {!Adb.Browser} browser |
| 529 */ |
| 530 _updateBrowserSection(section, browser) { |
| 531 if (!section.browser || section.browser.adbBrowserName !== browser.adbBrowse
rName || |
| 532 section.browser.adbBrowserVersion !== browser.adbBrowserVersion) { |
| 533 if (browser.adbBrowserVersion) |
| 534 section.title.textContent = String.sprintf('%s (%s)', browser.adbBrowser
Name, browser.adbBrowserVersion); |
| 535 else |
| 536 section.title.textContent = browser.adbBrowserName; |
| 537 } |
| 538 |
| 539 var pageIds = new Set(); |
| 540 for (var page of browser.pages) |
| 541 pageIds.add(page.id); |
| 542 |
| 543 for (var pageId of section.pageSections.keys()) { |
| 544 if (!pageIds.has(pageId)) { |
| 545 section.pageSections.get(pageId).element.remove(); |
| 546 section.pageSections.remove(pageId); |
| 547 } |
| 548 } |
| 549 |
| 550 for (var index = 0; index < browser.pages.length; ++index) { |
| 551 var page = browser.pages[index]; |
| 552 var pageSection = section.pageSections.get(page.id); |
| 553 if (!pageSection) { |
| 554 pageSection = this._createPageSection(); |
| 555 section.pageSections.set(page.id, pageSection); |
| 556 section.pages.appendChild(pageSection.element); |
| 557 } |
| 558 this._updatePageSection(pageSection, page); |
| 559 if (!index && section.pages.firstChild !== pageSection.element) |
| 560 section.pages.insertBefore(pageSection.element, section.pages.firstChild
); |
| 561 } |
| 562 |
| 563 var kViewMoreCount = 3; |
| 564 for (var index = 0, element = section.pages.firstChild; element; element = e
lement.nextSibling, ++index) |
| 565 element.classList.toggle('device-view-more-page', index >= kViewMoreCount)
; |
| 566 section.viewMore.classList.toggle('device-needs-view-more', browser.pages.le
ngth > kViewMoreCount); |
| 567 section.newTab.classList.toggle('hidden', !browser.adbBrowserChromeVersion); |
| 568 section.browser = browser; |
| 569 } |
| 570 |
| 571 /** |
| 572 * @return {!WebInspector.DevicesView.PageSection} |
| 573 */ |
| 574 _createPageSection() { |
| 575 var element = createElementWithClass('div', 'vbox'); |
| 576 |
| 577 var titleRow = element.createChild('div', 'device-page-title-row'); |
| 578 var title = titleRow.createChild('div', 'device-page-title'); |
| 579 var inspect = |
| 580 createTextButton(WebInspector.UIString('Inspect'), doAction.bind(null, '
inspect'), 'device-inspect-button'); |
| 581 titleRow.appendChild(inspect); |
| 582 |
| 583 var toolbar = new WebInspector.Toolbar(''); |
| 584 toolbar.appendToolbarItem(new WebInspector.ToolbarMenuButton(appendActions))
; |
| 585 titleRow.appendChild(toolbar.element); |
| 586 |
| 587 var url = element.createChild('div', 'device-page-url'); |
| 588 var section = {page: null, element: element, title: title, url: url, inspect
: inspect}; |
| 589 return section; |
| 590 |
| 591 /** |
| 592 * @param {!WebInspector.ContextMenu} contextMenu |
| 593 */ |
| 594 function appendActions(contextMenu) { |
| 595 contextMenu.appendItem(WebInspector.UIString('Reload'), doAction.bind(null
, 'reload')); |
| 596 contextMenu.appendItem(WebInspector.UIString('Focus'), doAction.bind(null,
'activate')); |
| 597 contextMenu.appendItem(WebInspector.UIString('Close'), doAction.bind(null,
'close')); |
| 598 } |
| 599 |
| 600 /** |
| 601 * @param {string} action |
| 602 */ |
| 603 function doAction(action) { |
| 604 if (section.page) |
| 605 InspectorFrontendHost.performActionOnRemotePage(section.page.id, action)
; |
| 606 } |
| 607 } |
| 608 |
| 609 /** |
| 610 * @param {!WebInspector.DevicesView.PageSection} section |
| 611 * @param {!Adb.Page} page |
| 612 */ |
| 613 _updatePageSection(section, page) { |
| 614 if (!section.page || section.page.name !== page.name) { |
| 615 section.title.textContent = page.name; |
| 616 section.title.title = page.name; |
| 617 } |
| 618 if (!section.page || section.page.url !== page.url) { |
| 619 section.url.textContent = ''; |
| 620 section.url.appendChild(WebInspector.linkifyURLAsNode(page.url, undefined,
undefined, true)); |
| 621 } |
| 622 section.inspect.disabled = page.attached; |
| 623 |
| 624 section.page = page; |
| 625 } |
| 626 |
| 627 /** |
| 628 * @param {!Adb.DevicePortForwardingStatus} status |
| 629 */ |
| 630 portForwardingStatusChanged(status) { |
| 631 var json = JSON.stringify(status); |
| 632 if (json === this._cachedPortStatus) |
| 633 return; |
| 634 this._cachedPortStatus = json; |
| 635 |
| 636 this._portStatus.removeChildren(); |
| 637 this._portStatus.createChild('div', 'device-port-status-text').textContent = |
| 638 WebInspector.UIString('Port Forwarding:'); |
| 639 var connected = []; |
| 640 var transient = []; |
| 641 var error = []; |
| 642 var empty = true; |
| 643 for (var port in status.ports) { |
| 644 if (!status.ports.hasOwnProperty(port)) |
| 645 continue; |
| 646 |
| 647 empty = false; |
| 648 var portStatus = status.ports[port]; |
| 649 var portNumber = createElementWithClass('div', 'device-view-port-number mo
nospace'); |
| 650 portNumber.textContent = ':' + port; |
| 651 if (portStatus >= 0) |
| 652 this._portStatus.appendChild(portNumber); |
| 653 else |
| 654 this._portStatus.insertBefore(portNumber, this._portStatus.firstChild); |
| 655 |
| 656 var portIcon = createElementWithClass('div', 'device-view-port-icon'); |
| 657 if (portStatus >= 0) { |
| 658 connected.push(port); |
| 659 } else if (portStatus === -1 || portStatus === -2) { |
| 660 portIcon.classList.add('device-view-port-icon-transient'); |
| 661 transient.push(port); |
| 662 } else if (portStatus < 0) { |
| 663 portIcon.classList.add('device-view-port-icon-error'); |
| 664 error.push(port); |
| 665 } |
| 666 this._portStatus.insertBefore(portIcon, portNumber); |
| 667 } |
| 668 |
| 669 var title = []; |
| 670 if (connected.length) |
| 671 title.push(WebInspector.UIString('Connected: %s', connected.join(', '))); |
| 672 if (transient.length) |
| 673 title.push(WebInspector.UIString('Transient: %s', transient.join(', '))); |
| 674 if (error.length) |
| 675 title.push(WebInspector.UIString('Error: %s', error.join(', '))); |
| 676 this._portStatus.title = title.join('; '); |
| 677 this._portStatus.classList.toggle('hidden', empty); |
| 678 } |
432 }; | 679 }; |
433 | 680 |
434 /** @typedef {!{browser: ?Adb.Browser, element: !Element, title: !Element, pages
: !Element, viewMore: !Element, newTab: !Element, pageSections: !Map<string, !We
bInspector.DevicesView.PageSection>}} */ | 681 /** @typedef {!{browser: ?Adb.Browser, element: !Element, title: !Element, pages
: !Element, viewMore: !Element, newTab: !Element, pageSections: !Map<string, !We
bInspector.DevicesView.PageSection>}} */ |
435 WebInspector.DevicesView.BrowserSection; | 682 WebInspector.DevicesView.BrowserSection; |
436 | 683 |
437 /** @typedef {!{page: ?Adb.Page, element: !Element, title: !Element, url: !Eleme
nt, inspect: !Element}} */ | 684 /** @typedef {!{page: ?Adb.Page, element: !Element, title: !Element, url: !Eleme
nt, inspect: !Element}} */ |
438 WebInspector.DevicesView.PageSection; | 685 WebInspector.DevicesView.PageSection; |
439 | |
440 WebInspector.DevicesView.DeviceView.prototype = { | |
441 /** | |
442 * @param {!Adb.Device} device | |
443 */ | |
444 update: function(device) | |
445 { | |
446 if (!this._device || this._device.adbModel !== device.adbModel) | |
447 this._deviceTitle.textContent = device.adbModel; | |
448 | |
449 if (!this._device || this._device.adbSerial !== device.adbSerial) | |
450 this._deviceSerial.textContent = "#" + device.adbSerial; | |
451 | |
452 this._deviceOffline.classList.toggle("hidden", device.adbConnected); | |
453 this._noBrowsers.classList.toggle("hidden", !device.adbConnected || !!de
vice.browsers.length); | |
454 this._browsers.classList.toggle("hidden", !device.adbConnected || !devic
e.browsers.length); | |
455 | |
456 var browserIds = new Set(); | |
457 for (var browser of device.browsers) | |
458 browserIds.add(browser.id); | |
459 | |
460 for (var browserId of this._browserById.keys()) { | |
461 if (!browserIds.has(browserId)) { | |
462 this._browserById.get(browserId).element.remove(); | |
463 this._browserById.remove(browserId); | |
464 } | |
465 } | |
466 | |
467 for (var browser of device.browsers) { | |
468 var section = this._browserById.get(browser.id); | |
469 if (!section) { | |
470 section = this._createBrowserSection(); | |
471 this._browserById.set(browser.id, section); | |
472 this._browsers.appendChild(section.element); | |
473 } | |
474 this._updateBrowserSection(section, browser); | |
475 } | |
476 | |
477 this._device = device; | |
478 }, | |
479 | |
480 /** | |
481 * @return {!WebInspector.DevicesView.BrowserSection} | |
482 */ | |
483 _createBrowserSection: function() | |
484 { | |
485 var element = createElementWithClass("div", "vbox flex-none"); | |
486 var topRow = element.createChild("div", ""); | |
487 var title = topRow.createChild("div", "device-browser-title"); | |
488 | |
489 var newTabRow = element.createChild("div", "device-browser-new-tab"); | |
490 newTabRow.createChild("div", "").textContent = WebInspector.UIString("Ne
w tab:"); | |
491 var newTabInput = newTabRow.createChild("input", ""); | |
492 newTabInput.type = "text"; | |
493 newTabInput.placeholder = WebInspector.UIString("Enter URL"); | |
494 newTabInput.addEventListener("keydown", newTabKeyDown, false); | |
495 var newTabButton = createTextButton(WebInspector.UIString("Open"), openN
ewTab); | |
496 newTabRow.appendChild(newTabButton); | |
497 | |
498 var pages = element.createChild("div", "device-page-list vbox"); | |
499 | |
500 var viewMore = element.createChild("div", "device-view-more"); | |
501 viewMore.addEventListener("click", viewMoreClick, false); | |
502 updateViewMoreTitle(); | |
503 | |
504 var section = {browser: null, element: element, title: title, pages: pag
es, viewMore: viewMore, newTab: newTabRow, pageSections: new Map()}; | |
505 return section; | |
506 | |
507 function viewMoreClick() | |
508 { | |
509 pages.classList.toggle("device-view-more-toggled"); | |
510 updateViewMoreTitle(); | |
511 } | |
512 | |
513 function updateViewMoreTitle() | |
514 { | |
515 viewMore.textContent = pages.classList.contains("device-view-more-to
ggled") ? WebInspector.UIString("View less tabs\u2026") : WebInspector.UIString(
"View more tabs\u2026"); | |
516 } | |
517 | |
518 /** | |
519 * @param {!Event} event | |
520 */ | |
521 function newTabKeyDown(event) | |
522 { | |
523 if (event.key === "Enter") { | |
524 event.consume(true); | |
525 openNewTab(); | |
526 } | |
527 } | |
528 | |
529 function openNewTab() | |
530 { | |
531 if (section.browser) { | |
532 InspectorFrontendHost.openRemotePage(section.browser.id, newTabI
nput.value.trim() || "about:blank"); | |
533 newTabInput.value = ""; | |
534 } | |
535 } | |
536 }, | |
537 | |
538 /** | |
539 * @param {!WebInspector.DevicesView.BrowserSection} section | |
540 * @param {!Adb.Browser} browser | |
541 */ | |
542 _updateBrowserSection: function(section, browser) | |
543 { | |
544 if (!section.browser || section.browser.adbBrowserName !== browser.adbBr
owserName || section.browser.adbBrowserVersion !== browser.adbBrowserVersion) { | |
545 if (browser.adbBrowserVersion) | |
546 section.title.textContent = String.sprintf("%s (%s)", browser.ad
bBrowserName, browser.adbBrowserVersion); | |
547 else | |
548 section.title.textContent = browser.adbBrowserName; | |
549 } | |
550 | |
551 var pageIds = new Set(); | |
552 for (var page of browser.pages) | |
553 pageIds.add(page.id); | |
554 | |
555 for (var pageId of section.pageSections.keys()) { | |
556 if (!pageIds.has(pageId)) { | |
557 section.pageSections.get(pageId).element.remove(); | |
558 section.pageSections.remove(pageId); | |
559 } | |
560 } | |
561 | |
562 for (var index = 0; index < browser.pages.length; ++index) { | |
563 var page = browser.pages[index]; | |
564 var pageSection = section.pageSections.get(page.id); | |
565 if (!pageSection) { | |
566 pageSection = this._createPageSection(); | |
567 section.pageSections.set(page.id, pageSection); | |
568 section.pages.appendChild(pageSection.element); | |
569 } | |
570 this._updatePageSection(pageSection, page); | |
571 if (!index && section.pages.firstChild !== pageSection.element) | |
572 section.pages.insertBefore(pageSection.element, section.pages.fi
rstChild); | |
573 } | |
574 | |
575 var kViewMoreCount = 3; | |
576 for (var index = 0, element = section.pages.firstChild; element; element
= element.nextSibling, ++index) | |
577 element.classList.toggle("device-view-more-page", index >= kViewMore
Count); | |
578 section.viewMore.classList.toggle("device-needs-view-more", browser.page
s.length > kViewMoreCount); | |
579 section.newTab.classList.toggle("hidden", !browser.adbBrowserChromeVersi
on); | |
580 section.browser = browser; | |
581 }, | |
582 | |
583 /** | |
584 * @return {!WebInspector.DevicesView.PageSection} | |
585 */ | |
586 _createPageSection: function() | |
587 { | |
588 var element = createElementWithClass("div", "vbox"); | |
589 | |
590 var titleRow = element.createChild("div", "device-page-title-row"); | |
591 var title = titleRow.createChild("div", "device-page-title"); | |
592 var inspect = createTextButton(WebInspector.UIString("Inspect"), doActio
n.bind(null, "inspect"), "device-inspect-button"); | |
593 titleRow.appendChild(inspect); | |
594 | |
595 var toolbar = new WebInspector.Toolbar(""); | |
596 toolbar.appendToolbarItem(new WebInspector.ToolbarMenuButton(appendActio
ns)); | |
597 titleRow.appendChild(toolbar.element); | |
598 | |
599 var url = element.createChild("div", "device-page-url"); | |
600 var section = {page: null, element: element, title: title, url: url, ins
pect: inspect}; | |
601 return section; | |
602 | |
603 /** | |
604 * @param {!WebInspector.ContextMenu} contextMenu | |
605 */ | |
606 function appendActions(contextMenu) | |
607 { | |
608 contextMenu.appendItem(WebInspector.UIString("Reload"), doAction.bin
d(null, "reload")); | |
609 contextMenu.appendItem(WebInspector.UIString("Focus"), doAction.bind
(null, "activate")); | |
610 contextMenu.appendItem(WebInspector.UIString("Close"), doAction.bind
(null, "close")); | |
611 } | |
612 | |
613 /** | |
614 * @param {string} action | |
615 */ | |
616 function doAction(action) | |
617 { | |
618 if (section.page) | |
619 InspectorFrontendHost.performActionOnRemotePage(section.page.id,
action); | |
620 } | |
621 }, | |
622 | |
623 /** | |
624 * @param {!WebInspector.DevicesView.PageSection} section | |
625 * @param {!Adb.Page} page | |
626 */ | |
627 _updatePageSection: function(section, page) | |
628 { | |
629 if (!section.page || section.page.name !== page.name) { | |
630 section.title.textContent = page.name; | |
631 section.title.title = page.name; | |
632 } | |
633 if (!section.page || section.page.url !== page.url) { | |
634 section.url.textContent = ""; | |
635 section.url.appendChild(WebInspector.linkifyURLAsNode(page.url, unde
fined, undefined, true)); | |
636 } | |
637 section.inspect.disabled = page.attached; | |
638 | |
639 section.page = page; | |
640 }, | |
641 | |
642 /** | |
643 * @param {!Adb.DevicePortForwardingStatus} status | |
644 */ | |
645 portForwardingStatusChanged: function(status) | |
646 { | |
647 var json = JSON.stringify(status); | |
648 if (json === this._cachedPortStatus) | |
649 return; | |
650 this._cachedPortStatus = json; | |
651 | |
652 this._portStatus.removeChildren(); | |
653 this._portStatus.createChild("div", "device-port-status-text").textConte
nt = WebInspector.UIString("Port Forwarding:"); | |
654 var connected = []; | |
655 var transient = []; | |
656 var error = []; | |
657 var empty = true; | |
658 for (var port in status.ports) { | |
659 if (!status.ports.hasOwnProperty(port)) | |
660 continue; | |
661 | |
662 empty = false; | |
663 var portStatus = status.ports[port]; | |
664 var portNumber = createElementWithClass("div", "device-view-port-num
ber monospace"); | |
665 portNumber.textContent = ":" + port; | |
666 if (portStatus >= 0) | |
667 this._portStatus.appendChild(portNumber); | |
668 else | |
669 this._portStatus.insertBefore(portNumber, this._portStatus.first
Child); | |
670 | |
671 var portIcon = createElementWithClass("div", "device-view-port-icon"
); | |
672 if (portStatus >= 0) { | |
673 connected.push(port); | |
674 } else if (portStatus === -1 || portStatus === -2) { | |
675 portIcon.classList.add("device-view-port-icon-transient"); | |
676 transient.push(port); | |
677 } else if (portStatus < 0) { | |
678 portIcon.classList.add("device-view-port-icon-error"); | |
679 error.push(port); | |
680 } | |
681 this._portStatus.insertBefore(portIcon, portNumber); | |
682 } | |
683 | |
684 var title = []; | |
685 if (connected.length) | |
686 title.push(WebInspector.UIString("Connected: %s", connected.join(",
"))); | |
687 if (transient.length) | |
688 title.push(WebInspector.UIString("Transient: %s", transient.join(",
"))); | |
689 if (error.length) | |
690 title.push(WebInspector.UIString("Error: %s", error.join(", "))); | |
691 this._portStatus.title = title.join("; "); | |
692 this._portStatus.classList.toggle("hidden", empty); | |
693 }, | |
694 | |
695 __proto__: WebInspector.VBox.prototype | |
696 }; | |
OLD | NEW |