| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/frame_host/navigation_controller_impl.h" | 5 #include "content/browser/frame_host/navigation_controller_impl.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #include "content/public/test/test_navigation_observer.h" | 37 #include "content/public/test/test_navigation_observer.h" |
| 38 #include "content/public/test/test_utils.h" | 38 #include "content/public/test/test_utils.h" |
| 39 #include "content/shell/browser/shell.h" | 39 #include "content/shell/browser/shell.h" |
| 40 #include "content/shell/common/shell_switches.h" | 40 #include "content/shell/common/shell_switches.h" |
| 41 #include "content/test/content_browser_test_utils_internal.h" | 41 #include "content/test/content_browser_test_utils_internal.h" |
| 42 #include "content/test/test_frame_navigation_observer.h" | 42 #include "content/test/test_frame_navigation_observer.h" |
| 43 #include "net/dns/mock_host_resolver.h" | 43 #include "net/dns/mock_host_resolver.h" |
| 44 #include "net/test/embedded_test_server/embedded_test_server.h" | 44 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 45 #include "net/test/url_request/url_request_failed_job.h" | 45 #include "net/test/url_request/url_request_failed_job.h" |
| 46 | 46 |
| 47 namespace { |
| 48 |
| 49 static std::string kAddNamedFrameScript = |
| 50 "var f = document.createElement('iframe');" |
| 51 "f.name = 'foo-frame-name';" |
| 52 "document.body.appendChild(f);"; |
| 53 static std::string kAddFrameScript = |
| 54 "var f = document.createElement('iframe');" |
| 55 "document.body.appendChild(f);"; |
| 56 static std::string kRemoveFrameScript = |
| 57 "var f = document.querySelector('iframe');" |
| 58 "f.parentNode.removeChild(f);"; |
| 59 |
| 60 } // namespace |
| 61 |
| 47 namespace content { | 62 namespace content { |
| 48 | 63 |
| 49 class NavigationControllerBrowserTest : public ContentBrowserTest { | 64 class NavigationControllerBrowserTest : public ContentBrowserTest { |
| 50 protected: | 65 protected: |
| 51 void SetUpOnMainThread() override { | 66 void SetUpOnMainThread() override { |
| 52 host_resolver()->AddRule("*", "127.0.0.1"); | 67 host_resolver()->AddRule("*", "127.0.0.1"); |
| 53 ASSERT_TRUE(embedded_test_server()->Start()); | 68 ASSERT_TRUE(embedded_test_server()->Start()); |
| 54 } | 69 } |
| 55 }; | 70 }; |
| 56 | 71 |
| (...skipping 5362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5419 // the body of the page. | 5434 // the body of the page. |
| 5420 std::string body; | 5435 std::string body; |
| 5421 EXPECT_TRUE(ExecuteScriptAndExtractString( | 5436 EXPECT_TRUE(ExecuteScriptAndExtractString( |
| 5422 shell()->web_contents(), | 5437 shell()->web_contents(), |
| 5423 "window.domAutomationController.send(" | 5438 "window.domAutomationController.send(" |
| 5424 "document.getElementsByTagName('pre')[0].innerText);", | 5439 "document.getElementsByTagName('pre')[0].innerText);", |
| 5425 &body)); | 5440 &body)); |
| 5426 EXPECT_EQ("text=value\n", body); | 5441 EXPECT_EQ("text=value\n", body); |
| 5427 } | 5442 } |
| 5428 | 5443 |
| 5444 // Tests that inserting a named subframe into the FrameTree clears any |
| 5445 // previously existing FrameNavigationEntry objects for the same name. |
| 5446 // See https://crbug.com/628677. |
| 5447 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, |
| 5448 EnsureFrameNavigationEntriesClearedOnMismatch) { |
| 5449 WebContentsImpl* web_contents = |
| 5450 static_cast<WebContentsImpl*>(shell()->web_contents()); |
| 5451 NavigationControllerImpl& controller = web_contents->GetController(); |
| 5452 FrameTreeNode* root = web_contents->GetFrameTree()->root(); |
| 5453 |
| 5454 // Start by navigating to a page with complex frame hierarchy. |
| 5455 GURL start_url(embedded_test_server()->GetURL("/frame_tree/top.html")); |
| 5456 EXPECT_TRUE(NavigateToURL(shell(), start_url)); |
| 5457 EXPECT_EQ(3U, root->child_count()); |
| 5458 EXPECT_EQ(2U, root->child_at(0)->child_count()); |
| 5459 |
| 5460 NavigationEntryImpl* entry = controller.GetLastCommittedEntry(); |
| 5461 |
| 5462 // Verify only the parts of the NavigationEntry affected by this test. |
| 5463 { |
| 5464 // * Main frame has 3 subframes. |
| 5465 FrameNavigationEntry* root_entry = entry->GetFrameEntry(root); |
| 5466 EXPECT_NE(nullptr, root_entry); |
| 5467 EXPECT_EQ("", root_entry->frame_unique_name()); |
| 5468 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { |
| 5469 EXPECT_EQ(3U, entry->root_node()->children.size()); |
| 5470 |
| 5471 // * The first child of the main frame is named and has two more children. |
| 5472 FrameTreeNode* frame = root->child_at(0); |
| 5473 FrameNavigationEntry* frame_entry = entry->GetFrameEntry(frame); |
| 5474 EXPECT_NE(nullptr, frame_entry); |
| 5475 EXPECT_EQ("1-1-name", frame_entry->frame_unique_name()); |
| 5476 EXPECT_EQ(2U, entry->root_node()->children[0]->children.size()); |
| 5477 } |
| 5478 } |
| 5479 |
| 5480 // Removing the first child of the main frame should remove the corresponding |
| 5481 // FrameTreeNode. |
| 5482 EXPECT_TRUE(ExecuteScript(root, kRemoveFrameScript)); |
| 5483 EXPECT_EQ(2U, root->child_count()); |
| 5484 |
| 5485 // However, the FrameNavigationEntry objects for the frame that was removed |
| 5486 // should still be around. |
| 5487 { |
| 5488 FrameNavigationEntry* root_entry = entry->GetFrameEntry(root); |
| 5489 EXPECT_NE(nullptr, root_entry); |
| 5490 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { |
| 5491 EXPECT_EQ(3U, entry->root_node()->children.size()); |
| 5492 EXPECT_EQ(2U, entry->root_node()->children[0]->children.size()); |
| 5493 } |
| 5494 } |
| 5495 |
| 5496 // Now, insert a frame with the same name as the previously removed one |
| 5497 // at a different layer of the frame tree. |
| 5498 FrameTreeNode* subframe = root->child_at(1)->child_at(1)->child_at(0); |
| 5499 EXPECT_EQ(2U, root->child_at(1)->child_count()); |
| 5500 EXPECT_EQ(0U, subframe->child_count()); |
| 5501 std::string add_matching_name_frame_script = |
| 5502 "var f = document.createElement('iframe');" |
| 5503 "f.name = '1-1-name';" |
| 5504 "document.body.appendChild(f);"; |
| 5505 EXPECT_TRUE(ExecuteScript(subframe, add_matching_name_frame_script)); |
| 5506 EXPECT_EQ(1U, subframe->child_count()); |
| 5507 |
| 5508 // Verify that the FrameNavigationEntry for the original frame is now gone. |
| 5509 { |
| 5510 FrameNavigationEntry* root_entry = entry->GetFrameEntry(root); |
| 5511 EXPECT_NE(nullptr, root_entry); |
| 5512 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { |
| 5513 EXPECT_EQ(2U, entry->root_node()->children.size()); |
| 5514 } |
| 5515 } |
| 5516 } |
| 5517 |
| 5518 // Tests that sending a PageState update from a named subframe does not get |
| 5519 // incorrectly set on previously existing FrameNavigationEntry for the same |
| 5520 // name. It is similar to EnsureFrameNavigationEntriesClearedOnMismatch, but |
| 5521 // doesn't navigate the iframes to real URLs when added to the DOM. |
| 5522 // See https://crbug.com/628677. |
| 5523 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, |
| 5524 EnsureFrameNavigationEntriesClearedOnMismatchNoSrc) { |
| 5525 WebContentsImpl* web_contents = |
| 5526 static_cast<WebContentsImpl*>(shell()->web_contents()); |
| 5527 FrameTreeNode* root = web_contents->GetFrameTree()->root(); |
| 5528 |
| 5529 GURL start_url(embedded_test_server()->GetURL("/title1.html")); |
| 5530 EXPECT_TRUE(NavigateToURL(shell(), start_url)); |
| 5531 NavigationEntryImpl* nav_entry = |
| 5532 web_contents->GetController().GetLastCommittedEntry(); |
| 5533 |
| 5534 EXPECT_TRUE(ExecuteScript(root, kAddNamedFrameScript)); |
| 5535 EXPECT_EQ(1U, root->child_count()); |
| 5536 EXPECT_EQ("foo-frame-name", root->child_at(0)->frame_name()); |
| 5537 |
| 5538 EXPECT_TRUE(ExecuteScript(root, kRemoveFrameScript)); |
| 5539 EXPECT_EQ(0U, root->child_count()); |
| 5540 |
| 5541 // When a frame is removed from the page, the corresponding |
| 5542 // FrameNavigationEntry is not removed. This is done intentionally to support |
| 5543 // back-forward navigations in subframes and more intuitive UX on tab restore. |
| 5544 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { |
| 5545 EXPECT_EQ(1U, nav_entry->root_node()->children.size()); |
| 5546 FrameNavigationEntry* frame_entry = |
| 5547 nav_entry->root_node()->children[0]->frame_entry.get(); |
| 5548 EXPECT_EQ("foo-frame-name", frame_entry->frame_unique_name()); |
| 5549 } |
| 5550 |
| 5551 EXPECT_TRUE(ExecuteScript(root, kAddFrameScript)); |
| 5552 EXPECT_EQ(1U, root->child_count()); |
| 5553 EXPECT_NE("foo-frame-name", root->child_at(0)->frame_name()); |
| 5554 |
| 5555 // Add a nested frame with the previously used name. |
| 5556 EXPECT_TRUE(ExecuteScript(root->child_at(0), kAddNamedFrameScript)); |
| 5557 EXPECT_EQ(1U, root->child_at(0)->child_count()); |
| 5558 EXPECT_EQ("foo-frame-name", root->child_at(0)->child_at(0)->frame_name()); |
| 5559 |
| 5560 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { |
| 5561 EXPECT_EQ(1U, nav_entry->root_node()->children.size()); |
| 5562 |
| 5563 NavigationEntryImpl::TreeNode* tree_node = |
| 5564 nav_entry->root_node()->children[0]; |
| 5565 EXPECT_EQ(1U, tree_node->children.size()); |
| 5566 |
| 5567 tree_node = tree_node->children[0]; |
| 5568 EXPECT_EQ(0U, tree_node->children.size()); |
| 5569 EXPECT_EQ("foo-frame-name", tree_node->frame_entry->frame_unique_name()); |
| 5570 } |
| 5571 |
| 5572 EXPECT_TRUE(ExecuteScript(root->child_at(0), kRemoveFrameScript)); |
| 5573 EXPECT_EQ(0U, root->child_at(0)->child_count()); |
| 5574 } |
| 5575 |
| 5576 // This test ensures that the comparison of tree position between a |
| 5577 // FrameTreeNode and FrameNavigationEntry works correctly for matching |
| 5578 // first-level frames. |
| 5579 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, |
| 5580 EnsureFirstLevelFrameNavigationEntriesMatch) { |
| 5581 WebContentsImpl* web_contents = |
| 5582 static_cast<WebContentsImpl*>(shell()->web_contents()); |
| 5583 FrameTreeNode* root = web_contents->GetFrameTree()->root(); |
| 5584 NavigationEntryImpl::TreeNode* tree_node = nullptr; |
| 5585 |
| 5586 GURL start_url(embedded_test_server()->GetURL("/title1.html")); |
| 5587 EXPECT_TRUE(NavigateToURL(shell(), start_url)); |
| 5588 NavigationEntryImpl* nav_entry = |
| 5589 web_contents->GetController().GetLastCommittedEntry(); |
| 5590 |
| 5591 // Add, then remove a named frame. It will create a FrameNavigationEntry |
| 5592 // for the name and leave it around. |
| 5593 EXPECT_TRUE(ExecuteScript(root, kAddNamedFrameScript)); |
| 5594 EXPECT_EQ(1U, root->child_count()); |
| 5595 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { |
| 5596 EXPECT_EQ(1U, nav_entry->root_node()->children.size()); |
| 5597 tree_node = nav_entry->root_node()->children[0]; |
| 5598 } |
| 5599 |
| 5600 EXPECT_TRUE(ExecuteScript(root, kRemoveFrameScript)); |
| 5601 EXPECT_EQ(0U, root->child_count()); |
| 5602 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) |
| 5603 EXPECT_EQ(1U, nav_entry->root_node()->children.size()); |
| 5604 |
| 5605 // Add another frame with the same name as before. The matching logic |
| 5606 // should consider them the same and result in the FrameNavigationEntry |
| 5607 // being reused. |
| 5608 EXPECT_TRUE(ExecuteScript(root, kAddNamedFrameScript)); |
| 5609 EXPECT_EQ(1U, root->child_count()); |
| 5610 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { |
| 5611 EXPECT_EQ(1U, nav_entry->root_node()->children.size()); |
| 5612 EXPECT_EQ(tree_node, nav_entry->root_node()->children[0]); |
| 5613 } |
| 5614 |
| 5615 EXPECT_TRUE(ExecuteScript(root, kRemoveFrameScript)); |
| 5616 EXPECT_EQ(0U, root->child_count()); |
| 5617 } |
| 5618 |
| 5429 } // namespace content | 5619 } // namespace content |
| OLD | NEW |