Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(779)

Unified Diff: content/browser/frame_host/navigation_controller_impl_browsertest.cc

Issue 1422333009: OOPIF: History navigations for new child frames. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Improve comment. Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/frame_host/navigation_controller_impl_browsertest.cc
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index 49095dc565ded919f14d22b69a91e207239042a4..6fd46e39caa97164eb9ad70336fb91178fad77ae 100644
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -1959,7 +1959,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify subframe entries if they're enabled (e.g. in --site-per-process).
if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
- // The entry should have a new FrameNavigationEntries for the subframe.
+ // The entry should have a FrameNavigationEntry for the subframe.
ASSERT_EQ(1U, entry2->root_node()->children.size());
EXPECT_EQ(frame_url2, entry2->root_node()->children[0]->frame_entry->url());
} else {
@@ -1981,7 +1981,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify subframe entries if they're enabled (e.g. in --site-per-process).
if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
- // The entry should have a new FrameNavigationEntries for the subframe.
+ // The entry should have a FrameNavigationEntry for the subframe.
ASSERT_EQ(1U, entry1->root_node()->children.size());
EXPECT_EQ(frame_url, entry1->root_node()->children[0]->frame_entry->url());
} else {
@@ -2003,7 +2003,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify subframe entries if they're enabled (e.g. in --site-per-process).
if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
- // The entry should have a new FrameNavigationEntries for the subframe.
+ // The entry should have a FrameNavigationEntry for the subframe.
ASSERT_EQ(1U, entry2->root_node()->children.size());
EXPECT_EQ(frame_url2, entry2->root_node()->children[0]->frame_entry->url());
} else {
@@ -2025,7 +2025,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify subframe entries if they're enabled (e.g. in --site-per-process).
if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
- // The entry should have a new FrameNavigationEntries for the subframe.
+ // The entry should have a FrameNavigationEntry for the subframe.
ASSERT_EQ(1U, entry3->root_node()->children.size());
EXPECT_EQ(frame_url3, entry3->root_node()->children[0]->frame_entry->url());
} else {
@@ -2034,6 +2034,350 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
}
}
+// Verify the tree of FrameNavigationEntries after subframes are recreated in
+// history navigations, including nested frames. The history will look like:
+// 1. initial_url
+// 2. main_url_a (data_url)
+// 3. main_url_a (frame_url_b (data_url))
+// 4. main_url_a (frame_url_b (frame_url_c))
+// 5. main_url_d
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ FrameNavigationEntry_RecreatedSubframeBackForward) {
+ // 1. Start on a page with no frames.
+ GURL initial_url(embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_1.html"));
+ NavigateToURL(shell(), initial_url);
+ const NavigationControllerImpl& controller =
+ static_cast<const NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ EXPECT_EQ(initial_url, root->current_url());
+ NavigationEntryImpl* entry1 = controller.GetLastCommittedEntry();
+ EXPECT_EQ(0U, entry1->root_node()->children.size());
+
+ // 2. Navigate to a page with a data URL iframe.
+ GURL main_url_a(embedded_test_server()->GetURL(
+ "a.com", "/navigation_controller/page_with_data_iframe.html"));
+ GURL data_url("data:text/html,Subframe");
+ NavigateToURL(shell(), main_url_a);
+ ASSERT_EQ(1U, root->child_count());
+ ASSERT_EQ(0U, root->child_at(0)->child_count());
+ EXPECT_EQ(main_url_a, root->current_url());
+ EXPECT_EQ(data_url, root->child_at(0)->current_url());
+
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ NavigationEntryImpl* entry2 = controller.GetLastCommittedEntry();
+
+ // Verify subframe entries if they're enabled (e.g. in --site-per-process).
+ if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
+ // The entry should have a FrameNavigationEntry for the data subframe.
+ ASSERT_EQ(1U, entry2->root_node()->children.size());
+ EXPECT_EQ(data_url, entry2->root_node()->children[0]->frame_entry->url());
+ } else {
+ // There are no subframe FrameNavigationEntries by default.
+ EXPECT_EQ(0U, entry2->root_node()->children.size());
+ }
+
+ // 3. Navigate the iframe cross-site to a page with a nested iframe.
+ GURL frame_url_b(embedded_test_server()->GetURL(
+ "b.com", "/navigation_controller/page_with_data_iframe.html"));
+ {
+ FrameNavigateParamsCapturer capturer(root->child_at(0));
+ NavigateFrameToURL(root->child_at(0), frame_url_b);
+ capturer.Wait();
+ }
+ ASSERT_EQ(1U, root->child_count());
+ EXPECT_EQ(main_url_a, root->current_url());
+ EXPECT_EQ(frame_url_b, root->child_at(0)->current_url());
+ EXPECT_EQ(data_url, root->child_at(0)->child_at(0)->current_url());
+
+ EXPECT_EQ(3, controller.GetEntryCount());
+ EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
+ NavigationEntryImpl* entry3 = controller.GetLastCommittedEntry();
+
+ // Verify subframe entries if they're enabled (e.g. in --site-per-process).
+ if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
+ // The entry should have a FrameNavigationEntry for the b.com subframe.
+ ASSERT_EQ(1U, entry3->root_node()->children.size());
+ ASSERT_EQ(1U, entry3->root_node()->children[0]->children.size());
+ EXPECT_EQ(frame_url_b,
+ entry3->root_node()->children[0]->frame_entry->url());
+ EXPECT_EQ(
+ data_url,
+ entry3->root_node()->children[0]->children[0]->frame_entry->url());
+ } else {
+ // There are no subframe FrameNavigationEntries by default.
+ EXPECT_EQ(0U, entry3->root_node()->children.size());
+ }
+
+ // 4. Navigate the nested iframe cross-site.
+ GURL frame_url_c(embedded_test_server()->GetURL(
+ "c.com", "/navigation_controller/simple_page_2.html"));
+ {
+ FrameNavigateParamsCapturer capturer(root->child_at(0)->child_at(0));
+ NavigateFrameToURL(root->child_at(0)->child_at(0), frame_url_c);
+ capturer.Wait();
+ }
+ ASSERT_EQ(1U, root->child_count());
+ EXPECT_EQ(main_url_a, root->current_url());
+ EXPECT_EQ(frame_url_b, root->child_at(0)->current_url());
+ EXPECT_EQ(frame_url_c, root->child_at(0)->child_at(0)->current_url());
+
+ EXPECT_EQ(4, controller.GetEntryCount());
+ EXPECT_EQ(3, controller.GetLastCommittedEntryIndex());
+ NavigationEntryImpl* entry4 = controller.GetLastCommittedEntry();
+
+ // Verify subframe entries if they're enabled (e.g. in --site-per-process).
+ if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
+ // The entry should have FrameNavigationEntries for the subframes.
+ ASSERT_EQ(1U, entry4->root_node()->children.size());
+ ASSERT_EQ(1U, entry4->root_node()->children[0]->children.size());
+ EXPECT_EQ(frame_url_b,
+ entry4->root_node()->children[0]->frame_entry->url());
+ EXPECT_EQ(
+ frame_url_c,
+ entry4->root_node()->children[0]->children[0]->frame_entry->url());
+ } else {
+ // There are no subframe FrameNavigationEntries by default.
+ EXPECT_EQ(0U, entry4->root_node()->children.size());
+ }
+
+ // 5. Navigate main frame cross-site, destroying the frames.
+ GURL main_url_d(embedded_test_server()->GetURL(
+ "d.com", "/navigation_controller/simple_page_2.html"));
+ NavigateToURL(shell(), main_url_d);
+ ASSERT_EQ(0U, root->child_count());
+ EXPECT_EQ(main_url_d, root->current_url());
+
+ EXPECT_EQ(5, controller.GetEntryCount());
+ EXPECT_EQ(4, controller.GetLastCommittedEntryIndex());
+ NavigationEntryImpl* entry5 = controller.GetLastCommittedEntry();
+ EXPECT_EQ(0U, entry5->root_node()->children.size());
+
+ // 6. Go back, recreating the iframe and its nested iframe.
+ {
+ TestNavigationObserver back_load_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_load_observer.Wait();
+ }
+ ASSERT_EQ(1U, root->child_count());
+ ASSERT_EQ(1U, root->child_at(0)->child_count());
+ EXPECT_EQ(main_url_a, root->current_url());
+ EXPECT_EQ(frame_url_b, root->child_at(0)->current_url());
+ EXPECT_EQ(frame_url_c, root->child_at(0)->child_at(0)->current_url());
+
+ EXPECT_EQ(5, controller.GetEntryCount());
+ EXPECT_EQ(3, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(entry4, controller.GetLastCommittedEntry());
+
+ // Verify subframe entries if they're enabled (e.g. in --site-per-process).
+ if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
+ // The entry should have FrameNavigationEntries for the subframes.
+ ASSERT_EQ(1U, entry4->root_node()->children.size());
+ ASSERT_EQ(1U, entry4->root_node()->children[0]->children.size());
+ EXPECT_EQ(frame_url_b,
+ entry4->root_node()->children[0]->frame_entry->url());
+ EXPECT_EQ(
+ frame_url_c,
+ entry4->root_node()->children[0]->children[0]->frame_entry->url());
+ } else {
+ // There are no subframe FrameNavigationEntries by default.
+ EXPECT_EQ(0U, entry4->root_node()->children.size());
+ }
+
+ // 7. Go back again, to the data URL in the nested iframe.
+ {
+ TestNavigationObserver back_load_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_load_observer.Wait();
+ }
+ ASSERT_EQ(1U, root->child_count());
+ ASSERT_EQ(1U, root->child_at(0)->child_count());
+ EXPECT_EQ(main_url_a, root->current_url());
+ EXPECT_EQ(frame_url_b, root->child_at(0)->current_url());
+ EXPECT_EQ(data_url, root->child_at(0)->child_at(0)->current_url());
+
+ EXPECT_EQ(5, controller.GetEntryCount());
+ EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(entry3, controller.GetLastCommittedEntry());
+
+ // Verify subframe entries if they're enabled (e.g. in --site-per-process).
+ if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
+ // The entry should have FrameNavigationEntries for the subframes.
+ ASSERT_EQ(1U, entry3->root_node()->children.size());
+ ASSERT_EQ(1U, entry3->root_node()->children[0]->children.size());
+ EXPECT_EQ(frame_url_b,
+ entry3->root_node()->children[0]->frame_entry->url());
+ EXPECT_EQ(
+ data_url,
+ entry3->root_node()->children[0]->children[0]->frame_entry->url());
+ } else {
+ // There are no subframe FrameNavigationEntries by default.
+ EXPECT_EQ(0U, entry3->root_node()->children.size());
+ }
+
+ // 8. Go back again, to the data URL in the first subframe.
+ {
+ TestNavigationObserver back_load_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_load_observer.Wait();
+ }
+ ASSERT_EQ(1U, root->child_count());
+ ASSERT_EQ(0U, root->child_at(0)->child_count());
+ EXPECT_EQ(main_url_a, root->current_url());
+ EXPECT_EQ(data_url, root->child_at(0)->current_url());
+
+ EXPECT_EQ(5, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(entry2, controller.GetLastCommittedEntry());
+
+ // Verify subframe entries if they're enabled (e.g. in --site-per-process).
+ if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
+ // The entry should have a FrameNavigationEntry for the subframe.
+ ASSERT_EQ(1U, entry2->root_node()->children.size());
+ EXPECT_EQ(data_url, entry2->root_node()->children[0]->frame_entry->url());
+ } else {
+ // There are no subframe FrameNavigationEntries by default.
+ EXPECT_EQ(0U, entry2->root_node()->children.size());
+ }
+
+ // 9. Go back again, to the initial main frame page.
+ {
+ TestNavigationObserver back_load_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_load_observer.Wait();
+ }
+ ASSERT_EQ(0U, root->child_count());
+ EXPECT_EQ(initial_url, root->current_url());
+
+ EXPECT_EQ(5, controller.GetEntryCount());
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(entry1, controller.GetLastCommittedEntry());
+ EXPECT_EQ(0U, entry1->root_node()->children.size());
+
+ // 10. Go forward multiple entries and verify the correct subframe URLs load.
+ {
+ TestNavigationObserver back_load_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoToOffset(2);
+ back_load_observer.Wait();
+ }
+ ASSERT_EQ(1U, root->child_count());
+ EXPECT_EQ(main_url_a, root->current_url());
+ EXPECT_EQ(frame_url_b, root->child_at(0)->current_url());
+ EXPECT_EQ(data_url, root->child_at(0)->child_at(0)->current_url());
+
+ EXPECT_EQ(5, controller.GetEntryCount());
+ EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(entry3, controller.GetLastCommittedEntry());
+
+ // Verify subframe entries if they're enabled (e.g. in --site-per-process).
+ if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
+ // The entry should have FrameNavigationEntries for the subframes.
+ ASSERT_EQ(1U, entry3->root_node()->children.size());
+ EXPECT_EQ(frame_url_b,
+ entry3->root_node()->children[0]->frame_entry->url());
+ EXPECT_EQ(
+ data_url,
+ entry3->root_node()->children[0]->children[0]->frame_entry->url());
+ } else {
+ // There are no subframe FrameNavigationEntries by default.
+ EXPECT_EQ(0U, entry3->root_node()->children.size());
+ }
+}
+
+// Verify that we navigate to the fallback (original) URL if a subframe's
+// FrameNavigationEntry can't be found during a history navigation.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ FrameNavigationEntry_SubframeHistoryFallback) {
+ // This test only makes sense when subframe FrameNavigationEntries are in use.
+ if (!SiteIsolationPolicy::UseSubframeNavigationEntries())
+ return;
+
+ // 1. Start on a page with a data URL iframe.
+ GURL main_url_a(embedded_test_server()->GetURL(
+ "a.com", "/navigation_controller/page_with_data_iframe.html"));
+ GURL data_url("data:text/html,Subframe");
+ NavigateToURL(shell(), main_url_a);
+ const NavigationControllerImpl& controller =
+ static_cast<const NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root->child_count());
+ ASSERT_EQ(0U, root->child_at(0)->child_count());
+ EXPECT_EQ(main_url_a, root->current_url());
+ EXPECT_EQ(data_url, root->child_at(0)->current_url());
+
+ EXPECT_EQ(1, controller.GetEntryCount());
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+ NavigationEntryImpl* entry1 = controller.GetLastCommittedEntry();
+
+ // The entry should have a FrameNavigationEntry for the data subframe.
+ ASSERT_EQ(1U, entry1->root_node()->children.size());
+ EXPECT_EQ(data_url, entry1->root_node()->children[0]->frame_entry->url());
+
+ // 2. Navigate the iframe cross-site to a page with a nested iframe.
+ GURL frame_url_b(embedded_test_server()->GetURL(
+ "b.com", "/navigation_controller/simple_page_1.html"));
+ {
+ FrameNavigateParamsCapturer capturer(root->child_at(0));
+ NavigateFrameToURL(root->child_at(0), frame_url_b);
+ capturer.Wait();
+ }
+ ASSERT_EQ(1U, root->child_count());
+ EXPECT_EQ(main_url_a, root->current_url());
+ EXPECT_EQ(frame_url_b, root->child_at(0)->current_url());
+
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ NavigationEntryImpl* entry2 = controller.GetLastCommittedEntry();
+
+ // The entry should have a FrameNavigationEntry for the b.com subframe.
+ ASSERT_EQ(1U, entry2->root_node()->children.size());
+ EXPECT_EQ(frame_url_b, entry2->root_node()->children[0]->frame_entry->url());
+
+ // 3. Navigate main frame cross-site, destroying the frames.
+ GURL main_url_c(embedded_test_server()->GetURL(
+ "c.com", "/navigation_controller/simple_page_2.html"));
+ NavigateToURL(shell(), main_url_c);
+ ASSERT_EQ(0U, root->child_count());
+ EXPECT_EQ(main_url_c, root->current_url());
+
+ EXPECT_EQ(3, controller.GetEntryCount());
+ EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
+ NavigationEntryImpl* entry3 = controller.GetLastCommittedEntry();
+ EXPECT_EQ(0U, entry3->root_node()->children.size());
+
+ // Force the subframe entry to have the wrong name, so that it isn't found
+ // when we go back.
+ entry2->root_node()->children[0]->frame_entry->set_frame_unique_name("wrong");
+
+ // 4. Go back, recreating the iframe. The subframe entry won't be found, and
+ // we should fall back to the default URL.
+ {
+ TestNavigationObserver back_load_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_load_observer.Wait();
+ }
+ ASSERT_EQ(1U, root->child_count());
+ EXPECT_EQ(main_url_a, root->current_url());
+ EXPECT_EQ(data_url, root->child_at(0)->current_url());
+
+ EXPECT_EQ(3, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(entry2, controller.GetLastCommittedEntry());
+
+ // The entry should have both the stale FrameNavigationEntry with the old
+ // name and the new FrameNavigationEntry for the fallback navigation.
+ ASSERT_EQ(2U, entry2->root_node()->children.size());
+ EXPECT_EQ(frame_url_b, entry2->root_node()->children[0]->frame_entry->url());
+ EXPECT_EQ(data_url, entry2->root_node()->children[1]->frame_entry->url());
+}
+
// Verifies that the |frame_unique_name| is set to the correct frame, so that we
// can match subframe FrameNavigationEntries to newly created frames after
// back/forward and restore.
« no previous file with comments | « content/browser/frame_host/frame_navigation_entry.h ('k') | content/browser/frame_host/navigation_controller_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698