| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/favicon/favicon_tab_helper.h" |
| #include "chrome/browser/prefs/pref_service.h" |
| #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h" |
| #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| #include "chrome/browser/ui/tab_contents/test_tab_contents.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "content/public/browser/navigation_controller.h" |
| #include "content/public/browser/site_instance.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/common/referrer.h" |
| #include "content/public/test/test_browser_thread.h" |
| #include "content/public/test/test_renderer_host.h" |
| #include "content/public/test/web_contents_tester.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using content::BrowserThread; |
| using content::NavigationController; |
| using content::RenderViewHost; |
| using content::RenderViewHostTester; |
| using content::SiteInstance; |
| using content::WebContents; |
| using content::WebContentsTester; |
| |
| // TODO(avi): Kill this when TabContents goes away. |
| class WebUITestContentsCreator { |
| public: |
| static TabContents* CreateTabContents(content::WebContents* contents) { |
| return TabContents::Factory::CreateTabContents(contents); |
| } |
| }; |
| |
| class WebUITest : public TabContentsTestHarness { |
| public: |
| WebUITest() : ui_thread_(BrowserThread::UI, MessageLoop::current()) {} |
| |
| // Tests navigating with a Web UI from a fresh (nothing pending or committed) |
| // state, through pending, committed, then another navigation. The first page |
| // ID that we should use is passed as a parameter. We'll use the next two |
| // values. This must be increasing for the life of the tests. |
| static void DoNavigationTest(TabContents* tab_contents, int page_id) { |
| WebContents* contents = tab_contents->web_contents(); |
| NavigationController* controller = &contents->GetController(); |
| |
| // Start a pending load. |
| GURL new_tab_url(chrome::kChromeUINewTabURL); |
| controller->LoadURL(new_tab_url, content::Referrer(), |
| content::PAGE_TRANSITION_LINK, |
| std::string()); |
| |
| // The navigation entry should be pending with no committed entry. |
| ASSERT_TRUE(controller->GetPendingEntry()); |
| ASSERT_FALSE(controller->GetLastCommittedEntry()); |
| |
| // Check the things the pending Web UI should have set. |
| EXPECT_FALSE(tab_contents->favicon_tab_helper()->ShouldDisplayFavicon()); |
| EXPECT_TRUE(contents->FocusLocationBarByDefault()); |
| |
| // Now commit the load. |
| RenderViewHostTester::For( |
| contents->GetRenderViewHost())->SendNavigate(page_id, new_tab_url); |
| |
| // The same flags should be set as before now that the load has committed. |
| EXPECT_FALSE(tab_contents->favicon_tab_helper()->ShouldDisplayFavicon()); |
| EXPECT_TRUE(contents->FocusLocationBarByDefault()); |
| |
| // Start a pending navigation to a regular page. |
| GURL next_url("http://google.com/"); |
| controller->LoadURL(next_url, content::Referrer(), |
| content::PAGE_TRANSITION_LINK, |
| std::string()); |
| |
| // Check the flags. Some should reflect the new page (URL, title), some |
| // should reflect the old one (bookmark bar) until it has committed. |
| EXPECT_TRUE(tab_contents->favicon_tab_helper()->ShouldDisplayFavicon()); |
| EXPECT_FALSE(contents->FocusLocationBarByDefault()); |
| |
| // Commit the regular page load. Note that we must send it to the "pending" |
| // RenderViewHost if there is one, since this transition will also cause a |
| // process transition, and our RVH pointer will be the "committed" one. |
| // In the second call to this function from WebUIToStandard, it won't |
| // actually be pending, which is the point of this test. |
| RenderViewHost* pending_rvh = |
| RenderViewHostTester::GetPendingForController(controller); |
| if (pending_rvh) { |
| RenderViewHostTester::For( |
| pending_rvh)->SendNavigate(page_id + 1, next_url); |
| } else { |
| RenderViewHostTester::For( |
| contents->GetRenderViewHost())->SendNavigate(page_id + 1, next_url); |
| } |
| |
| // The state should now reflect a regular page. |
| EXPECT_TRUE(tab_contents->favicon_tab_helper()->ShouldDisplayFavicon()); |
| EXPECT_FALSE(contents->FocusLocationBarByDefault()); |
| } |
| |
| private: |
| content::TestBrowserThread ui_thread_; |
| |
| DISALLOW_COPY_AND_ASSIGN(WebUITest); |
| }; |
| |
| // Tests that the New Tab Page flags are correctly set and propogated by |
| // WebContents when we first navigate to a Web UI page, then to a standard |
| // non-DOM-UI page. |
| TEST_F(WebUITest, WebUIToStandard) { |
| DoNavigationTest(tab_contents(), 1); |
| |
| // Test the case where we're not doing the initial navigation. This is |
| // slightly different than the very-first-navigation case since the |
| // SiteInstance will be the same (the original WebContents must still be |
| // alive), which will trigger different behavior in RenderViewHostManager. |
| WebContents* contents2 = |
| WebContentsTester::CreateTestWebContents(profile(), NULL); |
| scoped_ptr<TabContents> tab_contents2( |
| WebUITestContentsCreator::CreateTabContents(contents2)); |
| |
| DoNavigationTest(tab_contents2.get(), 101); |
| } |
| |
| TEST_F(WebUITest, WebUIToWebUI) { |
| // Do a load (this state is tested above). |
| GURL new_tab_url(chrome::kChromeUINewTabURL); |
| controller().LoadURL(new_tab_url, content::Referrer(), |
| content::PAGE_TRANSITION_LINK, |
| std::string()); |
| rvh_tester()->SendNavigate(1, new_tab_url); |
| |
| // Start another pending load of the new tab page. |
| controller().LoadURL(new_tab_url, content::Referrer(), |
| content::PAGE_TRANSITION_LINK, |
| std::string()); |
| rvh_tester()->SendNavigate(2, new_tab_url); |
| |
| // The flags should be the same as the non-pending state. |
| EXPECT_FALSE(tab_contents()->favicon_tab_helper()->ShouldDisplayFavicon()); |
| EXPECT_TRUE(contents()->FocusLocationBarByDefault()); |
| } |
| |
| TEST_F(WebUITest, StandardToWebUI) { |
| // Start a pending navigation to a regular page. |
| GURL std_url("http://google.com/"); |
| |
| controller().LoadURL(std_url, content::Referrer(), |
| content::PAGE_TRANSITION_LINK, |
| std::string()); |
| |
| // The state should now reflect the default. |
| EXPECT_TRUE(tab_contents()->favicon_tab_helper()->ShouldDisplayFavicon()); |
| EXPECT_FALSE(contents()->FocusLocationBarByDefault()); |
| |
| // Commit the load, the state should be the same. |
| rvh_tester()->SendNavigate(1, std_url); |
| EXPECT_TRUE(tab_contents()->favicon_tab_helper()->ShouldDisplayFavicon()); |
| EXPECT_FALSE(contents()->FocusLocationBarByDefault()); |
| |
| // Start a pending load for a WebUI. |
| GURL new_tab_url(chrome::kChromeUINewTabURL); |
| controller().LoadURL(new_tab_url, content::Referrer(), |
| content::PAGE_TRANSITION_LINK, |
| std::string()); |
| EXPECT_TRUE(tab_contents()->favicon_tab_helper()->ShouldDisplayFavicon()); |
| EXPECT_TRUE(contents()->FocusLocationBarByDefault()); |
| |
| // Committing Web UI is tested above. |
| } |
| |
| TEST_F(WebUITest, FocusOnNavigate) { |
| // Setup. |wc| will be used to track when we try to focus the location bar. |
| WebContents* wc = |
| WebContentsTester::CreateTestWebContentsCountSetFocusToLocationBar( |
| contents()->GetBrowserContext(), |
| SiteInstance::Create(contents()->GetBrowserContext())); |
| WebContentsTester* wct = WebContentsTester::For(wc); |
| wc->GetController().CopyStateFrom(controller()); |
| SetContents(wc); |
| int page_id = 200; |
| |
| // Load the NTP. |
| GURL new_tab_url(chrome::kChromeUINewTabURL); |
| controller().LoadURL(new_tab_url, content::Referrer(), |
| content::PAGE_TRANSITION_LINK, |
| std::string()); |
| rvh_tester()->SendNavigate(page_id, new_tab_url); |
| |
| // Navigate to another page. |
| GURL next_url("http://google.com/"); |
| int next_page_id = page_id + 1; |
| controller().LoadURL(next_url, content::Referrer(), |
| content::PAGE_TRANSITION_LINK, |
| std::string()); |
| RenderViewHost* old_rvh = rvh(); |
| RenderViewHostTester::For(old_rvh)->SendShouldCloseACK(true); |
| RenderViewHostTester::For( |
| pending_rvh())->SendNavigate(next_page_id, next_url); |
| RenderViewHostTester::For(old_rvh)->SimulateSwapOutACK(); |
| |
| // Navigate back. Should focus the location bar. |
| int focus_called = wct->GetNumberOfFocusCalls(); |
| ASSERT_TRUE(controller().CanGoBack()); |
| controller().GoBack(); |
| old_rvh = rvh(); |
| RenderViewHostTester::For(old_rvh)->SendShouldCloseACK(true); |
| RenderViewHostTester::For(pending_rvh())->SendNavigate(page_id, new_tab_url); |
| RenderViewHostTester::For(old_rvh)->SimulateSwapOutACK(); |
| EXPECT_LT(focus_called, wct->GetNumberOfFocusCalls()); |
| |
| // Navigate forward. Shouldn't focus the location bar. |
| focus_called = wct->GetNumberOfFocusCalls(); |
| ASSERT_TRUE(controller().CanGoForward()); |
| controller().GoForward(); |
| old_rvh = rvh(); |
| RenderViewHostTester::For(old_rvh)->SendShouldCloseACK(true); |
| RenderViewHostTester::For( |
| pending_rvh())->SendNavigate(next_page_id, next_url); |
| RenderViewHostTester::For(old_rvh)->SimulateSwapOutACK(); |
| EXPECT_EQ(focus_called, wct->GetNumberOfFocusCalls()); |
| } |