Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / HeapSnapshotView.js
index f6d9b27..e05a9ca 100644 (file)
 /**
  * @constructor
  * @extends {WebInspector.View}
- * @param {!WebInspector.ProfilesPanel} parent
  * @param {!WebInspector.HeapProfileHeader} profile
  */
-WebInspector.HeapSnapshotView = function(parent, profile)
+WebInspector.HeapSnapshotView = function(profile)
 {
     WebInspector.View.call(this);
 
     this.element.classList.add("heap-snapshot-view");
 
-    this.parent = parent;
-    profile.profileType().addEventListener(WebInspector.ProfileType.Events.AddProfileHeader, this._onProfileHeaderAdded, this);
+    profile.profileType().addEventListener(WebInspector.HeapSnapshotProfileType.SnapshotReceived, this._onReceivSnapshot, this);
     profile.profileType().addEventListener(WebInspector.ProfileType.Events.RemoveProfileHeader, this._onProfileHeaderRemoved, this);
 
     if (profile._profileType.id === WebInspector.TrackingHeapSnapshotProfileType.TypeId) {
@@ -50,84 +48,74 @@ WebInspector.HeapSnapshotView = function(parent, profile)
         this._trackingOverviewGrid.show(this.element);
     }
 
-    this.viewsContainer = document.createElement("div");
-    this.viewsContainer.classList.add("views-container");
-    this.element.appendChild(this.viewsContainer);
+    this.viewsContainer = new WebInspector.SplitView(false, true, "heapSnapshotRetainersViewSize", 200, 200);
+    this.viewsContainer.show(this.element);
+    this.viewsContainer.setMainElementConstraints(50, 50);
+    this.viewsContainer.setSidebarElementConstraints(70, 70);
 
     this.containmentView = new WebInspector.View();
-    this.containmentView.element.classList.add("view");
     this.containmentDataGrid = new WebInspector.HeapSnapshotContainmentDataGrid();
     this.containmentDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true);
     this.containmentDataGrid.show(this.containmentView.element);
     this.containmentDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this);
 
     this.constructorsView = new WebInspector.View();
-    this.constructorsView.element.classList.add("view");
-    this.constructorsView.element.appendChild(this._createToolbarWithClassNameFilter());
 
     this.constructorsDataGrid = new WebInspector.HeapSnapshotConstructorsDataGrid();
-    this.constructorsDataGrid.element.classList.add("class-view-grid");
     this.constructorsDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true);
     this.constructorsDataGrid.show(this.constructorsView.element);
     this.constructorsDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this);
 
     this.dataGrid = /** @type {!WebInspector.HeapSnapshotSortableDataGrid} */ (this.constructorsDataGrid);
     this.currentView = this.constructorsView;
-    this.currentView.show(this.viewsContainer);
+    this.currentView.show(this.viewsContainer.mainElement());
 
     this.diffView = new WebInspector.View();
-    this.diffView.element.classList.add("view");
-    this.diffView.element.appendChild(this._createToolbarWithClassNameFilter());
 
     this.diffDataGrid = new WebInspector.HeapSnapshotDiffDataGrid();
-    this.diffDataGrid.element.classList.add("class-view-grid");
     this.diffDataGrid.show(this.diffView.element);
     this.diffDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this);
 
     this.dominatorView = new WebInspector.View();
-    this.dominatorView.element.classList.add("view");
     this.dominatorDataGrid = new WebInspector.HeapSnapshotDominatorsDataGrid();
     this.dominatorDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true);
     this.dominatorDataGrid.show(this.dominatorView.element);
     this.dominatorDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this);
 
-    if (WebInspector.HeapSnapshotView.enableAllocationProfiler) {
+    if (WebInspector.experimentsSettings.allocationProfiler.isEnabled() && profile.profileType() === WebInspector.ProfileTypeRegistry.instance.trackingHeapSnapshotProfileType) {
         this.allocationView = new WebInspector.View();
-        this.allocationView.element.classList.add("view");
         this.allocationDataGrid = new WebInspector.AllocationDataGrid();
         this.allocationDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true);
         this.allocationDataGrid.show(this.allocationView.element);
         this.allocationDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this);
     }
 
-    this.retainmentViewHeader = document.createElement("div");
-    this.retainmentViewHeader.classList.add("retainers-view-header");
-    WebInspector.installDragHandle(this.retainmentViewHeader, this._startRetainersHeaderDragging.bind(this), this._retainersHeaderDragging.bind(this), this._endRetainersHeaderDragging.bind(this), "ns-resize");
-    var retainingPathsTitleDiv = document.createElement("div");
-    retainingPathsTitleDiv.className = "title";
-    var retainingPathsTitle = document.createElement("span");
+    this.retainmentViewHeader = document.createElementWithClass("div", "retainers-view-header");
+    var retainingPathsTitleDiv = this.retainmentViewHeader.createChild("div", "title");
+    var retainingPathsTitle = retainingPathsTitleDiv.createChild("span");
     retainingPathsTitle.textContent = WebInspector.UIString("Object's retaining tree");
-    retainingPathsTitleDiv.appendChild(retainingPathsTitle);
-    this.retainmentViewHeader.appendChild(retainingPathsTitleDiv);
-    this.element.appendChild(this.retainmentViewHeader);
+    this.viewsContainer.hideDefaultResizer();
+    this.viewsContainer.installResizer(this.retainmentViewHeader);
 
     this.retainmentView = new WebInspector.View();
-    this.retainmentView.element.classList.add("view");
     this.retainmentView.element.classList.add("retaining-paths-view");
+    this.retainmentView.element.appendChild(this.retainmentViewHeader);
     this.retainmentDataGrid = new WebInspector.HeapSnapshotRetainmentDataGrid();
     this.retainmentDataGrid.show(this.retainmentView.element);
     this.retainmentDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._inspectedObjectChanged, this);
-    this.retainmentView.show(this.element);
+    this.retainmentView.show(this.viewsContainer.sidebarElement());
     this.retainmentDataGrid.reset();
 
     this.viewSelect = new WebInspector.StatusBarComboBox(this._onSelectedViewChanged.bind(this));
 
-    this.views = [{title: WebInspector.UIString("Summary"), view: this.constructorsView, grid: this.constructorsDataGrid},
-                  {title: WebInspector.UIString("Comparison"), view: this.diffView, grid: this.diffDataGrid},
-                  {title: WebInspector.UIString("Containment"), view: this.containmentView, grid: this.containmentDataGrid}];
+    this.views = [{title: WebInspector.UIString("Summary"), view: this.constructorsView, grid: this.constructorsDataGrid}];
+
+    if (profile.profileType() !== WebInspector.ProfileTypeRegistry.instance.trackingHeapSnapshotProfileType)
+        this.views.push({title: WebInspector.UIString("Comparison"), view: this.diffView, grid: this.diffDataGrid});
+    this.views.push({title: WebInspector.UIString("Containment"), view: this.containmentView, grid: this.containmentDataGrid});
     if (WebInspector.settings.showAdvancedHeapSnapshotProperties.get())
         this.views.push({title: WebInspector.UIString("Dominators"), view: this.dominatorView, grid: this.dominatorDataGrid});
-    if (WebInspector.HeapSnapshotView.enableAllocationProfiler)
+    if (this.allocationView)
         this.views.push({title: WebInspector.UIString("Allocation"), view: this.allocationView, grid: this.allocationDataGrid});
     this.views.current = 0;
     for (var i = 0; i < this.views.length; ++i)
@@ -136,21 +124,22 @@ WebInspector.HeapSnapshotView = function(parent, profile)
     this._profile = profile;
 
     this.baseSelect = new WebInspector.StatusBarComboBox(this._changeBase.bind(this));
-    this.baseSelect.element.classList.add("hidden");
     this._updateBaseOptions();
 
-    this.filterSelect = new WebInspector.StatusBarComboBox(this._changeFilter.bind(this));
+    this._filterSelect = new WebInspector.StatusBarComboBox(this._changeFilter.bind(this));
     this._updateFilterOptions();
 
+    this._classNameFilter = new WebInspector.StatusBarInput("Class filter");
+    this._classNameFilter.setOnChangeHandler(this._onClassFilterChanged.bind(this));
+
     this.selectedSizeText = new WebInspector.StatusBarText("");
 
     this._popoverHelper = new WebInspector.ObjectPopoverHelper(this.element, this._getHoverAnchor.bind(this), this._resolveObjectForPopover.bind(this), undefined, true);
 
+    this._updateSelectorsVisibility();
     this._refreshView();
 }
 
-WebInspector.HeapSnapshotView.enableAllocationProfiler = false;
-
 WebInspector.HeapSnapshotView.prototype = {
     _refreshView: function()
     {
@@ -165,6 +154,8 @@ WebInspector.HeapSnapshotView.prototype = {
             var profileIndex = list.indexOf(this._profile);
             this.baseSelect.setSelectedIndex(Math.max(0, profileIndex - 1));
             this.dataGrid.setDataSource(heapSnapshotProxy);
+            if (this._trackingOverviewGrid)
+                this._trackingOverviewGrid._updateGrid();
         }
     },
 
@@ -179,7 +170,11 @@ WebInspector.HeapSnapshotView.prototype = {
 
     get statusBarItems()
     {
-        return [this.viewSelect.element, this.baseSelect.element, this.filterSelect.element, this.selectedSizeText.element];
+        var result = [this.viewSelect.element, this._classNameFilter.element];
+        if (this._profile.profileType() !== WebInspector.ProfileTypeRegistry.instance.trackingHeapSnapshotProfileType)
+            result.push(this.baseSelect.element, this._filterSelect.element);
+        result.push(this.selectedSizeText.element);
+        return result;
     },
 
     wasShown: function()
@@ -205,12 +200,6 @@ WebInspector.HeapSnapshotView.prototype = {
             this.helpPopover.hide();
     },
 
-    onResize: function()
-    {
-        var height = this.retainmentView.element.clientHeight;
-        this._updateRetainmentViewHeight(height);
-    },
-
     searchCanceled: function()
     {
         if (this._searchResults) {
@@ -394,12 +383,12 @@ WebInspector.HeapSnapshotView.prototype = {
 
     _changeFilter: function()
     {
-        var profileIndex = this.filterSelect.selectedIndex() - 1;
+        var profileIndex = this._filterSelect.selectedIndex() - 1;
         this.dataGrid.filterSelectIndexChanged(this._profiles(), profileIndex);
 
         WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
             action: WebInspector.UserMetrics.UserActionNames.HeapSnapshotFilterChanged,
-            label: this.filterSelect.selectedOption().label
+            label: this._filterSelect.selectedOption().label
         });
 
         if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
@@ -412,22 +401,12 @@ WebInspector.HeapSnapshotView.prototype = {
         this.performSearch(this.currentQuery, this._searchFinishedCallback);
     },
 
-    _createToolbarWithClassNameFilter: function()
-    {
-        var toolbar = document.createElement("div");
-        toolbar.classList.add("class-view-toolbar");
-        var classNameFilter = document.createElement("input");
-        classNameFilter.classList.add("class-name-filter");
-        classNameFilter.setAttribute("placeholder", WebInspector.UIString("Class filter"));
-        classNameFilter.addEventListener("keyup", this._changeNameFilter.bind(this, classNameFilter), false);
-        toolbar.appendChild(classNameFilter);
-        return toolbar;
-    },
-
-    _changeNameFilter: function(classNameInputElement)
+    /**
+     * @param {string} value
+     */
+    _onClassFilterChanged: function(value)
     {
-        var filter = classNameInputElement.value;
-        this.dataGrid.changeNameFilter(filter);
+        this.dataGrid.changeNameFilter(value);
     },
 
     /**
@@ -444,7 +423,7 @@ WebInspector.HeapSnapshotView.prototype = {
      */
     populateContextMenu: function(contextMenu, event)
     {
-        this.dataGrid.populateContextMenu(this.parent, contextMenu, event);
+        this.dataGrid.populateContextMenu(contextMenu, event);
     },
 
     _selectionChanged: function(event)
@@ -552,24 +531,14 @@ WebInspector.HeapSnapshotView.prototype = {
 
     _updateSelectorsVisibility: function()
     {
-        if (this.currentView === this.diffView)
-            this.baseSelect.element.classList.remove("hidden");
-        else
-            this.baseSelect.element.classList.add("hidden");
+        this.baseSelect.visible = (this.currentView === this.diffView);
+        this._filterSelect.visible = (this.currentView === this.constructorsView);
+        this._classNameFilter.visible = (this.currentView === this.constructorsView || this.currentView === this.diffView);
 
-        if (this.currentView === this.constructorsView) {
-            if (this._trackingOverviewGrid) {
-                this._trackingOverviewGrid.element.classList.remove("hidden");
+        if (this._trackingOverviewGrid) {
+            this._trackingOverviewGrid.element.classList.toggle("hidden", this.currentView !== this.constructorsView);
+            if (this.currentView === this.constructorsView)
                 this._trackingOverviewGrid.update();
-                this.viewsContainer.classList.add("reserve-80px-at-top");
-            }
-            this.filterSelect.element.classList.remove("hidden");
-        } else {
-            this.filterSelect.element.classList.add("hidden");
-            if (this._trackingOverviewGrid) {
-                this._trackingOverviewGrid.element.classList.add("hidden");
-                this.viewsContainer.classList.remove("reserve-80px-at-top");
-            }
         }
     },
 
@@ -583,7 +552,7 @@ WebInspector.HeapSnapshotView.prototype = {
         var view = this.views[this.views.current];
         this.currentView = view.view;
         this.dataGrid = view.grid;
-        this.currentView.show(this.viewsContainer);
+        this.currentView.show(this.viewsContainer.mainElement());
         this.refreshVisibleData();
         this.dataGrid.updateWidths();
 
@@ -620,44 +589,6 @@ WebInspector.HeapSnapshotView.prototype = {
         element.node.queryObjectContent(showCallback, objectGroupName);
     },
 
-    /**
-     * @return {boolean}
-     */
-    _startRetainersHeaderDragging: function(event)
-    {
-        if (!this.isShowing())
-            return false;
-
-        this._previousDragPosition = event.pageY;
-        return true;
-    },
-
-    _retainersHeaderDragging: function(event)
-    {
-        var height = this.retainmentView.element.clientHeight;
-        height += this._previousDragPosition - event.pageY;
-        this._previousDragPosition = event.pageY;
-        this._updateRetainmentViewHeight(height);
-        event.consume(true);
-    },
-
-    _endRetainersHeaderDragging: function(event)
-    {
-        delete this._previousDragPosition;
-        event.consume();
-    },
-
-    _updateRetainmentViewHeight: function(height)
-    {
-        height = Number.constrain(height, Preferences.minConsoleHeight, this.element.clientHeight - Preferences.minConsoleHeight);
-        this.viewsContainer.style.bottom = (height + this.retainmentViewHeader.clientHeight) + "px";
-        if (this._trackingOverviewGrid && this.currentView === this.constructorsView)
-            this.viewsContainer.classList.add("reserve-80px-at-top");
-        this.retainmentView.element.style.height = height + "px";
-        this.retainmentViewHeader.style.bottom = height + "px";
-        this.currentView.doResize();
-    },
-
     _updateBaseOptions: function()
     {
         var list = this._profiles();
@@ -675,19 +606,19 @@ WebInspector.HeapSnapshotView.prototype = {
     {
         var list = this._profiles();
         // We're assuming that snapshots can only be added.
-        if (this.filterSelect.size() - 1 === list.length)
+        if (this._filterSelect.size() - 1 === list.length)
             return;
 
-        if (!this.filterSelect.size())
-            this.filterSelect.createOption(WebInspector.UIString("All objects"));
+        if (!this._filterSelect.size())
+            this._filterSelect.createOption(WebInspector.UIString("All objects"));
 
-        for (var i = this.filterSelect.size() - 1, n = list.length; i < n; ++i) {
+        for (var i = this._filterSelect.size() - 1, n = list.length; i < n; ++i) {
             var title = list[i].title;
             if (!i)
                 title = WebInspector.UIString("Objects allocated before %s", title);
             else
                 title = WebInspector.UIString("Objects allocated between %s and %s", list[i - 1].title, title);
-            this.filterSelect.createOption(title);
+            this._filterSelect.createOption(title);
         }
     },
 
@@ -700,7 +631,7 @@ WebInspector.HeapSnapshotView.prototype = {
     /**
      * @param {!WebInspector.Event} event
      */
-    _onProfileHeaderAdded: function(event)
+    _onReceivSnapshot: function(event)
     {
         this._updateControls();
     },
@@ -713,7 +644,7 @@ WebInspector.HeapSnapshotView.prototype = {
         var profile = event.data;
         if (this._profile === profile) {
             this.detach();
-            this._profile.profileType().removeEventListener(WebInspector.ProfileType.Events.AddProfileHeader, this._onProfileHeaderAdded, this);
+            this._profile.profileType().removeEventListener(WebInspector.ProfileType.Events.AddProfileHeader, this._onReceivSnapshot, this);
             this._profile.profileType().removeEventListener(WebInspector.ProfileType.Events.RemoveProfileHeader, this._onProfileHeaderRemoved, this);
         } else {
             this._updateControls();
@@ -769,19 +700,10 @@ WebInspector.HeapProfilerDispatcher.prototype = {
     },
 
     /**
-     * @param {!HeapProfilerAgent.ProfileHeader} profileHeader
-     */
-    addProfileHeader: function(profileHeader)
-    {
-        this._genericCaller("addProfileHeader");
-    },
-
-    /**
      * @override
-     * @param {number} uid
      * @param {string} chunk
      */
-    addHeapSnapshotChunk: function(uid, chunk)
+    addHeapSnapshotChunk: function(chunk)
     {
         this._genericCaller("addHeapSnapshotChunk");
     },
@@ -790,8 +712,9 @@ WebInspector.HeapProfilerDispatcher.prototype = {
      * @override
      * @param {number} done
      * @param {number} total
+     * @param {boolean=} finished
      */
-    reportHeapSnapshotProgress: function(done, total)
+    reportHeapSnapshotProgress: function(done, total, finished)
     {
         this._genericCaller("reportHeapSnapshotProgress");
     },
@@ -811,10 +734,12 @@ WebInspector.HeapProfilerDispatcher._dispatcher = new WebInspector.HeapProfilerD
  * @constructor
  * @extends {WebInspector.ProfileType}
  * @implements {HeapProfilerAgent.Dispatcher}
+ * @param {string=} id
+ * @param {string=} title
  */
-WebInspector.HeapSnapshotProfileType = function()
+WebInspector.HeapSnapshotProfileType = function(id, title)
 {
-    WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("Take Heap Snapshot"));
+    WebInspector.ProfileType.call(this, id || WebInspector.HeapSnapshotProfileType.TypeId, title || WebInspector.UIString("Take Heap Snapshot"));
     WebInspector.HeapProfilerDispatcher._dispatcher.register(this);
 }
 
@@ -897,57 +822,51 @@ WebInspector.HeapSnapshotProfileType.prototype = {
     {
         if (this.profileBeingRecorded())
             return;
-        this._profileBeingRecorded = new WebInspector.HeapProfileHeader(this, WebInspector.UIString("Snapshotting\u2026"));
+        this._profileBeingRecorded = new WebInspector.HeapProfileHeader(this);
         this.addProfile(this._profileBeingRecorded);
-        HeapProfilerAgent.takeHeapSnapshot(true, callback);
-    },
+        this._profileBeingRecorded.updateStatus(WebInspector.UIString("Snapshotting\u2026"));
 
-    /**
-     * @param {!HeapProfilerAgent.ProfileHeader} profileHeader
-     */
-    addProfileHeader: function(profileHeader)
-    {
-        var profile = this.profileBeingRecorded();
-        if (!profile)
-            return;
-        profile.title = profileHeader.title;
-        profile.uid = profileHeader.uid;
-
-        profile.sidebarElement.mainTitle = profile.title;
-        profile.sidebarElement.subtitle = "";
-        profile.sidebarElement.wait = false;
-
-        this._profileSamples = null;
-        this._profileBeingRecorded = null;
-
-        WebInspector.panels.profiles._showProfile(profile);
-        profile.existingView()._refreshView();
+        /**
+         * @param {?string} error
+         * @this {WebInspector.HeapSnapshotProfileType}
+         */
+        function didTakeHeapSnapshot(error)
+        {
+            var profile = this._profileBeingRecorded;
+            profile.title = WebInspector.UIString("Snapshot %d", profile.uid);
+            profile._finishLoad();
+            this._profileBeingRecorded = null;
+            WebInspector.panels.profiles.showProfile(profile);
+            callback();
+        }
+        HeapProfilerAgent.takeHeapSnapshot(true, didTakeHeapSnapshot.bind(this));
     },
 
     /**
      * @override
-     * @param {number} uid
      * @param {string} chunk
      */
-    addHeapSnapshotChunk: function(uid, chunk)
+    addHeapSnapshotChunk: function(chunk)
     {
-        var profile = this.getProfile(uid);
-        if (profile)
-            profile.transferChunk(chunk);
+        if (!this.profileBeingRecorded())
+            return;
+        this.profileBeingRecorded().transferChunk(chunk);
     },
 
     /**
      * @override
      * @param {number} done
      * @param {number} total
+     * @param {boolean=} finished
      */
-    reportHeapSnapshotProgress: function(done, total)
+    reportHeapSnapshotProgress: function(done, total, finished)
     {
         var profile = this.profileBeingRecorded();
         if (!profile)
             return;
-        profile.sidebarElement.subtitle = WebInspector.UIString("%.0f%", (done / total) * 100);
-        profile.sidebarElement.wait = true;
+        profile.updateStatus(WebInspector.UIString("%.0f%", (done / total) * 100), true);
+        if (finished)
+            profile._prepareToLoad();
     },
 
     /**
@@ -958,17 +877,6 @@ WebInspector.HeapSnapshotProfileType.prototype = {
         this._reset();
     },
 
-    /**
-     * @override
-     * @param {!WebInspector.ProfileHeader} profile
-     */
-    removeProfile: function(profile)
-    {
-        if (this._profileBeingRecorded !== profile && !profile.fromFile())
-            HeapProfilerAgent.removeProfile(profile.uid);
-        WebInspector.ProfileType.prototype.removeProfile.call(this, profile);
-    },
-
     _snapshotReceived: function(profile)
     {
         if (this._profileBeingRecorded === profile)
@@ -986,8 +894,7 @@ WebInspector.HeapSnapshotProfileType.prototype = {
  */
 WebInspector.TrackingHeapSnapshotProfileType = function()
 {
-    WebInspector.ProfileType.call(this, WebInspector.TrackingHeapSnapshotProfileType.TypeId, WebInspector.UIString("Record Heap Allocations"));
-    WebInspector.HeapProfilerDispatcher._dispatcher.register(this);
+    WebInspector.HeapSnapshotProfileType.call(this, WebInspector.TrackingHeapSnapshotProfileType.TypeId, WebInspector.UIString("Record Heap Allocations"));
 }
 
 WebInspector.TrackingHeapSnapshotProfileType.TypeId = "HEAP-RECORD";
@@ -1038,10 +945,7 @@ WebInspector.TrackingHeapSnapshotProfileType.prototype = {
         if (profileSamples.totalTime < timestamp - profileSamples.timestamps[0])
             profileSamples.totalTime *= 2;
         this.dispatchEventToListeners(WebInspector.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._profileSamples);
-        var profile = this._profileBeingRecorded;
-        profile.sidebarElement.wait = true;
-        if (profile.sidebarElement && !profile.sidebarElement.wait)
-            profile.sidebarElement.wait = true;
+        this._profileBeingRecorded.updateStatus(null, true);
     },
 
     /**
@@ -1080,7 +984,7 @@ WebInspector.TrackingHeapSnapshotProfileType.prototype = {
     {
         if (this.profileBeingRecorded())
             return;
-        this._profileBeingRecorded = new WebInspector.HeapProfileHeader(this, WebInspector.UIString("Recording\u2026"));
+        this._profileBeingRecorded = new WebInspector.HeapProfileHeader(this);
         this._lastSeenIndex = -1;
         this._profileSamples = {
             'sizes': [],
@@ -1092,13 +996,30 @@ WebInspector.TrackingHeapSnapshotProfileType.prototype = {
         this._profileBeingRecorded._profileSamples = this._profileSamples;
         this._recording = true;
         this.addProfile(this._profileBeingRecorded);
-        HeapProfilerAgent.startTrackingHeapObjects();
+        this._profileBeingRecorded.updateStatus(WebInspector.UIString("Recording\u2026"));
+        HeapProfilerAgent.startTrackingHeapObjects(WebInspector.experimentsSettings.allocationProfiler.isEnabled());
         this.dispatchEventToListeners(WebInspector.TrackingHeapSnapshotProfileType.TrackingStarted);
     },
 
     _stopRecordingProfile: function()
     {
-        HeapProfilerAgent.stopTrackingHeapObjects(true);
+        this._profileBeingRecorded.updateStatus(WebInspector.UIString("Snapshotting\u2026"));
+        /**
+         * @param {?string} error
+         * @this {WebInspector.HeapSnapshotProfileType}
+         */
+        function didTakeHeapSnapshot(error)
+        {
+            var profile = this._profileBeingRecorded;
+            if (!profile)
+                return;
+            profile._finishLoad();
+            this._profileSamples = null;
+            this._profileBeingRecorded = null;
+            WebInspector.panels.profiles.showProfile(profile);
+        }
+
+        HeapProfilerAgent.stopTrackingHeapObjects(true, didTakeHeapSnapshot.bind(this));
         this._recording = false;
         this.dispatchEventToListeners(WebInspector.TrackingHeapSnapshotProfileType.TrackingStopped);
     },
@@ -1133,15 +1054,11 @@ WebInspector.TrackingHeapSnapshotProfileType.prototype = {
 
     /**
      * @override
-     * @param {!WebInspector.ProfileHeader} profile
      */
-    removeProfile: function(profile)
+    profileBeingRecordedRemoved: function()
     {
-        if (this._profileBeingRecorded === profile) {
-            this._stopRecordingProfile();
-            this._profileSamples = null;
-        }
-        WebInspector.HeapSnapshotProfileType.prototype.removeProfile.call(this, profile);
+        this._stopRecordingProfile();
+        this._profileSamples = null;
     },
 
     __proto__: WebInspector.HeapSnapshotProfileType.prototype
@@ -1150,13 +1067,12 @@ WebInspector.TrackingHeapSnapshotProfileType.prototype = {
 /**
  * @constructor
  * @extends {WebInspector.ProfileHeader}
- * @param {!WebInspector.ProfileType} type
- * @param {string} title
- * @param {number=} uid
+ * @param {!WebInspector.HeapSnapshotProfileType} type
+ * @param {string=} title
  */
-WebInspector.HeapProfileHeader = function(type, title, uid)
+WebInspector.HeapProfileHeader = function(type, title)
 {
-    WebInspector.ProfileHeader.call(this, type, title, uid);
+    WebInspector.ProfileHeader.call(this, type, title || WebInspector.UIString("Snapshot %d", type._nextProfileUid));
     this.maxJSObjectId = -1;
     /**
      * @type {?WebInspector.HeapSnapshotWorkerProxy}
@@ -1175,7 +1091,6 @@ WebInspector.HeapProfileHeader = function(type, title, uid)
      */
     this._loadCallbacks = [];
     this._totalNumberOfChunks = 0;
-    this._transferHandler = null;
     this._bufferedWriter = null;
 }
 
@@ -1191,12 +1106,11 @@ WebInspector.HeapProfileHeader.prototype = {
 
     /**
      * @override
-     * @param {!WebInspector.ProfilesPanel} profilesPanel
      * @return {!WebInspector.HeapSnapshotView}
      */
-    createView: function(profilesPanel)
+    createView: function()
     {
-        return new WebInspector.HeapSnapshotView(profilesPanel, this);
+        return new WebInspector.HeapSnapshotView(this);
     },
 
     /**
@@ -1211,36 +1125,23 @@ WebInspector.HeapProfileHeader.prototype = {
             callback(this._snapshotProxy);
             return;
         }
-
-        this._numberOfChunks = 0;
-        if (!this._receiver) {
-            this._setupWorker();
-            this._transferHandler = new WebInspector.BackendSnapshotLoader(this);
-            this.sidebarElement.subtitle = WebInspector.UIString("Loading\u2026");
-            this.sidebarElement.wait = true;
-            this._transferSnapshot();
-        }
-        console.assert(this._receiver);
         this._loadCallbacks.push(callback);
     },
 
-    _transferSnapshot: function()
+    _prepareToLoad: function()
     {
-        /**
-         * @this {WebInspector.HeapProfileHeader}
-         */
-        function finishTransfer()
-        {
-            if (this._transferHandler) {
-                this._transferHandler.finishTransfer();
-                this._totalNumberOfChunks = this._transferHandler._totalNumberOfChunks;
-            }
-            if (this._bufferedWriter) {
-                this._bufferedWriter.close(this._didWriteToTempFile.bind(this));
-                this._bufferedWriter = null;
-            }
+        console.assert(!this._receiver, "Already loading");
+        this._setupWorker();
+        this.updateStatus(WebInspector.UIString("Loading\u2026"), true);
+    },
+
+    _finishLoad: function()
+    {
+        this._receiver.close(function() {});
+        if (this._bufferedWriter) {
+            this._bufferedWriter.close(this._didWriteToTempFile.bind(this));
+            this._bufferedWriter = null;
         }
-        HeapProfilerAgent.getHeapSnapshot(this.uid, finishTransfer.bind(this));
     },
 
     _didWriteToTempFile: function(tempFile)
@@ -1254,22 +1155,6 @@ WebInspector.HeapProfileHeader.prototype = {
         }
     },
 
-    /**
-     * @return {string}
-     */
-    snapshotConstructorName: function()
-    {
-        return "JSHeapSnapshot";
-    },
-
-    /**
-     * @return {function (new:WebInspector.HeapSnapshotProxy, !WebInspector.HeapSnapshotWorkerProxy, string)}
-     */
-    snapshotProxyConstructor: function()
-    {
-        return WebInspector.HeapSnapshotProxy;
-    },
-
     _setupWorker: function()
     {
         /**
@@ -1277,12 +1162,12 @@ WebInspector.HeapProfileHeader.prototype = {
          */
         function setProfileWait(event)
         {
-            this.sidebarElement.wait = event.data;
+            this.updateStatus(null, event.data);
         }
         console.assert(!this._workerProxy, "HeapSnapshotWorkerProxy already exists");
         this._workerProxy = new WebInspector.HeapSnapshotWorkerProxy(this._handleWorkerEvent.bind(this));
         this._workerProxy.addEventListener("wait", setProfileWait, this);
-        this._receiver = this._workerProxy.createLoader(this.snapshotConstructorName(), this.snapshotProxyConstructor(), this._snapshotReceived.bind(this));
+        this._receiver = this._workerProxy.createLoader(this.uid, this._snapshotReceived.bind(this));
     },
 
     /**
@@ -1293,7 +1178,8 @@ WebInspector.HeapProfileHeader.prototype = {
     {
         if (WebInspector.HeapSnapshotProgressEvent.Update !== eventName)
             return;
-        this._updateSubtitle(data);
+        var subtitle = /** @type {string} */ (data);
+        this.updateStatus(subtitle);
     },
 
     /**
@@ -1307,17 +1193,11 @@ WebInspector.HeapProfileHeader.prototype = {
         this._wasDisposed = true;
     },
 
-    _updateSubtitle: function(value)
-    {
-        this.sidebarElement.subtitle = value;
-    },
-
     _didCompleteSnapshotTransfer: function()
     {
         if (!this._snapshotProxy)
             return;
-        this.sidebarElement.subtitle = Number.bytesToString(this._snapshotProxy.totalSize);
-        this.sidebarElement.wait = false;
+        this.updateStatus(Number.bytesToString(this._snapshotProxy.totalSize), false);
     },
 
     /**
@@ -1328,7 +1208,9 @@ WebInspector.HeapProfileHeader.prototype = {
         if (!this._bufferedWriter)
             this._bufferedWriter = new WebInspector.BufferedTempFileWriter("heap-profiler", this.uid);
         this._bufferedWriter.write(chunk);
-        this._transferHandler.transferChunk(chunk);
+
+        ++this._totalNumberOfChunks;
+        this._receiver.write(chunk, function() {});
     },
 
     _snapshotReceived: function(snapshotProxy)
@@ -1349,6 +1231,8 @@ WebInspector.HeapProfileHeader.prototype = {
             this._loadCallbacks[i](this._snapshotProxy);
         this._loadCallbacks = null;
         this._profileType._snapshotReceived(this);
+        if (this.canSaveToFile())
+            this.dispatchEventToListeners(WebInspector.ProfileHeader.Events.ProfileReceived);
     },
 
     // Hook point for tests.
@@ -1362,7 +1246,7 @@ WebInspector.HeapProfileHeader.prototype = {
      */
     canSaveToFile: function()
     {
-        return !this.fromFile() && !this._bufferedWriter && !this._failedToCreateTempFile;
+        return !this.fromFile() && this._snapshotProxy;
     },
 
     /**
@@ -1399,7 +1283,7 @@ WebInspector.HeapProfileHeader.prototype = {
     _updateSaveProgress: function(value, total)
     {
         var percentValue = ((total ? (value / total) : 0) * 100).toFixed(0);
-        this._updateSubtitle(WebInspector.UIString("Saving\u2026 %d\%", percentValue));
+        this.updateStatus(WebInspector.UIString("Saving\u2026 %d\%", percentValue));
     },
 
     /**
@@ -1408,10 +1292,8 @@ WebInspector.HeapProfileHeader.prototype = {
      */
     loadFromFile: function(file)
     {
-        this.sidebarElement.subtitle = WebInspector.UIString("Loading\u2026");
-        this.sidebarElement.wait = true;
+        this.updateStatus(WebInspector.UIString("Loading\u2026"), true);
         this._setupWorker();
-
         var delegate = new WebInspector.HeapSnapshotLoadFromFileDelegate(this);
         var fileReader = this._createFileReader(file, delegate);
         fileReader.start(this._receiver);
@@ -1425,74 +1307,6 @@ WebInspector.HeapProfileHeader.prototype = {
     __proto__: WebInspector.ProfileHeader.prototype
 }
 
-
-/**
- * @constructor
- * @param {!WebInspector.HeapProfileHeader} header
- * @param {string} title
- */
-WebInspector.SnapshotTransferHandler = function(header, title)
-{
-    this._numberOfChunks = 0;
-    this._savedChunks = 0;
-    this._header = header;
-    this._totalNumberOfChunks = 0;
-    this._title = title;
-}
-
-
-WebInspector.SnapshotTransferHandler.prototype = {
-    /**
-     * @param {string} chunk
-     */
-    transferChunk: function(chunk)
-    {
-        ++this._numberOfChunks;
-        this._header._receiver.write(chunk, this._didTransferChunk.bind(this));
-    },
-
-    finishTransfer: function()
-    {
-    },
-
-    _didTransferChunk: function()
-    {
-        this._updateProgress(++this._savedChunks, this._totalNumberOfChunks);
-    },
-
-    _updateProgress: function(value, total)
-    {
-    }
-}
-
-
-/**
- * @constructor
- * @param {!WebInspector.HeapProfileHeader} header
- * @extends {WebInspector.SnapshotTransferHandler}
- */
-WebInspector.BackendSnapshotLoader = function(header)
-{
-    WebInspector.SnapshotTransferHandler.call(this, header, "Loading\u2026 %d\%");
-}
-
-
-WebInspector.BackendSnapshotLoader.prototype = {
-    finishTransfer: function()
-    {
-        this._header._receiver.close(this._didFinishTransfer.bind(this));
-        this._totalNumberOfChunks = this._numberOfChunks;
-    },
-
-    _didFinishTransfer: function()
-    {
-        console.assert(this._totalNumberOfChunks === this._savedChunks, "Not all chunks were transfered.");
-    },
-
-    __proto__: WebInspector.SnapshotTransferHandler.prototype
-}
-
-
 /**
  * @constructor
  * @implements {WebInspector.OutputStreamDelegate}
@@ -1523,18 +1337,20 @@ WebInspector.HeapSnapshotLoadFromFileDelegate.prototype = {
      */
     onError: function (reader, e)
     {
+        var subtitle;
         switch(e.target.error.code) {
         case e.target.error.NOT_FOUND_ERR:
-            this._snapshotHeader._updateSubtitle(WebInspector.UIString("'%s' not found.", reader.fileName()));
-        break;
+            subtitle = WebInspector.UIString("'%s' not found.", reader.fileName());
+            break;
         case e.target.error.NOT_READABLE_ERR:
-            this._snapshotHeader._updateSubtitle(WebInspector.UIString("'%s' is not readable", reader.fileName()));
-        break;
-        case e.target.error.ABORT_ERR:
+            subtitle = WebInspector.UIString("'%s' is not readable", reader.fileName());
             break;
+        case e.target.error.ABORT_ERR:
+            return;
         default:
-            this._snapshotHeader._updateSubtitle(WebInspector.UIString("'%s' error %d", reader.fileName(), e.target.error.code));
+            subtitle = WebInspector.UIString("'%s' error %d", reader.fileName(), e.target.error.code);
         }
+        this._snapshotHeader.updateStatus(subtitle);
     }
 }
 
@@ -1588,6 +1404,7 @@ WebInspector.HeapTrackingOverviewGrid = function(heapProfileHeader)
     WebInspector.View.call(this);
     this.registerRequiredCSS("flameChart.css");
     this.element.id = "heap-recording-view";
+    this.element.classList.add("heap-tracking-overview");
 
     this._overviewContainer = this.element.createChild("div", "overview-container");
     this._overviewGrid = new WebInspector.OverviewGrid("heap-recording");