| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 /** | 4 /** |
| 5 * @implements {WebInspector.TargetManager.Observer} | 5 * @implements {WebInspector.TargetManager.Observer} |
| 6 * @unrestricted | 6 * @unrestricted |
| 7 */ | 7 */ |
| 8 WebInspector.ThreadsSidebarPane = class extends WebInspector.VBox { | 8 WebInspector.ThreadsSidebarPane = class extends WebInspector.VBox { |
| 9 constructor() { | 9 constructor() { |
| 10 super(); | 10 super(); |
| 11 | 11 |
| 12 /** @type {!Map.<!WebInspector.DebuggerModel, !WebInspector.UIList.Item>} */ | |
| 13 this._debuggerModelToListItems = new Map(); | |
| 14 /** @type {!Map.<!WebInspector.UIList.Item, !WebInspector.Target>} */ | |
| 15 this._listItemsToTargets = new Map(); | |
| 16 /** @type {?WebInspector.UIList.Item} */ | 12 /** @type {?WebInspector.UIList.Item} */ |
| 17 this._selectedListItem = null; | 13 this._selectedListItem = null; |
| 14 /** @type {!Map<!WebInspector.PendingTarget, !WebInspector.UIList.Item>} */ |
| 15 this._pendingToListItem = new Map(); |
| 16 /** @type {!Map<!WebInspector.Target, !WebInspector.PendingTarget>} */ |
| 17 this._targetToPending = new Map(); |
| 18 /** @type {?WebInspector.PendingTarget} */ |
| 19 this._mainTargetPending = null; |
| 18 this.threadList = new WebInspector.UIList(); | 20 this.threadList = new WebInspector.UIList(); |
| 19 this.threadList.show(this.element); | 21 this.threadList.show(this.element); |
| 20 WebInspector.targetManager.addModelListener( | 22 WebInspector.targetManager.addModelListener( |
| 21 WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerPa
used, this._onDebuggerStateChanged, | 23 WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerPa
used, this._onDebuggerStateChanged, |
| 22 this); | 24 this); |
| 23 WebInspector.targetManager.addModelListener( | 25 WebInspector.targetManager.addModelListener( |
| 24 WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerRe
sumed, this._onDebuggerStateChanged, | 26 WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerRe
sumed, this._onDebuggerStateChanged, |
| 25 this); | 27 this); |
| 26 WebInspector.targetManager.addModelListener( | 28 WebInspector.targetManager.addModelListener( |
| 27 WebInspector.RuntimeModel, WebInspector.RuntimeModel.Events.ExecutionCon
textChanged, | 29 WebInspector.RuntimeModel, WebInspector.RuntimeModel.Events.ExecutionCon
textChanged, |
| 28 this._onExecutionContextChanged, this); | 30 this._onExecutionContextChanged, this); |
| 29 WebInspector.context.addFlavorChangeListener(WebInspector.Target, this._targ
etChanged, this); | 31 WebInspector.context.addFlavorChangeListener(WebInspector.Target, this._targ
etChanged, this); |
| 30 WebInspector.targetManager.addEventListener( | 32 WebInspector.targetManager.addEventListener( |
| 31 WebInspector.TargetManager.Events.NameChanged, this._targetNameChanged,
this); | 33 WebInspector.TargetManager.Events.NameChanged, this._targetNameChanged,
this); |
| 34 WebInspector.targetManager.addModelListener(WebInspector.SubTargetsManager,
WebInspector.SubTargetsManager.Events.PendingTargetAdded, this._addTargetItem, t
his); |
| 35 WebInspector.targetManager.addModelListener(WebInspector.SubTargetsManager,
WebInspector.SubTargetsManager.Events.PendingTargetRemoved, this._pendingTargetR
emoved, this); |
| 36 WebInspector.targetManager.addModelListener(WebInspector.SubTargetsManager,
WebInspector.SubTargetsManager.Events.PendingTargetAttached, this._addTargetItem
, this); |
| 37 WebInspector.targetManager.addModelListener(WebInspector.SubTargetsManager,
WebInspector.SubTargetsManager.Events.PendingTargetDetached, this._targetDetache
d, this); |
| 32 WebInspector.targetManager.observeTargets(this); | 38 WebInspector.targetManager.observeTargets(this); |
| 39 |
| 40 var pendingTargets = []; |
| 41 for (var target of WebInspector.targetManager.targets(WebInspector.Target.Ca
pability.Target)) |
| 42 pendingTargets = pendingTargets.concat(WebInspector.SubTargetsManager.from
Target(target).pendingTargets()); |
| 43 |
| 44 pendingTargets |
| 45 .sort(WebInspector.ThreadsSidebarPane._pendingTargetsComparator) |
| 46 .forEach(pendingTarget => this._addListItem(pendingTarget)); |
| 47 } |
| 48 |
| 49 /** |
| 50 * @return {boolean} |
| 51 */ |
| 52 static shouldBeShown() { |
| 53 if (WebInspector.targetManager.targets(WebInspector.Target.Capability.JS).le
ngth > 1) |
| 54 return true; |
| 55 for (var target of WebInspector.targetManager.targets(WebInspector.Target.Ca
pability.Target)) { |
| 56 var pendingTargets = WebInspector.SubTargetsManager.fromTarget(target).pen
dingTargets(); |
| 57 if (pendingTargets.some(pendingTarget => pendingTarget.canConnect())) |
| 58 return true; |
| 59 } |
| 60 return false; |
| 61 } |
| 62 |
| 63 /** |
| 64 * Sorts show tha connected targets appear first, followed by pending subtarge
ts. |
| 65 * |
| 66 * @param {!WebInspector.PendingTarget} c1 |
| 67 * @param {!WebInspector.PendingTarget} c2 |
| 68 * @return {number} |
| 69 */ |
| 70 static _pendingTargetsComparator(c1, c2) |
| 71 { |
| 72 var t1 = c1.target(); |
| 73 var t2 = c2.target(); |
| 74 var name1 = t1 ? t1.name() : c1.name(); |
| 75 var name2 = t2 ? t2.name() : c2.name(); |
| 76 if (!!t1 === !!t2) { // Either both are connected or disconnected |
| 77 return name1.toLowerCase().localeCompare(name2.toLowerCase()); |
| 78 } else if (t1) { |
| 79 return -1; |
| 80 } |
| 81 return 1; |
| 82 } |
| 83 |
| 84 /** |
| 85 * @param {!WebInspector.Event} event |
| 86 */ |
| 87 _addTargetItem(event) { |
| 88 this._addListItem(/** @type {!WebInspector.PendingTarget} */ (event.data)); |
| 89 } |
| 90 |
| 91 /** |
| 92 * @param {!WebInspector.Event} event |
| 93 */ |
| 94 _pendingTargetRemoved(event) { |
| 95 this._removeListItem(/** @type {!WebInspector.PendingTarget} */ (event.data)
); |
| 96 } |
| 97 |
| 98 /** |
| 99 * @param {!WebInspector.Event} event |
| 100 */ |
| 101 _targetDetached(event) { |
| 102 this._targetRemoved(/** @type {!WebInspector.PendingTarget} */ (event.data))
; |
| 103 } |
| 104 |
| 105 /** |
| 106 * @param {!WebInspector.PendingTarget} pendingTarget |
| 107 */ |
| 108 _addListItem(pendingTarget) { |
| 109 var target = pendingTarget.target(); |
| 110 if (!pendingTarget.canConnect() && !(target && target.hasJSCapability())) |
| 111 return; |
| 112 |
| 113 var listItem = this._pendingToListItem.get(pendingTarget); |
| 114 if (!listItem) { |
| 115 listItem = new WebInspector.UIList.Item('', '', false); |
| 116 listItem[WebInspector.ThreadsSidebarPane._pendingTargetSymbol] = pendingTa
rget; |
| 117 listItem[WebInspector.ThreadsSidebarPane._targetSymbol] = target; |
| 118 this._pendingToListItem.set(pendingTarget, listItem); |
| 119 this.threadList.addItem(listItem); |
| 120 listItem.element.addEventListener('click', this._onListItemClick.bind(this
, listItem), false); |
| 121 } |
| 122 this._updateListItem(listItem, pendingTarget); |
| 123 this._updateDebuggerState(pendingTarget); |
| 124 var currentTarget = WebInspector.context.flavor(WebInspector.Target); |
| 125 if (currentTarget === target) |
| 126 this._selectListItem(listItem); |
| 127 if (target) |
| 128 this._targetToPending.set(target, pendingTarget); |
| 33 } | 129 } |
| 34 | 130 |
| 35 /** | 131 /** |
| 36 * @override | 132 * @override |
| 37 * @param {!WebInspector.Target} target | 133 * @param {!WebInspector.Target} target |
| 38 */ | 134 */ |
| 39 targetAdded(target) { | 135 targetAdded(target) { |
| 40 var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); | 136 if (target !== WebInspector.targetManager.mainTarget()) |
| 41 if (!debuggerModel) | |
| 42 return; | 137 return; |
| 43 | 138 console.assert(!this._mainTargetPending); |
| 44 var listItem = new WebInspector.UIList.Item(this._titleForTarget(target), ''
); | 139 this._mainTargetPending = new WebInspector.ThreadsSidebarPane.MainTargetConn
ection(target); |
| 45 listItem.element.addEventListener('click', this._onListItemClick.bind(this,
listItem), false); | 140 this._addListItem(this._mainTargetPending); |
| 46 var currentTarget = WebInspector.context.flavor(WebInspector.Target); | |
| 47 if (currentTarget === target) | |
| 48 this._selectListItem(listItem); | |
| 49 | |
| 50 this._debuggerModelToListItems.set(debuggerModel, listItem); | |
| 51 this._listItemsToTargets.set(listItem, target); | |
| 52 this.threadList.addItem(listItem); | |
| 53 this._updateDebuggerState(debuggerModel); | |
| 54 } | 141 } |
| 55 | 142 |
| 56 /** | 143 /** |
| 57 * @override | 144 * @override |
| 58 * @param {!WebInspector.Target} target | 145 * @param {!WebInspector.Target} target |
| 59 */ | 146 */ |
| 60 targetRemoved(target) { | 147 targetRemoved(target) { |
| 61 var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); | 148 var subtargetManager = WebInspector.SubTargetsManager.fromTarget(target); |
| 62 if (!debuggerModel) | 149 var pendingTargets = subtargetManager ? subtargetManager.pendingTargets() :
[]; |
| 63 return; | 150 for (var pendingTarget of pendingTargets) { |
| 64 var listItem = this._debuggerModelToListItems.remove(debuggerModel); | 151 if (pendingTarget.target()) |
| 65 if (listItem) { | 152 this._targetRemoved(pendingTarget); |
| 66 this._listItemsToTargets.remove(listItem); | 153 } |
| 67 this.threadList.removeItem(listItem); | 154 if (target === WebInspector.targetManager.mainTarget() && this._mainTargetPe
nding) { |
| 155 this._targetRemoved(this._mainTargetPending); |
| 156 this._mainTargetPending = null; |
| 68 } | 157 } |
| 69 } | 158 } |
| 70 | 159 |
| 71 /** | 160 /** |
| 72 * @param {!WebInspector.Event} event | 161 * @param {!WebInspector.Event} event |
| 73 */ | 162 */ |
| 74 _targetNameChanged(event) { | 163 _targetNameChanged(event) { |
| 75 var target = /** @type {!WebInspector.Target} */ (event.data); | 164 var target = /** @type {!WebInspector.Target} */ (event.data); |
| 76 var listItem = this._listItemForTarget(target); | 165 var listItem = this._listItemForTarget(target); |
| 77 if (listItem) | 166 if (listItem) |
| 78 listItem.setTitle(this._titleForTarget(target)); | 167 listItem.setTitle(this._titleForPending(this._targetToPending.get(target))
); |
| 79 } | 168 } |
| 80 | 169 |
| 81 /** | 170 /** |
| 82 * @param {!WebInspector.Event} event | 171 * @param {!WebInspector.Event} event |
| 83 */ | 172 */ |
| 84 _targetChanged(event) { | 173 _targetChanged(event) { |
| 85 var listItem = this._listItemForTarget(/** @type {!WebInspector.Target} */ (
event.data)); | 174 var listItem = this._listItemForTarget(/** @type {!WebInspector.Target} */ (
event.data)); |
| 86 if (listItem) | 175 if (listItem) |
| 87 this._selectListItem(listItem); | 176 this._selectListItem(listItem); |
| 88 } | 177 } |
| 89 | 178 |
| 90 /** | 179 /** |
| 91 * @param {!WebInspector.Target} target | 180 * @param {!WebInspector.Target} target |
| 92 * @return {?WebInspector.UIList.Item} | 181 * @return {?WebInspector.UIList.Item} |
| 93 */ | 182 */ |
| 94 _listItemForTarget(target) { | 183 _listItemForTarget(target) { |
| 95 var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); | 184 var pendingTarget = this._targetToPending.get(target); |
| 96 if (!debuggerModel) | 185 return this._pendingToListItem.get(pendingTarget) || null; |
| 97 return null; | |
| 98 return this._debuggerModelToListItems.get(debuggerModel) || null; | |
| 99 } | 186 } |
| 100 | 187 |
| 101 /** | 188 /** |
| 102 * @param {!WebInspector.Target} target | 189 * @param {!WebInspector.PendingTarget} pendingTarget |
| 103 * @return {string} | 190 * @return {string} |
| 104 */ | 191 */ |
| 105 _titleForTarget(target) { | 192 _titleForPending(pendingTarget) { |
| 193 var target = pendingTarget.target(); |
| 194 if (!target) |
| 195 return pendingTarget.name(); |
| 106 var executionContext = target.runtimeModel.defaultExecutionContext(); | 196 var executionContext = target.runtimeModel.defaultExecutionContext(); |
| 107 return executionContext && executionContext.label() ? executionContext.label
() : target.name(); | 197 return executionContext && executionContext.label() ? executionContext.label
() : target.name(); |
| 108 } | 198 } |
| 109 | 199 |
| 110 /** | 200 /** |
| 111 * @param {!WebInspector.Event} event | 201 * @param {!WebInspector.Event} event |
| 112 */ | 202 */ |
| 113 _onDebuggerStateChanged(event) { | 203 _onDebuggerStateChanged(event) { |
| 114 var debuggerModel = /** @type {!WebInspector.DebuggerModel} */ (event.target
); | 204 var debuggerModel = /** @type {!WebInspector.DebuggerModel} */ (event.target
); |
| 115 this._updateDebuggerState(debuggerModel); | 205 var pendingTarget = this._targetToPending.get(debuggerModel.target()); |
| 206 this._updateDebuggerState(pendingTarget); |
| 116 } | 207 } |
| 117 | 208 |
| 118 /** | 209 /** |
| 119 * @param {!WebInspector.Event} event | 210 * @param {!WebInspector.Event} event |
| 120 */ | 211 */ |
| 121 _onExecutionContextChanged(event) { | 212 _onExecutionContextChanged(event) { |
| 122 var executionContext = /** @type {!WebInspector.ExecutionContext} */ (event.
data); | 213 var executionContext = /** @type {!WebInspector.ExecutionContext} */ (event.
data); |
| 123 if (!executionContext.isDefault) | 214 if (!executionContext.isDefault) |
| 124 return; | 215 return; |
| 125 var debuggerModel = | 216 var pendingTarget = this._targetToPending.get(executionContext.target()); |
| 126 /** @type {!WebInspector.DebuggerModel} */ (WebInspector.DebuggerModel.f
romTarget(executionContext.target())); | 217 var listItem = this._pendingToListItem.get(pendingTarget); |
| 127 var listItem = this._debuggerModelToListItems.get(debuggerModel); | |
| 128 if (listItem && executionContext.label()) | 218 if (listItem && executionContext.label()) |
| 129 listItem.setTitle(executionContext.label()); | 219 listItem.setTitle(executionContext.label()); |
| 130 } | 220 } |
| 131 | 221 |
| 132 /** | 222 /** |
| 133 * @param {!WebInspector.DebuggerModel} debuggerModel | 223 * @param {!WebInspector.PendingTarget} pendingTarget |
| 134 */ | 224 */ |
| 135 _updateDebuggerState(debuggerModel) { | 225 _updateDebuggerState(pendingTarget) { |
| 136 var listItem = this._debuggerModelToListItems.get(debuggerModel); | 226 var listItem = this._pendingToListItem.get(pendingTarget); |
| 137 listItem.setSubtitle(WebInspector.UIString(debuggerModel.isPaused() ? 'pause
d' : '')); | 227 var target = pendingTarget.target(); |
| 228 var debuggerModel = target && WebInspector.DebuggerModel.fromTarget(target); |
| 229 var isPaused = !!debuggerModel && debuggerModel.isPaused(); |
| 230 listItem.setSubtitle(WebInspector.UIString(isPaused ? 'paused' : '')); |
| 138 } | 231 } |
| 139 | 232 |
| 140 /** | 233 /** |
| 141 * @param {!WebInspector.UIList.Item} listItem | 234 * @param {!WebInspector.UIList.Item} listItem |
| 142 */ | 235 */ |
| 143 _selectListItem(listItem) { | 236 _selectListItem(listItem) { |
| 144 if (listItem === this._selectedListItem) | 237 if (listItem === this._selectedListItem) |
| 145 return; | 238 return; |
| 146 | 239 |
| 147 if (this._selectedListItem) | 240 if (this._selectedListItem) |
| 148 this._selectedListItem.setSelected(false); | 241 this._selectedListItem.setSelected(false); |
| 149 | 242 |
| 150 this._selectedListItem = listItem; | 243 this._selectedListItem = listItem; |
| 151 listItem.setSelected(true); | 244 listItem.setSelected(true); |
| 152 } | 245 } |
| 153 | 246 |
| 154 /** | 247 /** |
| 155 * @param {!WebInspector.UIList.Item} listItem | 248 * @param {!WebInspector.UIList.Item} listItem |
| 156 */ | 249 */ |
| 157 _onListItemClick(listItem) { | 250 _onListItemClick(listItem) { |
| 158 WebInspector.context.setFlavor(WebInspector.Target, this._listItemsToTargets
.get(listItem)); | 251 var pendingTarget = listItem[WebInspector.ThreadsSidebarPane._pendingTargetS
ymbol]; |
| 252 var target = pendingTarget.target(); |
| 253 if (!target) |
| 254 return; |
| 255 WebInspector.context.setFlavor(WebInspector.Target, target); |
| 159 listItem.element.scrollIntoViewIfNeeded(); | 256 listItem.element.scrollIntoViewIfNeeded(); |
| 160 } | 257 } |
| 258 |
| 259 /** |
| 260 * @param {!WebInspector.UIList.Item} item |
| 261 * @param {!WebInspector.PendingTarget} pendingTarget |
| 262 */ |
| 263 _updateListItem(item, pendingTarget) { |
| 264 item.setTitle(this._titleForPending(pendingTarget)); |
| 265 item.setSubtitle(''); |
| 266 var target = pendingTarget.target(); |
| 267 var action = null; |
| 268 var actionLabel = null; |
| 269 if (pendingTarget.canConnect()) { |
| 270 actionLabel = target ? 'Disconnect' : 'Connect'; |
| 271 action = this._toggleConnection.bind(this, pendingTarget); |
| 272 } |
| 273 item.setAction(actionLabel, action); |
| 274 item.setDimmed(!target); |
| 275 } |
| 276 |
| 277 /** |
| 278 * @param {!WebInspector.Target} target |
| 279 */ |
| 280 _selectNewlyAddedTarget(target) { |
| 281 setTimeout(() => WebInspector.context.setFlavor(WebInspector.Target, target)
); |
| 282 } |
| 283 |
| 284 /** |
| 285 * @param {!WebInspector.PendingTarget} pendingTarget |
| 286 * @return {!Promise} |
| 287 */ |
| 288 _toggleConnection(pendingTarget) { |
| 289 var target = pendingTarget.target(); |
| 290 if (target) |
| 291 return pendingTarget.detach(); |
| 292 else |
| 293 return pendingTarget.attach().then(target => this._selectNewlyAddedTarget(
target)); |
| 294 } |
| 295 |
| 296 /** |
| 297 * @param {!WebInspector.PendingTarget} pendingTarget |
| 298 */ |
| 299 _targetRemoved(pendingTarget) { |
| 300 var item = this._pendingToListItem.get(pendingTarget); |
| 301 if (!item) // Not all targets are represented in the UI. |
| 302 return; |
| 303 var target = item[WebInspector.ThreadsSidebarPane._targetSymbol]; |
| 304 item[WebInspector.ThreadsSidebarPane._targetSymbol] = null; |
| 305 this._targetToPending.remove(target); |
| 306 if (pendingTarget.canConnect()) |
| 307 this._updateListItem(item, pendingTarget); |
| 308 else |
| 309 this._removeListItem(pendingTarget); |
| 310 } |
| 311 |
| 312 /** |
| 313 * @param {!WebInspector.PendingTarget} pendingTarget |
| 314 */ |
| 315 _removeListItem(pendingTarget) { |
| 316 var item = this._pendingToListItem.get(pendingTarget); |
| 317 if (!item) |
| 318 return; |
| 319 this.threadList.removeItem(item); |
| 320 this._pendingToListItem.delete(pendingTarget); |
| 321 } |
| 161 }; | 322 }; |
| 323 |
| 324 WebInspector.ThreadsSidebarPane._pendingTargetSymbol = Symbol('_subtargetSymbol'
); |
| 325 WebInspector.ThreadsSidebarPane._targetSymbol = Symbol('_targetSymbol'); |
| 326 |
| 327 /** |
| 328 * @unrestricted |
| 329 */ |
| 330 WebInspector.ThreadsSidebarPane.MainTargetConnection = class extends WebInspecto
r.PendingTarget { |
| 331 /** |
| 332 * @param {!WebInspector.Target} target |
| 333 */ |
| 334 constructor(target) { |
| 335 super('main-target-list-node-' + target.id(), target.title, false, null); |
| 336 this._target = target; |
| 337 } |
| 338 |
| 339 /** |
| 340 * @override |
| 341 * @return {!WebInspector.Target} |
| 342 */ |
| 343 target() { |
| 344 return this._target; |
| 345 } |
| 346 |
| 347 /** |
| 348 * @override |
| 349 * @return {string} |
| 350 */ |
| 351 name() { |
| 352 return this._target.name(); |
| 353 } |
| 354 }; |
| OLD | NEW |