blob: c3679162dd91bf7edc152c8b25ac162c6e76d78d [file] [log] [blame]
// 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());
}