Web Inspector: move profile type specific code out of ProfilesPanel (refactor)
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Feb 2013 10:53:00 +0000 (10:53 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Feb 2013 10:53:00 +0000 (10:53 +0000)
https://bugs.webkit.org/show_bug.cgi?id=110597

Patch by Alexei Filippov <alph@chromium.org> on 2013-02-25
Reviewed by Yury Semikhatsky.

Move profile type specific functionality out of ProfilesPanel class.
This is a first part of WebInspector.ProfilesPanel refactoring.

No new tests as the functionality isn't changed.

Source/WebCore:

* English.lproj/localizedStrings.js:
* inspector/front-end/CPUProfileView.js:
(WebInspector.CPUProfileType):
(WebInspector.CPUProfileType.prototype.addProfileHeader):
(WebInspector.CPUProfileType.prototype.removeProfile):
(WebInspector.CPUProfileType.prototype._requestProfilesFromBackend):
(WebInspector.CPUProfileType.prototype.resetProfiles):
(WebInspector.CPUProfileType.prototype.addHeapSnapshotChunk):
(WebInspector.CPUProfileType.prototype.finishHeapSnapshot):
(WebInspector.CPUProfileType.prototype.reportHeapSnapshotProgress):
* inspector/front-end/CSSSelectorProfileView.js:
(WebInspector.CSSSelectorProfileType.prototype.buttonClicked):
(WebInspector.CSSSelectorProfileType.prototype._startRecordingProfile):
(WebInspector.CSSSelectorProfileType.prototype._stopRecordingProfile):
* inspector/front-end/CanvasProfileView.js:
(WebInspector.CanvasProfileType.prototype.buttonClicked):
(WebInspector.CanvasProfileType.prototype._runSingleFrameCapturing):
(WebInspector.CanvasProfileType.prototype._startFrameCapturing):
(WebInspector.CanvasProfileType.prototype._didStartCapturingFrame):
(WebInspector.CanvasProfileType.prototype._reset):
(WebInspector.CanvasProfileType.prototype.removeProfile):
(WebInspector.CanvasProfileHeader.prototype.dispose):
* inspector/front-end/HeapSnapshotView.js:
(WebInspector.HeapSnapshotView.prototype._profiles):
(WebInspector.HeapSnapshotProfileType):
(WebInspector.HeapSnapshotProfileType.prototype.buttonClicked):
(WebInspector.HeapSnapshotProfileType.prototype.addProfileHeader):
(WebInspector.HeapSnapshotProfileType.prototype.addHeapSnapshotChunk):
(WebInspector.HeapSnapshotProfileType.prototype.finishHeapSnapshot):
(WebInspector.HeapSnapshotProfileType.prototype.reportHeapSnapshotProgress):
(WebInspector.HeapSnapshotProfileType.prototype.resetProfiles):
(WebInspector.HeapSnapshotProfileType.prototype.removeProfile):
(WebInspector.HeapSnapshotProfileType.prototype._requestProfilesFromBackend):
(WebInspector.HeapProfileHeader.prototype._updateTransferProgress):
* inspector/front-end/NativeMemorySnapshotView.js:
(WebInspector.NativeSnapshotProfileType):
(WebInspector.NativeSnapshotProfileType.prototype.addNativeSnapshotChunk):
* inspector/front-end/ProfilesPanel.js:
(WebInspector.ProfileType):
(WebInspector.ProfileType.prototype.buttonClicked):
(WebInspector.ProfileType.prototype.get description):
(WebInspector.ProfileType.prototype.getProfiles):
(WebInspector.ProfileType.prototype.getProfile):
(WebInspector.ProfileType.prototype._makeKey):
(WebInspector.ProfileType.prototype.addProfile):
(WebInspector.ProfileType.prototype.removeProfile):
(WebInspector.ProfileType.prototype.findTemporaryProfile):
(WebInspector.ProfileType.prototype._reset):
(WebInspector.ProfileType.prototype._requestProfilesFromBackend):
(WebInspector.ProfileHeader):
(WebInspector.ProfileHeader.prototype.dispose):
(WebInspector.ProfilesPanel):
(WebInspector.ProfilesPanel.prototype._loadFromFile):
(WebInspector.ProfilesPanel.prototype.toggleRecordButton):
(WebInspector.ProfilesPanel.prototype._populateAllProfiles):
(WebInspector.ProfilesPanel.prototype.wasShown):
(WebInspector.ProfilesPanel.prototype._profilerWasEnabled):
(WebInspector.ProfilesPanel.prototype._reset):
(WebInspector.ProfilesPanel.prototype._registerProfileType.onAddProfileHeader):
(WebInspector.ProfilesPanel.prototype._registerProfileType.onRemoveProfileHeader):
(WebInspector.ProfilesPanel.prototype._registerProfileType.onProgressUpdated):
(WebInspector.ProfilesPanel.prototype._registerProfileType):
(WebInspector.ProfilesPanel.prototype._addProfileHeader):
(WebInspector.ProfilesPanel.prototype._removeProfileHeader):
(WebInspector.ProfilesPanel.prototype._createTemporaryProfile):
(WebInspector.ProfilesPanel.prototype._removeTemporaryProfile):
(WebInspector.ProfilesPanel.prototype.getProfile):
(WebInspector.ProfilesPanel.prototype.showProfile):
(WebInspector.ProfilesPanel.prototype._getAllProfiles):
(WebInspector.ProfilesPanel.prototype._searchableViews):
(WebInspector.ProfilesPanel.prototype.searchCanceled):
(WebInspector.ProfilesPanel.prototype.setRecordingProfile):
(WebInspector.ProfilesPanel.prototype._reportProfileProgress):

LayoutTests:

* inspector/profiler/canvas2d/canvas-replay-log-grid.html:
* inspector/profiler/heap-snapshot-inspect-dom-wrapper-expected.txt:
* inspector/profiler/heap-snapshot-inspect-dom-wrapper.html:
* inspector/profiler/heap-snapshot-loader.html:
* inspector/profiler/heap-snapshot-test.js:
(initialize_HeapSnapshotTest.):
(initialize_HeapSnapshotTest):
* inspector/profiler/profiler-test.js:
(initialize_ProfilerTest.InspectorTest.startProfilerTest.startTest):
(initialize_ProfilerTest.InspectorTest.startProfilerTest):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@143900 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/profiler/canvas2d/canvas-replay-log-grid.html
LayoutTests/inspector/profiler/heap-snapshot-inspect-dom-wrapper-expected.txt
LayoutTests/inspector/profiler/heap-snapshot-inspect-dom-wrapper.html
LayoutTests/inspector/profiler/heap-snapshot-loader.html
LayoutTests/inspector/profiler/heap-snapshot-test.js
LayoutTests/inspector/profiler/profiler-test.js
Source/WebCore/ChangeLog
Source/WebCore/English.lproj/localizedStrings.js
Source/WebCore/inspector/front-end/CPUProfileView.js
Source/WebCore/inspector/front-end/CSSSelectorProfileView.js
Source/WebCore/inspector/front-end/CanvasProfileView.js
Source/WebCore/inspector/front-end/HeapSnapshotView.js
Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js
Source/WebCore/inspector/front-end/ProfilesPanel.js

index 2e8d59e..f127ffd 100644 (file)
@@ -1,3 +1,26 @@
+2013-02-25  Alexei Filippov  <alph@chromium.org>
+
+        Web Inspector: move profile type specific code out of ProfilesPanel (refactor)
+        https://bugs.webkit.org/show_bug.cgi?id=110597
+
+        Reviewed by Yury Semikhatsky.
+
+        Move profile type specific functionality out of ProfilesPanel class.
+        This is a first part of WebInspector.ProfilesPanel refactoring.
+
+        No new tests as the functionality isn't changed.
+
+        * inspector/profiler/canvas2d/canvas-replay-log-grid.html:
+        * inspector/profiler/heap-snapshot-inspect-dom-wrapper-expected.txt:
+        * inspector/profiler/heap-snapshot-inspect-dom-wrapper.html:
+        * inspector/profiler/heap-snapshot-loader.html:
+        * inspector/profiler/heap-snapshot-test.js:
+        (initialize_HeapSnapshotTest.):
+        (initialize_HeapSnapshotTest):
+        * inspector/profiler/profiler-test.js:
+        (initialize_ProfilerTest.InspectorTest.startProfilerTest.startTest):
+        (initialize_ProfilerTest.InspectorTest.startProfilerTest):
+
 2013-02-25  Ádám Kallai  <kadam@inf.u-szeged.hu>
 
         [Qt] Unreviewed gardening. Skipped failing tests.
index 42c0430..083750c 100644 (file)
@@ -52,9 +52,9 @@ function test()
     var profileView;
     var dataGrid;
 
-    function didStartCapturingFrame(profilesPanel, frameId, error, traceLogId)
+    function didStartCapturingFrame(frameId, error, traceLogId)
     {
-        profileHeader = profilesPanel.getProfiles(WebInspector.CanvasProfileType.TypeId)[0];
+        profileHeader = profileType.getProfiles()[0]
         profilesPanel._showProfile(profileHeader);
         InspectorTest.addSniffer(profileHeader, "_updateCapturingStatus", didReceiveFirstFrame);
         InspectorTest.evaluateInConsole("doSomeCanvasCalls(2)");
index 7fd5d10..61e07b7 100644 (file)
@@ -1,6 +1,6 @@
 Test that resolving heap snaphot object to a JS object will not crash on DOM wrapper boilerplate. Test passes if it doesn't crash.
 
-_finishHeapSnapshot 1
+finishHeapSnapshot 1
 _callLoadCallbacks
 Error resolving heap snapshot object: Object is not available
 Error resolving heap snapshot object: Object is not available
index 924d5c5..2380848 100644 (file)
@@ -18,16 +18,17 @@ function test()
 
     function step0()
     {
-        var profiles = WebInspector.panels.profiles.getProfiles("HEAP");
+        var heapProfileType =  WebInspector.panels.profiles.getProfileType("HEAP");
+        var profiles = heapProfileType.getProfiles();
         WebInspector.panels.profiles._showProfile(profiles[profiles.length - 1]);
-        InspectorTest.addSniffer(WebInspector.panels.profiles, "_finishHeapSnapshot", step1);
+        InspectorTest.addSniffer(heapProfileType, "finishHeapSnapshot", step1);
     }
 
     function step1(uid)
     {
-        InspectorTest.addResult("_finishHeapSnapshot " + uid);
+        InspectorTest.addResult("finishHeapSnapshot " + uid);
         var panel = WebInspector.panels.profiles;
-        var profile = panel._profilesIdMap[panel._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
+        var profile = panel.getProfile(WebInspector.HeapSnapshotProfileType.TypeId, uid);
         profile.load(step2.bind(this));
     }
 
index 0cdabdd..158f308 100644 (file)
@@ -28,7 +28,7 @@ function test()
             maxJSObjectId: 6
         });
 
-        var profileHeader = panel._profiles[0];
+        var profileHeader = panel.getProfileType("HEAP").getProfiles()[0];
 
         function getHeapSnapshotMock(uid) {
             for (var i = 0, l = sourceStringified.length; i < l; i += partSize)
index 2e6bb1f..29ca761 100644 (file)
@@ -732,12 +732,12 @@ InspectorTest.takeAndOpenSnapshot = function(generator, callback)
         snapshot.snapshot.typeId = "HEAP";
         snapshot.snapshot.title = profile.title;
         snapshot.snapshot.uid = profile.uid;
-        WebInspector.panels.profiles._addHeapSnapshotChunk(uid, JSON.stringify(snapshot));
-        WebInspector.panels.profiles._finishHeapSnapshot(uid);
+        profileType.addHeapSnapshotChunk(uid, JSON.stringify(snapshot));
+        profileType.finishHeapSnapshot(uid);
     }
     InspectorTest.override(HeapProfilerAgent, "getHeapSnapshot", pushGeneratedSnapshot);
     InspectorTest._takeAndOpenSnapshotCallback = callback;
-    WebInspector.panels.profiles.addProfileHeader(profile);
+    profileType.addProfile(profile);
     WebInspector.panels.profiles._showProfile(profile);
 };
 
index 2bcf30e..17b89d4 100644 (file)
@@ -7,7 +7,7 @@ InspectorTest.startProfilerTest = function(callback)
     function startTest()
     {
         InspectorTest.addResult("Profiler was enabled.");
-        InspectorTest.addSniffer(WebInspector.panels.profiles, "addProfileHeader", InspectorTest._profileHeaderAdded, true);
+        InspectorTest.addSniffer(WebInspector.panels.profiles, "_addProfileHeader", InspectorTest._profileHeaderAdded, true);
         InspectorTest.addSniffer(WebInspector.CPUProfileView.prototype, "refresh", InspectorTest._profileViewRefresh, true);
         InspectorTest.safeWrap(callback)();
     }
index 743984a..18552af 100644 (file)
@@ -1,3 +1,89 @@
+2013-02-25  Alexei Filippov  <alph@chromium.org>
+
+        Web Inspector: move profile type specific code out of ProfilesPanel (refactor)
+        https://bugs.webkit.org/show_bug.cgi?id=110597
+
+        Reviewed by Yury Semikhatsky.
+
+        Move profile type specific functionality out of ProfilesPanel class.
+        This is a first part of WebInspector.ProfilesPanel refactoring.
+
+        No new tests as the functionality isn't changed.
+
+        * English.lproj/localizedStrings.js:
+        * inspector/front-end/CPUProfileView.js:
+        (WebInspector.CPUProfileType):
+        (WebInspector.CPUProfileType.prototype.addProfileHeader):
+        (WebInspector.CPUProfileType.prototype.removeProfile):
+        (WebInspector.CPUProfileType.prototype._requestProfilesFromBackend):
+        (WebInspector.CPUProfileType.prototype.resetProfiles):
+        (WebInspector.CPUProfileType.prototype.addHeapSnapshotChunk):
+        (WebInspector.CPUProfileType.prototype.finishHeapSnapshot):
+        (WebInspector.CPUProfileType.prototype.reportHeapSnapshotProgress):
+        * inspector/front-end/CSSSelectorProfileView.js:
+        (WebInspector.CSSSelectorProfileType.prototype.buttonClicked):
+        (WebInspector.CSSSelectorProfileType.prototype._startRecordingProfile):
+        (WebInspector.CSSSelectorProfileType.prototype._stopRecordingProfile):
+        * inspector/front-end/CanvasProfileView.js:
+        (WebInspector.CanvasProfileType.prototype.buttonClicked):
+        (WebInspector.CanvasProfileType.prototype._runSingleFrameCapturing):
+        (WebInspector.CanvasProfileType.prototype._startFrameCapturing):
+        (WebInspector.CanvasProfileType.prototype._didStartCapturingFrame):
+        (WebInspector.CanvasProfileType.prototype._reset):
+        (WebInspector.CanvasProfileType.prototype.removeProfile):
+        (WebInspector.CanvasProfileHeader.prototype.dispose):
+        * inspector/front-end/HeapSnapshotView.js:
+        (WebInspector.HeapSnapshotView.prototype._profiles):
+        (WebInspector.HeapSnapshotProfileType):
+        (WebInspector.HeapSnapshotProfileType.prototype.buttonClicked):
+        (WebInspector.HeapSnapshotProfileType.prototype.addProfileHeader):
+        (WebInspector.HeapSnapshotProfileType.prototype.addHeapSnapshotChunk):
+        (WebInspector.HeapSnapshotProfileType.prototype.finishHeapSnapshot):
+        (WebInspector.HeapSnapshotProfileType.prototype.reportHeapSnapshotProgress):
+        (WebInspector.HeapSnapshotProfileType.prototype.resetProfiles):
+        (WebInspector.HeapSnapshotProfileType.prototype.removeProfile):
+        (WebInspector.HeapSnapshotProfileType.prototype._requestProfilesFromBackend):
+        (WebInspector.HeapProfileHeader.prototype._updateTransferProgress):
+        * inspector/front-end/NativeMemorySnapshotView.js:
+        (WebInspector.NativeSnapshotProfileType):
+        (WebInspector.NativeSnapshotProfileType.prototype.addNativeSnapshotChunk):
+        * inspector/front-end/ProfilesPanel.js:
+        (WebInspector.ProfileType):
+        (WebInspector.ProfileType.prototype.buttonClicked):
+        (WebInspector.ProfileType.prototype.get description):
+        (WebInspector.ProfileType.prototype.getProfiles):
+        (WebInspector.ProfileType.prototype.getProfile):
+        (WebInspector.ProfileType.prototype._makeKey):
+        (WebInspector.ProfileType.prototype.addProfile):
+        (WebInspector.ProfileType.prototype.removeProfile):
+        (WebInspector.ProfileType.prototype.findTemporaryProfile):
+        (WebInspector.ProfileType.prototype._reset):
+        (WebInspector.ProfileType.prototype._requestProfilesFromBackend):
+        (WebInspector.ProfileHeader):
+        (WebInspector.ProfileHeader.prototype.dispose):
+        (WebInspector.ProfilesPanel):
+        (WebInspector.ProfilesPanel.prototype._loadFromFile):
+        (WebInspector.ProfilesPanel.prototype.toggleRecordButton):
+        (WebInspector.ProfilesPanel.prototype._populateAllProfiles):
+        (WebInspector.ProfilesPanel.prototype.wasShown):
+        (WebInspector.ProfilesPanel.prototype._profilerWasEnabled):
+        (WebInspector.ProfilesPanel.prototype._reset):
+        (WebInspector.ProfilesPanel.prototype._registerProfileType.onAddProfileHeader):
+        (WebInspector.ProfilesPanel.prototype._registerProfileType.onRemoveProfileHeader):
+        (WebInspector.ProfilesPanel.prototype._registerProfileType.onProgressUpdated):
+        (WebInspector.ProfilesPanel.prototype._registerProfileType):
+        (WebInspector.ProfilesPanel.prototype._addProfileHeader):
+        (WebInspector.ProfilesPanel.prototype._removeProfileHeader):
+        (WebInspector.ProfilesPanel.prototype._createTemporaryProfile):
+        (WebInspector.ProfilesPanel.prototype._removeTemporaryProfile):
+        (WebInspector.ProfilesPanel.prototype.getProfile):
+        (WebInspector.ProfilesPanel.prototype.showProfile):
+        (WebInspector.ProfilesPanel.prototype._getAllProfiles):
+        (WebInspector.ProfilesPanel.prototype._searchableViews):
+        (WebInspector.ProfilesPanel.prototype.searchCanceled):
+        (WebInspector.ProfilesPanel.prototype.setRecordingProfile):
+        (WebInspector.ProfilesPanel.prototype._reportProfileProgress):
+
 2013-02-25  Ilya Tikhonovsky  <loislo@chromium.org>
 
         Unreviewed fix of type annotation for this._liveLocations.
index 9020348..5d72a43 100644 (file)
@@ -11,6 +11,7 @@ localizedStrings["%.1f\u2009hrs"] = "%.1f\u2009hrs";
 localizedStrings["%.1f\u2009min"] = "%.1f\u2009min";
 localizedStrings["%.1f\u2009KB"] = "%.1f\u2009KB";
 localizedStrings["%.1f\u2009MB"] = "%.1f\u2009MB";
+localizedStrings["%.0f%"] = "%.0f%";
 localizedStrings["%.2f%"] = "%.2f%";
 localizedStrings["%.2f\u2009s"] = "%.2f\u2009s";
 localizedStrings["%.3f\u2009ms"] = "%.3f\u2009ms";
index 03fbc3b..c26796e 100644 (file)
@@ -571,10 +571,12 @@ WebInspector.CPUProfileView.prototype = {
 /**
  * @constructor
  * @extends {WebInspector.ProfileType}
+ * @implements {ProfilerAgent.Dispatcher}
  */
 WebInspector.CPUProfileType = function()
 {
     WebInspector.ProfileType.call(this, WebInspector.CPUProfileType.TypeId, WebInspector.UIString("Collect JavaScript CPU Profile"));
+    InspectorBackend.registerProfilerDispatcher(this);
     this._recording = false;
     WebInspector.CPUProfileType.instance = this;
 }
@@ -612,6 +614,14 @@ WebInspector.CPUProfileType.prototype = {
         return WebInspector.UIString("CPU profiles show where the execution time is spent in your page's JavaScript functions.");
     },
 
+    /**
+     * @param {ProfilerAgent.ProfileHeader} profileHeader
+     */
+    addProfileHeader: function(profileHeader)
+    {
+        this.addProfile(this.createProfile(profileHeader));
+    },
+
     isRecordingProfile: function()
     {
         return this._recording;
@@ -630,6 +640,9 @@ WebInspector.CPUProfileType.prototype = {
         ProfilerAgent.stop();
     },
 
+    /**
+     * @param {boolean} isProfiling
+     */
     setRecordingProfile: function(isProfiling)
     {
         this._recording = isProfiling;
@@ -638,7 +651,7 @@ WebInspector.CPUProfileType.prototype = {
     /**
      * @override
      * @param {string=} title
-     * @return {WebInspector.ProfileHeader}
+     * @return {!WebInspector.ProfileHeader}
      */
     createTemporaryProfile: function(title)
     {
@@ -649,13 +662,59 @@ WebInspector.CPUProfileType.prototype = {
     /**
      * @override
      * @param {ProfilerAgent.ProfileHeader} profile
-     * @return {WebInspector.ProfileHeader}
+     * @return {!WebInspector.ProfileHeader}
      */
     createProfile: function(profile)
     {
         return new WebInspector.CPUProfileHeader(this, profile.title, profile.uid);
     },
 
+    /**
+     * @override
+     * @param {!WebInspector.ProfileHeader} profile
+     */
+    removeProfile: function(profile)
+    {
+        WebInspector.ProfileType.prototype.removeProfile.call(this, profile);
+        if (!profile.isTemporary)
+            ProfilerAgent.removeProfile(this.id, profile.uid);
+    },
+
+    /**
+     * @override
+     * @param {function(this:WebInspector.ProfileType, ?string, Array.<ProfilerAgent.ProfileHeader>)} populateCallback
+     */
+    _requestProfilesFromBackend: function(populateCallback)
+    {
+        ProfilerAgent.getProfileHeaders(populateCallback);
+    },
+
+    /**
+     * @override
+     */
+    resetProfiles: function()
+    {
+        this._reset();
+    },
+
+    /** @deprecated To be removed from the protocol */
+    addHeapSnapshotChunk: function(uid, chunk)
+    {
+        throw new Error("Never called");
+    },
+
+    /** @deprecated To be removed from the protocol */
+    finishHeapSnapshot: function(uid)
+    {
+        throw new Error("Never called");
+    },
+
+    /** @deprecated To be removed from the protocol */
+    reportHeapSnapshotProgress: function(done, total)
+    {
+        throw new Error("Never called");
+    },
+
     __proto__: WebInspector.ProfileType.prototype
 }
 
index b0107e0..f433c13 100644 (file)
@@ -286,16 +286,15 @@ WebInspector.CSSSelectorProfileType.prototype = {
 
     /**
      * @override
-     * @param {WebInspector.ProfilesPanel} profilesPanel
      * @return {boolean}
      */
-    buttonClicked: function(profilesPanel)
+    buttonClicked: function()
     {
         if (this._recording) {
-            this._stopRecordingProfile(profilesPanel);
+            this._stopRecordingProfile();
             return false;
         } else {
-            this._startRecordingProfile(profilesPanel);
+            this._startRecordingProfile();
             return true;
         }
     },
@@ -320,20 +319,13 @@ WebInspector.CSSSelectorProfileType.prototype = {
         this._recording = isProfiling;
     },
 
-    /**
-     * @param {WebInspector.ProfilesPanel} profilesPanel
-     */
-    _startRecordingProfile: function(profilesPanel)
+    _startRecordingProfile: function()
     {
         this._recording = true;
         CSSAgent.startSelectorProfiler();
-        profilesPanel.setRecordingProfile(WebInspector.CSSSelectorProfileType.TypeId, true);
     },
 
-    /**
-     * @param {WebInspector.ProfilesPanel} profilesPanel
-     */
-    _stopRecordingProfile: function(profilesPanel)
+    _stopRecordingProfile: function()
     {
         /**
          * @param {?Protocol.Error} error
@@ -346,9 +338,7 @@ WebInspector.CSSSelectorProfileType.prototype = {
 
             var uid = this._profileUid++;
             var title = WebInspector.UIString("Profile %d", uid) + String.sprintf(" (%s)", Number.secondsToString(profile.totalTime / 1000));
-            var profileHeader = new WebInspector.CSSProfileHeader(this, title, uid, profile);
-            profilesPanel.addProfileHeader(profileHeader);
-            profilesPanel.setRecordingProfile(WebInspector.CSSSelectorProfileType.TypeId, false);
+            this.addProfile(new WebInspector.CSSProfileHeader(this, title, uid, profile));
         }
 
         this._recording = false;
index 7b383b8..68a7ee1 100644 (file)
@@ -559,41 +559,33 @@ WebInspector.CanvasProfileType.prototype = {
 
     /**
      * @override
-     * @param {WebInspector.ProfilesPanel} profilesPanel
      * @return {boolean}
      */
-    buttonClicked: function(profilesPanel)
+    buttonClicked: function()
     {
         if (this._recording) {
             this._recording = false;
             this._stopFrameCapturing();
         } else if (this._isSingleFrameMode()) {
             this._recording = false;
-            this._runSingleFrameCapturing(profilesPanel);
+            this._runSingleFrameCapturing();
         } else {
             this._recording = true;
-            this._startFrameCapturing(profilesPanel);
+            this._startFrameCapturing();
         }
-        profilesPanel.setRecordingProfile(WebInspector.CanvasProfileType.TypeId, this._recording);
         return this._recording;
     },
 
-    /**
-     * @param {WebInspector.ProfilesPanel} profilesPanel
-     */
-    _runSingleFrameCapturing: function(profilesPanel)
+    _runSingleFrameCapturing: function()
     {
         var frameId = this._selectedFrameId();
-        CanvasAgent.captureFrame(frameId, this._didStartCapturingFrame.bind(this, profilesPanel, frameId));
+        CanvasAgent.captureFrame(frameId, this._didStartCapturingFrame.bind(this, frameId));
     },
 
-    /**
-     * @param {WebInspector.ProfilesPanel} profilesPanel
-     */
-    _startFrameCapturing: function(profilesPanel)
+    _startFrameCapturing: function()
     {
         var frameId = this._selectedFrameId();
-        CanvasAgent.startCapturing(frameId, this._didStartCapturingFrame.bind(this, profilesPanel, frameId));
+        CanvasAgent.startCapturing(frameId, this._didStartCapturingFrame.bind(this, frameId));
     },
 
     _stopFrameCapturing: function()
@@ -611,19 +603,18 @@ WebInspector.CanvasProfileType.prototype = {
     },
 
     /**
-     * @param {WebInspector.ProfilesPanel} profilesPanel
      * @param {string|undefined} frameId
      * @param {?Protocol.Error} error
      * @param {CanvasAgent.TraceLogId} traceLogId
      */
-    _didStartCapturingFrame: function(profilesPanel, frameId, error, traceLogId)
+    _didStartCapturingFrame: function(frameId, error, traceLogId)
     {
         if (error || this._lastProfileHeader && this._lastProfileHeader.traceLogId() === traceLogId)
             return;
         var profileHeader = new WebInspector.CanvasProfileHeader(this, WebInspector.UIString("Trace Log %d", this._nextProfileUid), this._nextProfileUid, traceLogId, frameId);
         ++this._nextProfileUid;
         this._lastProfileHeader = profileHeader;
-        profilesPanel.addProfileHeader(profileHeader);
+        this.addProfile(profileHeader);
         profileHeader._updateCapturingStatus();
     },
 
@@ -649,11 +640,23 @@ WebInspector.CanvasProfileType.prototype = {
     /**
      * @override
      */
-    reset: function()
+    _reset: function()
     {
+        WebInspector.ProfileType.prototype._reset.call(this);
         this._nextProfileUid = 1;
     },
 
+    /**
+     * @override
+     * @param {!WebInspector.ProfileHeader} profile
+     */
+    removeProfile: function(profile)
+    {
+        WebInspector.ProfileType.prototype.removeProfile.call(this, profile);
+        if (this._recording && profile === this._lastProfileHeader)
+            this._recording = false;
+    },
+
     setRecordingProfile: function(isProfiling)
     {
         this._recording = isProfiling;
@@ -662,7 +665,7 @@ WebInspector.CanvasProfileType.prototype = {
     /**
      * @override
      * @param {string=} title
-     * @return {WebInspector.ProfileHeader}
+     * @return {!WebInspector.ProfileHeader}
      */
     createTemporaryProfile: function(title)
     {
@@ -673,7 +676,7 @@ WebInspector.CanvasProfileType.prototype = {
     /**
      * @override
      * @param {ProfilerAgent.ProfileHeader} profile
-     * @return {WebInspector.ProfileHeader}
+     * @return {!WebInspector.ProfileHeader}
      */
     createProfile: function(profile)
     {
@@ -895,15 +898,12 @@ WebInspector.CanvasProfileHeader.prototype = {
 
     /**
      * @override
-     * @param {!WebInspector.ProfilesPanel} profilesPanel
      */
-    dispose: function(profilesPanel)
+    dispose: function()
     {
         if (this._traceLogId) {
             CanvasAgent.dropTraceLog(this._traceLogId);
             clearTimeout(this._requestStatusTimer);
-            if (this._alive)
-                profilesPanel.setRecordingProfile(WebInspector.CanvasProfileType.TypeId, false);
             this._alive = false;
         }
     },
index fb765f9..a5a0009 100644 (file)
@@ -427,7 +427,7 @@ WebInspector.HeapSnapshotView.prototype = {
      */
     _profiles: function()
     {
-        return this.parent.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
+        return this.parent.getProfileType(WebInspector.HeapSnapshotProfileType.TypeId).getProfiles();
     },
 
     /**
@@ -754,10 +754,12 @@ WebInspector.HeapSnapshotView.prototype = {
 /**
  * @constructor
  * @extends {WebInspector.ProfileType}
+ * @implements {HeapProfilerAgent.Dispatcher}
  */
 WebInspector.HeapSnapshotProfileType = function()
 {
     WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("Take Heap Snapshot"));
+    InspectorBackend.registerHeapProfilerDispatcher(this);
 }
 
 WebInspector.HeapSnapshotProfileType.TypeId = "HEAP";
@@ -770,12 +772,11 @@ WebInspector.HeapSnapshotProfileType.prototype = {
 
     /**
      * @override
-     * @param {WebInspector.ProfilesPanel} profilesPanel
      * @return {boolean}
      */
-    buttonClicked: function(profilesPanel)
+    buttonClicked: function()
     {
-        profilesPanel.takeHeapSnapshot();
+        this._takeHeapSnapshot();
         return false;
     },
 
@@ -792,7 +793,7 @@ WebInspector.HeapSnapshotProfileType.prototype = {
     /**
      * @override
      * @param {string=} title
-     * @return {WebInspector.ProfileHeader}
+     * @return {!WebInspector.ProfileHeader}
      */
     createTemporaryProfile: function(title)
     {
@@ -803,13 +804,93 @@ WebInspector.HeapSnapshotProfileType.prototype = {
     /**
      * @override
      * @param {HeapProfilerAgent.ProfileHeader} profile
-     * @return {WebInspector.ProfileHeader}
+     * @return {!WebInspector.ProfileHeader}
      */
     createProfile: function(profile)
     {
         return new WebInspector.HeapProfileHeader(this, profile.title, profile.uid, profile.maxJSObjectId || 0);
     },
 
+    _takeHeapSnapshot: function()
+    {
+        var temporaryProfile = this.findTemporaryProfile();
+        if (!temporaryProfile)
+            this.addProfile(this.createTemporaryProfile());
+        HeapProfilerAgent.takeHeapSnapshot(true, function() {});
+        WebInspector.userMetrics.ProfilesHeapProfileTaken.record();
+    },
+
+    /**
+     * @param {HeapProfilerAgent.ProfileHeader} profileHeader
+     */
+    addProfileHeader: function(profileHeader)
+    {
+        this.addProfile(this.createProfile(profileHeader));
+    },
+
+    /**
+     * @override
+     * @param {number} uid
+     * @param {string} chunk
+     */
+    addHeapSnapshotChunk: function(uid, chunk)
+    {
+        var profile = this._profilesIdMap[this._makeKey(uid)];
+        if (profile)
+            profile.transferChunk(chunk);
+    },
+
+    /**
+     * @override
+     * @param {number} uid
+     */
+    finishHeapSnapshot: function(uid)
+    {
+        var profile = this._profilesIdMap[this._makeKey(uid)];
+        if (profile)
+            profile.finishHeapSnapshot();
+    },
+
+    /**
+     * @override
+     * @param {number} done
+     * @param {number} total
+     */
+    reportHeapSnapshotProgress: function(done, total)
+    {
+        var profile = this.findTemporaryProfile();
+        if (profile)
+            this.dispatchEventToListeners(WebInspector.ProfileType.Events.ProgressUpdated, {"profile": profile, "done": done, "total": total});
+    },
+
+    /**
+     * @override
+     */
+    resetProfiles: function()
+    {
+        this._reset();
+    },
+
+    /**
+     * @override
+     * @param {!WebInspector.ProfileHeader} profile
+     */
+    removeProfile: function(profile)
+    {
+        WebInspector.ProfileType.prototype.removeProfile.call(this, profile);
+        if (!profile.isTemporary)
+            HeapProfilerAgent.removeProfile(profile.uid);
+    },
+
+    /**
+     * @override
+     * @param {function(this:WebInspector.ProfileType, ?string, Array.<ProfilerAgent.ProfileHeader>)} populateCallback
+     */
+    _requestProfilesFromBackend: function(populateCallback)
+    {
+        HeapProfilerAgent.getProfileHeaders(populateCallback);
+    },
+
     __proto__: WebInspector.ProfileType.prototype
 }
 
@@ -901,6 +982,9 @@ WebInspector.HeapProfileHeader.prototype = {
         this._receiver = loaderProxy;
     },
 
+    /**
+     * @override
+     */
     dispose: function()
     {
         if (this._receiver)
@@ -915,7 +999,7 @@ WebInspector.HeapProfileHeader.prototype = {
      */
     _updateTransferProgress: function(value, maxValue)
     {
-        var percentValue = ((maxValue ? (value / maxValue) : 0) * 100).toFixed(2);
+        var percentValue = ((maxValue ? (value / maxValue) : 0) * 100).toFixed(0);
         if (this._savingToFile)
             this.sidebarElement.subtitle = WebInspector.UIString("Saving\u2026 %d\%", percentValue);
         else
index 4ee4b0e..e213e2e 100644 (file)
@@ -235,10 +235,12 @@ WebInspector.NativeSnapshotNode.prototype = {
 /**
  * @constructor
  * @extends {WebInspector.ProfileType}
+ * @implements {MemoryAgent.Dispatcher}
  */
 WebInspector.NativeSnapshotProfileType = function()
 {
     WebInspector.ProfileType.call(this, WebInspector.NativeSnapshotProfileType.TypeId, WebInspector.UIString("Take Native Heap Snapshot"));
+    InspectorBackend.registerMemoryDispatcher(this);
     this._nextProfileUid = 1;
 }
 
@@ -252,15 +254,14 @@ WebInspector.NativeSnapshotProfileType.prototype = {
 
     /**
      * @override
-     * @param {WebInspector.ProfilesPanel} profilesPanel
      * @return {boolean}
      */
-    buttonClicked: function(profilesPanel)
+    buttonClicked: function()
     {
         var profileHeader = new WebInspector.NativeSnapshotProfileHeader(this, WebInspector.UIString("Snapshot %d", this._nextProfileUid), this._nextProfileUid);
         ++this._nextProfileUid;
         profileHeader.isTemporary = true;
-        profilesPanel.addProfileHeader(profileHeader);
+        this.addProfile(profileHeader);
         profileHeader.load(function() { });
 
         /**
@@ -347,6 +348,17 @@ WebInspector.NativeSnapshotProfileType.prototype = {
         return new WebInspector.NativeSnapshotProfileHeader(this, profile.title, -1);
     },
 
+    /**
+     * @override
+     * @param {MemoryAgent.HeapSnapshotChunk} chunk
+     */
+    addNativeSnapshotChunk: function(chunk)
+    {
+        var tempProfile = this.findTemporaryProfile();
+        if (tempProfile)
+            tempProfile.addNativeSnapshotChunk(chunk);
+    },
+
     __proto__: WebInspector.ProfileType.prototype
 }
 
@@ -401,6 +413,8 @@ WebInspector.NativeSnapshotProfileHeader.prototype = {
 /**
  * @constructor
  * @extends {WebInspector.HeapSnapshotView}
+ * @param {WebInspector.ProfilesPanel} parent
+ * @param {WebInspector.NativeSnapshotProfileHeader} profile
  */
 WebInspector.NativeHeapSnapshotView = function(parent, profile)
 {
@@ -439,15 +453,14 @@ WebInspector.NativeMemoryProfileType.prototype = {
 
     /**
      * @override
-     * @param {WebInspector.ProfilesPanel} profilesPanel
      * @return {boolean}
      */
-    buttonClicked: function(profilesPanel)
+    buttonClicked: function()
     {
         var profileHeader = new WebInspector.NativeMemoryProfileHeader(this, WebInspector.UIString("Snapshot %d", this._nextProfileUid), this._nextProfileUid);
         ++this._nextProfileUid;
         profileHeader.isTemporary = true;
-        profilesPanel.addProfileHeader(profileHeader);
+        this.addProfile(profileHeader);
         /**
          * @param {?string} error
          * @param {?MemoryAgent.MemoryBlock} memoryBlock
index 9ac7511..18c3705 100644 (file)
@@ -35,14 +35,18 @@ WebInspector.ProfileType = function(id, name)
 {
     this._id = id;
     this._name = name;
-    /**
-     * @type {WebInspector.SidebarSectionTreeElement}
-     */
+    /** @type {!Array.<!WebInspector.ProfileHeader>} */
+    this._profiles = [];
+    this._profilesIdMap = {};
+    /** @type {WebInspector.SidebarSectionTreeElement} */
     this.treeElement = null;
 }
 
 WebInspector.ProfileType.Events = {
-  ViewUpdated: "view-updated",
+    AddProfileHeader: "add-profile-header",
+    RemoveProfileHeader: "remove-profile-header",
+    ProgressUpdated: "progress-updated",
+    ViewUpdated: "view-updated"
 }
 
 WebInspector.ProfileType.prototype = {
@@ -72,21 +76,24 @@ WebInspector.ProfileType.prototype = {
     },
 
     /**
-     * @param {WebInspector.ProfilesPanel} profilesPanel
      * @return {boolean}
      */
-    buttonClicked: function(profilesPanel)
+    buttonClicked: function()
     {
         return false;
     },
 
-    reset: function()
+    get description()
     {
+        return "";
     },
 
-    get description()
+    /**
+     * @return {!Array.<!WebInspector.ProfileHeader>}
+     */
+    getProfiles: function()
     {
-        return "";
+        return this._profiles.filter(function(profile) { return !profile.isTemporary; });
     },
 
     /**
@@ -97,10 +104,20 @@ WebInspector.ProfileType.prototype = {
         return null;
     },
 
+    /**
+     * @nosideeffects
+     * @param {number} uid
+     * @return {WebInspector.ProfileHeader}
+     */
+    getProfile: function(uid)
+    {
+        return this._profilesIdMap[this._makeKey(uid)];
+    },
+
     // Must be implemented by subclasses.
     /**
      * @param {string=} title
-     * @return {WebInspector.ProfileHeader}
+     * @return {!WebInspector.ProfileHeader}
      */
     createTemporaryProfile: function(title)
     {
@@ -109,13 +126,103 @@ WebInspector.ProfileType.prototype = {
 
     /**
      * @param {ProfilerAgent.ProfileHeader} profile
-     * @return {WebInspector.ProfileHeader}
+     * @return {!WebInspector.ProfileHeader}
      */
     createProfile: function(profile)
     {
         throw new Error("Not supported for " + this._name + " profiles.");
     },
 
+    /**
+     * @nosideeffects
+     * @param {number} id
+     * @return {string}
+     */
+    _makeKey: function(id)
+    {
+        return id + '/' + escape(this.id);
+    },
+
+    /**
+     * @param {!WebInspector.ProfileHeader} profile
+     */
+    addProfile: function(profile)
+    {
+        this._profiles.push(profile);
+        // FIXME: uid only based key should be enough.
+        this._profilesIdMap[this._makeKey(profile.uid)] = profile;
+        this.dispatchEventToListeners(WebInspector.ProfileType.Events.AddProfileHeader, profile);
+    },
+
+    /**
+     * @param {!WebInspector.ProfileHeader} profile
+     */
+    removeProfile: function(profile)
+    {
+        for (var i = 0; i < this._profiles.length; ++i) {
+            if (this._profiles[i].uid === profile.uid) {
+                this._profiles.splice(i, 1);
+                break;
+            }
+        }
+        delete this._profilesIdMap[this._makeKey(profile.uid)];
+    },
+
+    /**
+     * @nosideeffects
+     * @return {WebInspector.ProfileHeader}
+     */
+    findTemporaryProfile: function()
+    {
+        for (var i = 0; i < this._profiles.length; ++i) {
+            if (this._profiles[i].isTemporary)
+                return this._profiles[i];
+        }
+        return null;
+    },
+
+    _reset: function()
+    {
+        var profiles = this._profiles.slice(0);
+        for (var i = 0; i < profiles.length; ++i) {
+            var profile = profiles[i];
+            var view = profile.existingView();
+            if (view) {
+                view.detach();
+                if ("dispose" in view)
+                    view.dispose();
+            }
+            this.dispatchEventToListeners(WebInspector.ProfileType.Events.RemoveProfileHeader, profile);
+        }
+        this.treeElement.removeChildren();
+        this._profiles = [];
+        this._profilesIdMap = {};
+    },
+
+    /**
+     * @param {function(this:WebInspector.ProfileType, ?string, !Array.<!ProfilerAgent.ProfileHeader>)} populateCallback
+     */
+    _requestProfilesFromBackend: function(populateCallback)
+    {
+    },
+
+    _populateProfiles: function()
+    {
+        /**
+         * @param {?string} error
+         * @param {!Array.<!ProfilerAgent.ProfileHeader>} profileHeaders
+         */
+        function populateCallback(error, profileHeaders) {
+            if (error)
+                return;
+            profileHeaders.sort(function(a, b) { return a.uid - b.uid; });
+            var count = profileHeaders.length;
+            for (var i = 0; i < count; ++i)
+                this.addProfile(this.createProfile(profileHeaders[i]));
+        }
+        this._requestProfilesFromBackend(populateCallback.bind(this));
+    },
+
     __proto__: WebInspector.Object.prototype
 }
 
@@ -129,13 +236,8 @@ WebInspector.ProfileHeader = function(profileType, title, uid)
 {
     this._profileType = profileType;
     this.title = title;
-    if (uid === undefined) {
-        this.uid = -1;
-        this.isTemporary = true;
-    } else {
-        this.uid = uid;
-        this.isTemporary = false;
-    }
+    this.isTemporary = uid === undefined;
+    this.uid = this.isTemporary ? -1 : uid;
     this._fromFile = false;
 }
 
@@ -184,10 +286,7 @@ WebInspector.ProfileHeader.prototype = {
         throw new Error("Not implemented.");
     },
 
-    /**
-     * @param {!WebInspector.ProfilesPanel} profilesPanel
-     */
-    dispose: function(profilesPanel)
+    dispose: function()
     {
     },
 
@@ -285,8 +384,6 @@ WebInspector.ProfilesPanel = function()
     this._profileViewStatusBarItemsContainer = document.createElement("div");
     this._profileViewStatusBarItemsContainer.className = "status-bar-items";
 
-    /** @type {!Array.<!WebInspector.ProfileHeader>} */
-    this._profiles = [];
     this._profilerEnabled = !Capabilities.profilerCausesRecompilation;
 
     this._launcherView = new WebInspector.ProfileLauncherView(this);
@@ -305,10 +402,6 @@ WebInspector.ProfilesPanel = function()
     if (WebInspector.experimentsSettings.canvasInspection.isEnabled())
         this._registerProfileType(new WebInspector.CanvasProfileType());
 
-    InspectorBackend.registerProfilerDispatcher(new WebInspector.ProfilerDispatcher(this));
-    InspectorBackend.registerHeapProfilerDispatcher(new WebInspector.HeapProfilerDispatcher(this));
-    InspectorBackend.registerMemoryDispatcher(new WebInspector.MemoryDispatcher(this));
-
     this._createFileSelectorElement();
     this.element.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);
 
@@ -334,14 +427,14 @@ WebInspector.ProfilesPanel.prototype = {
             return;
         }
 
-        if (!!this.findTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId)) {
+        var profileType = this.getProfileType(WebInspector.HeapSnapshotProfileType.TypeId);
+        if (!!profileType.findTemporaryProfile()) {
             WebInspector.log(WebInspector.UIString("Can't load profile when other profile is recording."));
             return;
         }
 
-        var profileType = this.getProfileType(WebInspector.HeapSnapshotProfileType.TypeId);
         var temporaryProfile = profileType.createTemporaryProfile(WebInspector.ProfilesPanelDescriptor.UserInitiatedProfileName + "." + file.name);
-        this.addProfileHeader(temporaryProfile);
+        profileType.addProfile(temporaryProfile);
 
         temporaryProfile._fromFile = true;
         temporaryProfile.loadFromFile(file);
@@ -355,19 +448,23 @@ WebInspector.ProfilesPanel.prototype = {
 
     toggleRecordButton: function()
     {
-        var isProfiling = this._selectedProfileType.buttonClicked(this);
-        this.recordButton.toggled = isProfiling;
-        this.recordButton.title = this._selectedProfileType.buttonTooltip;
-        if (isProfiling)
-            this._launcherView.profileStarted();
-        else
-            this._launcherView.profileFinished();
+        var isProfiling = this._selectedProfileType.buttonClicked();
+        this.setRecordingProfile(this._selectedProfileType.id, isProfiling);
+    },
+
+    _populateAllProfiles: function()
+    {
+        if (!this._profilerEnabled || this._profilesWereRequested)
+            return;
+        this._profilesWereRequested = true;
+        for (var typeId in this._profileTypesByIdMap)
+            this._profileTypesByIdMap[typeId]._populateProfiles();
     },
 
     wasShown: function()
     {
         WebInspector.Panel.prototype.wasShown.call(this);
-        this._populateProfiles();
+        this._populateAllProfiles();
     },
 
     _profilerWasEnabled: function()
@@ -379,7 +476,7 @@ WebInspector.ProfilesPanel.prototype = {
 
         this._reset();
         if (this.isShowing())
-            this._populateProfiles();
+            this._populateAllProfiles();
     },
 
     _profilerWasDisabled: function()
@@ -417,30 +514,13 @@ WebInspector.ProfilesPanel.prototype = {
     {
         WebInspector.Panel.prototype.reset.call(this);
 
-        for (var i = 0; i < this._profiles.length; ++i) {
-            var view = this._profiles[i].existingView();
-            if (view) {
-                view.detach();
-                if ("dispose" in view)
-                    view.dispose();
-            }
-            this._profiles[i].dispose(this);
-        }
-        delete this.visibleView;
+        for (var typeId in this._profileTypesByIdMap)
+            this._profileTypesByIdMap[typeId]._reset();
 
+        delete this.visibleView;
         delete this.currentQuery;
         this.searchCanceled();
 
-        for (var id in this._profileTypesByIdMap) {
-            var profileType = this._profileTypesByIdMap[id];
-            var treeElement = profileType.treeElement;
-            treeElement.removeChildren();
-            treeElement.hidden = true;
-            profileType.reset();
-        }
-
-        this._profiles = [];
-        this._profilesIdMap = {};
         this._profileGroups = {};
         this._profileGroupsForLinks = {};
         this._profilesWereRequested = false;
@@ -482,7 +562,7 @@ WebInspector.ProfilesPanel.prototype = {
     },
 
     /**
-     * @param {WebInspector.ProfileType} profileType
+     * @param {!WebInspector.ProfileType} profileType
      */
     _registerProfileType: function(profileType)
     {
@@ -492,7 +572,22 @@ WebInspector.ProfilesPanel.prototype = {
         profileType.treeElement.hidden = true;
         this.sidebarTree.appendChild(profileType.treeElement);
         profileType.treeElement.childrenListElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);
+        function onAddProfileHeader(event)
+        {
+            this._addProfileHeader(event.data);
+        }
+        function onRemoveProfileHeader(event)
+        {
+            this._removeProfileHeader(event.data);
+        }
+        function onProgressUpdated(event)
+        {
+            this._reportProfileProgress(event.data.profile, event.data.done, event.data.total);
+        }
         profileType.addEventListener(WebInspector.ProfileType.Events.ViewUpdated, this._updateProfileTypeSpecificUI, this);
+        profileType.addEventListener(WebInspector.ProfileType.Events.AddProfileHeader, onAddProfileHeader, this);
+        profileType.addEventListener(WebInspector.ProfileType.Events.RemoveProfileHeader, onRemoveProfileHeader, this);
+        profileType.addEventListener(WebInspector.ProfileType.Events.ProgressUpdated, onProgressUpdated, this);
     },
 
     /**
@@ -520,6 +615,7 @@ WebInspector.ProfilesPanel.prototype = {
     },
 
     /**
+     * @nosideeffects
      * @param {string} text
      * @param {string} profileTypeId
      * @return {string}
@@ -530,21 +626,12 @@ WebInspector.ProfilesPanel.prototype = {
     },
 
     /**
-     * @param {number} id
-     * @param {string} profileTypeId
-     * @return {string}
+     * @param {!WebInspector.ProfileHeader} profile
      */
-    _makeKey: function(id, profileTypeId)
+    _addProfileHeader: function(profile)
     {
-        return id + '/' + escape(profileTypeId);
-    },
-
-    /**
-     * @param {WebInspector.ProfileHeader} profile
-     */
-    addProfileHeader: function(profile)
-    {
-        this._removeTemporaryProfile(profile.profileType().id);
+        if (!profile.isTemporary)
+            this._removeTemporaryProfile(profile.profileType().id);
 
         var profileType = profile.profileType();
         var typeId = profileType.id;
@@ -553,9 +640,6 @@ WebInspector.ProfilesPanel.prototype = {
         var small = false;
         var alternateTitle;
 
-        this._profiles.push(profile);
-        this._profilesIdMap[this._makeKey(profile.uid, typeId)] = profile;
-
         if (!WebInspector.ProfilesPanelDescriptor.isUserInitiatedProfile(profile.title)) {
             var profileTitleKey = this._makeTitleKey(profile.title, typeId);
             if (!(profileTitleKey in this._profileGroups))
@@ -563,7 +647,6 @@ WebInspector.ProfilesPanel.prototype = {
 
             var group = this._profileGroups[profileTitleKey];
             group.push(profile);
-
             if (group.length === 2) {
                 // Make a group TreeElement now that there are 2 profiles.
                 group._profilesTreeElement = new WebInspector.ProfileGroupSidebarTreeElement(profile.title);
@@ -610,34 +693,25 @@ WebInspector.ProfilesPanel.prototype = {
     },
 
     /**
-     * @param {WebInspector.ProfileHeader} profile
+     * @param {!WebInspector.ProfileHeader} profile
      */
     _removeProfileHeader: function(profile)
     {
-        var sidebarParent = profile.profileType().treeElement;
-
-        for (var i = 0; i < this._profiles.length; ++i) {
-            if (this._profiles[i].uid === profile.uid) {
-                profile = this._profiles[i];
-                this._profiles.splice(i, 1);
-                profile.dispose(this);
-                break;
-            }
-        }
-        delete this._profilesIdMap[this._makeKey(profile.uid, profile.profileType().id)];
+        profile.dispose();
+        profile.profileType().removeProfile(profile);
 
+        var sidebarParent = profile.profileType().treeElement;
         var profileTitleKey = this._makeTitleKey(profile.title, profile.profileType().id);
-        delete this._profileGroups[profileTitleKey];
+        var group = this._profileGroups[profileTitleKey];
+        if (group) {
+            var index = group.indexOf(profile);
+            sidebarParent = group._profilesTreeElement || sidebarParent;
+            if (index !== -1)
+                group.splice(index, 1);
+        }
 
         sidebarParent.removeChild(profile._profilesTreeElement);
 
-        if (!profile.isTemporary) {
-            if (profile.profileType().id == WebInspector.HeapSnapshotProfileType.TypeId)
-                HeapProfilerAgent.removeProfile(profile.uid);
-            else
-                ProfilerAgent.removeProfile(profile.profileType().id, profile.uid);
-        }
-
         // No other item will be selected if there aren't any other profiles, so
         // make sure that view gets cleared when the last profile is removed.
         if (!sidebarParent.children.length) {
@@ -648,7 +722,7 @@ WebInspector.ProfilesPanel.prototype = {
     },
 
     /**
-     * @param {WebInspector.ProfileHeader} profile
+     * @param {!WebInspector.ProfileHeader} profile
      */
     _showProfile: function(profile)
     {
@@ -678,31 +752,15 @@ WebInspector.ProfilesPanel.prototype = {
     },
 
     /**
-     * @param {string} typeId
-     * @return {!Array.<!WebInspector.ProfileHeader>}
-     */
-    getProfiles: function(typeId)
-    {
-        var result = [];
-        var profilesCount = this._profiles.length;
-        for (var i = 0; i < profilesCount; ++i) {
-            var profile = this._profiles[i];
-            if (!profile.isTemporary && profile.profileType().id === typeId)
-                result.push(profile);
-        }
-        return result;
-    },
-
-    /**
      * @param {HeapProfilerAgent.HeapSnapshotObjectId} snapshotObjectId
      * @param {string} viewName
      */
     showObject: function(snapshotObjectId, viewName)
     {
-        var heapProfiles = this.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
+        var heapProfiles = this.getProfileType(WebInspector.HeapSnapshotProfileType.TypeId).getProfiles();
         for (var i = 0; i < heapProfiles.length; i++) {
             var profile = heapProfiles[i];
-            // TODO: allow to choose snapshot if there are several options.
+            // FIXME: allow to choose snapshot if there are several options.
             if (profile.maxJSObjectId >= snapshotObjectId) {
                 this._showProfile(profile);
                 profile.view().changeView(viewName, function() {
@@ -715,15 +773,12 @@ WebInspector.ProfilesPanel.prototype = {
 
     /**
      * @param {string} typeId
-     * @return {WebInspector.ProfileHeader}
      */
-    findTemporaryProfile: function(typeId)
+    _createTemporaryProfile: function(typeId)
     {
-        var profilesCount = this._profiles.length;
-        for (var i = 0; i < profilesCount; ++i)
-            if (this._profiles[i].profileType().id === typeId && this._profiles[i].isTemporary)
-                return this._profiles[i];
-        return null;
+        var type = this.getProfileType(typeId);
+        if (!type.findTemporaryProfile())
+            type.addProfile(type.createTemporaryProfile());
     },
 
     /**
@@ -731,8 +786,8 @@ WebInspector.ProfilesPanel.prototype = {
      */
     _removeTemporaryProfile: function(typeId)
     {
-        var temporaryProfile = this.findTemporaryProfile(typeId);
-        if (temporaryProfile)
+        var temporaryProfile = this.getProfileType(typeId).findTemporaryProfile();
+        if (!!temporaryProfile)
             this._removeProfileHeader(temporaryProfile);
     },
 
@@ -742,30 +797,7 @@ WebInspector.ProfilesPanel.prototype = {
      */
     getProfile: function(typeId, uid)
     {
-        return this._profilesIdMap[this._makeKey(uid, typeId)];
-    },
-
-    /**
-     * @param {number} uid
-     * @param {string} chunk
-     */
-    _addHeapSnapshotChunk: function(uid, chunk)
-    {
-        var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
-        if (!profile)
-            return;
-        profile.transferChunk(chunk);
-    },
-
-    /**
-     * @param {number} uid
-     */
-    _finishHeapSnapshot: function(uid)
-    {
-        var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
-        if (!profile)
-            return;
-        profile.finishHeapSnapshot();
+        return this.getProfileType(typeId).getProfile(uid);
     },
 
     /**
@@ -790,7 +822,7 @@ WebInspector.ProfilesPanel.prototype = {
      */
     showProfile: function(typeId, uid)
     {
-        this._showProfile(this._profilesIdMap[this._makeKey(Number(uid), typeId)]);
+        this._showProfile(this.getProfile(typeId, Number(uid)));
     },
 
     closeVisibleView: function()
@@ -948,24 +980,36 @@ WebInspector.ProfilesPanel.prototype = {
             currentView.jumpToPreviousSearchResult();
     },
 
-    _searchableViews: function()
+    /**
+     * @return {!Array.<!WebInspector.ProfileHeader>}
+     */
+    _getAllProfiles: function()
     {
-        var views = [];
-
-        const visibleView = this.visibleView;
-        if (visibleView && visibleView.performSearch)
-            views.push(visibleView);
+        var profiles = [];
+        for (var typeId in this._profileTypesByIdMap)
+            profiles = profiles.concat(this._profileTypesByIdMap[typeId].getProfiles());
+        return profiles;
+    },
 
-        var profilesLength = this._profiles.length;
-        for (var i = 0; i < profilesLength; ++i) {
-            var profile = this._profiles[i];
-            var view = profile.view();
-            if (!view.performSearch || view === visibleView)
-                continue;
-            views.push(view);
+    /**
+     * @return {!Array.<!WebInspector.View>}
+     */
+    _searchableViews: function()
+    {
+        var profiles = this._getAllProfiles();
+        var searchableViews = [];
+        for (var i = 0; i < profiles.length; ++i) {
+            var view = profiles[i].view();
+            if (view.performSearch)
+                searchableViews.push(view)
         }
-
-        return views;
+        var index = searchableViews.indexOf(this.visibleView);
+        if (index > 0) {
+            // Move visibleView to the first position.
+            searchableViews[index] = searchableViews[0];
+            searchableViews[0] = this.visibleView;
+        }
+        return searchableViews;
     },
 
     searchMatchFound: function(view, matches)
@@ -995,13 +1039,9 @@ WebInspector.ProfilesPanel.prototype = {
         this._currentSearchResultIndex = 0;
         this._searchResults = [];
 
-        if (!this._profiles)
-            return;
-
-        for (var i = 0; i < this._profiles.length; ++i) {
-            var profile = this._profiles[i];
-            profile._profilesTreeElement.searchMatches = 0;
-        }
+        var profiles = this._getAllProfiles();
+        for (var i = 0; i < profiles.length; ++i)
+            profiles[i]._profilesTreeElement.searchMatches = 0;
     },
 
     _updateInterface: function()
@@ -1064,34 +1104,6 @@ WebInspector.ProfilesPanel.prototype = {
         }
     },
 
-    _populateProfiles: function()
-    {
-        if (!this._profilerEnabled || this._profilesWereRequested)
-            return;
-
-        /**
-         * @param {?string} type
-         * @param {?string} error
-         * @param {Array.<ProfilerAgent.ProfileHeader>} profileHeaders
-         */
-        function populateCallback(type, error, profileHeaders) {
-            if (error)
-                return;
-            profileHeaders.sort(function(a, b) { return a.uid - b.uid; });
-            var profileHeadersLength = profileHeaders.length;
-            for (var i = 0; i < profileHeadersLength; ++i) {
-                var profileHeader = profileHeaders[i];
-                var profileType = this.getProfileType(type || profileHeader.typeId);
-                this.addProfileHeader(profileType.createProfile(profileHeader));
-            }
-        }
-
-        ProfilerAgent.getProfileHeaders(populateCallback.bind(this, null));
-        HeapProfilerAgent.getProfileHeaders(populateCallback.bind(this, WebInspector.HeapSnapshotProfileType.TypeId));
-
-        this._profilesWereRequested = true;
-    },
-
     /**
      * @param {!WebInspector.Event} event
      */
@@ -1125,47 +1137,24 @@ WebInspector.ProfilesPanel.prototype = {
     setRecordingProfile: function(profileType, isProfiling)
     {
         var profileTypeObject = this.getProfileType(profileType);
-        profileTypeObject.setRecordingProfile(isProfiling);
         this.recordButton.toggled = isProfiling;
         this.recordButton.title = profileTypeObject.buttonTooltip;
         if (isProfiling) {
             this._launcherView.profileStarted();
-            if (!this.findTemporaryProfile(profileType))
-                this.addProfileHeader(profileTypeObject.createTemporaryProfile());
-        } else {
+            this._createTemporaryProfile(profileType);
+        } else
             this._launcherView.profileFinished();
-            this._removeTemporaryProfile(profileType);
-        }
-    },
-
-    takeHeapSnapshot: function()
-    {
-        var temporaryRecordingProfile = this.findTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId);
-        if (!temporaryRecordingProfile) {
-            var profileTypeObject = this.getProfileType(WebInspector.HeapSnapshotProfileType.TypeId);
-            this.addProfileHeader(profileTypeObject.createTemporaryProfile());
-        }
-        this._launcherView.profileStarted();
-        function done() {
-            this._launcherView.profileFinished();
-        }
-        HeapProfilerAgent.takeHeapSnapshot(true, done.bind(this));
-        WebInspector.userMetrics.ProfilesHeapProfileTaken.record();
     },
 
     /**
+     * @param {!WebInspector.ProfileHeader} profile
      * @param {number} done
      * @param {number} total
      */
-    _reportHeapSnapshotProgress: function(done, total)
-    {
-        var temporaryProfile = this.findTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId);
-        if (temporaryProfile) {
-            temporaryProfile.sidebarElement.subtitle = WebInspector.UIString("%.2f%", (done / total) * 100);
-            temporaryProfile.sidebarElement.wait = true;
-            if (done >= total)
-                this._removeTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId);
-        }
+    _reportProfileProgress: function(profile, done, total)
+    {
+        profile.sidebarElement.subtitle = WebInspector.UIString("%.0f%", (done / total) * 100);
+        profile.sidebarElement.wait = true;
     },
 
     /** 
@@ -1182,7 +1171,7 @@ WebInspector.ProfilesPanel.prototype = {
         if (!objectId)
             return;
 
-        var heapProfiles = this.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
+        var heapProfiles = this.getProfileType(WebInspector.HeapSnapshotProfileType.TypeId).getProfiles();
         if (!heapProfiles.length)
             return;
 
@@ -1208,156 +1197,6 @@ WebInspector.ProfilesPanel.prototype = {
 
 /**
  * @constructor
- * @implements {MemoryAgent.Dispatcher}
- * @param {WebInspector.ProfilesPanel} profilesPanel
- */
-WebInspector.MemoryDispatcher = function(profilesPanel)
-{
-    this._profilesPanel = profilesPanel;
-}
-
-WebInspector.MemoryDispatcher.prototype = {
-
-    /**
-     * @override
-     * @param {MemoryAgent.HeapSnapshotChunk} chunk
-     */
-    addNativeSnapshotChunk: function(chunk)
-    {
-        var profile = this._profilesPanel.findTemporaryProfile(WebInspector.NativeSnapshotProfileType.TypeId);
-        if (!profile)
-            return;
-        profile.addNativeSnapshotChunk(chunk);
-    }
-}
-
-/**
- * @constructor
- * @implements {ProfilerAgent.Dispatcher}
- * @param {WebInspector.ProfilesPanel} profilesPanel
- */
-WebInspector.ProfilerDispatcher = function(profilesPanel)
-{
-    this._profilesPanel = profilesPanel;
-}
-
-WebInspector.ProfilerDispatcher.prototype = {
-    /**
-     * @param {ProfilerAgent.ProfileHeader} profile
-     */
-    addProfileHeader: function(profile)
-    {
-        var profileType = this._profilesPanel.getProfileType(profile.typeId);
-        this._profilesPanel.addProfileHeader(profileType.createProfile(profile));
-    },
-
-    /**
-     * @override
-     * @param {number} uid
-     * @param {string} chunk
-     */
-    addHeapSnapshotChunk: function(uid, chunk)
-    {
-        this._profilesPanel._addHeapSnapshotChunk(uid, chunk);
-    },
-
-    /**
-     * @override
-     * @param {number} uid
-     */
-    finishHeapSnapshot: function(uid)
-    {
-        this._profilesPanel._finishHeapSnapshot(uid);
-    },
-
-    /**
-     * @override
-     * @param {boolean} isProfiling
-     */
-    setRecordingProfile: function(isProfiling)
-    {
-        this._profilesPanel.setRecordingProfile(WebInspector.CPUProfileType.TypeId, isProfiling);
-    },
-
-    /**
-     * @override
-     */
-    resetProfiles: function()
-    {
-        this._profilesPanel._reset();
-    },
-
-    /**
-     * @override
-     * @param {number} done
-     * @param {number} total
-     */
-    reportHeapSnapshotProgress: function(done, total)
-    {
-        this._profilesPanel._reportHeapSnapshotProgress(done, total);
-    }
-}
-
-/**
- * @constructor
- * @implements {HeapProfilerAgent.Dispatcher}
- * @param {WebInspector.ProfilesPanel} profilesPanel
- */
-WebInspector.HeapProfilerDispatcher = function(profilesPanel)
-{
-    this._profilesPanel = profilesPanel;
-}
-
-WebInspector.HeapProfilerDispatcher.prototype = {
-    /**
-     * @param {HeapProfilerAgent.ProfileHeader} profile
-     */
-    addProfileHeader: function(profile)
-    {
-        var profileType = this._profilesPanel.getProfileType(WebInspector.HeapSnapshotProfileType.TypeId);
-        this._profilesPanel.addProfileHeader(profileType.createProfile(profile));
-    },
-
-    /**
-     * @override
-     * @param {number} uid
-     * @param {string} chunk
-     */
-    addHeapSnapshotChunk: function(uid, chunk)
-    {
-        this._profilesPanel._addHeapSnapshotChunk(uid, chunk);
-    },
-
-    /**
-     * @override
-     * @param {number} uid
-     */
-    finishHeapSnapshot: function(uid)
-    {
-        this._profilesPanel._finishHeapSnapshot(uid);
-    },
-
-    /**
-     * @override
-     */
-    resetProfiles: function()
-    {
-        this._profilesPanel._reset();
-    },
-
-    /**
-     * @override
-     * @param {number} done
-     * @param {number} total
-     */
-    reportHeapSnapshotProgress: function(done, total)
-    {
-        this._profilesPanel._reportHeapSnapshotProgress(done, total);
-    }
-}
-
-/**
- * @constructor
  * @extends {WebInspector.SidebarTreeElement}
  * @param {!WebInspector.ProfileHeader} profile
  * @param {string} titleFormat