Chromium Code Reviews| Index: content/browser/frame_host/render_frame_host_manager_unittest.cc |
| diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc |
| index 1ac1b088f2b653cfb57d5bdb268ab8d7b6ba5b2a..8c157958e09a419cd9cc30454cbc74fee1cfe436 100644 |
| --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc |
| +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc |
| @@ -38,6 +38,7 @@ |
| #include "content/public/test/mock_render_process_host.h" |
| #include "content/public/test/test_notification_tracker.h" |
| #include "content/public/test/test_utils.h" |
| +#include "content/test/browser_side_navigation_test_utils.h" |
| #include "content/test/test_content_browser_client.h" |
| #include "content/test/test_content_client.h" |
| #include "content/test/test_render_frame_host.h" |
| @@ -70,7 +71,8 @@ class RenderFrameHostManagerTestWebUIControllerFactory |
| : public WebUIControllerFactory { |
| public: |
| RenderFrameHostManagerTestWebUIControllerFactory() |
| - : should_create_webui_(false) { |
| + : should_create_webui_(false), type_(1) { |
| + CHECK_NE(reinterpret_cast<WebUI::TypeID>(type_), WebUI::kNoWebUI); |
| } |
| ~RenderFrameHostManagerTestWebUIControllerFactory() override {} |
| @@ -78,16 +80,34 @@ class RenderFrameHostManagerTestWebUIControllerFactory |
| should_create_webui_ = should_create_webui; |
| } |
| + // This method simulates the expectation that different WebUI instance types |
| + // would be created. The |type| value will be returned by GetWebUIType casted |
| + // to WebUI::TypeID. |
| + // As WebUI::TypeID is a typedef to void pointer, factory implementations |
| + // return values that they know to be unique to their respective cases. So |
| + // values set here should be safe if kept very low (just above zero). |
| + void set_webui_type(uintptr_t type) { |
| + CHECK_NE(reinterpret_cast<WebUI::TypeID>(type), WebUI::kNoWebUI); |
| + type_ = type; |
| + } |
| + |
| // WebUIFactory implementation. |
| WebUIController* CreateWebUIControllerForURL(WebUI* web_ui, |
| const GURL& url) const override { |
| - if (!(should_create_webui_ && HasWebUIScheme(url))) |
| - return NULL; |
| - return new WebUIController(web_ui); |
| + // If WebUI creation is enabled for the test and this is a WebUI URL, |
| + // returns a new instance. |
| + if (should_create_webui_ && HasWebUIScheme(url)) |
| + return new WebUIController(web_ui); |
| + return nullptr; |
| } |
| WebUI::TypeID GetWebUIType(BrowserContext* browser_context, |
| const GURL& url) const override { |
| + // If WebUI creation is enabled for the test and this is a WebUI URL, |
| + // returns a mock WebUI type. |
| + if (should_create_webui_ && HasWebUIScheme(url)) { |
| + return reinterpret_cast<WebUI::TypeID>(type_); |
| + } |
| return WebUI::kNoWebUI; |
| } |
| @@ -103,6 +123,7 @@ class RenderFrameHostManagerTestWebUIControllerFactory |
| private: |
| bool should_create_webui_; |
| + uintptr_t type_; |
| DISALLOW_COPY_AND_ASSIGN(RenderFrameHostManagerTestWebUIControllerFactory); |
| }; |
| @@ -280,6 +301,8 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness { |
| factory_.set_should_create_webui(should_create_webui); |
| } |
| + void set_webui_type(int type) { factory_.set_webui_type(type); } |
| + |
| void NavigateActiveAndCommit(const GURL& url) { |
| // Note: we navigate the active RenderFrameHost because previous navigations |
| // won't have committed yet, so NavigateAndCommit does the wrong thing |
| @@ -411,12 +434,28 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness { |
| FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get(); |
| if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kEnableBrowserSideNavigation)) { |
| + NavigationControllerImpl* controller = |
| + static_cast<NavigationControllerImpl*>(manager->current_frame_host() |
| + ->frame_tree_node() |
| + ->navigator() |
| + ->GetController()); |
| + // TODO(carlosk): This implementation below will not work with restore |
| + // navigations. Method GetNavigationType should be exposed from |
| + // navigator_impl.cc and used here to determine FrameMsg_Navigate_Type. |
| + CHECK(entry.restore_type() == NavigationEntryImpl::RESTORE_NONE); |
| scoped_ptr<NavigationRequest> navigation_request = |
| NavigationRequest::CreateBrowserInitiated( |
| manager->frame_tree_node_, frame_entry->url(), |
| frame_entry->referrer(), *frame_entry, entry, |
| FrameMsg_Navigate_Type::NORMAL, false, base::TimeTicks::Now(), |
| - static_cast<NavigationControllerImpl*>(&controller())); |
| + controller); |
| + |
| + // Simulates request creation that triggers the 1st internal call to |
| + // GetFrameHostForNavigation. |
| + manager->DidCreateNavigationRequest(*navigation_request); |
| + |
| + // And also simulates the 2nd and final call to GetFrameHostForNavigation |
| + // that determines the final frame that will commit the navigation. |
| TestRenderFrameHost* frame_host = static_cast<TestRenderFrameHost*>( |
| manager->GetFrameHostForNavigation(*navigation_request)); |
| CHECK(frame_host); |
| @@ -447,6 +486,19 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness { |
| nodes_with_back_links); |
| } |
| + void BaseSimultaneousNavigationWithOneWebUI( |
| + const std::function<void(RenderFrameHostImpl*, |
| + RenderFrameHostImpl*, |
| + WebUIImpl*, |
| + RenderFrameHostManager*)>& commit_lambda); |
| + |
| + void BaseSimultaneousNavigationWithTwoWebUIs( |
| + const std::function<void(RenderFrameHostImpl*, |
| + RenderFrameHostImpl*, |
| + WebUIImpl*, |
| + WebUIImpl*, |
| + RenderFrameHostManager*)>& commit_lambda); |
| + |
| private: |
| RenderFrameHostManagerTestWebUIControllerFactory factory_; |
| }; |
| @@ -1089,7 +1141,7 @@ TEST_F(RenderFrameHostManagerTest, WebUI) { |
| RenderFrameHostImpl* initial_rfh = manager->current_frame_host(); |
| EXPECT_FALSE(manager->current_host()->IsRenderViewLive()); |
| - EXPECT_FALSE(manager->web_ui()); |
| + EXPECT_FALSE(manager->current_frame_host()->web_ui()); |
| EXPECT_TRUE(initial_rfh); |
| const GURL kUrl("chrome://foo"); |
| @@ -1118,11 +1170,17 @@ TEST_F(RenderFrameHostManagerTest, WebUI) { |
| // used yet. UpdateStateForNavigate() took the short cut path. |
| if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kEnableBrowserSideNavigation)) { |
| - EXPECT_FALSE(manager->speculative_web_ui()); |
| + // In PlzNavigate, there will be a navigating WebUI because |
| + // GetFrameHostForNavigation was already called twice and the committed |
| + // WebUI should be set to be reused. |
| + EXPECT_TRUE(manager->GetNavigatingWebUI()); |
| + EXPECT_EQ(host->web_ui(), manager->GetNavigatingWebUI()); |
| + EXPECT_EQ(host->web_ui(), host->pending_web_ui()); |
| } else { |
| - EXPECT_FALSE(manager->pending_web_ui()); |
| + // The WebUI was immediately committed and there should be none navigating. |
| + EXPECT_FALSE(manager->GetNavigatingWebUI()); |
| } |
| - EXPECT_TRUE(manager->web_ui()); |
| + EXPECT_TRUE(manager->current_frame_host()->web_ui()); |
| // Commit. |
| manager->DidNavigateFrame(host, true); |
| @@ -1191,12 +1249,8 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) { |
| // No cross-process transition happens because we are already in the right |
| // SiteInstance. We should grant bindings immediately. |
| EXPECT_EQ(host2, manager2->current_frame_host()); |
| - if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| - switches::kEnableBrowserSideNavigation)) { |
| - EXPECT_TRUE(manager2->speculative_web_ui()); |
| - } else { |
| - EXPECT_TRUE(manager2->pending_web_ui()); |
| - } |
| + EXPECT_TRUE(manager2->GetNavigatingWebUI()); |
| + EXPECT_FALSE(host2->web_ui()); |
| EXPECT_TRUE( |
| host2->render_view_host()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI); |
| @@ -1210,16 +1264,14 @@ TEST_F(RenderFrameHostManagerTest, WebUIWasReused) { |
| // Navigate to a WebUI page. |
| const GURL kUrl1("chrome://foo"); |
| contents()->NavigateAndCommit(kUrl1); |
| - RenderFrameHostManager* manager = |
| - main_test_rfh()->frame_tree_node()->render_manager(); |
| - WebUIImpl* web_ui = manager->web_ui(); |
| + WebUIImpl* web_ui = main_test_rfh()->web_ui(); |
| EXPECT_TRUE(web_ui); |
| // Navigate to another WebUI page which should be same-site and keep the |
| // current WebUI. |
| const GURL kUrl2("chrome://foo/bar"); |
| contents()->NavigateAndCommit(kUrl2); |
| - EXPECT_EQ(web_ui, manager->web_ui()); |
| + EXPECT_EQ(web_ui, main_test_rfh()->web_ui()); |
| } |
| // Tests that a WebUI is correctly cleaned up when navigating from a chrome:// |
| @@ -1230,12 +1282,12 @@ TEST_F(RenderFrameHostManagerTest, WebUIWasCleared) { |
| // Navigate to a WebUI page. |
| const GURL kUrl1("chrome://foo"); |
| contents()->NavigateAndCommit(kUrl1); |
| - EXPECT_TRUE(main_test_rfh()->frame_tree_node()->render_manager()->web_ui()); |
| + EXPECT_TRUE(main_test_rfh()->web_ui()); |
| // Navigate to a non-WebUI page. |
| const GURL kUrl2("http://www.google.com"); |
| contents()->NavigateAndCommit(kUrl2); |
| - EXPECT_FALSE(main_test_rfh()->frame_tree_node()->render_manager()->web_ui()); |
| + EXPECT_FALSE(main_test_rfh()->web_ui()); |
| } |
| // Tests that we don't end up in an inconsistent state if a page does a back and |
| @@ -2662,4 +2714,433 @@ TEST_F(RenderFrameHostManagerTest, |
| VerifyPageFocusMessage(hostC->GetProcess(), true, proxy->GetRoutingID()); |
| } |
| +// Checks that a restore navigation to a WebUI works. |
| +TEST_F(RenderFrameHostManagerTest, RestoreNavigationToWebUI) { |
| + set_should_create_webui(true); |
| + |
| + const GURL kInitUrl("chrome://foo/"); |
| + SiteInstanceImpl* initial_instance = |
| + static_cast<SiteInstanceImpl*>(SiteInstance::Create(browser_context())); |
| + initial_instance->SetSite(kInitUrl); |
| + scoped_ptr<TestWebContents> web_contents( |
| + TestWebContents::Create(browser_context(), initial_instance)); |
| + RenderFrameHostManager* manager = web_contents->GetRenderManagerForTesting(); |
| + NavigationControllerImpl& controller = web_contents->GetController(); |
| + |
| + // Setup a restored entry. |
| + std::vector<scoped_ptr<NavigationEntry>> entries; |
| + scoped_ptr<NavigationEntry> new_entry = |
| + NavigationControllerImpl::CreateNavigationEntry( |
| + kInitUrl, Referrer(), ui::PAGE_TRANSITION_TYPED, false, std::string(), |
| + browser_context()); |
| + new_entry->SetPageID(0); |
| + entries.push_back(new_entry.Pass()); |
| + controller.Restore( |
| + 0, NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY, &entries); |
| + ASSERT_EQ(0u, entries.size()); |
| + ASSERT_EQ(1, controller.GetEntryCount()); |
| + |
| + RenderFrameHostImpl* initial_host = manager->current_frame_host(); |
| + ASSERT_TRUE(initial_host); |
| + EXPECT_FALSE(initial_host->IsRenderFrameLive()); |
| + EXPECT_FALSE(initial_host->web_ui()); |
| + |
| + // Navigation request to an entry from a previous browsing session. |
| + NavigationEntryImpl entry(nullptr /* instance */, 0 /* page_id */, kInitUrl, |
| + Referrer(), base::string16() /* title */, |
| + ui::PAGE_TRANSITION_RELOAD, |
| + false /* is_renderer_init */); |
| + entry.set_restore_type( |
| + NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY); |
| + NavigateToEntry(manager, entry); |
| + |
| + // As the initial renderer was not live, the new RenderFrameHost should be |
| + // made immediately active at request time. |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + TestRenderFrameHost* current_host = |
| + static_cast<TestRenderFrameHost*>(manager->current_frame_host()); |
| + ASSERT_TRUE(current_host); |
| + EXPECT_EQ(current_host, initial_host); |
| + EXPECT_TRUE(current_host->IsRenderFrameLive()); |
| + WebUIImpl* web_ui = manager->GetNavigatingWebUI(); |
| + EXPECT_TRUE(web_ui); |
| + EXPECT_EQ(web_ui, current_host->pending_web_ui()); |
| + EXPECT_FALSE(current_host->web_ui()); |
| + |
| + // The RenderFrameHost committed. |
| + manager->DidNavigateFrame(current_host, true); |
| + EXPECT_EQ(current_host, manager->current_frame_host()); |
| + EXPECT_EQ(web_ui, current_host->web_ui()); |
| + EXPECT_FALSE(current_host->pending_web_ui()); |
| +} |
| + |
| +// Shared code until before commit for the SimultaneousNavigationWithOneWebUI* |
| +// tests, accepting a lambda to execute the commit step. |
| +void RenderFrameHostManagerTest::BaseSimultaneousNavigationWithOneWebUI( |
| + const std::function<void(RenderFrameHostImpl*, |
| + RenderFrameHostImpl*, |
| + WebUIImpl*, |
| + RenderFrameHostManager*)>& commit_lambda) { |
| + set_should_create_webui(true); |
| + NavigateActiveAndCommit(GURL("chrome://foo/")); |
| + |
| + RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting(); |
| + RenderFrameHostImpl* host1 = manager->current_frame_host(); |
| + EXPECT_TRUE(host1->IsRenderFrameLive()); |
| + WebUIImpl* web_ui = host1->web_ui(); |
| + EXPECT_TRUE(web_ui); |
| + |
| + // Starts a reload of the WebUI page. |
| + contents()->GetController().Reload(true); |
| + |
| + // It should be a same-site navigation reusing the same WebUI. |
| + EXPECT_EQ(web_ui, manager->GetNavigatingWebUI()); |
| + EXPECT_EQ(web_ui, host1->web_ui()); |
| + EXPECT_EQ(web_ui, host1->pending_web_ui()); |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + |
| + // Navigation request to a non-WebUI page. |
| + const GURL kUrl("http://google.com"); |
| + NavigationEntryImpl entry(NULL /* instance */, -1 /* page_id */, kUrl, |
| + Referrer(), base::string16() /* title */, |
| + ui::PAGE_TRANSITION_TYPED, |
| + false /* is_renderer_init */); |
| + RenderFrameHostImpl* host2 = NavigateToEntry(manager, entry); |
| + ASSERT_TRUE(host2); |
| + |
| + // The previous navigation should still be ongoing along with the new, |
| + // cross-site one. |
| + // Note: Simultaneous navigations are weird: there are two ongoing |
| + // navigations, a same-site using a WebUI and a cross-site not using one. So |
| + // it's unclear what GetNavigatingWebUI should return in this case. As it |
| + // currently favors the cross-site navigation it returns null. |
| + EXPECT_FALSE(manager->GetNavigatingWebUI()); |
| + EXPECT_EQ(web_ui, host1->web_ui()); |
| + EXPECT_EQ(web_ui, host1->pending_web_ui()); |
| + |
| + EXPECT_NE(host2, host1); |
| + EXPECT_EQ(host2, GetPendingFrameHost(manager)); |
| + EXPECT_FALSE(host2->web_ui()); |
| + EXPECT_FALSE(host2->pending_web_ui()); |
| + EXPECT_NE(web_ui, host2->web_ui()); |
| + |
| + commit_lambda(host1, host2, web_ui, manager); |
| +} |
| + |
| +// Simulates two simultaneous navigations involving one WebUI where the current |
| +// RenderFrameHost commits. |
| +TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithOneWebUI1) { |
| + auto commit_current_frame_host = [this]( |
| + RenderFrameHostImpl* host1, RenderFrameHostImpl* host2, WebUIImpl* web_ui, |
| + RenderFrameHostManager* manager) { |
| + // The current RenderFrameHost commits; its WebUI should still be in place. |
| + manager->DidNavigateFrame(host1, true); |
| + EXPECT_EQ(host1, manager->current_frame_host()); |
| + EXPECT_EQ(web_ui, host1->web_ui()); |
| + EXPECT_FALSE(host1->pending_web_ui()); |
| + EXPECT_FALSE(manager->GetNavigatingWebUI()); |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + }; |
| + |
| + BaseSimultaneousNavigationWithOneWebUI(commit_current_frame_host); |
| +} |
| + |
| +// Simulates two simultaneous navigations involving one WebUI where the new, |
| +// cross-site RenderFrameHost commits. |
| +TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithOneWebUI2) { |
| + auto commit_new_frame_host = [this]( |
| + RenderFrameHostImpl* host1, RenderFrameHostImpl* host2, WebUIImpl* web_ui, |
| + RenderFrameHostManager* manager) { |
| + // The new RenderFrameHost commits; there should be no active WebUI. |
| + manager->DidNavigateFrame(host2, true); |
| + EXPECT_EQ(host2, manager->current_frame_host()); |
| + EXPECT_FALSE(host2->web_ui()); |
| + EXPECT_FALSE(host2->pending_web_ui()); |
| + EXPECT_FALSE(manager->GetNavigatingWebUI()); |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + }; |
| + |
| + BaseSimultaneousNavigationWithOneWebUI(commit_new_frame_host); |
| +} |
| + |
| +// Shared code until before commit for the SimultaneousNavigationWithTwoWebUIs* |
| +// tests, accepting a lambda to execute the commit step. |
| +void RenderFrameHostManagerTest::BaseSimultaneousNavigationWithTwoWebUIs( |
| + const std::function<void(RenderFrameHostImpl*, |
| + RenderFrameHostImpl*, |
| + WebUIImpl*, |
| + WebUIImpl*, |
| + RenderFrameHostManager*)>& commit_lambda) { |
| + set_should_create_webui(true); |
| + set_webui_type(1); |
| + NavigateActiveAndCommit(GURL("chrome://foo/")); |
| + |
| + RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting(); |
| + RenderFrameHostImpl* host1 = manager->current_frame_host(); |
| + EXPECT_TRUE(host1->IsRenderFrameLive()); |
| + WebUIImpl* web_ui1 = host1->web_ui(); |
| + EXPECT_TRUE(web_ui1); |
| + |
| + // Starts a reload of the WebUI page. |
| + contents()->GetController().Reload(true); |
| + |
| + // It should be a same-site navigation reusing the same WebUI. |
| + EXPECT_EQ(web_ui1, manager->GetNavigatingWebUI()); |
| + EXPECT_EQ(web_ui1, host1->web_ui()); |
| + EXPECT_EQ(web_ui1, host1->pending_web_ui()); |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + |
| + // Navigation another WebUI page, with a different type. |
| + set_webui_type(2); |
| + const GURL kUrl("chrome://bar/"); |
| + NavigationEntryImpl entry(NULL /* instance */, -1 /* page_id */, kUrl, |
| + Referrer(), base::string16() /* title */, |
| + ui::PAGE_TRANSITION_TYPED, |
| + false /* is_renderer_init */); |
| + RenderFrameHostImpl* host2 = NavigateToEntry(manager, entry); |
| + ASSERT_TRUE(host2); |
| + |
| + // The previous navigation should still be ongoing along with the new, |
| + // cross-site one. |
| + // Note: simultaneous navigations are weird: there are two ongoing |
| + // navigations, a same-site and a cross-site both going to WebUIs. So it's |
| + // unclear what GetNavigatingWebUI should return in this case. As it currently |
| + // favors the cross-site navigation it returns the speculative/pending |
| + // RenderFrameHost's WebUI instance. |
| + EXPECT_EQ(web_ui1, host1->web_ui()); |
| + EXPECT_EQ(web_ui1, host1->pending_web_ui()); |
| + WebUIImpl* web_ui2 = manager->GetNavigatingWebUI(); |
| + EXPECT_TRUE(web_ui2); |
| + EXPECT_NE(web_ui2, web_ui1); |
| + |
| + EXPECT_NE(host2, host1); |
| + EXPECT_EQ(host2, GetPendingFrameHost(manager)); |
| + EXPECT_EQ(web_ui2, host2->web_ui()); |
| + EXPECT_FALSE(host2->pending_web_ui()); |
| + |
| + commit_lambda(host1, host2, web_ui1, web_ui2, manager); |
| +} |
| + |
| +// Simulates two simultaneous navigations involving two WebUIs where the current |
| +// RenderFrameHost commits. |
| +TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithTwoWebUIs1) { |
| + auto commit_current_frame_host = [this]( |
| + RenderFrameHostImpl* host1, RenderFrameHostImpl* host2, |
| + WebUIImpl* web_ui1, WebUIImpl* web_ui2, RenderFrameHostManager* manager) { |
| + // The current RenderFrameHost commits; its WebUI should still be active. |
| + manager->DidNavigateFrame(host1, true); |
| + EXPECT_EQ(host1, manager->current_frame_host()); |
| + EXPECT_EQ(web_ui1, host1->web_ui()); |
| + EXPECT_FALSE(host1->pending_web_ui()); |
| + EXPECT_FALSE(manager->GetNavigatingWebUI()); |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + }; |
| + |
| + BaseSimultaneousNavigationWithTwoWebUIs(commit_current_frame_host); |
| +} |
| + |
| +// Simulates two simultaneous navigations involving two WebUIs where the new, |
| +// cross-site RenderFrameHost commits. |
| +TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithTwoWebUIs2) { |
| + auto commit_new_frame_host = [this]( |
| + RenderFrameHostImpl* host1, RenderFrameHostImpl* host2, |
| + WebUIImpl* web_ui1, WebUIImpl* web_ui2, RenderFrameHostManager* manager) { |
| + // The new RenderFrameHost commits; its WebUI should now be active. |
| + manager->DidNavigateFrame(host2, true); |
| + EXPECT_EQ(host2, manager->current_frame_host()); |
| + EXPECT_EQ(web_ui2, host2->web_ui()); |
| + EXPECT_FALSE(host2->pending_web_ui()); |
| + EXPECT_FALSE(manager->GetNavigatingWebUI()); |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + }; |
| + |
| + BaseSimultaneousNavigationWithTwoWebUIs(commit_new_frame_host); |
| +} |
| + |
| +// RenderFrameHostManagerTest extension for PlzNavigate enabled tests. |
| +class RenderFrameHostManagerTestWithBrowserSideNavigation |
| + : public RenderFrameHostManagerTest { |
| + public: |
| + void SetUp() override { |
| + EnableBrowserSideNavigation(); |
| + RenderFrameHostManagerTest::SetUp(); |
| + } |
| +}; |
| + |
| +// PlzNavigate: Tests that the correct intermediary and final navigation states |
| +// are reached when navigating from a renderer that is not live to a WebUI URL. |
| +TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation, |
| + NavigateFromDeadRendererToWebUI) { |
| + set_should_create_webui(true); |
| + RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting(); |
| + |
| + RenderFrameHostImpl* initial_host = manager->current_frame_host(); |
| + ASSERT_TRUE(initial_host); |
| + EXPECT_FALSE(initial_host->IsRenderFrameLive()); |
| + |
| + // Navigation request. |
| + const GURL kUrl("chrome://foo"); |
| + NavigationEntryImpl entry(nullptr /* instance */, -1 /* page_id */, kUrl, |
| + Referrer(), base::string16() /* title */, |
| + ui::PAGE_TRANSITION_TYPED, |
| + false /* is_renderer_init */); |
| + FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get(); |
| + scoped_ptr<NavigationRequest> navigation_request = |
| + NavigationRequest::CreateBrowserInitiated( |
| + contents()->GetFrameTree()->root(), frame_entry->url(), |
| + frame_entry->referrer(), *frame_entry, entry, |
| + FrameMsg_Navigate_Type::NORMAL, false, base::TimeTicks::Now(), |
| + static_cast<NavigationControllerImpl*>(&controller())); |
| + manager->DidCreateNavigationRequest(*navigation_request); |
| + |
| + // As the initial RenderFrame was not live, the new RenderFrameHost should be |
| + // made as active/current immediately along with its WebUI at request time. |
| + RenderFrameHostImpl* host = manager->current_frame_host(); |
| + ASSERT_TRUE(host); |
| + EXPECT_NE(host, initial_host); |
| + EXPECT_TRUE(host->IsRenderFrameLive()); |
| + WebUIImpl* web_ui = host->web_ui(); |
| + EXPECT_TRUE(web_ui); |
| + EXPECT_FALSE(host->pending_web_ui()); |
| + EXPECT_FALSE(manager->GetNavigatingWebUI()); |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + |
| + // Prepare to commit, update the navigating RenderFrameHost. |
| + EXPECT_EQ(host, manager->GetFrameHostForNavigation(*navigation_request)); |
| + |
| + // There should be a pending WebUI set to reuse the current one. |
| + EXPECT_EQ(web_ui, host->web_ui()); |
| + EXPECT_EQ(web_ui, host->pending_web_ui()); |
| + EXPECT_EQ(web_ui, manager->GetNavigatingWebUI()); |
| + |
| + // No pending RenderFrameHost as the current one should be reused. |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + |
| + // The RenderFrameHost committed. |
| + manager->DidNavigateFrame(host, true); |
| + EXPECT_EQ(host, manager->current_frame_host()); |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + EXPECT_EQ(web_ui, host->web_ui()); |
| + EXPECT_FALSE(host->pending_web_ui()); |
| + EXPECT_FALSE(manager->GetNavigatingWebUI()); |
| +} |
| + |
| +// PlzNavigate: Tests that the correct intermediary and final navigation states |
| +// are reached when navigating same-site between two WebUIs of the same type. |
| +TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation, |
| + NavigateSameSiteBetweenWebUIs) { |
| + set_should_create_webui(true); |
| + NavigateActiveAndCommit(GURL("chrome://foo")); |
| + |
| + RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting(); |
| + RenderFrameHostImpl* host = manager->current_frame_host(); |
| + EXPECT_TRUE(host->IsRenderFrameLive()); |
| + WebUIImpl* web_ui = host->web_ui(); |
| + EXPECT_TRUE(web_ui); |
| + |
| + // Navigation request. No change in the returned WebUI type. |
| + const GURL kUrl("chrome://foo/bar"); |
| + NavigationEntryImpl entry(nullptr /* instance */, -1 /* page_id */, kUrl, |
| + Referrer(), base::string16() /* title */, |
| + ui::PAGE_TRANSITION_TYPED, |
| + false /* is_renderer_init */); |
| + FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get(); |
| + scoped_ptr<NavigationRequest> navigation_request = |
| + NavigationRequest::CreateBrowserInitiated( |
| + contents()->GetFrameTree()->root(), frame_entry->url(), |
| + frame_entry->referrer(), *frame_entry, entry, |
| + FrameMsg_Navigate_Type::NORMAL, false, base::TimeTicks::Now(), |
| + static_cast<NavigationControllerImpl*>(&controller())); |
| + manager->DidCreateNavigationRequest(*navigation_request); |
| + |
| + // The current WebUI should still be in place and the pending WebUI should be |
| + // set to reuse it. |
| + EXPECT_EQ(web_ui, manager->GetNavigatingWebUI()); |
| + EXPECT_EQ(web_ui, host->web_ui()); |
| + EXPECT_EQ(web_ui, host->pending_web_ui()); |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + |
| + // Prepare to commit, update the navigating RenderFrameHost. |
| + EXPECT_EQ(host, manager->GetFrameHostForNavigation(*navigation_request)); |
| + |
| + EXPECT_EQ(web_ui, manager->GetNavigatingWebUI()); |
| + EXPECT_EQ(web_ui, host->web_ui()); |
| + EXPECT_EQ(web_ui, host->pending_web_ui()); |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
|
nasko
2015/11/30 16:57:49
Why do we have no speculative RFH before we've com
carlosk
2015/11/30 19:54:16
We never have one in this navigation as it is a sa
nasko
2015/12/01 00:52:14
D'oh! Yes indeed!
|
| + |
| + // The RenderFrameHost committed. |
| + manager->DidNavigateFrame(host, true); |
| + EXPECT_EQ(web_ui, host->web_ui()); |
| + EXPECT_FALSE(manager->GetNavigatingWebUI()); |
| + EXPECT_FALSE(host->pending_web_ui()); |
| +} |
| + |
| +// PlzNavigate: Tests that the correct intermediary and final navigation states |
| +// are reached when navigating cross-site between two different WebUI types. |
| +TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation, |
| + NavigateCrossSiteBetweenWebUIs) { |
| + // Cross-site navigations will always cause the change of the WebUI instance |
| + // but for consistency sake different types will be set for each navigation. |
| + set_should_create_webui(true); |
| + set_webui_type(1); |
| + NavigateActiveAndCommit(GURL("chrome://foo")); |
| + |
| + RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting(); |
| + RenderFrameHostImpl* host = manager->current_frame_host(); |
| + EXPECT_TRUE(host->IsRenderFrameLive()); |
| + EXPECT_TRUE(host->web_ui()); |
| + |
| + // Set the WebUI controller to return a different WebUIType value. This will |
| + // cause the next navigation to "chrome://bar" to require a different WebUI |
| + // than the current one, forcing it to be treated as cross-site. |
| + set_webui_type(2); |
| + |
| + // Navigation request. |
| + const GURL kUrl("chrome://bar"); |
| + NavigationEntryImpl entry(nullptr /* instance */, -1 /* page_id */, kUrl, |
| + Referrer(), base::string16() /* title */, |
| + ui::PAGE_TRANSITION_TYPED, |
| + false /* is_renderer_init */); |
| + FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get(); |
| + scoped_ptr<NavigationRequest> navigation_request = |
| + NavigationRequest::CreateBrowserInitiated( |
| + contents()->GetFrameTree()->root(), frame_entry->url(), |
| + frame_entry->referrer(), *frame_entry, entry, |
| + FrameMsg_Navigate_Type::NORMAL, false, base::TimeTicks::Now(), |
| + static_cast<NavigationControllerImpl*>(&controller())); |
| + manager->DidCreateNavigationRequest(*navigation_request); |
| + |
| + // The current WebUI should still be in place and there should be a new |
| + // active WebUI instance in the speculative RenderFrameHost. |
| + EXPECT_TRUE(manager->current_frame_host()->web_ui()); |
| + EXPECT_FALSE(manager->current_frame_host()->pending_web_ui()); |
| + RenderFrameHostImpl* speculative_host = GetPendingFrameHost(manager); |
| + EXPECT_TRUE(speculative_host); |
| + WebUIImpl* next_web_ui = manager->GetNavigatingWebUI(); |
| + EXPECT_TRUE(next_web_ui); |
| + EXPECT_EQ(next_web_ui, speculative_host->web_ui()); |
| + EXPECT_NE(next_web_ui, manager->current_frame_host()->web_ui()); |
| + EXPECT_FALSE(speculative_host->pending_web_ui()); |
| + |
| + // Prepare to commit, update the navigating RenderFrameHost. |
| + EXPECT_EQ(speculative_host, |
| + manager->GetFrameHostForNavigation(*navigation_request)); |
| + |
| + EXPECT_TRUE(manager->current_frame_host()->web_ui()); |
| + EXPECT_FALSE(manager->current_frame_host()->pending_web_ui()); |
| + EXPECT_EQ(speculative_host, GetPendingFrameHost(manager)); |
| + EXPECT_NE(next_web_ui, manager->current_frame_host()->web_ui()); |
| + EXPECT_EQ(next_web_ui, speculative_host->web_ui()); |
| + EXPECT_EQ(next_web_ui, manager->GetNavigatingWebUI()); |
| + EXPECT_FALSE(speculative_host->pending_web_ui()); |
| + |
| + // The RenderFrameHost committed. |
| + manager->DidNavigateFrame(speculative_host, true); |
| + EXPECT_EQ(speculative_host, manager->current_frame_host()); |
| + EXPECT_EQ(next_web_ui, manager->current_frame_host()->web_ui()); |
| + EXPECT_FALSE(GetPendingFrameHost(manager)); |
| + EXPECT_FALSE(speculative_host->pending_web_ui()); |
| + EXPECT_FALSE(manager->GetNavigatingWebUI()); |
| +} |
| + |
| } // namespace content |