summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-10 01:48:35 +0000
committercbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-10 01:48:35 +0000
commitc9b69d4b5bfa297f9bf383729bfd5ac01c9679c7 (patch)
tree0a8257f497e6e33176feb3040f9af3923f21242f
parentb0d382907637c86d2975ecb04c62ae4f3250c8b2 (diff)
downloadchromium_src-c9b69d4b5bfa297f9bf383729bfd5ac01c9679c7.zip
chromium_src-c9b69d4b5bfa297f9bf383729bfd5ac01c9679c7.tar.gz
chromium_src-c9b69d4b5bfa297f9bf383729bfd5ac01c9679c7.tar.bz2
Merge 96109 - A fairly recent change introduced a history of page_ids for each RenderView, to validate that Navigation's go to legitimate pages.
In the prerender and instant cases, the history of page_id's was not accurate, because it was not offset to reflect the point in time when the page was swapped in. For example, if the history for the tab looks like about:blank http://www.launchprerender.com/ http://www.prerendered_page.com/first_page.html http://www.prerendered_page.com/second_page.html The history of page_id's in the prerender-page RenderView should look like [-1, -1, 13, 14] - with the first two entries being -1 since they are not captured in this render view. Before this fix, it would look like [13, 14] - and when the back navigation was attempted, the length was not as long as expected. BUG=89798 TEST=Go to prerender_test.appspot.com, do a prerender on dev.chromium.org, click on a link within dev.chromium.org, press back and see that it works instead of spinning forever. Also, browser_tests --gtest_filter=*BackToPrerenderedPage, which fails without the change. Review URL: http://codereview.chromium.org/7491096 TBR=cbentzel@chromium.org Review URL: http://codereview.chromium.org/7459010 git-svn-id: svn://svn.chromium.org/chrome/branches/835/src@96111 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/prerender/prerender_browsertest.cc57
-rw-r--r--chrome/test/data/prerender/prerender_loader.html18
-rw-r--r--chrome/test/data/prerender/prerender_page_with_link.html30
-rw-r--r--content/browser/tab_contents/navigation_controller.cc3
-rw-r--r--content/browser/tab_contents/tab_contents.cc8
-rw-r--r--content/browser/tab_contents/tab_contents.h7
-rw-r--r--content/common/view_messages.h12
-rw-r--r--content/renderer/render_view.cc28
-rw-r--r--content/renderer/render_view.h1
9 files changed, 159 insertions, 5 deletions
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 77858d1..37a537a 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -473,6 +473,26 @@ class PrerenderBrowserTest : public InProcessBrowserTest {
}
}
+ void OpenDestUrlViaClick() const {
+ // Make sure in navigating we have a URL to use in the PrerenderManager.
+ TestPrerenderContents* prerender_contents = GetPrerenderContents();
+ ASSERT_TRUE(prerender_contents != NULL);
+ prerender_contents->set_quit_message_loop_on_destruction(false);
+
+ bool click_prerendered_link_result = false;
+ ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ browser()->GetSelectedTabContents()->render_view_host(), L"",
+ L"window.domAutomationController.send(ClickOpenLink())",
+ &click_prerendered_link_result));
+ EXPECT_TRUE(click_prerendered_link_result);
+
+ // If the prerender contents has not been destroyed, run message loop.
+ if (GetPrerenderContents() != NULL) {
+ prerender_contents->set_quit_message_loop_on_destruction(true);
+ ui_test_utils::RunMessageLoop();
+ }
+ }
+
// Should be const but test_server()->GetURL(...) is not const.
void NavigateToURL(const std::string& dest_html_file) {
GURL dest_url = test_server()->GetURL(dest_html_file);
@@ -1611,4 +1631,41 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelAll) {
EXPECT_TRUE(GetPrerenderContents() == NULL);
}
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, BackToPrerenderedPage) {
+ PrerenderTestURL("files/prerender/prerender_page_with_link.html",
+ FINAL_STATUS_USED,
+ 1);
+
+ OpenDestUrlViaClick();
+
+ // Click on the link in the page and wait for it to commit
+ {
+ ui_test_utils::WindowedNotificationObserver new_page_observer(
+ content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+ NotificationService::AllSources());
+ bool click_link_result = false;
+ ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ browser()->GetSelectedTabContents()->render_view_host(), L"",
+ L"window.domAutomationController.send(ClickOpenLink())",
+ &click_link_result));
+ EXPECT_TRUE(click_link_result);
+ new_page_observer.Wait();
+ }
+
+ // Now, go back to the prerendered page.
+ {
+ ui_test_utils::WindowedNotificationObserver back_nav_observer(
+ content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+ NotificationService::AllSources());
+ browser()->GoBack(CURRENT_TAB);
+ back_nav_observer.Wait();
+ bool original_prerender_page = false;
+ ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ browser()->GetSelectedTabContents()->render_view_host(), L"",
+ L"window.domAutomationController.send(IsOriginalPrerenderPage())",
+ &original_prerender_page));
+ EXPECT_TRUE(original_prerender_page);
+ }
+}
+
} // namespace prerender
diff --git a/chrome/test/data/prerender/prerender_loader.html b/chrome/test/data/prerender/prerender_loader.html
index f8089d3..3a364b6 100644
--- a/chrome/test/data/prerender/prerender_loader.html
+++ b/chrome/test/data/prerender/prerender_loader.html
@@ -4,14 +4,21 @@
<script>
function ClickOpenLinkInNewWindow() {
- var eventObject = document.createEvent("MouseEvents");
+ var eventObject = document.createEvent('MouseEvents');
eventObject.initMouseEvent('click');
- document.getElementById("toClick").dispatchEvent(eventObject);
+ document.getElementById('toClickTarget').dispatchEvent(eventObject);
+ return true;
+ }
+
+ function ClickOpenLink() {
+ var eventObject = document.createEvent('MouseEvents');
+ eventObject.initMouseEvent('click');
+ document.getElementById('toClick').dispatchEvent(eventObject);
return true;
}
function JsOpenLinkInNewWindow() {
- window.open("REPLACE_WITH_PRERENDER_URL");
+ window.open('REPLACE_WITH_PRERENDER_URL');
return true;
}
</script>
@@ -21,7 +28,8 @@
<script>
document.write('<link rel="prerender" href="REPLACE_WITH_PRERENDER_URL"/>');
</script>
-<a target="_blank" id="toClick"
- href="REPLACE_WITH_PRERENDER_URL">Link To Click</a>
+<a target="_blank" id="toClickTarget"
+ href="REPLACE_WITH_PRERENDER_URL">Link To click in new window</a>
+<a id="toClick" href="REPLACE_WITH_PRERENDER_URL">Link to click</a>
</body>
</html>
diff --git a/chrome/test/data/prerender/prerender_page_with_link.html b/chrome/test/data/prerender/prerender_page_with_link.html
new file mode 100644
index 0000000..29c1b81
--- /dev/null
+++ b/chrome/test/data/prerender/prerender_page_with_link.html
@@ -0,0 +1,30 @@
+<html>
+<head>
+<title>Prerendered page with link</title>
+
+<script>
+var pageWasPrerendered = false;
+
+// Make sure plugin was not loaded while prerendering.
+function DidPrerenderPass() {
+ pageWasPrerendered = true;
+ return true;
+}
+
+function ClickOpenLink() {
+ var eventObject = document.createEvent('MouseEvents');
+ eventObject.initMouseEvent('click');
+ document.getElementById('toClick').dispatchEvent(eventObject);
+ return true;
+}
+
+function IsOriginalPrerenderPage() {
+ return true;
+}
+</script>
+
+</head>
+<body>
+<a id="toClick" href="prerender_page.html">Link to click</a>
+</body>
+</html>
diff --git a/content/browser/tab_contents/navigation_controller.cc b/content/browser/tab_contents/navigation_controller.cc
index 3ffbad2..bb5d8f9 100644
--- a/content/browser/tab_contents/navigation_controller.cc
+++ b/content/browser/tab_contents/navigation_controller.cc
@@ -936,6 +936,9 @@ void NavigationController::CopyStateFromAndPrune(NavigationController* source,
if (last_committed_entry_index_ != -1)
last_committed_entry_index_--;
}
+
+ // Update the history in the RenderView.
+ tab_contents_->SetHistoryLengthAndClear(max_source_index);
}
void NavigationController::PruneAllButActive() {
diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc
index 0981985..a5c409b 100644
--- a/content/browser/tab_contents/tab_contents.cc
+++ b/content/browser/tab_contents/tab_contents.cc
@@ -584,6 +584,14 @@ bool TabContents::NavigateToEntry(
return true;
}
+void TabContents::SetHistoryLengthAndClear(int history_length) {
+ RenderViewHost* rvh = render_view_host();
+ if (!rvh)
+ return;
+ rvh->Send(new ViewMsg_SetHistoryLengthAndClear(rvh->routing_id(),
+ history_length));
+}
+
void TabContents::Stop() {
render_manager_.Stop();
FOR_EACH_OBSERVER(TabContentsObserver, observers_, StopNavigation());
diff --git a/content/browser/tab_contents/tab_contents.h b/content/browser/tab_contents/tab_contents.h
index 933871f..8309c54 100644
--- a/content/browser/tab_contents/tab_contents.h
+++ b/content/browser/tab_contents/tab_contents.h
@@ -610,6 +610,13 @@ class TabContents : public PageNavigator,
bool NavigateToEntry(const NavigationEntry& entry,
NavigationController::ReloadType reload_type);
+ // 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);
+
+
// Misc non-view stuff -------------------------------------------------------
// Helper functions for sending notifications.
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 31c3da1..a63f585 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -732,6 +732,18 @@ IPC_STRUCT_END()
IPC_MESSAGE_CONTROL1(ViewMsg_SetNextPageID,
int32 /* next_page_id */)
+// Sets the history length of page_ids for a RenderView to
+// |length| entries, and moves the current page_id to the last
+// entry if it is valid.
+// The main use for this is prerendered pages, but Instant pages also use this.
+// For example, assume that there are 3 entries in the history when a
+// prerendered page is created. The new prerendered page will have a single
+// entry history like [7]. When it is swapped in, we need to extend the history
+// so it has a total length of 4 (3 for the previous history, 1 for the
+// prerendered page), so it looks like [-1 -1 -1 7].
+IPC_MESSAGE_ROUTED1(ViewMsg_SetHistoryLengthAndClear,
+ int /* length */)
+
// Sends System Colors corresponding to a set of CSS color keywords
// down the pipe.
// This message must be sent to the renderer immediately on launch
diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc
index c7f0ee0..cf82b20 100644
--- a/content/renderer/render_view.cc
+++ b/content/renderer/render_view.cc
@@ -699,6 +699,8 @@ bool RenderView::OnMessageReceived(const IPC::Message& message) {
#endif
IPC_MESSAGE_HANDLER(ViewMsg_UpdateRemoteAccessClientFirewallTraversal,
OnUpdateRemoteAccessClientFirewallTraversal)
+ IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryLengthAndClear,
+ OnSetHistoryLengthAndClear)
// Have the super handle all other messages.
IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message))
IPC_END_MESSAGE_MAP()
@@ -1004,6 +1006,32 @@ void RenderView::OnScrollFocusedEditableNodeIntoView() {
}
}
+void RenderView::OnSetHistoryLengthAndClear(int history_length) {
+ DCHECK(history_length >= 0);
+
+ // history_list_length_ may be 0 if this is called between
+ // a navigate and a commit of the provisional load. Otherwise,
+ // only add one entry, regardless of how long the current history is.
+ // TODO(cbentzel): Investigate what happens if a prerendered page
+ // navigates to several entries before it is swapped in. Cropping
+ // those may be a bad idea.
+ int new_history_list_length = history_length;
+ if (history_list_length_ > 0)
+ ++new_history_list_length;
+
+ DCHECK(page_id_ == -1 ||
+ (history_list_offset_ >= 0 &&
+ page_id_ == history_page_ids_[history_list_offset_]));
+
+ // Generate the new list.
+ std::vector<int32> new_history_page_ids(new_history_list_length, -1);
+ if (page_id_ != -1)
+ new_history_page_ids[new_history_list_length - 1] = page_id_;
+ new_history_page_ids.swap(history_page_ids_);
+ history_list_offset_ = new_history_list_length - 1;
+ history_list_length_ = new_history_list_length;
+}
+
///////////////////////////////////////////////////////////////////////////////
// Tell the embedding application that the URL of the active page has changed
diff --git a/content/renderer/render_view.h b/content/renderer/render_view.h
index 100d1c1..142afa6 100644
--- a/content/renderer/render_view.h
+++ b/content/renderer/render_view.h
@@ -841,6 +841,7 @@ class RenderView : public RenderWidget,
void OnUpdateTargetURLAck();
void OnUpdateWebPreferences(const WebPreferences& prefs);
void OnUpdateRemoteAccessClientFirewallTraversal(const std::string& policy);
+ void OnSetHistoryLengthAndClear(int history_length);
#if defined(OS_MACOSX)
void OnWindowFrameChanged(const gfx::Rect& window_frame,