summaryrefslogtreecommitdiffstats
path: root/content/browser/tab_contents
diff options
context:
space:
mode:
Diffstat (limited to 'content/browser/tab_contents')
-rw-r--r--content/browser/tab_contents/navigation_controller.cc23
-rw-r--r--content/browser/tab_contents/navigation_controller_unittest.cc14
-rw-r--r--content/browser/tab_contents/tab_contents.cc25
-rw-r--r--content/browser/tab_contents/tab_contents.h7
-rw-r--r--content/browser/tab_contents/test_tab_contents.cc29
-rw-r--r--content/browser/tab_contents/test_tab_contents.h30
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_