diff options
author | cbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-14 16:49:19 +0000 |
---|---|---|
committer | cbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-14 16:49:19 +0000 |
commit | 9e1ad4b286a342d27726908a0df47b4e54e9b50e (patch) | |
tree | 2de9bd6fcfbbe2158c1e1712265c81b33185dffb /content/browser/tab_contents | |
parent | 5dcda9d959b5a3062976d98ae0eab575cfb321d4 (diff) | |
download | chromium_src-9e1ad4b286a342d27726908a0df47b4e54e9b50e.zip chromium_src-9e1ad4b286a342d27726908a0df47b4e54e9b50e.tar.gz chromium_src-9e1ad4b286a342d27726908a0df47b4e54e9b50e.tar.bz2 |
A number of issues weren't addressed with the earlier patch for prerender + browsing history, particularly for instant pages.
- The "remove first entry" option used by instant was not being handled correctly when there was only one committed entry in the NavigationController.
- Renderer-issued navigations which were committed in the browser but not yet known by the browser/NavigationController were being incorrectly pruned. This did not happen regularly in the prerender case, but does in the instant case, particularly when changing what's typed in the omnibox.
- Some additional sanity testing to make sure that the message is sent to the correct render process.
- Additional unit tests are added.
BUG=89798
TEST=NavigationControllerTest.CopyStateFromAndPrune*, RenderViewTest.SetHistoryLengthAndPrune.
Review URL: http://codereview.chromium.org/7618016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96724 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/tab_contents')
-rw-r--r-- | content/browser/tab_contents/navigation_controller.cc | 23 | ||||
-rw-r--r-- | content/browser/tab_contents/navigation_controller_unittest.cc | 14 | ||||
-rw-r--r-- | content/browser/tab_contents/tab_contents.cc | 25 | ||||
-rw-r--r-- | content/browser/tab_contents/tab_contents.h | 7 | ||||
-rw-r--r-- | content/browser/tab_contents/test_tab_contents.cc | 29 | ||||
-rw-r--r-- | content/browser/tab_contents/test_tab_contents.h | 30 |
6 files changed, 114 insertions, 14 deletions
diff --git a/content/browser/tab_contents/navigation_controller.cc b/content/browser/tab_contents/navigation_controller.cc index 0144fef..315a4711 100644 --- a/content/browser/tab_contents/navigation_controller.cc +++ b/content/browser/tab_contents/navigation_controller.cc @@ -883,6 +883,14 @@ void NavigationController::CopyStateFrom(const NavigationController& source) { void NavigationController::CopyStateFromAndPrune(NavigationController* source, bool remove_first_entry) { + // The SiteInstance and page_id of the last committed entry needs to be + // remembered at this point, in case there is only one committed entry + // and it is pruned. + NavigationEntry* last_committed = GetLastCommittedEntry(); + SiteInstance* site_instance = + last_committed ? last_committed->site_instance() : NULL; + int32 minimum_page_id = last_committed ? last_committed->page_id() : -1; + // This code is intended for use when the last entry is the active entry. DCHECK((transient_entry_index_ != -1 && transient_entry_index_ == entry_count() - 1) || @@ -891,6 +899,16 @@ void NavigationController::CopyStateFromAndPrune(NavigationController* source, (!pending_entry_ && last_committed_entry_index_ == entry_count() - 1)); if (remove_first_entry && entry_count()) { + // If there is only one committed entry and |remove_first_entry| is true, + // it needs to be pruned. This is accomplished by specifying a larger + // |minimum_page_id| than the committed entry's page_id in the + // ViewMsg_SetHistoryLengthAndPrune message. However, any pages which are + // committed between now and when the RenderView handles the message will + // need to be retained. Both constraints can be met by incrementing the + // |minimum_page_id| by 1. + DCHECK(minimum_page_id >= 0); + if (entry_count() == 1) + ++minimum_page_id; // Save then restore the pending entry (RemoveEntryAtIndexInternal chucks // the pending entry). NavigationEntry* pending_entry = pending_entry_; @@ -932,8 +950,9 @@ void NavigationController::CopyStateFromAndPrune(NavigationController* source, last_committed_entry_index_--; } - // Update the history in the RenderView. - tab_contents_->SetHistoryLengthAndClear(max_source_index); + tab_contents_->SetHistoryLengthAndPrune(site_instance, + max_source_index, + minimum_page_id); } void NavigationController::PruneAllButActive() { diff --git a/content/browser/tab_contents/navigation_controller_unittest.cc b/content/browser/tab_contents/navigation_controller_unittest.cc index f7992c2..4e1ec10 100644 --- a/content/browser/tab_contents/navigation_controller_unittest.cc +++ b/content/browser/tab_contents/navigation_controller_unittest.cc @@ -1923,6 +1923,9 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune) { scoped_ptr<TestTabContents> other_contents(CreateTestTabContents()); NavigationController& other_controller = other_contents->controller(); other_contents->NavigateAndCommit(url3); + other_contents->ExpectSetHistoryLengthAndPrune( + other_controller.GetEntryAtIndex(0)->site_instance(), 2, + other_controller.GetEntryAtIndex(0)->page_id()); other_controller.CopyStateFromAndPrune(&controller(), false); // other_controller should now contain the 3 urls: url1, url2 and url3. @@ -1949,6 +1952,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune2) { scoped_ptr<TestTabContents> other_contents(CreateTestTabContents()); NavigationController& other_controller = other_contents->controller(); + other_contents->ExpectSetHistoryLengthAndPrune(NULL, 1, -1); other_controller.CopyStateFromAndPrune(&controller(), false); // other_controller should now contain the 1 url: url1. @@ -1974,6 +1978,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune3) { scoped_ptr<TestTabContents> other_contents(CreateTestTabContents()); NavigationController& other_controller = other_contents->controller(); other_controller.LoadURL(url3, GURL(), PageTransition::TYPED); + other_contents->ExpectSetHistoryLengthAndPrune(NULL, 1, -1); other_controller.CopyStateFromAndPrune(&controller(), false); // other_controller should now contain 1 entry for url1, and a pending entry @@ -2000,6 +2005,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune4) { scoped_ptr<TestTabContents> other_contents(CreateTestTabContents()); NavigationController& other_controller = other_contents->controller(); + other_contents->ExpectSetHistoryLengthAndPrune(NULL, 1, -1); other_controller.CopyStateFromAndPrune(&controller(), true); // other_controller should now contain 1 entry for url1. @@ -2025,6 +2031,10 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune5) { scoped_ptr<TestTabContents> other_contents(CreateTestTabContents()); NavigationController& other_controller = other_contents->controller(); other_contents->NavigateAndCommit(url2); + other_contents->ExpectSetHistoryLengthAndPrune( + other_controller.GetEntryAtIndex(0)->site_instance(), + 1, + other_controller.GetEntryAtIndex(0)->page_id() + 1); other_controller.CopyStateFromAndPrune(&controller(), true); // other_controller should now contain 1 entry, url1. @@ -2050,6 +2060,10 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune6) { NavigationController& other_controller = other_contents->controller(); other_contents->NavigateAndCommit(url2); other_controller.LoadURL(url3, GURL(), PageTransition::TYPED); + other_contents->ExpectSetHistoryLengthAndPrune( + other_controller.GetEntryAtIndex(0)->site_instance(), + 1, + other_controller.GetEntryAtIndex(0)->page_id() + 1); other_controller.CopyStateFromAndPrune(&controller(), true); // other_controller should now contain 2 entries: url1, and url3. diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc index 1fdccbf..b14a4cc 100644 --- a/content/browser/tab_contents/tab_contents.cc +++ b/content/browser/tab_contents/tab_contents.cc @@ -596,12 +596,29 @@ bool TabContents::NavigateToEntry( return true; } -void TabContents::SetHistoryLengthAndClear(int history_length) { +void TabContents::SetHistoryLengthAndPrune(const SiteInstance* site_instance, + int history_length, + int32 minimum_page_id) { + // SetHistoryLengthAndPrune doesn't handle pending cross-site navigations + // cleanly. Since it's only used when swapping in instant and prerendered + // TabContents, checks are done at a higher level to ensure that the pages + // are not swapped in during this case. + if (render_manager_.pending_render_view_host()) { + NOTREACHED(); + return; + } RenderViewHost* rvh = render_view_host(); - if (!rvh) + if (!rvh) { + NOTREACHED(); return; - rvh->Send(new ViewMsg_SetHistoryLengthAndClear(rvh->routing_id(), - history_length)); + } + if (site_instance && rvh->site_instance() != site_instance) { + NOTREACHED(); + return; + } + rvh->Send(new ViewMsg_SetHistoryLengthAndPrune(rvh->routing_id(), + history_length, + minimum_page_id)); } void TabContents::Stop() { diff --git a/content/browser/tab_contents/tab_contents.h b/content/browser/tab_contents/tab_contents.h index 13b5c28..3f416e4 100644 --- a/content/browser/tab_contents/tab_contents.h +++ b/content/browser/tab_contents/tab_contents.h @@ -626,9 +626,10 @@ class TabContents : public PageNavigator, // Sets the history for this tab_contents to |history_length| entries, and // moves the current page_id to the last entry in the list if it's valid. // This is mainly used when a prerendered page is swapped into the current - // tab. - void SetHistoryLengthAndClear(int history_length); - + // tab. The method is virtual for testing. + virtual void SetHistoryLengthAndPrune(const SiteInstance* site_instance, + int merge_history_length, + int32 minimum_page_id); // Misc non-view stuff ------------------------------------------------------- diff --git a/content/browser/tab_contents/test_tab_contents.cc b/content/browser/tab_contents/test_tab_contents.cc index 4252114..13cb1d9 100644 --- a/content/browser/tab_contents/test_tab_contents.cc +++ b/content/browser/tab_contents/test_tab_contents.cc @@ -17,7 +17,14 @@ TestTabContents::TestTabContents(content::BrowserContext* browser_context, SiteInstance* instance) : TabContents(browser_context, instance, MSG_ROUTING_NONE, NULL, NULL), transition_cross_site(false), - delegate_view_override_(NULL) { + delegate_view_override_(NULL), + expect_set_history_length_and_prune_(false), + expect_set_history_length_and_prune_site_instance_(NULL), + expect_set_history_length_and_prune_history_length_(0), + expect_set_history_length_and_prune_min_page_id_(-1) { +} + +TestTabContents::~TestTabContents() { } TestRenderViewHost* TestTabContents::pending_rvh() const { @@ -90,3 +97,23 @@ RenderViewHostDelegate::View* TestTabContents::GetViewDelegate() { return delegate_view_override_; return TabContents::GetViewDelegate(); } + +void TestTabContents::ExpectSetHistoryLengthAndPrune( + const SiteInstance* site_instance, + int history_length, + int32 min_page_id) { + expect_set_history_length_and_prune_ = true; + expect_set_history_length_and_prune_site_instance_ = site_instance; + expect_set_history_length_and_prune_history_length_ = history_length; + expect_set_history_length_and_prune_min_page_id_ = min_page_id; +} + +void TestTabContents::SetHistoryLengthAndPrune( + const SiteInstance* site_instance, int history_length, int32 min_page_id) { + EXPECT_TRUE(expect_set_history_length_and_prune_); + expect_set_history_length_and_prune_ = false; + EXPECT_EQ(expect_set_history_length_and_prune_site_instance_, site_instance); + EXPECT_EQ(expect_set_history_length_and_prune_history_length_, + history_length); + EXPECT_EQ(expect_set_history_length_and_prune_min_page_id_, min_page_id); +} diff --git a/content/browser/tab_contents/test_tab_contents.h b/content/browser/tab_contents/test_tab_contents.h index fb7b1bc..72170ab 100644 --- a/content/browser/tab_contents/test_tab_contents.h +++ b/content/browser/tab_contents/test_tab_contents.h @@ -17,6 +17,7 @@ class TestTabContents : public TabContents { public: TestTabContents(content::BrowserContext* browser_context, SiteInstance* instance); + virtual ~TestTabContents(); TestRenderViewHost* pending_rvh() const; @@ -42,12 +43,12 @@ class TestTabContents : public TabContents { // Prevent interaction with views. virtual bool CreateRenderViewForRenderManager( - RenderViewHost* render_view_host); - virtual void UpdateRenderViewSizeForRenderManager() {} + RenderViewHost* render_view_host) OVERRIDE; + virtual void UpdateRenderViewSizeForRenderManager() OVERRIDE {} // Returns a clone of this TestTabContents. The returned object is also a // TestTabContents. The caller owns the returned object. - virtual TabContents* Clone(); + virtual TabContents* Clone() OVERRIDE; // Creates a pending navigation to the given URL with the default parameters // and then commits the load with a page ID one larger than any seen. This @@ -67,12 +68,33 @@ class TestTabContents : public TabContents { bool transition_cross_site; // Allow mocking of the RenderViewHostDelegate::View. - virtual RenderViewHostDelegate::View* GetViewDelegate(); + virtual RenderViewHostDelegate::View* GetViewDelegate() OVERRIDE; void set_view_delegate(RenderViewHostDelegate::View* view) { delegate_view_override_ = view; } + + // Establish expected arguments for |SetHistoryLengthAndPrune()|. When + // |SetHistoryLengthAndPrune()| is called, the arguments are compared + // with the expected arguments specified here. + void ExpectSetHistoryLengthAndPrune(const SiteInstance* site_instance, + int history_length, + int32 min_page_id); + + // Compares the arguments passed in with the expected arguments passed in + // to |ExpectSetHistoryLengthAndPrune()|. + virtual void SetHistoryLengthAndPrune(const SiteInstance* site_instance, + int history_length, + int32 min_page_id) OVERRIDE; + private: RenderViewHostDelegate::View* delegate_view_override_; + + // Expectations for arguments of |SetHistoryLengthAndPrune()|. + bool expect_set_history_length_and_prune_; + scoped_refptr<const SiteInstance> + expect_set_history_length_and_prune_site_instance_; + int expect_set_history_length_and_prune_history_length_; + int32 expect_set_history_length_and_prune_min_page_id_; }; #endif // CONTENT_BROWSER_TAB_CONTENTS_TEST_TAB_CONTENTS_H_ |