Web Inspector: save and restore source positions in back/forward history
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 Oct 2013 23:33:14 +0000 (23:33 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 Oct 2013 23:33:14 +0000 (23:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=122062

Patch by Brian J. Burg <burg@cs.washington.edu> on 2013-10-02
Reviewed by Timothy Hatcher.

Previously, the back/forward entries comprised of only the content
views, but not their positions if navigated via hyperlink (i.e.,
handling script.js:42).  When multiple instances of the same
content view appeared in the back/forward list, the most recent
navigation was displayed rather than the linked position.

We now store context necessary to re-navigate such hyperlinks by
storing view- specific data inside a cookie object, and invoke a
supplied callback to take any position initialization actions,
such as calling TextEditor.revealPosition.  This state is
encapsulated into BackForwardEntry instances.

Functions that save and restore scroll positions inside content
views have been changed to store state in BackForwardEntry
instances, so multiple scroll positions can be saved for a content
view appearing in the navigation history more than once.

* UserInterface/BackForwardEntry.js: Added.
(WebInspector.BackForwardEntry):
(WebInspector.BackForwardEntry.prototype.get contentView):
(WebInspector.BackForwardEntry.prototype.get cookie):
(WebInspector.BackForwardEntry.prototype.prepareToShow):
(WebInspector.BackForwardEntry.prototype.prepareToHide):
(WebInspector.BackForwardEntry.prototype._restoreFromCookie):
(WebInspector.BackForwardEntry.prototype._restoreScrollPositions):
(WebInspector.BackForwardEntry.prototype._saveScrollPositions):
* UserInterface/ContentBrowser.js:
(WebInspector.ContentBrowser.prototype.showContentView):
(WebInspector.ContentBrowser.prototype._updateContentViewNavigationItems):
(WebInspector.ContentBrowser.prototype._updateFindBanner):
* UserInterface/ContentViewContainer.js:
(WebInspector.ContentViewContainer.prototype.get currentContentView):
(WebInspector.ContentViewContainer.prototype.get currentBackForwardEntry):
(WebInspector.ContentViewContainer.prototype.showContentView):
(WebInspector.ContentViewContainer.prototype.showBackForwardEntryForIndex):
(WebInspector.ContentViewContainer.prototype.replaceContentView):
(WebInspector.ContentViewContainer.prototype.closeAllContentViewsOfPrototype):
(WebInspector.ContentViewContainer.prototype.closeAllContentViews):
(WebInspector.ContentViewContainer.prototype.goBack):
(WebInspector.ContentViewContainer.prototype.goForward):
(WebInspector.ContentViewContainer.prototype.shown):
(WebInspector.ContentViewContainer.prototype.hidden):
(WebInspector.ContentViewContainer.prototype._showEntry):
(WebInspector.ContentViewContainer.prototype._hideEntry):
* UserInterface/Main.html:
* UserInterface/Main.js:
(WebInspector.openURL):
* UserInterface/ResourceSidebarPanel.js:
(WebInspector.ResourceSidebarPanel.prototype.restoreCallback):
(WebInspector.ResourceSidebarPanel.prototype.showSourceCode):

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

Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/BackForwardEntry.js [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/ContentBrowser.js
Source/WebInspectorUI/UserInterface/ContentViewContainer.js
Source/WebInspectorUI/UserInterface/Main.html
Source/WebInspectorUI/UserInterface/Main.js
Source/WebInspectorUI/UserInterface/ResourceSidebarPanel.js

index b7a32e080ee2a6384d337fb66f8dde17ce8762d6..7ddba3b81ace0074002cbf41fac90a5817ba5eb7 100644 (file)
@@ -1,3 +1,61 @@
+2013-10-02  Brian J. Burg  <burg@cs.washington.edu>
+
+        Web Inspector: save and restore source positions in back/forward history
+        https://bugs.webkit.org/show_bug.cgi?id=122062
+
+        Reviewed by Timothy Hatcher.
+
+        Previously, the back/forward entries comprised of only the content
+        views, but not their positions if navigated via hyperlink (i.e.,
+        handling script.js:42).  When multiple instances of the same
+        content view appeared in the back/forward list, the most recent
+        navigation was displayed rather than the linked position.
+
+        We now store context necessary to re-navigate such hyperlinks by
+        storing view- specific data inside a cookie object, and invoke a
+        supplied callback to take any position initialization actions,
+        such as calling TextEditor.revealPosition.  This state is
+        encapsulated into BackForwardEntry instances.
+
+        Functions that save and restore scroll positions inside content
+        views have been changed to store state in BackForwardEntry
+        instances, so multiple scroll positions can be saved for a content
+        view appearing in the navigation history more than once.
+
+        * UserInterface/BackForwardEntry.js: Added.
+        (WebInspector.BackForwardEntry):
+        (WebInspector.BackForwardEntry.prototype.get contentView):
+        (WebInspector.BackForwardEntry.prototype.get cookie):
+        (WebInspector.BackForwardEntry.prototype.prepareToShow):
+        (WebInspector.BackForwardEntry.prototype.prepareToHide):
+        (WebInspector.BackForwardEntry.prototype._restoreFromCookie):
+        (WebInspector.BackForwardEntry.prototype._restoreScrollPositions):
+        (WebInspector.BackForwardEntry.prototype._saveScrollPositions):
+        * UserInterface/ContentBrowser.js:
+        (WebInspector.ContentBrowser.prototype.showContentView):
+        (WebInspector.ContentBrowser.prototype._updateContentViewNavigationItems):
+        (WebInspector.ContentBrowser.prototype._updateFindBanner):
+        * UserInterface/ContentViewContainer.js:
+        (WebInspector.ContentViewContainer.prototype.get currentContentView):
+        (WebInspector.ContentViewContainer.prototype.get currentBackForwardEntry):
+        (WebInspector.ContentViewContainer.prototype.showContentView):
+        (WebInspector.ContentViewContainer.prototype.showBackForwardEntryForIndex):
+        (WebInspector.ContentViewContainer.prototype.replaceContentView):
+        (WebInspector.ContentViewContainer.prototype.closeAllContentViewsOfPrototype):
+        (WebInspector.ContentViewContainer.prototype.closeAllContentViews):
+        (WebInspector.ContentViewContainer.prototype.goBack):
+        (WebInspector.ContentViewContainer.prototype.goForward):
+        (WebInspector.ContentViewContainer.prototype.shown):
+        (WebInspector.ContentViewContainer.prototype.hidden):
+        (WebInspector.ContentViewContainer.prototype._showEntry):
+        (WebInspector.ContentViewContainer.prototype._hideEntry):
+        * UserInterface/Main.html:
+        * UserInterface/Main.js:
+        (WebInspector.openURL):
+        * UserInterface/ResourceSidebarPanel.js:
+        (WebInspector.ResourceSidebarPanel.prototype.restoreCallback):
+        (WebInspector.ResourceSidebarPanel.prototype.showSourceCode):
+
 2013-10-02  Antoine Quint  <graouts@apple.com>
 
         Web Inspector: highlight newly added console messages in the Activity Viewer
diff --git a/Source/WebInspectorUI/UserInterface/BackForwardEntry.js b/Source/WebInspectorUI/UserInterface/BackForwardEntry.js
new file mode 100644 (file)
index 0000000..faab28a
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ *  Copyright (C) 2013 University of Washington. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.BackForwardEntry = function(contentView, cookie, restoreCallback)
+{
+    WebInspector.Object.call(this);
+    this._contentView = contentView;
+    // Cookies are compared with Object.shallowEqual, so should not store objects or arrays.
+    this._cookie = cookie || {};
+    this._scrollPositions = [];
+    this._restoreCallback = restoreCallback;
+};
+
+WebInspector.BackForwardEntry.prototype = {
+    constructor: WebInspector.BackForwardEntry,
+    __proto__: WebInspector.Object.prototype,
+
+    // Public
+
+    get contentView()
+    {
+        return this._contentView;
+    },
+
+    get cookie()
+    {
+        // Cookies are immutable; they represent a specific navigation action.
+        return Object.shallowCopy(this._cookie);
+    },
+
+    prepareToShow: function()
+    {
+        this._restoreFromCookie();
+
+        this.contentView.visible = true;
+        this.contentView.shown();
+        this.contentView.updateLayout();
+    },
+
+    prepareToHide: function()
+    {
+        this.contentView.visible = false;
+        this.contentView.hidden();
+
+        this._saveScrollPositions();
+    },
+
+    // Private
+
+    _restoreFromCookie: function()
+    {
+        this._restoreScrollPositions();
+
+        if (this._restoreCallback && typeof this._restoreCallback === "function")
+            this._restoreCallback.call(null, this.contentView, this.cookie);
+    },
+
+    _restoreScrollPositions: function()
+    {
+        // If no scroll positions are saved, do nothing.
+        if (!this._scrollPositions.length)
+            return;
+
+        var scrollableElements = this.contentView.scrollableElements || [];
+        console.assert(this._scrollPositions.length === scrollableElements.length);
+
+        for (var i = 0; i < scrollableElements.length; ++i) {
+            var position = this._scrollPositions[i];
+            var element = scrollableElements[i];
+            if (!element)
+                continue;
+
+            // Restore the top scroll position by either scrolling to the bottom or to the saved position.
+            element.scrollTop = position.isScrolledToBottom ? element.scrollHeight : position.scrollTop;
+
+            // Don't restore the left scroll position when scrolled to the bottom. This way the when content changes
+            // the user won't be left in a weird horizontal position.
+            element.scrollLeft = position.isScrolledToBottom ? 0 : position.scrollLeft;
+        }
+    },
+
+    _saveScrollPositions: function()
+    {
+        var scrollableElements = this.contentView.scrollableElements || [];
+        var scrollPositions = [];
+        for (var i = 0; i < scrollableElements.length; ++i) {
+            var element = scrollableElements[i];
+            if (!element)
+                continue;
+
+            var position = { scrollTop: element.scrollTop, scrollLeft: element.scrollLeft };
+            if (this.contentView.shouldKeepElementsScrolledToBottom)
+                position.isScrolledToBottom = element.isScrolledToBottom();
+
+            scrollPositions.push(position);
+        }
+
+        this._scrollPositions = scrollPositions;
+    }
+};
index 37f50af7abb5af75f52cc2702d384a4de1f39a52..db987a8b20b45b013057ff2535dcc274d0bfab72 100644 (file)
@@ -157,9 +157,9 @@ WebInspector.ContentBrowser.prototype = {
         return this._contentViewContainer.showContentViewForRepresentedObject(representedObject);
     },
 
-    showContentView: function(contentView)
+    showContentView: function(contentView, cookie, restoreCallback)
     {
-        return this._contentViewContainer.showContentView(contentView);
+        return this._contentViewContainer.showContentView(contentView, cookie, restoreCallback);
     },
 
     contentViewForRepresentedObject: function(representedObject, onlyExisting)
@@ -411,7 +411,7 @@ WebInspector.ContentBrowser.prototype = {
 
         // Go through each of the items of the new content view and add a divider before them.
         currentContentView.navigationItems.forEach(function(navigationItem, index) {
-            // Add dividers before items unless it's the first item and not a button. 
+            // Add dividers before items unless it's the first item and not a button.
             if (index !== 0 || navigationItem instanceof WebInspector.ButtonNavigationItem) {
                 var divider = new WebInspector.DividerNavigationItem;
                 navigationBar.insertNavigationItem(divider, insertionIndex++);
@@ -433,7 +433,7 @@ WebInspector.ContentBrowser.prototype = {
             this._findBanner.numberOfResults = null;
             return;
         }
-        
+
         this._findBanner.targetElement = currentContentView.element;
         this._findBanner.numberOfResults = currentContentView.hasPerformedSearch ? currentContentView.numberOfSearchResults : null;
 
index d73f2804df7c7f5dd9b61f3cdd7ed0dcb6fcf4bc..8550e6a1057c28704b683a74a622d72cd0206309 100644 (file)
@@ -61,6 +61,13 @@ WebInspector.ContentViewContainer.prototype = {
     },
 
     get currentContentView()
+    {
+        if (this._currentIndex < 0 || this._currentIndex > this._backForwardList.length - 1)
+            return null;
+        return this._backForwardList[this._currentIndex].contentView;
+    },
+
+    get currentBackForwardEntry()
     {
         if (this._currentIndex < 0 || this._currentIndex > this._backForwardList.length - 1)
             return null;
@@ -126,7 +133,7 @@ WebInspector.ContentViewContainer.prototype = {
         return contentView;
     },
 
-    showContentView: function(contentView)
+    showContentView: function(contentView, cookie, restoreCallback)
     {
         console.assert(contentView instanceof WebInspector.ContentView);
         if (!(contentView instanceof WebInspector.ContentView))
@@ -138,10 +145,11 @@ WebInspector.ContentViewContainer.prototype = {
         if (contentView.parentContainer && contentView.parentContainer !== this)
             return null;
 
-        // Don't do anything if the content view is already the current content view.
-        var currentContentView = this.currentContentView;
-        if (currentContentView === contentView)
-            return contentView;
+        var currentEntry = this.currentBackForwardEntry;
+        var provisionalEntry = new WebInspector.BackForwardEntry(contentView, cookie, restoreCallback);
+        // Don't do anything if we would have added an identical back/forward list entry.
+        if (currentEntry && currentEntry.contentView === contentView && Object.shallowEqual(provisionalEntry.cookie, currentEntry.cookie))
+            return currentEntry.contentView;
 
         // Showing a content view will truncate the back/forward list after the current index and insert the content view
         // at the end of the list. Finally, the current index will be updated to point to the end of the back/forward list.
@@ -150,29 +158,30 @@ WebInspector.ContentViewContainer.prototype = {
         var newIndex = this._currentIndex + 1;
 
         // Insert the content view at the new index. This will remove any content views greater than or equal to the index.
-        var removedItems = this._backForwardList.splice(newIndex, this._backForwardList.length - newIndex, contentView);
+        var removedEntries = this._backForwardList.splice(newIndex, this._backForwardList.length - newIndex, provisionalEntry);
 
         console.assert(newIndex === this._backForwardList.length - 1);
-        console.assert(this._backForwardList[newIndex] === contentView);
+        console.assert(this._backForwardList[newIndex] === provisionalEntry);
 
         // Disassociate with the removed content views.
-        for (var i = 0; i < removedItems.length; ++i) {
+        for (var i = 0; i < removedEntries.length; ++i) {
             // Skip disassociation if this content view is still in the back/forward list.
-            if (this._backForwardList.contains(removedItems[i]))
-                continue;
-
-            this._disassociateFromContentView(removedItems[i]);
+            var shouldDissociateContentView = this._backForwardList.some(function(existingEntry) {
+                return existingEntry.contentView === removedEntries[i].contentView;
+            });
+            if (shouldDissociateContentView)
+                this._disassociateFromContentView(removedEntries[i]);
         }
 
         // Associate with the new content view.
         contentView._parentContainer = this;
 
-        this.showBackForwardEntry(newIndex);
+        this.showBackForwardEntryForIndex(newIndex);
 
         return contentView;
     },
 
-    showBackForwardEntry: function(index)
+    showBackForwardEntryForIndex: function(index)
     {
         console.assert(index >= 0 && index <= this._backForwardList.length - 1);
         if (index < 0 || index > this._backForwardList.length - 1)
@@ -182,13 +191,15 @@ WebInspector.ContentViewContainer.prototype = {
             return;
 
         // Hide the currently visible content view.
-        var currentContentView = this.currentContentView;
-        if (currentContentView)
-            this._hideContentView(currentContentView);
+        var previousEntry = this.currentBackForwardEntry;
+        if (previousEntry)
+            this._hideEntry(previousEntry);
 
         this._currentIndex = index;
+        var currentEntry = this.currentBackForwardEntry;
+        console.assert(currentEntry);
 
-        this._showContentView(this.currentContentView);
+        this._showEntry(currentEntry);
 
         this.dispatchEventToListeners(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange);
     },
@@ -213,7 +224,7 @@ WebInspector.ContentViewContainer.prototype = {
 
         var currentlyShowing = (this.currentContentView === oldContentView);
         if (currentlyShowing)
-            this._hideContentView(oldContentView);
+            this._hideEntry(this.currentBackForwardEntry);
 
         // Disassociate with the old content view.
         this._disassociateFromContentView(oldContentView);
@@ -223,12 +234,13 @@ WebInspector.ContentViewContainer.prototype = {
 
         // Replace all occurrences of oldContentView with newContentView in the back/forward list.
         for (var i = 0; i < this._backForwardList.length; ++i) {
-            if (this._backForwardList[i] === oldContentView)
-                this._backForwardList[i] = newContentView;
+            if (this._backForwardList[i].contentView === oldContentView)
+                this._backForwardList[i].contentView = newContentView;
         }
 
+        // Re-show the current entry, because its content view instance was replaced.
         if (currentlyShowing) {
-            this._showContentView(newContentView);
+            this._showEntry(this.currentBackForwardEntry);
             this.dispatchEventToListeners(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange);
         }
     },
@@ -244,7 +256,7 @@ WebInspector.ContentViewContainer.prototype = {
         // If they all are we can use the quicker closeAllContentViews method.
         var allSamePrototype = true;
         for (var i = this._backForwardList.length - 1; i >= 0; --i) {
-            if (!(this._backForwardList[i] instanceof constructor)) {
+            if (!(this._backForwardList[i].contentView instanceof constructor)) {
                 allSamePrototype = false;
                 break;
             }
@@ -260,12 +272,12 @@ WebInspector.ContentViewContainer.prototype = {
         var backForwardListDidChange = false;
         // Hide and disassociate with all the content views that are instances of the constructor.
         for (var i = this._backForwardList.length - 1; i >= 0; --i) {
-            var contentView = this._backForwardList[i];
-            if (!(contentView instanceof constructor))
+            var entry = this._backForwardList[i];
+            if (!(entry.contentView instanceof constructor))
                 continue;
 
-            if (contentView === oldCurrentContentView)
-                this._hideContentView(contentView);
+            if (entry.contentView === oldCurrentContentView)
+                this._hideEntry(entry);
 
             if (this._currentIndex >= i) {
                 // Decrement the currentIndex since we will remove an item in the back/forward array
@@ -273,18 +285,18 @@ WebInspector.ContentViewContainer.prototype = {
                 --this._currentIndex;
             }
 
-            this._disassociateFromContentView(contentView);
+            this._disassociateFromContentView(entry.contentView);
 
             // Remove the item from the back/forward list.
             this._backForwardList.splice(i, 1);
             backForwardListDidChange = true;
         }
 
-        var currentContentView = this.currentContentView;
-        console.assert(currentContentView || (!currentContentView && this._currentIndex === -1));
+        var currentEntry = this.currentBackForwardEntry;
+        console.assert(currentEntry || (!currentEntry && this._currentIndex === -1));
 
-        if (currentContentView && (currentContentView !== oldCurrentContentView || backForwardListDidChange)) {
-            this._showContentView(currentContentView);
+        if (currentEntry && currentEntry.contentView !== oldCurrentContentView || backForwardListDidChange) {
+            this._showEntry(currentEntry);
             this.dispatchEventToListeners(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange);
         }
     },
@@ -298,10 +310,10 @@ WebInspector.ContentViewContainer.prototype = {
 
         // Hide and disassociate with all the content views.
         for (var i = 0; i < this._backForwardList.length; ++i) {
-            var contentView = this._backForwardList[i];
+            var entry = this._backForwardList[i];
             if (i === this._currentIndex)
-                this._hideContentView(contentView);
-            this._disassociateFromContentView(contentView);
+                this._hideEntry(entry);
+            this._disassociateFromContentView(entry.contentView);
         }
 
         this._backForwardList = [];
@@ -324,32 +336,32 @@ WebInspector.ContentViewContainer.prototype = {
     {
         if (!this.canGoBack())
             return;
-        this.showBackForwardEntry(this._currentIndex - 1);
+        this.showBackForwardEntryForIndex(this._currentIndex - 1);
     },
 
     goForward: function()
     {
         if (!this.canGoForward())
             return;
-        this.showBackForwardEntry(this._currentIndex + 1);
+        this.showBackForwardEntryForIndex(this._currentIndex + 1);
     },
 
     shown: function()
     {
-        var currentContentView = this.currentContentView;
-        if (!currentContentView)
+        var currentEntry = this.currentBackForwardEntry;
+        if (!currentEntry)
             return;
 
-        this._showContentView(currentContentView);
+        this._showEntry(currentEntry);
     },
 
     hidden: function()
     {
-        var currentContentView = this.currentContentView;
-        if (!currentContentView)
+        var currentEntry = this.currentBackForwardEntry;
+        if (!currentEntry)
             return;
 
-        this._hideContentView(currentContentView);
+        this._hideEntry(currentEntry);
     },
 
     // Private
@@ -381,72 +393,20 @@ WebInspector.ContentViewContainer.prototype = {
         contentView.closed();
     },
 
-    _saveScrollPositionsForContentView: function(contentView)
-    {
-        var scrollableElements = contentView.scrollableElements || [];
-        for (var i = 0; i < scrollableElements.length; ++i) {
-            var element = scrollableElements[i];
-            if (!element)
-                continue;
-            if (contentView.shouldKeepElementsScrolledToBottom)
-                element._savedIsScrolledToBottom = element.isScrolledToBottom();
-            element._savedScrollTop = element.scrollTop;
-            element._savedScrollLeft = element.scrollLeft;
-        }
-    },
-
-    _restoreScrollPositionsForContentView: function(contentView)
+    _showEntry: function(entry)
     {
-        var scrollableElements = contentView.scrollableElements || [];
-        for (var i = 0; i < scrollableElements.length; ++i) {
-            var element = scrollableElements[i];
-            if (!element)
-                continue;
-
-            // Restore the top scroll position by either scrolling to the bottom or to the saved position.
-            element.scrollTop = element._savedIsScrolledToBottom ? element.scrollHeight : element._savedScrollTop;
-
-            // Don't restore the left scroll position when scrolled to the bottom. This way the when content changes
-            // the user won't be left in a weird horizontal position.
-            element.scrollLeft = element._savedIsScrolledToBottom ? 0 : element._savedScrollLeft;
-        }
-    },
-
-    _showContentView: function(contentView)
-    {
-        if (contentView.visible)
-            return;
-
-        this._addContentViewElement(contentView);
-
-        this._prepareContentViewToShow(contentView);
-    },
-
-    _prepareContentViewToShow: function(contentView)
-    {
-        this._restoreScrollPositionsForContentView(contentView);
-
-        contentView.visible = true;
-        contentView.shown();
-        contentView.updateLayout();
-    },
-
-    _hideContentView: function(contentView)
-    {
-        if (!contentView.visible)
-            return;
-
-        this._prepareContentViewToHide(contentView);
+        console.assert(entry instanceof WebInspector.BackForwardEntry);
 
-        this._removeContentViewElement(contentView);
+        this._addContentViewElement(entry.contentView);
+        entry.prepareToShow();
     },
 
-    _prepareContentViewToHide: function(contentView)
+    _hideEntry: function(entry)
     {
-        contentView.visible = false;
-        contentView.hidden();
+        console.assert(entry instanceof WebInspector.BackForwardEntry);
 
-        this._saveScrollPositionsForContentView(contentView);
+        entry.prepareToHide();
+        this._removeContentViewElement(entry.contentView);
     }
 };
 
index f72a8d42072e9688236abde6db40c755603c3aa1..5f52c44e14ae978cb2d25ecb9a06906b2a7cc46f 100644 (file)
     <script src="TextEditor.js"></script>
     <script src="EventHandler.js"></script>
     <script src="SourceCodeTextEditor.js"></script>
+    <script src="BackForwardEntry.js"></script>
     <script src="ContentViewContainer.js"></script>
     <script src="ContentView.js"></script>
     <script src="ClusterContentView.js"></script>
index 6a0bbe8cdfb493766a8bd7dc9c83e5b7151f8d07..7e7ef623b2c4a9cb5b45292f8f8c985eb6ebc163 100644 (file)
@@ -511,7 +511,8 @@ WebInspector.openURL = function(url, frame, alwaysOpenExternally, lineNumber)
     // WebInspector.Frame.resourceForURL does not check the main resource, only sub-resources. So check both.
     var resource = frame.url === url ? frame.mainResource : frame.resourceForURL(url, searchChildFrames);
     if (resource) {
-        this.resourceSidebarPanel.showSourceCode(resource, lineNumber);
+        var position = new WebInspector.SourceCodePosition(lineNumber, 0);
+        this.resourceSidebarPanel.showSourceCode(resource, position);
         return;
     }
 
index 3f5870450687ecaaae41e0d0ecee4b29bc844196..e66af1bab08b8b56f1abb13fce7d7a96b344fc9e 100644 (file)
@@ -248,6 +248,7 @@ WebInspector.ResourceSidebarPanel.prototype = {
 
     showSourceCode: function(sourceCode, positionToReveal, textRangeToSelect, forceUnformatted)
     {
+        console.assert(!positionToReveal || positionToReveal instanceof WebInspector.SourceCodePosition, positionToReveal);
         var representedObject = sourceCode;
 
         if (representedObject instanceof WebInspector.Script) {
@@ -259,16 +260,23 @@ WebInspector.ResourceSidebarPanel.prototype = {
         if (representedObject instanceof WebInspector.Resource && representedObject.isMainResource())
             representedObject = representedObject.parentFrame;
 
-        var contentView = WebInspector.contentBrowser.contentViewForRepresentedObject(representedObject);
+        var newContentView = WebInspector.contentBrowser.contentViewForRepresentedObject(representedObject);
+        var cookie = {lineNumber: positionToReveal.lineNumber, columnNumber: positionToReveal.columnNumber};
 
-        if (contentView instanceof WebInspector.FrameContentView)
-            contentView.showSourceCode(positionToReveal, textRangeToSelect, forceUnformatted);
-        else if (contentView instanceof WebInspector.ResourceClusterContentView)
-            contentView.showResponse(positionToReveal, textRangeToSelect, forceUnformatted);
-        else if (contentView instanceof WebInspector.ScriptContentView)
-            contentView.revealPosition(positionToReveal, textRangeToSelect, forceUnformatted);
+        var restoreCallback = function(contentView, savedCookie) {
+            var lineNumber = savedCookie.lineNumber;
+            var columnNumber = savedCookie.columnNumber;
+            var position = new WebInspector.SourceCodePosition(lineNumber, columnNumber);
 
-        WebInspector.contentBrowser.showContentView(contentView);
+            if (contentView instanceof WebInspector.FrameContentView)
+                contentView.showSourceCode(position)
+            else if (contentView instanceof WebInspector.ResourceClusterContentView)
+                contentView.showResponse(position)
+            else if (contentView instanceof WebInspector.ScriptContentView)
+                contentView.revealPosition(position)
+        };
+
+        WebInspector.contentBrowser.showContentView(newContentView, cookie, restoreCallback);
     },
 
     showSourceCodeLocation: function(sourceCodeLocation)