Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / sources / AsyncOperationsSidebarPane.js
blobe04d60dddc03863224634bccd39ebf43ecb3ef51
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.
5 /**
6 * @constructor
7 * @extends {WebInspector.BreakpointsSidebarPaneBase}
8 * @implements {WebInspector.TargetManager.Observer}
9 */
10 WebInspector.AsyncOperationsSidebarPane = function()
12 WebInspector.BreakpointsSidebarPaneBase.call(this, WebInspector.UIString("Async Operation Breakpoints"));
13 this.element.classList.add("async-operations");
14 this._updateEmptyElement();
16 var refreshButton = new WebInspector.ToolbarButton(WebInspector.UIString("Refresh"), "refresh-toolbar-item");
17 refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this));
18 this.toolbar().appendToolbarItem(refreshButton);
20 /** @type {!Map.<!WebInspector.Target, !Map.<number, !DebuggerAgent.AsyncOperation>>} */
21 this._asyncOperationsByTarget = new Map();
22 /** @type {!Map.<number, !Element>} */
23 this._operationIdToElement = new Map();
25 this._revealBlackboxedCallFrames = false;
26 this._linkifier = new WebInspector.Linkifier(new WebInspector.Linkifier.DefaultFormatter(30));
28 this._popoverHelper = new WebInspector.PopoverHelper(this.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this));
29 this._popoverHelper.setTimeout(250, 250);
30 this.element.addEventListener("click", this._hidePopover.bind(this), true);
32 WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.AsyncOperationStarted, this._onAsyncOperationStarted, this);
33 WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.AsyncOperationCompleted, this._onAsyncOperationCompleted, this);
34 WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
35 WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
36 WebInspector.context.addFlavorChangeListener(WebInspector.Target, this._targetChanged, this);
38 WebInspector.moduleSetting("skipStackFramesPattern").addChangeListener(this._refresh, this);
39 WebInspector.moduleSetting("enableAsyncStackTraces").addChangeListener(this._asyncStackTracesStateChanged, this);
41 WebInspector.targetManager.observeTargets(this);
44 WebInspector.AsyncOperationsSidebarPane.prototype = {
45 _operationIdSymbol: Symbol("operationId"),
46 _checkedSymbol: Symbol("checked"),
48 /**
49 * @override
50 * @param {!WebInspector.Target} target
52 targetAdded: function(target)
56 /**
57 * @override
58 * @param {!WebInspector.Target} target
60 targetRemoved: function(target)
62 this._asyncOperationsByTarget.delete(target);
63 if (this._target === target) {
64 this._clear();
65 delete this._target;
69 /**
70 * @param {!WebInspector.Event} event
72 _targetChanged: function(event)
74 var target = /** @type {!WebInspector.Target} */ (event.data);
75 if (this._target === target)
76 return;
77 this._target = target;
78 this._refresh();
81 /**
82 * @param {?WebInspector.Target} target
83 * @param {number} operationId
84 * @return {?DebuggerAgent.AsyncOperation}
86 operationById: function(target, operationId)
88 if (!target)
89 return null;
90 var operationsMap = this._asyncOperationsByTarget.get(target);
91 if (!operationsMap)
92 return null;
93 return operationsMap.get(operationId) || null;
96 _asyncStackTracesStateChanged: function()
98 var enabled = WebInspector.moduleSetting("enableAsyncStackTraces").get();
99 if (enabled) {
100 this._target = WebInspector.context.flavor(WebInspector.Target);
101 } else if (this._target) {
102 this._asyncOperationsByTarget.delete(this._target);
103 delete this._target;
105 this._updateEmptyElement();
106 this._refresh();
109 _updateEmptyElement: function()
111 var enabled = WebInspector.moduleSetting("enableAsyncStackTraces").get();
112 if (enabled) {
113 this.emptyElement.textContent = WebInspector.UIString("No Async Operations");
114 } else {
115 this.emptyElement.textContent = WebInspector.UIString("Async stack traces are disabled.");
116 this.emptyElement.createTextChild(" ");
117 var enableLink = this.emptyElement.createChild("span", "link");
118 enableLink.textContent = WebInspector.UIString("Enable");
119 enableLink.addEventListener("click", enableAsyncStackTraces, true);
122 function enableAsyncStackTraces()
124 WebInspector.moduleSetting("enableAsyncStackTraces").set(true);
128 /** @override */
129 wasShown: function()
131 if (!this._target && WebInspector.moduleSetting("enableAsyncStackTraces").get()) {
132 this._target = WebInspector.context.flavor(WebInspector.Target);
133 this._refresh();
137 /** @override */
138 willHide: function()
140 this._hidePopover();
143 /** @override */
144 onResize: function()
146 this._hidePopover();
150 * @param {!WebInspector.Target} target
152 revealHiddenCallFrames: function(target)
154 if (this._target !== target || this._revealBlackboxedCallFrames)
155 return;
156 this._revealBlackboxedCallFrames = true;
157 this._refresh();
161 * @param {number} operationId
163 highlightBreakpoint: function(operationId)
165 this._breakpointHitId = operationId;
166 var element = this._operationIdToElement.get(operationId);
167 if (!element)
168 return;
169 this.expand();
170 element.classList.add("breakpoint-hit");
173 clearBreakpointHighlight: function()
175 if (!this._breakpointHitId)
176 return;
177 var element = this._operationIdToElement.get(this._breakpointHitId);
178 if (element)
179 element.classList.remove("breakpoint-hit");
180 delete this._breakpointHitId;
184 * @param {!WebInspector.Event} event
186 _debuggerResumed: function(event)
188 var target = /** @type {!WebInspector.Target} */ (event.target.target());
189 if (this._target !== target || !this._revealBlackboxedCallFrames)
190 return;
191 this._revealBlackboxedCallFrames = false;
192 this._refresh();
196 * @param {!WebInspector.Event} event
198 _debuggerReset: function(event)
200 var target = /** @type {!WebInspector.Target} */ (event.target.target());
201 this._asyncOperationsByTarget.delete(target);
202 if (this._target === target)
203 this._clear();
207 * @param {!WebInspector.Event} event
209 _refreshButtonClicked: function(event)
211 event.consume();
212 this.expand();
213 var debuggerModel = WebInspector.DebuggerModel.fromTarget(this._target);
214 if (debuggerModel)
215 debuggerModel.flushAsyncOperationEvents();
219 * @param {!WebInspector.Event} event
221 _onAsyncOperationStarted: function(event)
223 var target = /** @type {!WebInspector.Target} */ (event.target.target());
224 var operation = /** @type {!DebuggerAgent.AsyncOperation} */ (event.data);
226 var operationsMap = this._asyncOperationsByTarget.get(target);
227 if (!operationsMap) {
228 operationsMap = new Map();
229 this._asyncOperationsByTarget.set(target, operationsMap)
231 operationsMap.set(operation.id, operation);
233 if (this._target === target)
234 this._createAsyncOperationItem(operation);
238 * @param {!WebInspector.Event} event
240 _onAsyncOperationCompleted: function(event)
242 var target = /** @type {!WebInspector.Target} */ (event.target.target());
243 var operationId = /** @type {number} */ (event.data);
245 var operationsMap = this._asyncOperationsByTarget.get(target);
246 if (operationsMap)
247 operationsMap.delete(operationId);
249 if (this._target === target) {
250 var element = this._operationIdToElement.get(operationId);
251 if (element)
252 this.removeListElement(element);
253 this._operationIdToElement.delete(operationId);
254 if (!this._operationIdToElement.size)
255 this._clear();
259 _refresh: function()
261 this._clear();
262 if (!this._target)
263 return;
264 var operationsMap = this._asyncOperationsByTarget.get(this._target);
265 if (!operationsMap || !operationsMap.size)
266 return;
268 // The for..of loop iterates in insertion order.
269 for (var pair of operationsMap) {
270 var operation = /** @type {!DebuggerAgent.AsyncOperation} */ (pair[1]);
271 this._createAsyncOperationItem(operation);
276 * @param {!DebuggerAgent.AsyncOperation} operation
278 _createAsyncOperationItem: function(operation)
280 var element = createElementWithClass("li", "async-operation");
282 var title = operation.description || WebInspector.UIString("Async Operation");
283 var label = createCheckboxLabel(title, operation[this._checkedSymbol]);
284 label.checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, operation.id), false);
285 element.appendChild(label);
286 var debuggerModel = WebInspector.DebuggerModel.fromTarget(this._target);
287 var callFrame = WebInspector.DebuggerPresentationUtils.callFrameAnchorFromStackTrace(debuggerModel, operation.stackTrace, operation.asyncStackTrace, this._revealBlackboxedCallFrames);
288 if (callFrame)
289 element.createChild("div").appendChild(this._linkifier.linkifyConsoleCallFrame(this._target, callFrame));
291 element[this._operationIdSymbol] = operation.id;
292 this._operationIdToElement.set(operation.id, element);
293 this.addListElement(element, this.listElement.firstChild);
295 if (operation.id === this._breakpointHitId) {
296 element.classList.add("breakpoint-hit");
297 this.expand();
302 * @param {number} operationId
303 * @param {!Event} event
305 _checkboxClicked: function(operationId, event)
307 var operation = this.operationById(this._target, operationId);
308 if (!operation)
309 return;
310 var debuggerModel = WebInspector.DebuggerModel.fromTarget(this._target);
311 if (!debuggerModel)
312 return;
313 operation[this._checkedSymbol] = event.target.checked;
314 if (event.target.checked)
315 debuggerModel.setAsyncOperationBreakpoint(operationId);
316 else
317 debuggerModel.removeAsyncOperationBreakpoint(operationId);
320 _clear: function()
322 this._hidePopover();
323 this.reset();
324 this._operationIdToElement.clear();
325 this._linkifier.reset();
328 _hidePopover: function()
330 this._popoverHelper.hidePopover();
334 * @param {!Element} element
335 * @param {!Event} event
336 * @return {!Element|!AnchorBox|undefined}
338 _getPopoverAnchor: function(element, event)
340 var anchor = /** @type {?Element} */ (element.enclosingNodeOrSelfWithNodeName("a"));
341 if (!anchor)
342 return undefined;
343 var operation = this._operationForPopover(anchor);
344 return operation ? anchor : undefined;
348 * @param {!Element} anchor
349 * @param {!WebInspector.Popover} popover
351 _showPopover: function(anchor, popover)
353 var operation = this._operationForPopover(anchor);
354 if (!operation)
355 return;
356 var content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(this._target, this._linkifier, operation.stackTrace, operation.asyncStackTrace);
357 popover.setCanShrink(true);
358 popover.showForAnchor(content, anchor);
362 * @param {!Element} element
363 * @return {?DebuggerAgent.AsyncOperation}
365 _operationForPopover: function(element)
367 var asyncOperations = this._target && this._asyncOperationsByTarget.get(this._target);
368 if (!asyncOperations)
369 return null;
370 var anchor = element.enclosingNodeOrSelfWithClass("async-operation");
371 if (!anchor)
372 return null;
373 var operationId = anchor[this._operationIdSymbol];
374 var operation = operationId && asyncOperations.get(operationId);
375 if (!operation || !operation.stackTrace)
376 return null;
377 return operation;
380 __proto__: WebInspector.BreakpointsSidebarPaneBase.prototype