Title: [116764] trunk/Source/WebCore
Revision
116764
Author
loi...@chromium.org
Date
2012-05-11 06:53:30 -0700 (Fri, 11 May 2012)

Log Message

Web Inspector: load heap snapshot implementation.
https://bugs.webkit.org/show_bug.cgi?id=86097

The idea is to have a hidden file selector control.
When the user select a context menu item or click a button
we redirect this user-action to file selector.
As result we see the standard file selector dialog.
When the user selects a file we load it's chunks and push the chunks to the worker.
The loaded snapshot can be completely unrelated to the current page.
Thats why we have to skip range selection options in Summary tab.

Reviewed by Yury Semikhatsky.

* English.lproj/localizedStrings.js:
* inspector/front-end/CSSSelectorProfileView.js:
(WebInspector.CSSSelectorProfileType.prototype.createTemporaryProfile): now it accepts a custom title.
* inspector/front-end/HeapSnapshotView.js:
(WebInspector.HeapSnapshotView.prototype._updateFilterOptions): we have to skip the profiles loaded from file because there is no guaranty t
(WebInspector.HeapSnapshotProfileType.prototype.createTemporaryProfile): now it accepts a custom title.
(WebInspector.HeapSnapshotProfileType.prototype.createProfile): cosmetic changes.
(WebInspector.HeapProfileHeader):
(WebInspector.HeapProfileHeader.prototype._setupWorker): a common part was extracted from load method and reused in loadFromFile.
(WebInspector.HeapProfileHeader.prototype._saveStatusUpdate): cosmetic changes.
(WebInspector.HeapProfileHeader.prototype.finishHeapSnapshot):
(WebInspector.HeapProfileHeader.prototype.canSaveToFile): cosmetic rename for better consistency with 'load' part.
(WebInspector.HeapProfileHeader.prototype.saveToFile): cosmetic rename for better consistency with 'load' part.
(WebInspector.HeapProfileHeader.prototype.canLoadFromFile): cosmetic rename for better consistency with 'load' part.
(WebInspector.HeapProfileHeader.prototype.loadFromFile): chunk based file loader.
(WebInspector.HeapProfileHeader.prototype.loadFromFile.loadNextChunk):
(WebInspector.HeapProfileHeader.prototype.loadFromFile.onLoad):
* inspector/front-end/ProfileView.js:
(WebInspector.CPUProfileType.prototype.createTemporaryProfile): now it accepts a custom title.
* inspector/front-end/ProfilesPanel.js:
(WebInspector.ProfileType.prototype.createTemporaryProfile): now it accepts a custom title.
(WebInspector.ProfileHeader.prototype.canSaveToFile): cosmetic rename for better consistency with 'load' part.
(WebInspector.ProfileHeader.prototype.saveToFile): cosmetic rename for better consistency with 'load' part.
(WebInspector.ProfileHeader.prototype.canLoadFromFile): default implementation for 'load' part.
(WebInspector.ProfileHeader.prototype.loadFromFile): default implementation for 'load' part.
(WebInspector.ProfilesPanel.prototype._createFileSelectorElement):
(WebInspector.ProfilesPanel.prototype._loadFromFile):
(WebInspector.ProfileSidebarTreeElement.prototype.handleContextMenuEvent):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (116763 => 116764)


--- trunk/Source/WebCore/ChangeLog	2012-05-11 13:49:17 UTC (rev 116763)
+++ trunk/Source/WebCore/ChangeLog	2012-05-11 13:53:30 UTC (rev 116764)
@@ -1,3 +1,75 @@
+2012-05-11  Ilya Tikhonovsky  <loi...@chromium.org>
+
+        Web Inspector: load heap snapshot implementation.
+        https://bugs.webkit.org/show_bug.cgi?id=86097
+
+        The idea is to have a hidden file selector control.
+        When the user select a context menu item or click a button
+        we redirect this user-action to file selector.
+        As result we see the standard file selector dialog.
+        When the user selects a file we load it's chunks and push the chunks to the worker.
+        The loaded snapshot can be completely unrelated to the current page.
+        Thats why we have to skip range selection options in Summary tab.
+
+        Reviewed by Yury Semikhatsky.
+
+        * English.lproj/localizedStrings.js:
+        * inspector/front-end/CSSSelectorProfileView.js:
+        (WebInspector.CSSSelectorProfileType.prototype.createTemporaryProfile): now it accepts a custom title.
+        * inspector/front-end/HeapSnapshotView.js:
+        (WebInspector.HeapSnapshotView.prototype._updateFilterOptions): we have to skip the profiles loaded from file because there is no guaranty t
+        (WebInspector.HeapSnapshotProfileType.prototype.createTemporaryProfile): now it accepts a custom title.
+        (WebInspector.HeapSnapshotProfileType.prototype.createProfile): cosmetic changes.
+        (WebInspector.HeapProfileHeader):
+        (WebInspector.HeapProfileHeader.prototype._setupWorker): a common part was extracted from load method and reused in loadFromFile.
+        (WebInspector.HeapProfileHeader.prototype._saveStatusUpdate): cosmetic changes.
+        (WebInspector.HeapProfileHeader.prototype.finishHeapSnapshot):
+        (WebInspector.HeapProfileHeader.prototype.canSaveToFile): cosmetic rename for better consistency with 'load' part.
+        (WebInspector.HeapProfileHeader.prototype.saveToFile): cosmetic rename for better consistency with 'load' part.
+        (WebInspector.HeapProfileHeader.prototype.canLoadFromFile): cosmetic rename for better consistency with 'load' part.
+        (WebInspector.HeapProfileHeader.prototype.loadFromFile): chunk based file loader.
+        (WebInspector.HeapProfileHeader.prototype.loadFromFile.loadNextChunk):
+        (WebInspector.HeapProfileHeader.prototype.loadFromFile.onLoad):
+        * inspector/front-end/ProfileView.js:
+        (WebInspector.CPUProfileType.prototype.createTemporaryProfile): now it accepts a custom title.
+        * inspector/front-end/ProfilesPanel.js:
+        (WebInspector.ProfileType.prototype.createTemporaryProfile): now it accepts a custom title.
+        (WebInspector.ProfileHeader.prototype.canSaveToFile): cosmetic rename for better consistency with 'load' part.
+        (WebInspector.ProfileHeader.prototype.saveToFile): cosmetic rename for better consistency with 'load' part.
+        (WebInspector.ProfileHeader.prototype.canLoadFromFile): default implementation for 'load' part.
+        (WebInspector.ProfileHeader.prototype.loadFromFile): default implementation for 'load' part.
+        (WebInspector.ProfilesPanel.prototype._createFileSelectorElement):
+        (WebInspector.ProfilesPanel.prototype._loadFromFile):
+        (WebInspector.ProfileSidebarTreeElement.prototype.handleContextMenuEvent):
+
+2012-05-11  Dominik Röttsches  <dominik.rottsc...@intel.com>
+
+        [EFL][DRT] Input Attribute Placeholder RefTests failing
+        https://bugs.webkit.org/show_bug.cgi?id=85603
+
+        Reviewed by Hajime Morita.
+
+        Refrain from overriding style coloring by theme coloring.
+        RenderThemeEfl was always overriding colors and whitespace
+        handling leading to failures in reftests that verify placeholder styling
+        which expect the user agent stylesheet to be applied correctly
+        without any color overrides. Also, leave whitespace handling untouched.
+
+        No new tests, covered by existing tests. See also
+        the LayoutTests/ChangeLog in this commit for the required
+        rebaselining.
+
+        * platform/efl/RenderThemeEfl.cpp:
+        (WebCore::RenderThemeEfl::createEdje):
+        (WebCore::RenderThemeEfl::applyEdjeColors):
+        (WebCore::RenderThemeEfl::RenderThemeEfl):
+        (WebCore::RenderThemeEfl::adjustButtonStyle):
+        (WebCore::RenderThemeEfl::adjustMenuListStyle):
+        (WebCore::RenderThemeEfl::adjustTextFieldStyle):
+        (WebCore::RenderThemeEfl::adjustSearchFieldStyle):
+        * platform/efl/RenderThemeEfl.h:
+        (RenderThemeEfl):
+
 2012-05-11  Christophe Dumez  <christophe.du...@intel.com>
 
         Web Intents code only supports V8

Modified: trunk/Source/WebCore/English.lproj/localizedStrings.js


(Binary files differ)

Modified: trunk/Source/WebCore/inspector/front-end/CSSSelectorProfileView.js (116763 => 116764)


--- trunk/Source/WebCore/inspector/front-end/CSSSelectorProfileView.js	2012-05-11 13:49:17 UTC (rev 116763)
+++ trunk/Source/WebCore/inspector/front-end/CSSSelectorProfileView.js	2012-05-11 13:53:30 UTC (rev 116764)
@@ -353,11 +353,13 @@
 
     /**
      * @override
+     * @param {string=} title
      * @return {WebInspector.ProfileHeader}
      */
-    createTemporaryProfile: function()
+    createTemporaryProfile: function(title)
     {
-        return new WebInspector.ProfileHeader(WebInspector.CSSSelectorProfileType.TypeId, WebInspector.UIString("Recording\u2026"));
+        title = title || WebInspector.UIString("Recording\u2026");
+        return new WebInspector.ProfileHeader(WebInspector.CSSSelectorProfileType.TypeId, title);
     },
 
     /**

Modified: trunk/Source/WebCore/inspector/front-end/HeapSnapshotView.js (116763 => 116764)


--- trunk/Source/WebCore/inspector/front-end/HeapSnapshotView.js	2012-05-11 13:49:17 UTC (rev 116763)
+++ trunk/Source/WebCore/inspector/front-end/HeapSnapshotView.js	2012-05-11 13:53:30 UTC (rev 116764)
@@ -688,7 +688,10 @@
             this.filterSelectElement.appendChild(filterOption);
         }
 
+        if (this.profile._fromFile)
+            return;
         for (var i = this.filterSelectElement.length - 1, n = list.length; i < n; ++i) {
+            var profile = ""
             var filterOption = document.createElement("option");
             var title = list[i].title;
             if (!title.indexOf(UserInitiatedProfileName)) {
@@ -751,11 +754,13 @@
 
     /**
      * @override
+     * @param {string=} title
      * @return {WebInspector.ProfileHeader}
      */
-    createTemporaryProfile: function()
+    createTemporaryProfile: function(title)
     {
-        return new WebInspector.ProfileHeader(WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("Snapshotting\u2026"));
+        title = title || WebInspector.UIString("Snapshotting\u2026");
+        return new WebInspector.HeapProfileHeader(title);
     },
 
     /**
@@ -765,7 +770,7 @@
      */
     createProfile: function(profile)
     {
-        return new WebInspector.HeapProfileHeader(profile.typeId, profile.title, profile.uid, profile.maxJSObjectId || 0);
+        return new WebInspector.HeapProfileHeader(profile.title, profile.uid, profile.maxJSObjectId || 0);
     }
 }
 
@@ -774,16 +779,16 @@
 /**
  * @constructor
  * @extends {WebInspector.ProfileHeader}
- * @param {string} profileType
  * @param {string} title
- * @param {number} uid
- * @param {number} maxJSObjectId
+ * @param {number=} uid
+ * @param {number=} maxJSObjectId
  */
-WebInspector.HeapProfileHeader = function(profileType, title, uid, maxJSObjectId)
+WebInspector.HeapProfileHeader = function(title, uid, maxJSObjectId)
 {
-    WebInspector.ProfileHeader.call(this, profileType, title, uid);
+    WebInspector.ProfileHeader.call(this, WebInspector.HeapSnapshotProfileType.TypeId, title, uid);
     this.maxJSObjectId = maxJSObjectId;
     this._loaded = false;
+    this._fromFile = false;
     this._totalNumberOfChunks = 0;
 }
 
@@ -799,14 +804,8 @@
             return;
         }
 
-        if (!this._proxy) {
-            function setProfileWait(event) {
-                this.sidebarElement.wait = event.data;
-            }
-            var worker = new WebInspector.HeapSnapshotWorker();
-            worker.addEventListener("wait", setProfileWait, this);
-            this._proxy = worker.createObject("WebInspector.HeapSnapshotLoader");
-        }
+        if (!this._proxy)
+            this._setupWorker();
 
         if (this._proxy.startLoading(callback)) {
             this.sidebarElement.subtitle = WebInspector.UIString("Loading\u2026");
@@ -819,6 +818,16 @@
         }
     },
 
+    _setupWorker: function()
+    {
+        function setProfileWait(event) {
+            this.sidebarElement.wait = event.data;
+        }
+        var worker = new WebInspector.HeapSnapshotWorker();
+        worker.addEventListener("wait", setProfileWait, this);
+        this._proxy = worker.createObject("WebInspector.HeapSnapshotLoader");
+    },
+
     /**
      * @param {WebInspector.Event} event
      */
@@ -832,7 +841,7 @@
             this._savedChunksCount = 0;
             WebInspector.fileManager.removeEventListener(WebInspector.FileManager.EventTypes.AppendedToURL, this._saveStatusUpdate, this);
         } else
-            this.sidebarElement.subtitle = WebInspector.UIString("Saving\u2026 %d\%", Math.floor(this._savedChunksCount * 100 / this._totalNumberOfChunks));
+            this.sidebarElement.subtitle = WebInspector.UIString("Saving\u2026 %d\%", (this._savedChunksCount * 100 / this._totalNumberOfChunks).toFixed(2));
     },
 
     /**
@@ -857,6 +866,7 @@
             this.sidebarElement.subtitle = Number.bytesToString(snapshotProxy.totalSize);
             this.sidebarElement.wait = false;
             var worker = /** @type {WebInspector.HeapSnapshotWorker} */ snapshotProxy.worker;
+            this.isTemporary = false;
             worker.startCheckingForLongRunningCalls();
         }
         if (this._proxy.finishLoading(parsed.bind(this)))
@@ -867,34 +877,107 @@
      * @override
      * @return {boolean}
      */
-    canSave: function()
+    canSaveToFile: function()
     {
-        return this._loaded && !this._savedChunksCount && WebInspector.fileManager.canAppend();
+        return !this._fromFile && this._loaded && !this._savedChunksCount && WebInspector.fileManager.canAppend();
     },
 
     /**
      * @override
      */
-    save: function()
+    saveToFile: function()
     {
         /**
          * @param {WebInspector.Event} event
          */
-        function startWritingSnapshot(event)
+        function startSavingSnapshot(event)
         {
             if (event.data !== this._fileName)
                 return;
             this.sidebarElement.wait = true;
             this.sidebarElement.subtitle = WebInspector.UIString("Saving\u2026 %d\%", 0);
             this._savedChunksCount = 0;
-            WebInspector.fileManager.removeEventListener(WebInspector.FileManager.EventTypes.SavedURL, startWritingSnapshot, this);
+            WebInspector.fileManager.removeEventListener(WebInspector.FileManager.EventTypes.SavedURL, startSavingSnapshot, this);
             WebInspector.fileManager.addEventListener(WebInspector.FileManager.EventTypes.AppendedToURL, this._saveStatusUpdate, this);
             ProfilerAgent.getProfile(this.typeId, this.uid);
         }
 
         this._fileName = this._fileName || "Heap-" + new Date().toISO8601Compact() + ".json";
-        WebInspector.fileManager.addEventListener(WebInspector.FileManager.EventTypes.SavedURL, startWritingSnapshot, this);
+        WebInspector.fileManager.addEventListener(WebInspector.FileManager.EventTypes.SavedURL, startSavingSnapshot, this);
         WebInspector.fileManager.save(this._fileName, "", true);
+    },
+
+    /**
+     * @return {boolean}
+     */
+    canLoadFromFile: function()
+    {
+        return false;
+    },
+
+    /**
+     * @override
+     * @param {File} file
+     */
+    loadFromFile: function(file)
+    {
+        function onError(e)
+        {
+            switch(e.target.error.code) {
+            case e.target.error.NOT_FOUND_ERR:
+                this.sidebarElement.subtitle = WebInspector.UIString("'%s' not found.", file.name);
+            break;
+            case e.target.error.NOT_READABLE_ERR:
+                this.sidebarElement.subtitle = WebInspector.UIString("'%s' is not readable", file.name);
+            break;
+            case e.target.error.ABORT_ERR:
+                break;
+            default:
+                this.sidebarElement.subtitle = WebInspector.UIString("'%s' error %d", file.name, e.target.error.code);
+            }
+        }
+
+        this._fromFile = true;
+        this.title = file.name;
+        this.sidebarElement.subtitle = WebInspector.UIString("Loading\u2026");
+        this.sidebarElement.wait = true;
+        this._setupWorker();
+        this._proxy.startLoading(function() { });
+
+        function loadNextChunk(file, reader, loadedSize)
+        {
+            var chunkSize = 10000000;
+            var size = file.size < loadedSize + chunkSize ? file.size - loadedSize : chunkSize;
+            var nextPart = file.webkitSlice(loadedSize, loadedSize + size);
+            reader.readAsText(nextPart);
+        }
+
+        /**
+         * @param {Event} event
+         */
+        function onLoad(event)
+        {
+            if (event.target.readyState !== FileReader.DONE)
+                return;
+
+            this._loadedSize += event.target.result.length;
+            this._proxy.pushJSONChunk(event.target.result);
+            this.sidebarElement.subtitle = WebInspector.UIString("Loading\u2026 %d%", (this._loadedSize * 100 / file.size).toFixed(2));
+
+            if (this._loadedSize === file.size) {
+                this._loaded = true;
+                this.finishHeapSnapshot();
+                return;
+            }
+
+            loadNextChunk(file, reader, this._loadedSize);
+        }
+
+        var reader = new FileReader();
+        reader._onload_ = onLoad.bind(this);
+        reader._onerror_ = onError;
+        this._loadedSize = 0;
+        loadNextChunk(file, reader, this._loadedSize);
     }
 }
 

Modified: trunk/Source/WebCore/inspector/front-end/ProfileView.js (116763 => 116764)


--- trunk/Source/WebCore/inspector/front-end/ProfileView.js	2012-05-11 13:49:17 UTC (rev 116763)
+++ trunk/Source/WebCore/inspector/front-end/ProfileView.js	2012-05-11 13:53:30 UTC (rev 116764)
@@ -620,11 +620,13 @@
 
     /**
      * @override
+     * @param {string=} title
      * @return {WebInspector.ProfileHeader}
      */
-    createTemporaryProfile: function()
+    createTemporaryProfile: function(title)
     {
-        return new WebInspector.ProfileHeader(WebInspector.CPUProfileType.TypeId, WebInspector.UIString("Recording\u2026"));
+        title = title || WebInspector.UIString("Recording\u2026");
+        return new WebInspector.ProfileHeader(WebInspector.CPUProfileType.TypeId, title);
     },
 
     /**

Modified: trunk/Source/WebCore/inspector/front-end/ProfilesPanel.js (116763 => 116764)


--- trunk/Source/WebCore/inspector/front-end/ProfilesPanel.js	2012-05-11 13:49:17 UTC (rev 116763)
+++ trunk/Source/WebCore/inspector/front-end/ProfilesPanel.js	2012-05-11 13:53:30 UTC (rev 116764)
@@ -91,9 +91,10 @@
 
     // Must be implemented by subclasses.
     /**
+     * @param {string=} title
      * @return {WebInspector.ProfileHeader}
      */
-    createTemporaryProfile: function()
+    createTemporaryProfile: function(title)
     {
         throw new Error("Needs implemented.");
     },
@@ -145,9 +146,19 @@
     /**
      * @return {boolean}
      */
-    canSave: function() { return false; },
+    canSaveToFile: function() { return false; },
 
-    save: function() { throw new Error("Needs implemented"); }
+    saveToFile: function() { throw new Error("Needs implemented"); },
+
+    /**
+     * @return {boolean}
+     */
+    canLoadFromFile: function() { return false; },
+
+    /**
+     * @param {File} file
+     */
+    loadFromFile: function(file) { throw new Error("Needs implemented"); }
 }
 
 /**
@@ -210,6 +221,8 @@
 
     if (!Capabilities.profilerCausesRecompilation || WebInspector.settings.profilerEnabled.get())
         ProfilerAgent.enable(this._profilerWasEnabled.bind(this));
+
+    this._createFileSelectorElement();
 }
 
 WebInspector.ProfilesPanel.EventTypes = {
@@ -218,6 +231,41 @@
 }
 
 WebInspector.ProfilesPanel.prototype = {
+    _createFileSelectorElement: function()
+    {
+        if (this._fileSelectorElement)
+            this.element.removeChild(this._fileSelectorElement);
+
+        var fileSelectorElement = document.createElement("input");
+        fileSelectorElement.type = "file";
+        fileSelectorElement.style.zIndex = -1;
+        fileSelectorElement.style.position = "absolute";
+        fileSelectorElement._onchange_ = this._loadFromFile.bind(this);
+        this.element.appendChild(fileSelectorElement);
+        this._fileSelectorElement = fileSelectorElement;
+    },
+
+    _loadFromFile: function(event)
+    {
+        var file = this._fileSelectorElement.files[0];
+        if (!file.name.endsWith(".heapsnapshot")) {
+            WebInspector.log(WebInspector.UIString("Only heap snapshots from files with extension '.heapsnapshot' can be loaded."));
+            return;
+        }
+
+        if (!!this.findTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId)) {
+            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(UserInitiatedProfileName + "." + file.name);
+        this.addProfileHeader(temporaryProfile);
+
+        temporaryProfile.loadFromFile(file);
+        this._createFileSelectorElement();
+    },
+
     get toolbarItemLabel()
     {
         return WebInspector.UIString("Profiles");
@@ -1109,10 +1157,10 @@
     handleContextMenuEvent: function(event)
     {
         var profile = ""
-        if (!profile.canSave())
-            return;
         var contextMenu = new WebInspector.ContextMenu();
-        contextMenu.appendItem(WebInspector.UIString("Save profile"), profile.save.bind(profile));
+        if (profile.canSaveToFile())
+            contextMenu.appendItem(WebInspector.UIString("Save profile\u2026"), profile.saveToFile.bind(profile));
+        contextMenu.appendItem(WebInspector.UIString("Load profile\u2026"), WebInspector.panels.profiles._fileSelectorElement.click.bind(WebInspector.panels.profiles._fileSelectorElement));
         contextMenu.show(event);
     }
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to