2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * @implements {WebInspector.Searchable}
30 * @extends {WebInspector.VBox}
31 * @param {!WebInspector.CPUProfileHeader} profileHeader
33 WebInspector
.CPUProfileView = function(profileHeader
)
35 WebInspector
.VBox
.call(this);
36 this.element
.classList
.add("cpu-profile-view");
38 this._searchableView
= new WebInspector
.SearchableView(this);
39 this._searchableView
.setPlaceholder(WebInspector
.UIString("Find by cost (>50ms), name or file"));
40 this._searchableView
.show(this.element
);
42 this._viewType
= WebInspector
.settings
.createSetting("cpuProfilerView", WebInspector
.CPUProfileView
._TypeHeavy
);
45 columns
.push({id
: "self", title
: WebInspector
.UIString("Self"), width
: "120px", sort
: WebInspector
.DataGrid
.Order
.Descending
, sortable
: true});
46 columns
.push({id
: "total", title
: WebInspector
.UIString("Total"), width
: "120px", sortable
: true});
47 columns
.push({id
: "function", title
: WebInspector
.UIString("Function"), disclosure
: true, sortable
: true});
49 this.dataGrid
= new WebInspector
.DataGrid(columns
);
50 this.dataGrid
.addEventListener(WebInspector
.DataGrid
.Events
.SortingChanged
, this._sortProfile
, this);
52 this.viewSelectComboBox
= new WebInspector
.ToolbarComboBox(this._changeView
.bind(this));
55 options
[WebInspector
.CPUProfileView
._TypeFlame
] = this.viewSelectComboBox
.createOption(WebInspector
.UIString("Chart"), "", WebInspector
.CPUProfileView
._TypeFlame
);
56 options
[WebInspector
.CPUProfileView
._TypeHeavy
] = this.viewSelectComboBox
.createOption(WebInspector
.UIString("Heavy (Bottom Up)"), "", WebInspector
.CPUProfileView
._TypeHeavy
);
57 options
[WebInspector
.CPUProfileView
._TypeTree
] = this.viewSelectComboBox
.createOption(WebInspector
.UIString("Tree (Top Down)"), "", WebInspector
.CPUProfileView
._TypeTree
);
59 var optionName
= this._viewType
.get() || WebInspector
.CPUProfileView
._TypeFlame
;
60 var option
= options
[optionName
] || options
[WebInspector
.CPUProfileView
._TypeFlame
];
61 this.viewSelectComboBox
.select(option
);
63 this.focusButton
= new WebInspector
.ToolbarButton(WebInspector
.UIString("Focus selected function"), "visibility-toolbar-item");
64 this.focusButton
.setEnabled(false);
65 this.focusButton
.addEventListener("click", this._focusClicked
, this);
67 this.excludeButton
= new WebInspector
.ToolbarButton(WebInspector
.UIString("Exclude selected function"), "delete-toolbar-item");
68 this.excludeButton
.setEnabled(false);
69 this.excludeButton
.addEventListener("click", this._excludeClicked
, this);
71 this.resetButton
= new WebInspector
.ToolbarButton(WebInspector
.UIString("Restore all functions"), "refresh-toolbar-item");
72 this.resetButton
.setEnabled(false);
73 this.resetButton
.addEventListener("click", this._resetClicked
, this);
75 this._profileHeader
= profileHeader
;
76 this._linkifier
= new WebInspector
.Linkifier(new WebInspector
.Linkifier
.DefaultFormatter(30));
78 this.profile
= new WebInspector
.CPUProfileDataModel(profileHeader
._profile
|| profileHeader
.protocolProfile());
82 this._flameChart
.update();
85 WebInspector
.CPUProfileView
._TypeFlame
= "Flame";
86 WebInspector
.CPUProfileView
._TypeTree
= "Tree";
87 WebInspector
.CPUProfileView
._TypeHeavy
= "Heavy";
92 WebInspector
.CPUProfileView
.Searchable = function()
96 WebInspector
.CPUProfileView
.Searchable
.prototype = {
97 jumpToNextSearchResult: function() {},
98 jumpToPreviousSearchResult: function() {},
99 searchCanceled: function() {},
101 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
102 * @param {boolean} shouldJump
103 * @param {boolean=} jumpBackwards
106 performSearch: function(searchConfig
, shouldJump
, jumpBackwards
) {},
110 currentSearchResultIndex: function() {}
113 WebInspector
.CPUProfileView
.prototype = {
116 if (this._flameChart
)
117 this._flameChart
.focus();
119 WebInspector
.Widget
.prototype.focus
.call(this);
123 * @return {?WebInspector.Target}
127 return this._profileHeader
.target();
131 * @param {number} timeLeft
132 * @param {number} timeRight
134 selectRange: function(timeLeft
, timeRight
)
136 if (!this._flameChart
)
138 this._flameChart
.selectRange(timeLeft
, timeRight
);
142 * @return {!Array.<!WebInspector.ToolbarItem>}
144 toolbarItems: function()
146 return [this.viewSelectComboBox
, this.focusButton
, this.excludeButton
, this.resetButton
];
150 * @return {!WebInspector.ProfileDataGridTree}
152 _getBottomUpProfileDataGridTree: function()
154 if (!this._bottomUpProfileDataGridTree
)
155 this._bottomUpProfileDataGridTree
= new WebInspector
.BottomUpProfileDataGridTree(this, /** @type {!ProfilerAgent.CPUProfileNode} */ (this.profile
.profileHead
));
156 return this._bottomUpProfileDataGridTree
;
160 * @return {!WebInspector.ProfileDataGridTree}
162 _getTopDownProfileDataGridTree: function()
164 if (!this._topDownProfileDataGridTree
)
165 this._topDownProfileDataGridTree
= new WebInspector
.TopDownProfileDataGridTree(this, /** @type {!ProfilerAgent.CPUProfileNode} */ (this.profile
.profileHead
));
166 return this._topDownProfileDataGridTree
;
171 this._currentSearchResultIndex
= -1;
176 var selectedProfileNode
= this.dataGrid
.selectedNode
? this.dataGrid
.selectedNode
.profileNode
: null;
178 this.dataGrid
.rootNode().removeChildren();
180 var children
= this.profileDataGridTree
.children
;
181 var count
= children
.length
;
183 for (var index
= 0; index
< count
; ++index
)
184 this.dataGrid
.rootNode().appendChild(children
[index
]);
186 if (selectedProfileNode
)
187 selectedProfileNode
.selected
= true;
190 refreshVisibleData: function()
192 var child
= this.dataGrid
.rootNode().children
[0];
195 child
= child
.traverseNextNode(false, null, true);
200 * @return {!WebInspector.SearchableView}
202 searchableView: function()
204 return this._searchableView
;
211 supportsCaseSensitiveSearch: function()
220 supportsRegexSearch: function()
228 searchCanceled: function()
230 this._searchableElement
.searchCanceled();
235 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
236 * @param {boolean} shouldJump
237 * @param {boolean=} jumpBackwards
239 performSearch: function(searchConfig
, shouldJump
, jumpBackwards
)
241 var matchesCount
= this._searchableElement
.performSearch(searchConfig
, shouldJump
, jumpBackwards
);
242 this._searchableView
.updateSearchMatchesCount(matchesCount
);
243 this._searchableView
.updateCurrentMatchIndex(this._searchableElement
.currentSearchResultIndex());
249 jumpToNextSearchResult: function()
251 this._searchableElement
.jumpToNextSearchResult();
252 this._searchableView
.updateCurrentMatchIndex(this._searchableElement
.currentSearchResultIndex());
258 jumpToPreviousSearchResult: function()
260 this._searchableElement
.jumpToPreviousSearchResult();
261 this._searchableView
.updateCurrentMatchIndex(this._searchableElement
.currentSearchResultIndex());
264 _ensureFlameChartCreated: function()
266 if (this._flameChart
)
268 this._dataProvider
= new WebInspector
.CPUFlameChartDataProvider(this.profile
, this._profileHeader
.target());
269 this._flameChart
= new WebInspector
.CPUProfileFlameChart(this._dataProvider
);
270 this._flameChart
.addEventListener(WebInspector
.FlameChart
.Events
.EntrySelected
, this._onEntrySelected
.bind(this));
274 * @param {!WebInspector.Event} event
276 _onEntrySelected: function(event
)
278 var entryIndex
= event
.data
;
279 var node
= this._dataProvider
._entryNodes
[entryIndex
];
280 var debuggerModel
= this._profileHeader
._debuggerModel
;
281 if (!node
|| !node
.scriptId
|| !debuggerModel
)
283 var script
= debuggerModel
.scriptForId(node
.scriptId
);
286 var location
= /** @type {!WebInspector.DebuggerModel.Location} */ (debuggerModel
.createRawLocation(script
, node
.lineNumber
, node
.columnNumber
));
287 WebInspector
.Revealer
.reveal(WebInspector
.debuggerWorkspaceBinding
.rawLocationToUILocation(location
));
290 _changeView: function()
295 this._searchableView
.closeSearch();
297 if (this._visibleView
)
298 this._visibleView
.detach();
300 this._viewType
.set(this.viewSelectComboBox
.selectedOption().value
);
301 switch (this._viewType
.get()) {
302 case WebInspector
.CPUProfileView
._TypeFlame
:
303 this._ensureFlameChartCreated();
304 this._visibleView
= this._flameChart
;
305 this._searchableElement
= this._flameChart
;
307 case WebInspector
.CPUProfileView
._TypeTree
:
308 this.profileDataGridTree
= this._getTopDownProfileDataGridTree();
310 this._visibleView
= this.dataGrid
;
311 this._searchableElement
= this.profileDataGridTree
;
313 case WebInspector
.CPUProfileView
._TypeHeavy
:
314 this.profileDataGridTree
= this._getBottomUpProfileDataGridTree();
316 this._visibleView
= this.dataGrid
;
317 this._searchableElement
= this.profileDataGridTree
;
321 var isFlame
= this._viewType
.get() === WebInspector
.CPUProfileView
._TypeFlame
;
322 this.focusButton
.setVisible(!isFlame
);
323 this.excludeButton
.setVisible(!isFlame
);
324 this.resetButton
.setVisible(!isFlame
);
326 this._visibleView
.show(this._searchableView
.element
);
329 _focusClicked: function(event
)
331 if (!this.dataGrid
.selectedNode
)
334 this.resetButton
.setEnabled(true);
335 this.profileDataGridTree
.focus(this.dataGrid
.selectedNode
);
337 this.refreshVisibleData();
340 _excludeClicked: function(event
)
342 var selectedNode
= this.dataGrid
.selectedNode
;
347 selectedNode
.deselect();
349 this.resetButton
.setEnabled(true);
350 this.profileDataGridTree
.exclude(selectedNode
);
352 this.refreshVisibleData();
355 _resetClicked: function(event
)
357 this.resetButton
.setEnabled(false);
358 this.profileDataGridTree
.restore();
359 this._linkifier
.reset();
361 this.refreshVisibleData();
364 _dataGridNodeSelected: function(node
)
366 this.focusButton
.setEnabled(true);
367 this.excludeButton
.setEnabled(true);
370 _dataGridNodeDeselected: function(node
)
372 this.focusButton
.setEnabled(false);
373 this.excludeButton
.setEnabled(false);
376 _sortProfile: function()
378 var sortAscending
= this.dataGrid
.isSortOrderAscending();
379 var sortColumnIdentifier
= this.dataGrid
.sortColumnIdentifier();
382 "total": "totalTime",
383 "function": "functionName"
384 }[sortColumnIdentifier
];
386 this.profileDataGridTree
.sort(WebInspector
.ProfileDataGridTree
.propertyComparator(sortProperty
, sortAscending
));
391 __proto__
: WebInspector
.VBox
.prototype
396 * @extends {WebInspector.ProfileType}
398 WebInspector
.CPUProfileType = function()
400 WebInspector
.ProfileType
.call(this, WebInspector
.CPUProfileType
.TypeId
, WebInspector
.UIString("Collect JavaScript CPU Profile"));
401 this._recording
= false;
403 this._nextAnonymousConsoleProfileNumber
= 1;
404 this._anonymousConsoleProfileIdToTitle
= {};
406 WebInspector
.CPUProfileType
.instance
= this;
407 WebInspector
.targetManager
.addModelListener(WebInspector
.CPUProfilerModel
, WebInspector
.CPUProfilerModel
.EventTypes
.ConsoleProfileStarted
, this._consoleProfileStarted
, this);
408 WebInspector
.targetManager
.addModelListener(WebInspector
.CPUProfilerModel
, WebInspector
.CPUProfilerModel
.EventTypes
.ConsoleProfileFinished
, this._consoleProfileFinished
, this);
411 WebInspector
.CPUProfileType
.TypeId
= "CPU";
413 WebInspector
.CPUProfileType
.prototype = {
418 fileExtension: function()
420 return ".cpuprofile";
425 return this._recording
? WebInspector
.UIString("Stop CPU profiling") : WebInspector
.UIString("Start CPU profiling");
432 buttonClicked: function()
434 if (this._recording
) {
435 this.stopRecordingProfile();
438 this.startRecordingProfile();
445 return WebInspector
.UIString("CPU PROFILES");
450 return WebInspector
.UIString("CPU profiles show where the execution time is spent in your page's JavaScript functions.");
454 * @param {!WebInspector.Event} event
456 _consoleProfileStarted: function(event
)
458 var protocolId
= /** @type {string} */ (event
.data
.protocolId
);
459 var scriptLocation
= /** @type {!WebInspector.DebuggerModel.Location} */ (event
.data
.scriptLocation
);
460 var resolvedTitle
= /** @type {string|undefined} */ (event
.data
.title
);
461 if (!resolvedTitle
) {
462 resolvedTitle
= WebInspector
.UIString("Profile %s", this._nextAnonymousConsoleProfileNumber
++);
463 this._anonymousConsoleProfileIdToTitle
[protocolId
] = resolvedTitle
;
465 this._addMessageToConsole(WebInspector
.ConsoleMessage
.MessageType
.Profile
, scriptLocation
, WebInspector
.UIString("Profile '%s' started.", resolvedTitle
));
469 * @param {!WebInspector.Event} event
471 _consoleProfileFinished: function(event
)
473 var protocolId
= /** @type {string} */ (event
.data
.protocolId
);
474 var scriptLocation
= /** @type {!WebInspector.DebuggerModel.Location} */ (event
.data
.scriptLocation
);
475 var cpuProfile
= /** @type {!ProfilerAgent.CPUProfile} */ (event
.data
.cpuProfile
);
476 var resolvedTitle
= /** @type {string|undefined} */ (event
.data
.title
);
477 if (typeof resolvedTitle
=== "undefined") {
478 resolvedTitle
= this._anonymousConsoleProfileIdToTitle
[protocolId
];
479 delete this._anonymousConsoleProfileIdToTitle
[protocolId
];
482 var profile
= new WebInspector
.CPUProfileHeader(scriptLocation
.target(), this, resolvedTitle
);
483 profile
.setProtocolProfile(cpuProfile
);
484 this.addProfile(profile
);
485 this._addMessageToConsole(WebInspector
.ConsoleMessage
.MessageType
.ProfileEnd
, scriptLocation
, WebInspector
.UIString("Profile '%s' finished.", resolvedTitle
));
489 * @param {string} type
490 * @param {!WebInspector.DebuggerModel.Location} scriptLocation
491 * @param {string} messageText
493 _addMessageToConsole: function(type
, scriptLocation
, messageText
)
495 var script
= scriptLocation
.script();
496 var target
= scriptLocation
.target();
497 var message
= new WebInspector
.ConsoleMessage(
499 WebInspector
.ConsoleMessage
.MessageSource
.ConsoleAPI
,
500 WebInspector
.ConsoleMessage
.MessageLevel
.Debug
,
510 scriptId
: scriptLocation
.scriptId
,
511 url
: script
? script
.contentURL() : "",
512 lineNumber
: scriptLocation
.lineNumber
,
513 columnNumber
: scriptLocation
.columnNumber
|| 0
516 target
.consoleModel
.addMessage(message
);
519 startRecordingProfile: function()
521 var target
= WebInspector
.context
.flavor(WebInspector
.Target
);
522 if (this._profileBeingRecorded
|| !target
)
524 var profile
= new WebInspector
.CPUProfileHeader(target
, this);
525 this.setProfileBeingRecorded(profile
);
526 this.addProfile(profile
);
527 profile
.updateStatus(WebInspector
.UIString("Recording\u2026"));
528 this._recording
= true;
529 target
.cpuProfilerModel
.startRecording();
532 stopRecordingProfile: function()
534 this._recording
= false;
535 if (!this._profileBeingRecorded
|| !this._profileBeingRecorded
.target())
539 * @param {?ProfilerAgent.CPUProfile} profile
540 * @this {WebInspector.CPUProfileType}
542 function didStopProfiling(profile
)
544 if (!this._profileBeingRecorded
)
546 console
.assert(profile
);
547 this._profileBeingRecorded
.setProtocolProfile(profile
);
548 this._profileBeingRecorded
.updateStatus("");
549 var recordedProfile
= this._profileBeingRecorded
;
550 this.setProfileBeingRecorded(null);
551 this.dispatchEventToListeners(WebInspector
.ProfileType
.Events
.ProfileComplete
, recordedProfile
);
553 this._profileBeingRecorded
.target().cpuProfilerModel
.stopRecording().then(didStopProfiling
.bind(this));
558 * @param {string} title
559 * @return {!WebInspector.ProfileHeader}
561 createProfileLoadedFromFile: function(title
)
563 return new WebInspector
.CPUProfileHeader(null, this, title
);
569 profileBeingRecordedRemoved: function()
571 this.stopRecordingProfile();
574 __proto__
: WebInspector
.ProfileType
.prototype
579 * @extends {WebInspector.ProfileHeader}
580 * @implements {WebInspector.OutputStream}
581 * @implements {WebInspector.OutputStreamDelegate}
582 * @param {?WebInspector.Target} target
583 * @param {!WebInspector.CPUProfileType} type
584 * @param {string=} title
586 WebInspector
.CPUProfileHeader = function(target
, type
, title
)
588 WebInspector
.ProfileHeader
.call(this, target
, type
, title
|| WebInspector
.UIString("Profile %d", type
.nextProfileUid()));
589 this._debuggerModel
= WebInspector
.DebuggerModel
.fromTarget(target
);
590 this._tempFile
= null;
593 WebInspector
.CPUProfileHeader
.prototype = {
597 onTransferStarted: function()
599 this._jsonifiedProfile
= "";
600 this.updateStatus(WebInspector
.UIString("Loading\u2026 %s", Number
.bytesToString(this._jsonifiedProfile
.length
)), true);
605 * @param {!WebInspector.ChunkedReader} reader
607 onChunkTransferred: function(reader
)
609 this.updateStatus(WebInspector
.UIString("Loading\u2026 %d%%", Number
.bytesToString(this._jsonifiedProfile
.length
)));
615 onTransferFinished: function()
617 this.updateStatus(WebInspector
.UIString("Parsing\u2026"), true);
618 this._profile
= JSON
.parse(this._jsonifiedProfile
);
619 this._jsonifiedProfile
= null;
620 this.updateStatus(WebInspector
.UIString("Loaded"), false);
622 if (this._profileType
.profileBeingRecorded() === this)
623 this._profileType
.setProfileBeingRecorded(null);
628 * @param {!WebInspector.ChunkedReader} reader
631 onError: function(reader
, e
)
634 switch(e
.target
.error
.code
) {
635 case e
.target
.error
.NOT_FOUND_ERR
:
636 subtitle
= WebInspector
.UIString("'%s' not found.", reader
.fileName());
638 case e
.target
.error
.NOT_READABLE_ERR
:
639 subtitle
= WebInspector
.UIString("'%s' is not readable", reader
.fileName());
641 case e
.target
.error
.ABORT_ERR
:
644 subtitle
= WebInspector
.UIString("'%s' error %d", reader
.fileName(), e
.target
.error
.code
);
646 this.updateStatus(subtitle
);
651 * @param {string} text
653 write: function(text
)
655 this._jsonifiedProfile
+= text
;
661 close: function() { },
668 this.removeTempFile();
673 * @param {!WebInspector.ProfileType.DataDisplayDelegate} panel
674 * @return {!WebInspector.ProfileSidebarTreeElement}
676 createSidebarTreeElement: function(panel
)
678 return new WebInspector
.ProfileSidebarTreeElement(panel
, this, "profile-sidebar-tree-item");
683 * @return {!WebInspector.CPUProfileView}
685 createView: function()
687 return new WebInspector
.CPUProfileView(this);
694 canSaveToFile: function()
696 return !this.fromFile() && this._protocolProfile
;
699 saveToFile: function()
701 var fileOutputStream
= new WebInspector
.FileOutputStream();
704 * @param {boolean} accepted
705 * @this {WebInspector.CPUProfileHeader}
707 function onOpenForSave(accepted
)
711 function didRead(data
)
714 fileOutputStream
.write(data
, fileOutputStream
.close
.bind(fileOutputStream
));
716 fileOutputStream
.close();
718 if (this._failedToCreateTempFile
) {
719 WebInspector
.console
.error("Failed to open temp file with heap snapshot");
720 fileOutputStream
.close();
721 } else if (this._tempFile
) {
722 this._tempFile
.read(didRead
);
724 this._onTempFileReady
= onOpenForSave
.bind(this, accepted
);
727 this._fileName
= this._fileName
|| "CPU-" + new Date().toISO8601Compact() + this._profileType
.fileExtension();
728 fileOutputStream
.open(this._fileName
, onOpenForSave
.bind(this));
733 * @param {!File} file
735 loadFromFile: function(file
)
737 this.updateStatus(WebInspector
.UIString("Loading\u2026"), true);
738 var fileReader
= new WebInspector
.ChunkedFileReader(file
, 10000000, this);
739 fileReader
.start(this);
744 * @return {?ProfilerAgent.CPUProfile}
746 protocolProfile: function()
748 return this._protocolProfile
;
752 * @param {!ProfilerAgent.CPUProfile} cpuProfile
754 setProtocolProfile: function(cpuProfile
)
756 this._protocolProfile
= cpuProfile
;
757 this._saveProfileDataToTempFile(cpuProfile
);
758 if (this.canSaveToFile())
759 this.dispatchEventToListeners(WebInspector
.ProfileHeader
.Events
.ProfileReceived
);
763 * @param {!ProfilerAgent.CPUProfile} data
765 _saveProfileDataToTempFile: function(data
)
767 var serializedData
= JSON
.stringify(data
);
770 * @this {WebInspector.CPUProfileHeader}
772 function didCreateTempFile(tempFile
)
774 this._writeToTempFile(tempFile
, serializedData
);
776 WebInspector
.TempFile
.create("cpu-profiler", String(this.uid
))
777 .then(didCreateTempFile
.bind(this));
781 * @param {?WebInspector.TempFile} tempFile
782 * @param {string} serializedData
784 _writeToTempFile: function(tempFile
, serializedData
)
786 this._tempFile
= tempFile
;
788 this._failedToCreateTempFile
= true;
789 this._notifyTempFileReady();
793 * @param {number} fileSize
794 * @this {WebInspector.CPUProfileHeader}
796 function didWriteToTempFile(fileSize
)
799 this._failedToCreateTempFile
= true;
800 tempFile
.finishWriting();
801 this._notifyTempFileReady();
803 tempFile
.write([serializedData
], didWriteToTempFile
.bind(this));
806 _notifyTempFileReady: function()
808 if (this._onTempFileReady
) {
809 this._onTempFileReady();
810 this._onTempFileReady
= null;
814 __proto__
: WebInspector
.ProfileHeader
.prototype