Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1145)

Side by Side Diff: Source/devtools/front_end/profiler/CanvasProfileView.js

Issue 1073863003: DevTools: remove Canvas profiler from DevTools source base. See details in the bug. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: tests gone Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 /**
32 * @constructor
33 * @extends {WebInspector.VBox}
34 * @param {!WebInspector.CanvasProfileHeader} profile
35 */
36 WebInspector.CanvasProfileView = function(profile)
37 {
38 WebInspector.VBox.call(this);
39 this.registerRequiredCSS("profiler/canvasProfiler.css");
40 this.element.classList.add("canvas-profile-view");
41
42 this._profile = profile;
43 this._traceLogId = profile.traceLogId();
44 this._traceLogPlayer = /** @type {!WebInspector.CanvasTraceLogPlayerProxy} * / (profile.traceLogPlayer());
45 this._linkifier = new WebInspector.Linkifier();
46
47 this._replayInfoSplitView = new WebInspector.SplitView(true, true, "canvasPr ofileViewReplaySplitViewState", 0.34);
48 this._replayInfoSplitView.show(this.element);
49
50 this._imageSplitView = new WebInspector.SplitView(false, true, "canvasProfil eViewSplitViewState", 300);
51 this._replayInfoSplitView.setMainView(this._imageSplitView);
52
53 var replayImageContainerView = new WebInspector.VBoxWithResizeCallback(this. _onReplayImageResize.bind(this));
54 replayImageContainerView.setMinimumSize(50, 28);
55 this._imageSplitView.setMainView(replayImageContainerView);
56
57 var replayImageContainer = replayImageContainerView.element;
58 replayImageContainer.id = "canvas-replay-image-container";
59 var replayImageParent = replayImageContainer.createChild("div", "canvas-repl ay-image-parent");
60 replayImageParent.createChild("span"); // Helps to align the image verticall y.
61 this._replayImageElement = replayImageParent.createChild("img");
62 this._debugInfoElement = replayImageContainer.createChild("div", "canvas-deb ug-info hidden");
63 this._spinnerIcon = replayImageContainer.createChild("div", "spinner-icon sm all hidden");
64
65 var replayLogContainerView = new WebInspector.VBox();
66 replayLogContainerView.setMinimumSize(22, 22);
67 this._imageSplitView.setSidebarView(replayLogContainerView);
68
69 var replayLogContainer = replayLogContainerView.element;
70 var controlsToolbar = new WebInspector.StatusBar(replayLogContainer);
71 var logGridContainer = replayLogContainer.createChild("div", "canvas-replay- log");
72
73 this._createControlButton(controlsToolbar, "first-step-status-bar-item", Web Inspector.UIString("First call."), this._onReplayFirstStepClick.bind(this));
74 this._createControlButton(controlsToolbar, "step-out-status-bar-item", WebIn spector.UIString("Previous call."), this._onReplayStepClick.bind(this, false));
75 this._createControlButton(controlsToolbar, "step-in-status-bar-item", WebIns pector.UIString("Next call."), this._onReplayStepClick.bind(this, true));
76 this._createControlButton(controlsToolbar, "step-backwards-status-bar-item", WebInspector.UIString("Previous drawing call."), this._onReplayDrawingCallClick .bind(this, false));
77 this._createControlButton(controlsToolbar, "step-over-status-bar-item", WebI nspector.UIString("Next drawing call."), this._onReplayDrawingCallClick.bind(thi s, true));
78 this._createControlButton(controlsToolbar, "last-step-status-bar-item", WebI nspector.UIString("Last call."), this._onReplayLastStepClick.bind(this));
79
80 this._replayContextSelector = new WebInspector.StatusBarComboBox(this._onRep layContextChanged.bind(this));
81 this._replayContextSelector.createOption(WebInspector.UIString("<screenshot auto>"), WebInspector.UIString("Show screenshot of the last replayed resource.") , "");
82 controlsToolbar.appendStatusBarItem(this._replayContextSelector);
83
84 this._installReplayInfoSidebarWidgets(replayLogContainer);
85
86 this._replayStateView = new WebInspector.CanvasReplayStateView(this._traceLo gPlayer);
87 this._replayInfoSplitView.setSidebarView(this._replayStateView);
88
89 /** @type {!Object.<string, boolean>} */
90 this._replayContexts = {};
91
92 var columns = [
93 {title: "#", sortable: false, width: "5%"},
94 {title: WebInspector.UIString("Call"), sortable: false, width: "75%", di sclosure: true},
95 {title: WebInspector.UIString("Location"), sortable: false, width: "20%" }
96 ];
97
98 this._logGrid = new WebInspector.DataGrid(columns);
99 this._logGrid.element.classList.add("fill");
100 this._logGrid.show(logGridContainer);
101 this._logGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, th is._replayTraceLog, this);
102
103 this.element.addEventListener("mousedown", this._onMouseClick.bind(this), tr ue);
104
105 this._popoverHelper = new WebInspector.ObjectPopoverHelper(this.element, thi s._popoverAnchor.bind(this), this._resolveObjectForPopover.bind(this), this._onH idePopover.bind(this), true);
106 this._popoverHelper.setRemoteObjectFormatter(this._hexNumbersFormatter.bind( this));
107
108 this._requestTraceLog(0);
109 }
110
111 /**
112 * @const
113 * @type {number}
114 */
115 WebInspector.CanvasProfileView.TraceLogPollingInterval = 500;
116
117 WebInspector.CanvasProfileView.prototype = {
118 dispose: function()
119 {
120 this._linkifier.reset();
121 },
122
123 /**
124 * @return {!Array.<!WebInspector.StatusBarItem>}
125 */
126 statusBarItems: function()
127 {
128 return [];
129 },
130
131 get profile()
132 {
133 return this._profile;
134 },
135
136 _onReplayImageResize: function()
137 {
138 var parent = this._replayImageElement.parentElement;
139 this._replayImageElement.style.maxWidth = (parent.clientWidth - 1) + "px ";
140 this._replayImageElement.style.maxHeight = (parent.clientHeight - 1) + " px";
141 },
142
143 /**
144 * @override
145 * @return {!Array.<!Element>}
146 */
147 elementsToRestoreScrollPositionsFor: function()
148 {
149 return [this._logGrid.scrollContainer];
150 },
151
152 /**
153 * @param {!Element} replayLogElement
154 */
155 _installReplayInfoSidebarWidgets: function(replayLogElement)
156 {
157 this._replayInfoResizeWidgetElement = replayLogElement.createChild("div" , "resizer-widget");
158 this._replayInfoSplitView.addEventListener(WebInspector.SplitView.Events .ShowModeChanged, this._updateReplayInfoResizeWidget, this);
159 this._updateReplayInfoResizeWidget();
160 this._replayInfoSplitView.installResizer(this._replayInfoResizeWidgetEle ment);
161 },
162
163 _updateReplayInfoResizeWidget: function()
164 {
165 this._replayInfoResizeWidgetElement.classList.toggle("hidden", this._rep layInfoSplitView.showMode() !== WebInspector.SplitView.ShowMode.Both);
166 },
167
168 /**
169 * @param {!Event} event
170 */
171 _onMouseClick: function(event)
172 {
173 var resourceLinkElement = event.target.enclosingNodeOrSelfWithClass("can vas-formatted-resource");
174 if (resourceLinkElement) {
175 this._replayInfoSplitView.showBoth();
176 this._replayStateView.selectResource(resourceLinkElement.__resourceI d);
177 event.consume(true);
178 return;
179 }
180 if (event.target.enclosingNodeOrSelfWithClass("webkit-html-resource-link "))
181 event.consume(false);
182 },
183
184 /**
185 * @param {!WebInspector.StatusBar} toolbar
186 * @param {string} className
187 * @param {string} title
188 * @param {function(this:WebInspector.CanvasProfileView)} clickCallback
189 */
190 _createControlButton: function(toolbar, className, title, clickCallback)
191 {
192 var button = new WebInspector.StatusBarButton(title, className + " canva s-replay-button");
193 toolbar.appendStatusBarItem(button);
194
195 button.makeLongClickEnabled();
196 button.addEventListener("click", clickCallback, this);
197 button.addEventListener("longClickDown", clickCallback, this);
198 button.addEventListener("longClickPress", clickCallback, this);
199 },
200
201 _onReplayContextChanged: function()
202 {
203 var selectedContextId = this._replayContextSelector.selectedOption().val ue;
204
205 /**
206 * @param {?CanvasAgent.ResourceState} resourceState
207 * @this {WebInspector.CanvasProfileView}
208 */
209 function didReceiveResourceState(resourceState)
210 {
211 this._enableWaitIcon(false);
212 if (selectedContextId !== this._replayContextSelector.selectedOption ().value)
213 return;
214 var imageURL = (resourceState && resourceState.imageURL) || "";
215 this._replayImageElement.src = imageURL;
216 this._replayImageElement.style.visibility = imageURL ? "" : "hidden" ;
217 }
218
219 this._enableWaitIcon(true);
220 this._traceLogPlayer.getResourceState(selectedContextId, didReceiveResou rceState.bind(this));
221 },
222
223 /**
224 * @param {boolean} forward
225 */
226 _onReplayStepClick: function(forward)
227 {
228 var selectedNode = this._logGrid.selectedNode;
229 if (!selectedNode)
230 return;
231 var nextNode = selectedNode;
232 do {
233 nextNode = forward ? nextNode.traverseNextNode(false) : nextNode.tra versePreviousNode(false);
234 } while (nextNode && typeof nextNode.index !== "number");
235 (nextNode || selectedNode).revealAndSelect();
236 },
237
238 /**
239 * @param {boolean} forward
240 */
241 _onReplayDrawingCallClick: function(forward)
242 {
243 var selectedNode = this._logGrid.selectedNode;
244 if (!selectedNode)
245 return;
246 var nextNode = selectedNode;
247 while (nextNode) {
248 var sibling = forward ? nextNode.nextSibling : nextNode.previousSibl ing;
249 if (sibling) {
250 nextNode = sibling;
251 if (nextNode.hasChildren || nextNode.call.isDrawingCall)
252 break;
253 } else {
254 nextNode = nextNode.parent;
255 if (!forward)
256 break;
257 }
258 }
259 if (!nextNode && forward)
260 this._onReplayLastStepClick();
261 else
262 (nextNode || selectedNode).revealAndSelect();
263 },
264
265 _onReplayFirstStepClick: function()
266 {
267 var firstNode = this._logGrid.rootNode().children[0];
268 if (firstNode)
269 firstNode.revealAndSelect();
270 },
271
272 _onReplayLastStepClick: function()
273 {
274 var lastNode = this._logGrid.rootNode().children.peekLast();
275 if (!lastNode)
276 return;
277 while (lastNode.expanded) {
278 var lastChild = lastNode.children.peekLast();
279 if (!lastChild)
280 break;
281 lastNode = lastChild;
282 }
283 lastNode.revealAndSelect();
284 },
285
286 /**
287 * @param {boolean} enable
288 */
289 _enableWaitIcon: function(enable)
290 {
291 this._spinnerIcon.classList.toggle("hidden", !enable);
292 this._debugInfoElement.classList.toggle("hidden", enable);
293 },
294
295 _replayTraceLog: function()
296 {
297 if (this._pendingReplayTraceLogEvent)
298 return;
299 var index = this._selectedCallIndex();
300 if (index === -1 || index === this._lastReplayCallIndex)
301 return;
302 this._lastReplayCallIndex = index;
303 this._pendingReplayTraceLogEvent = true;
304
305 /**
306 * @param {?CanvasAgent.ResourceState} resourceState
307 * @param {number} replayTime
308 * @this {WebInspector.CanvasProfileView}
309 */
310 function didReplayTraceLog(resourceState, replayTime)
311 {
312 delete this._pendingReplayTraceLogEvent;
313 this._enableWaitIcon(false);
314
315 this._debugInfoElement.textContent = WebInspector.UIString("Replay t ime: %s", Number.secondsToString(replayTime / 1000, true));
316 this._onReplayContextChanged();
317
318 if (index !== this._selectedCallIndex())
319 this._replayTraceLog();
320 }
321 this._enableWaitIcon(true);
322 this._traceLogPlayer.replayTraceLog(index, didReplayTraceLog.bind(this)) ;
323 },
324
325 /**
326 * @param {number} offset
327 */
328 _requestTraceLog: function(offset)
329 {
330 /**
331 * @param {?CanvasAgent.TraceLog} traceLog
332 * @this {WebInspector.CanvasProfileView}
333 */
334 function didReceiveTraceLog(traceLog)
335 {
336 this._enableWaitIcon(false);
337 if (!traceLog)
338 return;
339 var callNodes = [];
340 var calls = traceLog.calls;
341 var index = traceLog.startOffset;
342 for (var i = 0, n = calls.length; i < n; ++i)
343 callNodes.push(this._createCallNode(index++, calls[i]));
344 var contexts = traceLog.contexts;
345 for (var i = 0, n = contexts.length; i < n; ++i) {
346 var contextId = contexts[i].resourceId || "";
347 var description = contexts[i].description || "";
348 if (this._replayContexts[contextId])
349 continue;
350 this._replayContexts[contextId] = true;
351 this._replayContextSelector.createOption(description, WebInspect or.UIString("Show screenshot of this context's canvas."), contextId);
352 }
353 this._appendCallNodes(callNodes);
354 if (traceLog.alive)
355 setTimeout(this._requestTraceLog.bind(this, index), WebInspector .CanvasProfileView.TraceLogPollingInterval);
356 else
357 this._flattenSingleFrameNode();
358 this._profile._updateCapturingStatus(traceLog);
359 this._onReplayLastStepClick(); // Automatically replay the last step .
360 }
361 this._enableWaitIcon(true);
362 this._traceLogPlayer.getTraceLog(offset, undefined, didReceiveTraceLog.b ind(this));
363 },
364
365 /**
366 * @return {number}
367 */
368 _selectedCallIndex: function()
369 {
370 var node = this._logGrid.selectedNode;
371 return node ? this._peekLastRecursively(node).index : -1;
372 },
373
374 /**
375 * @param {!WebInspector.DataGridNode} node
376 * @return {!WebInspector.DataGridNode}
377 */
378 _peekLastRecursively: function(node)
379 {
380 var lastChild;
381 while ((lastChild = node.children.peekLast()))
382 node = lastChild;
383 return node;
384 },
385
386 /**
387 * @param {!Array.<!WebInspector.DataGridNode>} callNodes
388 */
389 _appendCallNodes: function(callNodes)
390 {
391 var rootNode = this._logGrid.rootNode();
392 var frameNode = rootNode.children.peekLast();
393 if (frameNode && this._peekLastRecursively(frameNode).call.isFrameEndCal l)
394 frameNode = null;
395 for (var i = 0, n = callNodes.length; i < n; ++i) {
396 if (!frameNode) {
397 var index = rootNode.children.length;
398 var data = {};
399 data[0] = "";
400 data[1] = WebInspector.UIString("Frame #%d", index + 1);
401 data[2] = "";
402 frameNode = new WebInspector.DataGridNode(data);
403 frameNode.selectable = true;
404 rootNode.appendChild(frameNode);
405 }
406 var nextFrameCallIndex = i + 1;
407 while (nextFrameCallIndex < n && !callNodes[nextFrameCallIndex - 1]. call.isFrameEndCall)
408 ++nextFrameCallIndex;
409 this._appendCallNodesToFrameNode(frameNode, callNodes, i, nextFrameC allIndex);
410 i = nextFrameCallIndex - 1;
411 frameNode = null;
412 }
413 },
414
415 /**
416 * @param {!WebInspector.DataGridNode} frameNode
417 * @param {!Array.<!WebInspector.DataGridNode>} callNodes
418 * @param {number} fromIndex
419 * @param {number} toIndex not inclusive
420 */
421 _appendCallNodesToFrameNode: function(frameNode, callNodes, fromIndex, toInd ex)
422 {
423 var self = this;
424 function appendDrawCallGroup()
425 {
426 var index = self._drawCallGroupsCount || 0;
427 var data = {};
428 data[0] = "";
429 data[1] = WebInspector.UIString("Draw call group #%d", index + 1);
430 data[2] = "";
431 var node = new WebInspector.DataGridNode(data);
432 node.selectable = true;
433 self._drawCallGroupsCount = index + 1;
434 frameNode.appendChild(node);
435 return node;
436 }
437
438 function splitDrawCallGroup(drawCallGroup)
439 {
440 var splitIndex = 0;
441 var splitNode;
442 while ((splitNode = drawCallGroup.children[splitIndex])) {
443 if (splitNode.call.isDrawingCall)
444 break;
445 ++splitIndex;
446 }
447 var newDrawCallGroup = appendDrawCallGroup();
448 var lastNode;
449 while ((lastNode = drawCallGroup.children[splitIndex + 1]))
450 newDrawCallGroup.appendChild(lastNode);
451 return newDrawCallGroup;
452 }
453
454 var drawCallGroup = frameNode.children.peekLast();
455 var groupHasDrawCall = false;
456 if (drawCallGroup) {
457 for (var i = 0, n = drawCallGroup.children.length; i < n; ++i) {
458 if (drawCallGroup.children[i].call.isDrawingCall) {
459 groupHasDrawCall = true;
460 break;
461 }
462 }
463 } else
464 drawCallGroup = appendDrawCallGroup();
465
466 for (var i = fromIndex; i < toIndex; ++i) {
467 var node = callNodes[i];
468 drawCallGroup.appendChild(node);
469 if (node.call.isDrawingCall) {
470 if (groupHasDrawCall)
471 drawCallGroup = splitDrawCallGroup(drawCallGroup);
472 else
473 groupHasDrawCall = true;
474 }
475 }
476 },
477
478 /**
479 * @param {number} index
480 * @param {!CanvasAgent.Call} call
481 * @return {!WebInspector.DataGridNode}
482 */
483 _createCallNode: function(index, call)
484 {
485 var callViewElement = createElement("div");
486
487 var data = {};
488 data[0] = index + 1;
489 data[1] = callViewElement;
490 data[2] = "";
491 if (call.sourceURL) {
492 // FIXME(62725): stack trace line/column numbers are one-based.
493 var lineNumber = Math.max(0, call.lineNumber - 1) || 0;
494 var columnNumber = Math.max(0, call.columnNumber - 1) || 0;
495 data[2] = this._linkifier.linkifyScriptLocation(this._profile.target (), null, call.sourceURL, lineNumber, columnNumber);
496 }
497
498 var node = new WebInspector.DataGridNode(data);
499 node.index = index;
500 node.selectable = true;
501 node.call = call;
502
503 callViewElement.createChild("span", "canvas-function-name").textContent = call.functionName || "context." + call.property;
504 var target = this._profile.target();
505 if (!target)
506 return node;
507
508 if (call.arguments) {
509 callViewElement.createTextChild("(");
510 for (var i = 0, n = call.arguments.length; i < n; ++i) {
511 var argument = /** @type {!CanvasAgent.CallArgument} */ (call.ar guments[i]);
512 if (i)
513 callViewElement.createTextChild(", ");
514 var element = WebInspector.CanvasProfileDataGridHelper.createCal lArgumentElement(target, argument);
515 element.__argumentIndex = i;
516 callViewElement.appendChild(element);
517 }
518 callViewElement.createTextChild(")");
519 } else if (call.value) {
520 callViewElement.createTextChild(" = ");
521 callViewElement.appendChild(WebInspector.CanvasProfileDataGridHelper .createCallArgumentElement(target, call.value));
522 }
523
524 if (call.result) {
525 callViewElement.createTextChild(" => ");
526 callViewElement.appendChild(WebInspector.CanvasProfileDataGridHelper .createCallArgumentElement(target, call.result));
527 }
528
529 return node;
530 },
531
532 /**
533 * @param {!Element} element
534 * @param {!Event} event
535 * @return {!Element|!AnchorBox|undefined}
536 */
537 _popoverAnchor: function(element, event)
538 {
539 var argumentElement = element.enclosingNodeOrSelfWithClass("canvas-call- argument");
540 if (!argumentElement || argumentElement.__suppressPopover)
541 return;
542 return argumentElement;
543 },
544
545 _resolveObjectForPopover: function(argumentElement, showCallback, objectGrou pName)
546 {
547 /**
548 * @param {?Protocol.Error} error
549 * @param {!RuntimeAgent.RemoteObject=} result
550 * @param {!CanvasAgent.ResourceState=} resourceState
551 * @this {WebInspector.CanvasProfileView}
552 */
553 function showObjectPopover(error, result, resourceState)
554 {
555 if (error)
556 return;
557
558 // FIXME: handle resourceState also
559 if (!result)
560 return;
561
562 this._popoverAnchorElement = argumentElement.cloneNode(true);
563 this._popoverAnchorElement.classList.add("canvas-popover-anchor");
564 this._popoverAnchorElement.classList.add("source-frame-eval-expressi on");
565 argumentElement.parentElement.appendChild(this._popoverAnchorElement );
566
567 var diffLeft = this._popoverAnchorElement.boxInWindow().x - argument Element.boxInWindow().x;
568 this._popoverAnchorElement.style.left = this._popoverAnchorElement.o ffsetLeft - diffLeft + "px";
569
570 showCallback(this._profile.target().runtimeModel.createRemoteObject( result), false, this._popoverAnchorElement);
571 }
572
573 var evalResult = argumentElement.__evalResult;
574 if (evalResult)
575 showObjectPopover.call(this, null, evalResult);
576 else {
577 var dataGridNode = this._logGrid.dataGridNodeFromNode(argumentElemen t);
578 if (!dataGridNode || typeof dataGridNode.index !== "number") {
579 this._popoverHelper.hidePopover();
580 return;
581 }
582 var callIndex = dataGridNode.index;
583 var argumentIndex = argumentElement.__argumentIndex;
584 if (typeof argumentIndex !== "number")
585 argumentIndex = -1;
586 this._profile.target().canvasAgent().evaluateTraceLogCallArgument(th is._traceLogId, callIndex, argumentIndex, objectGroupName, showObjectPopover.bin d(this));
587 }
588 },
589
590 /**
591 * @param {!WebInspector.RemoteObject} object
592 * @return {string}
593 */
594 _hexNumbersFormatter: function(object)
595 {
596 if (object.type === "number") {
597 // Show enum values in hex with min length of 4 (e.g. 0x0012).
598 var str = "0000" + Number(object.description).toString(16).toUpperCa se();
599 str = str.replace(/^0+(.{4,})$/, "$1");
600 return "0x" + str;
601 }
602 return object.description || "";
603 },
604
605 _onHidePopover: function()
606 {
607 if (this._popoverAnchorElement) {
608 this._popoverAnchorElement.remove();
609 delete this._popoverAnchorElement;
610 }
611 },
612
613 _flattenSingleFrameNode: function()
614 {
615 var rootNode = this._logGrid.rootNode();
616 if (rootNode.children.length !== 1)
617 return;
618 var frameNode = rootNode.children[0];
619 while (frameNode.children[0])
620 rootNode.appendChild(frameNode.children[0]);
621 rootNode.removeChild(frameNode);
622 },
623
624 __proto__: WebInspector.VBox.prototype
625 }
626
627 /**
628 * @constructor
629 * @implements {WebInspector.TargetManager.Observer}
630 * @extends {WebInspector.ProfileType}
631 */
632 WebInspector.CanvasProfileType = function()
633 {
634 WebInspector.ProfileType.call(this, WebInspector.CanvasProfileType.TypeId, W ebInspector.UIString("Capture Canvas Frame"));
635 this._recording = false;
636 this._lastProfileHeader = null;
637
638 this._capturingModeSelector = new WebInspector.StatusBarComboBox(this._dispa tchViewUpdatedEvent.bind(this));
639 this._capturingModeSelector.element.title = WebInspector.UIString("Canvas ca pture mode.");
640 this._capturingModeSelector.createOption(WebInspector.UIString("Single Frame "), WebInspector.UIString("Capture a single canvas frame."), "");
641 this._capturingModeSelector.createOption(WebInspector.UIString("Consecutive Frames"), WebInspector.UIString("Capture consecutive canvas frames."), "1");
642
643 /** @type {!Object.<string, !Element>} */
644 this._frameOptions = {};
645
646 /** @type {!Object.<string, boolean>} */
647 this._framesWithCanvases = {};
648
649 this._frameSelector = new WebInspector.StatusBarComboBox(this._dispatchViewU pdatedEvent.bind(this));
650 this._frameSelector.element.title = WebInspector.UIString("Frame containing the canvases to capture.");
651 this._frameSelector.element.classList.add("hidden");
652
653 this._target = null;
654 WebInspector.targetManager.observeTargets(this);
655
656 this._canvasAgentEnabled = false;
657
658 this._decorationElement = createElement("div");
659 this._decorationElement.className = "profile-canvas-decoration";
660 this._updateDecorationElement();
661 }
662
663 WebInspector.CanvasProfileType.TypeId = "CANVAS_PROFILE";
664
665 WebInspector.CanvasProfileType.prototype = {
666 /**
667 * @override
668 * @param {!WebInspector.Target} target
669 */
670 targetAdded: function(target)
671 {
672 if (this._target || target !== WebInspector.targetManager.mainTarget())
673 return;
674 this._target = target;
675 this._target.resourceTreeModel.frames().forEach(this._addFrame, this);
676 this._target.resourceTreeModel.addEventListener(WebInspector.ResourceTre eModel.EventTypes.FrameAdded, this._frameAdded, this);
677 this._target.resourceTreeModel.addEventListener(WebInspector.ResourceTre eModel.EventTypes.FrameDetached, this._frameRemoved, this);
678 new WebInspector.CanvasDispatcher(this._target, this);
679 },
680
681 /**
682 * @override
683 * @param {!WebInspector.Target} target
684 */
685 targetRemoved: function(target)
686 {
687 if (this._target !== target)
688 return;
689 this._target.resourceTreeModel.removeEventListener(WebInspector.Resource TreeModel.EventTypes.FrameAdded, this._frameAdded, this);
690 this._target.resourceTreeModel.removeEventListener(WebInspector.Resource TreeModel.EventTypes.FrameDetached, this._frameRemoved, this);
691 this._target = null;
692 },
693
694 /**
695 * @override
696 * @return {!Array.<!WebInspector.StatusBarItem>}
697 */
698 statusBarItems: function()
699 {
700 return [this._capturingModeSelector, this._frameSelector];
701 },
702
703 get buttonTooltip()
704 {
705 if (this._isSingleFrameMode())
706 return WebInspector.UIString("Capture next canvas frame.");
707 else
708 return this._recording ? WebInspector.UIString("Stop capturing canva s frames.") : WebInspector.UIString("Start capturing canvas frames.");
709 },
710
711 /**
712 * @override
713 * @return {boolean}
714 */
715 buttonClicked: function()
716 {
717 if (!this._canvasAgentEnabled)
718 return false;
719 if (this._recording) {
720 this._recording = false;
721 this._stopFrameCapturing();
722 } else if (this._isSingleFrameMode()) {
723 this._recording = false;
724 this._runSingleFrameCapturing();
725 } else {
726 this._recording = true;
727 this._startFrameCapturing();
728 }
729 return this._recording;
730 },
731
732 _runSingleFrameCapturing: function()
733 {
734 var frameId = this._selectedFrameId();
735 WebInspector.targetManager.suspendAllTargets();
736 if (this._target)
737 this._target.canvasAgent().captureFrame(frameId, this._didStartCaptu ringFrame.bind(this, frameId));
738 WebInspector.targetManager.resumeAllTargets();
739 },
740
741 _startFrameCapturing: function()
742 {
743 var frameId = this._selectedFrameId();
744 WebInspector.targetManager.suspendAllTargets();
745 this._target.canvasAgent().startCapturing(frameId, this._didStartCapturi ngFrame.bind(this, frameId));
746 },
747
748 _stopFrameCapturing: function()
749 {
750 if (!this._lastProfileHeader) {
751 WebInspector.targetManager.resumeAllTargets();
752 return;
753 }
754 var profileHeader = this._lastProfileHeader;
755 var traceLogId = profileHeader.traceLogId();
756 this._lastProfileHeader = null;
757 function didStopCapturing()
758 {
759 profileHeader._updateCapturingStatus();
760 }
761 if (this._target)
762 this._target.canvasAgent().stopCapturing(traceLogId, didStopCapturin g);
763 WebInspector.targetManager.resumeAllTargets();
764 },
765
766 /**
767 * @param {string|undefined} frameId
768 * @param {?Protocol.Error} error
769 * @param {!CanvasAgent.TraceLogId} traceLogId
770 */
771 _didStartCapturingFrame: function(frameId, error, traceLogId)
772 {
773 if (error || this._lastProfileHeader && this._lastProfileHeader.traceLog Id() === traceLogId || !this._target)
774 return;
775 var profileHeader = new WebInspector.CanvasProfileHeader(this._target, t his, traceLogId, frameId);
776 this._lastProfileHeader = profileHeader;
777 this.addProfile(profileHeader);
778 profileHeader._updateCapturingStatus();
779 },
780
781 get treeItemTitle()
782 {
783 return WebInspector.UIString("CANVAS PROFILE");
784 },
785
786 get description()
787 {
788 return WebInspector.UIString("Canvas calls instrumentation");
789 },
790
791 /**
792 * @override
793 * @return {!Element}
794 */
795 decorationElement: function()
796 {
797 return this._decorationElement;
798 },
799
800 /**
801 * @override
802 * @param {!WebInspector.ProfileHeader} profile
803 */
804 removeProfile: function(profile)
805 {
806 WebInspector.ProfileType.prototype.removeProfile.call(this, profile);
807 if (this._recording && profile === this._lastProfileHeader)
808 this._recording = false;
809 },
810
811 /**
812 * @param {boolean=} forcePageReload
813 */
814 _updateDecorationElement: function(forcePageReload)
815 {
816 this._decorationElement.removeChildren();
817 this._decorationElement.createChild("label", "", "dt-icon-label").type = "warning-icon";
818 this._decorationElement.createTextChild(this._canvasAgentEnabled ? WebIn spector.UIString("Canvas Profiler is enabled.") : WebInspector.UIString("Canvas Profiler is disabled."));
819 var button = createTextButton(this._canvasAgentEnabled ? WebInspector.UI String("Disable") : WebInspector.UIString("Enable"), this._onProfilerEnableButto nClick.bind(this, !this._canvasAgentEnabled));
820 this._decorationElement.appendChild(button);
821
822 var target = this._target;
823 if (!target)
824 return;
825
826 /**
827 * @param {?Protocol.Error} error
828 * @param {boolean} result
829 */
830 function hasUninstrumentedCanvasesCallback(error, result)
831 {
832 if (error || result)
833 target.resourceTreeModel.reloadPage();
834 }
835
836 if (forcePageReload) {
837 if (this._canvasAgentEnabled) {
838 target.canvasAgent().hasUninstrumentedCanvases(hasUninstrumented CanvasesCallback);
839 } else {
840 for (var frameId in this._framesWithCanvases) {
841 if (this._framesWithCanvases.hasOwnProperty(frameId)) {
842 target.resourceTreeModel.reloadPage();
843 break;
844 }
845 }
846 }
847 }
848 },
849
850 /**
851 * @param {boolean} enable
852 */
853 _onProfilerEnableButtonClick: function(enable)
854 {
855 if (this._canvasAgentEnabled === enable || !this._target)
856 return;
857
858 /**
859 * @param {?Protocol.Error} error
860 * @this {WebInspector.CanvasProfileType}
861 */
862 function callback(error)
863 {
864 if (error)
865 return;
866 this._canvasAgentEnabled = enable;
867 this._updateDecorationElement(true);
868 this._dispatchViewUpdatedEvent();
869 }
870 if (enable)
871 this._target.canvasAgent().enable(callback.bind(this));
872 else
873 this._target.canvasAgent().disable(callback.bind(this));
874 },
875
876 /**
877 * @return {boolean}
878 */
879 _isSingleFrameMode: function()
880 {
881 return !this._capturingModeSelector.selectedOption().value;
882 },
883
884 /**
885 * @param {!WebInspector.Event} event
886 */
887 _frameAdded: function(event)
888 {
889 var frame = /** @type {!WebInspector.ResourceTreeFrame} */ (event.data);
890 this._addFrame(frame);
891 },
892
893 /**
894 * @param {!WebInspector.ResourceTreeFrame} frame
895 */
896 _addFrame: function(frame)
897 {
898 var frameId = frame.id;
899 var option = createElement("option");
900 option.text = frame.displayName();
901 option.title = frame.url;
902 option.value = frameId;
903
904 this._frameOptions[frameId] = option;
905
906 if (this._framesWithCanvases[frameId]) {
907 this._frameSelector.addOption(option);
908 this._dispatchViewUpdatedEvent();
909 }
910 },
911
912 /**
913 * @param {!WebInspector.Event} event
914 */
915 _frameRemoved: function(event)
916 {
917 var frame = /** @type {!WebInspector.ResourceTreeFrame} */ (event.data);
918 var frameId = frame.id;
919 var option = this._frameOptions[frameId];
920 if (option && this._framesWithCanvases[frameId]) {
921 this._frameSelector.removeOption(option);
922 this._dispatchViewUpdatedEvent();
923 }
924 delete this._frameOptions[frameId];
925 delete this._framesWithCanvases[frameId];
926 },
927
928 /**
929 * @param {string} frameId
930 */
931 _contextCreated: function(frameId)
932 {
933 if (this._framesWithCanvases[frameId])
934 return;
935 this._framesWithCanvases[frameId] = true;
936 var option = this._frameOptions[frameId];
937 if (option) {
938 this._frameSelector.addOption(option);
939 this._dispatchViewUpdatedEvent();
940 }
941 },
942
943 /**
944 * @param {!PageAgent.FrameId=} frameId
945 * @param {!CanvasAgent.TraceLogId=} traceLogId
946 */
947 _traceLogsRemoved: function(frameId, traceLogId)
948 {
949 var sidebarElementsToDelete = [];
950 var sidebarElements = /** @type {!Array.<!WebInspector.ProfileSidebarTre eElement>} */ (this.treeElement ? this.treeElement.children() : []);
951 for (var i = 0, n = sidebarElements.length; i < n; ++i) {
952 var header = /** @type {!WebInspector.CanvasProfileHeader} */ (sideb arElements[i].profile);
953 if (!header)
954 continue;
955 if (frameId && frameId !== header.frameId())
956 continue;
957 if (traceLogId && traceLogId !== header.traceLogId())
958 continue;
959 sidebarElementsToDelete.push(sidebarElements[i]);
960 }
961 for (var i = 0, n = sidebarElementsToDelete.length; i < n; ++i)
962 sidebarElementsToDelete[i].ondelete();
963 },
964
965 /**
966 * @return {string|undefined}
967 */
968 _selectedFrameId: function()
969 {
970 var option = this._frameSelector.selectedOption();
971 return option ? option.value : undefined;
972 },
973
974 _dispatchViewUpdatedEvent: function()
975 {
976 this._frameSelector.element.classList.toggle("hidden", this._frameSelect or.size() <= 1);
977 this.dispatchEventToListeners(WebInspector.ProfileType.Events.ViewUpdate d);
978 },
979
980 /**
981 * @override
982 * @return {boolean}
983 */
984 isInstantProfile: function()
985 {
986 return this._isSingleFrameMode();
987 },
988
989 /**
990 * @override
991 * @return {boolean}
992 */
993 isEnabled: function()
994 {
995 return this._canvasAgentEnabled;
996 },
997
998 __proto__: WebInspector.ProfileType.prototype
999 }
1000
1001 /**
1002 * @constructor
1003 * @implements {CanvasAgent.Dispatcher}
1004 * @param {!WebInspector.Target} target
1005 * @param {!WebInspector.CanvasProfileType} profileType
1006 */
1007 WebInspector.CanvasDispatcher = function(target, profileType)
1008 {
1009 this._profileType = profileType;
1010 target.registerCanvasDispatcher(this);
1011 }
1012
1013 WebInspector.CanvasDispatcher.prototype = {
1014 /**
1015 * @override
1016 * @param {string} frameId
1017 */
1018 contextCreated: function(frameId)
1019 {
1020 this._profileType._contextCreated(frameId);
1021 },
1022
1023 /**
1024 * @override
1025 * @param {!PageAgent.FrameId=} frameId
1026 * @param {!CanvasAgent.TraceLogId=} traceLogId
1027 */
1028 traceLogsRemoved: function(frameId, traceLogId)
1029 {
1030 this._profileType._traceLogsRemoved(frameId, traceLogId);
1031 }
1032 }
1033
1034 /**
1035 * @constructor
1036 * @extends {WebInspector.ProfileHeader}
1037 * @param {!WebInspector.Target} target
1038 * @param {!WebInspector.CanvasProfileType} type
1039 * @param {!CanvasAgent.TraceLogId=} traceLogId
1040 * @param {!PageAgent.FrameId=} frameId
1041 */
1042 WebInspector.CanvasProfileHeader = function(target, type, traceLogId, frameId)
1043 {
1044 WebInspector.ProfileHeader.call(this, target, type, WebInspector.UIString("T race Log %d", type.nextProfileUid()));
1045 /** @type {!CanvasAgent.TraceLogId} */
1046 this._traceLogId = traceLogId || "";
1047 this._frameId = frameId;
1048 this._alive = true;
1049 this._traceLogSize = 0;
1050 this._traceLogPlayer = traceLogId ? new WebInspector.CanvasTraceLogPlayerPro xy(target, traceLogId) : null;
1051 }
1052
1053 WebInspector.CanvasProfileHeader.prototype = {
1054 /**
1055 * @return {!CanvasAgent.TraceLogId}
1056 */
1057 traceLogId: function()
1058 {
1059 return this._traceLogId;
1060 },
1061
1062 /**
1063 * @return {?WebInspector.CanvasTraceLogPlayerProxy}
1064 */
1065 traceLogPlayer: function()
1066 {
1067 return this._traceLogPlayer;
1068 },
1069
1070 /**
1071 * @return {!PageAgent.FrameId|undefined}
1072 */
1073 frameId: function()
1074 {
1075 return this._frameId;
1076 },
1077
1078 /**
1079 * @override
1080 * @param {!WebInspector.ProfileType.DataDisplayDelegate} panel
1081 * @return {!WebInspector.ProfileSidebarTreeElement}
1082 */
1083 createSidebarTreeElement: function(panel)
1084 {
1085 return new WebInspector.ProfileSidebarTreeElement(panel, this, "profile- sidebar-tree-item");
1086 },
1087
1088 /**
1089 * @override
1090 * @return {!WebInspector.CanvasProfileView}
1091 */
1092 createView: function()
1093 {
1094 return new WebInspector.CanvasProfileView(this);
1095 },
1096
1097 /**
1098 * @override
1099 */
1100 dispose: function()
1101 {
1102 if (this._traceLogPlayer)
1103 this._traceLogPlayer.dispose();
1104 clearTimeout(this._requestStatusTimer);
1105 this._alive = false;
1106 },
1107
1108 /**
1109 * @param {!CanvasAgent.TraceLog=} traceLog
1110 */
1111 _updateCapturingStatus: function(traceLog)
1112 {
1113 if (!this._traceLogId)
1114 return;
1115
1116 if (traceLog) {
1117 this._alive = traceLog.alive;
1118 this._traceLogSize = traceLog.totalAvailableCalls;
1119 }
1120
1121 var subtitle = this._alive ? WebInspector.UIString("Capturing\u2026 %d c alls", this._traceLogSize) : WebInspector.UIString("Captured %d calls", this._tr aceLogSize);
1122 this.updateStatus(subtitle, this._alive);
1123
1124 if (this._alive) {
1125 clearTimeout(this._requestStatusTimer);
1126 this._requestStatusTimer = setTimeout(this._requestCapturingStatus.b ind(this), WebInspector.CanvasProfileView.TraceLogPollingInterval);
1127 }
1128 },
1129
1130 _requestCapturingStatus: function()
1131 {
1132 /**
1133 * @param {?CanvasAgent.TraceLog} traceLog
1134 * @this {WebInspector.CanvasProfileHeader}
1135 */
1136 function didReceiveTraceLog(traceLog)
1137 {
1138 if (!traceLog)
1139 return;
1140 this._alive = traceLog.alive;
1141 this._traceLogSize = traceLog.totalAvailableCalls;
1142 this._updateCapturingStatus();
1143 }
1144 this._traceLogPlayer.getTraceLog(0, 0, didReceiveTraceLog.bind(this));
1145 },
1146
1147 __proto__: WebInspector.ProfileHeader.prototype
1148 }
1149
1150 WebInspector.CanvasProfileDataGridHelper = {
1151 /**
1152 * @param {!WebInspector.Target} target
1153 * @param {!CanvasAgent.CallArgument} callArgument
1154 * @return {!Element}
1155 */
1156 createCallArgumentElement: function(target, callArgument)
1157 {
1158 if (callArgument.enumName)
1159 return WebInspector.CanvasProfileDataGridHelper.createEnumValueEleme nt(target, callArgument.enumName, +callArgument.description);
1160 var element = createElement("span");
1161 element.className = "canvas-call-argument";
1162 var description = callArgument.description;
1163 if (callArgument.type === "string") {
1164 const maxStringLength = 150;
1165 element.createTextChild("\"");
1166 element.createChild("span", "canvas-formatted-string").textContent = description.trimMiddle(maxStringLength);
1167 element.createTextChild("\"");
1168 element.__suppressPopover = (description.length <= maxStringLength & & !/[\r\n]/.test(description));
1169 if (!element.__suppressPopover)
1170 element.__evalResult = target.runtimeModel.createRemoteObjectFro mPrimitiveValue(description);
1171 } else {
1172 var type = callArgument.subtype || callArgument.type;
1173 if (type) {
1174 element.classList.add("canvas-formatted-" + type);
1175 if (["null", "undefined", "boolean", "number"].indexOf(type) >= 0)
1176 element.__suppressPopover = true;
1177 }
1178 element.textContent = description;
1179 if (callArgument.remoteObject)
1180 element.__evalResult = target.runtimeModel.createRemoteObject(ca llArgument.remoteObject);
1181 }
1182 if (callArgument.resourceId) {
1183 element.classList.add("canvas-formatted-resource");
1184 element.__resourceId = callArgument.resourceId;
1185 }
1186 return element;
1187 },
1188
1189 /**
1190 * @param {!WebInspector.Target} target
1191 * @param {string} enumName
1192 * @param {number} enumValue
1193 * @return {!Element}
1194 */
1195 createEnumValueElement: function(target, enumName, enumValue)
1196 {
1197 var element = createElement("span");
1198 element.className = "canvas-call-argument canvas-formatted-number";
1199 element.textContent = enumName;
1200 element.__evalResult = target.runtimeModel.createRemoteObjectFromPrimiti veValue(enumValue);
1201 return element;
1202 }
1203 }
1204
1205 /**
1206 * @extends {WebInspector.SDKObject}
1207 * @constructor
1208 * @param {!WebInspector.Target} target
1209 * @param {!CanvasAgent.TraceLogId} traceLogId
1210 */
1211 WebInspector.CanvasTraceLogPlayerProxy = function(target, traceLogId)
1212 {
1213 WebInspector.SDKObject.call(this, target);
1214 this._traceLogId = traceLogId;
1215 /** @type {!Object.<string, !CanvasAgent.ResourceState>} */
1216 this._currentResourceStates = {};
1217 /** @type {?CanvasAgent.ResourceId} */
1218 this._defaultResourceId = null;
1219 }
1220
1221 /** @enum {string} */
1222 WebInspector.CanvasTraceLogPlayerProxy.Events = {
1223 CanvasTraceLogReceived: "CanvasTraceLogReceived",
1224 CanvasReplayStateChanged: "CanvasReplayStateChanged",
1225 CanvasResourceStateReceived: "CanvasResourceStateReceived",
1226 }
1227
1228 WebInspector.CanvasTraceLogPlayerProxy.prototype = {
1229 /**
1230 * @param {number|undefined} startOffset
1231 * @param {number|undefined} maxLength
1232 * @param {function(?CanvasAgent.TraceLog):void} userCallback
1233 */
1234 getTraceLog: function(startOffset, maxLength, userCallback)
1235 {
1236 /**
1237 * @param {?Protocol.Error} error
1238 * @param {!CanvasAgent.TraceLog} traceLog
1239 * @this {WebInspector.CanvasTraceLogPlayerProxy}
1240 */
1241 function callback(error, traceLog)
1242 {
1243 if (error || !traceLog) {
1244 userCallback(null);
1245 return;
1246 }
1247 userCallback(traceLog);
1248 this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerProxy .Events.CanvasTraceLogReceived, traceLog);
1249 }
1250 this.target().canvasAgent().getTraceLog(this._traceLogId, startOffset, m axLength, callback.bind(this));
1251 },
1252
1253 dispose: function()
1254 {
1255 this._currentResourceStates = {};
1256 CanvasAgent.dropTraceLog(this._traceLogId);
1257 this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerProxy.Eve nts.CanvasReplayStateChanged);
1258 },
1259
1260 /**
1261 * @param {?CanvasAgent.ResourceId} resourceId
1262 * @param {function(?CanvasAgent.ResourceState):void} userCallback
1263 */
1264 getResourceState: function(resourceId, userCallback)
1265 {
1266 resourceId = resourceId || this._defaultResourceId;
1267 if (!resourceId) {
1268 userCallback(null); // Has not been replayed yet.
1269 return;
1270 }
1271 var effectiveResourceId = /** @type {!CanvasAgent.ResourceId} */ (resour ceId);
1272 if (this._currentResourceStates[effectiveResourceId]) {
1273 userCallback(this._currentResourceStates[effectiveResourceId]);
1274 return;
1275 }
1276
1277 /**
1278 * @param {?Protocol.Error} error
1279 * @param {!CanvasAgent.ResourceState} resourceState
1280 * @this {WebInspector.CanvasTraceLogPlayerProxy}
1281 */
1282 function callback(error, resourceState)
1283 {
1284 if (error || !resourceState) {
1285 userCallback(null);
1286 return;
1287 }
1288 this._currentResourceStates[effectiveResourceId] = resourceState;
1289 userCallback(resourceState);
1290 this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerProxy .Events.CanvasResourceStateReceived, resourceState);
1291 }
1292 this.target().canvasAgent().getResourceState(this._traceLogId, effective ResourceId, callback.bind(this));
1293 },
1294
1295 /**
1296 * @param {number} index
1297 * @param {function(?CanvasAgent.ResourceState, number):void} userCallback
1298 */
1299 replayTraceLog: function(index, userCallback)
1300 {
1301 /**
1302 * @param {?Protocol.Error} error
1303 * @param {!CanvasAgent.ResourceState} resourceState
1304 * @param {number} replayTime
1305 * @this {WebInspector.CanvasTraceLogPlayerProxy}
1306 */
1307 function callback(error, resourceState, replayTime)
1308 {
1309 this._currentResourceStates = {};
1310 if (error) {
1311 userCallback(null, replayTime);
1312 } else {
1313 this._defaultResourceId = resourceState.id;
1314 this._currentResourceStates[resourceState.id] = resourceState;
1315 userCallback(resourceState, replayTime);
1316 }
1317 this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerProxy .Events.CanvasReplayStateChanged);
1318 if (!error)
1319 this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerP roxy.Events.CanvasResourceStateReceived, resourceState);
1320 }
1321 this.target().canvasAgent().replayTraceLog(this._traceLogId, index, call back.bind(this));
1322 },
1323
1324 clearResourceStates: function()
1325 {
1326 this._currentResourceStates = {};
1327 this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerProxy.Eve nts.CanvasReplayStateChanged);
1328 },
1329
1330 __proto__: WebInspector.SDKObject.prototype
1331 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/main/Main.js ('k') | Source/devtools/front_end/profiler/CanvasReplayStateView.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698