1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/test/base/browser_with_test_window_test.h"
7 #include "base/run_loop.h"
8 #include "chrome/browser/profiles/profile_destroyer.h"
9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/browser_navigator.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/common/render_messages.h"
13 #include "chrome/test/base/testing_profile.h"
14 #include "content/public/browser/navigation_controller.h"
15 #include "content/public/browser/navigation_entry.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/common/page_transition_types.h"
18 #include "content/public/test/test_renderer_host.h"
21 #include "ui/aura/test/aura_test_helper.h"
25 #include "ash/test/ash_test_helper.h"
28 using content::NavigationController;
29 using content::RenderViewHost;
30 using content::RenderViewHostTester;
31 using content::WebContents;
33 BrowserWithTestWindowTest::BrowserWithTestWindowTest()
34 : host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE) {
37 BrowserWithTestWindowTest::~BrowserWithTestWindowTest() {
40 void BrowserWithTestWindowTest::SetHostDesktopType(
41 chrome::HostDesktopType host_desktop_type) {
43 host_desktop_type_ = host_desktop_type;
46 void BrowserWithTestWindowTest::SetUp() {
47 testing::Test::SetUp();
48 #if defined(OS_CHROMEOS)
49 // TODO(jamescook): Windows Ash support. This will require refactoring
50 // AshTestHelper and AuraTestHelper so they can be used at the same time,
51 // perhaps by AshTestHelper owning an AuraTestHelper.
52 ash_test_helper_.reset(new ash::test::AshTestHelper(
53 base::MessageLoopForUI::current()));
54 ash_test_helper_->SetUp(true);
55 #elif defined(USE_AURA)
56 aura_test_helper_.reset(new aura::test::AuraTestHelper(
57 base::MessageLoopForUI::current()));
58 aura_test_helper_->SetUp();
61 // Subclasses can provide their own Profile.
62 profile_ = CreateProfile();
63 // Subclasses can provide their own test BrowserWindow. If they return NULL
64 // then Browser will create the a production BrowserWindow and the subclass
65 // is responsible for cleaning it up (usually by NativeWidget destruction).
66 window_.reset(CreateBrowserWindow());
68 Browser::CreateParams params(profile(), host_desktop_type_);
69 params.window = window_.get();
70 browser_.reset(new Browser(params));
73 void BrowserWithTestWindowTest::TearDown() {
74 // Some tests end up posting tasks to the DB thread that must be completed
75 // before the profile can be destroyed and the test safely shut down.
76 base::RunLoop().RunUntilIdle();
78 // Reset the profile here because some profile keyed services (like the
79 // audio service) depend on test stubs that the helpers below will remove.
80 DestroyBrowserAndProfile();
82 #if defined(OS_CHROMEOS)
83 ash_test_helper_->TearDown();
84 #elif defined(USE_AURA)
85 aura_test_helper_->TearDown();
87 testing::Test::TearDown();
89 // A Task is leaked if we don't destroy everything, then run the message
91 base::MessageLoop::current()->PostTask(FROM_HERE,
92 base::MessageLoop::QuitClosure());
93 base::MessageLoop::current()->Run();
96 void BrowserWithTestWindowTest::AddTab(Browser* browser, const GURL& url) {
97 chrome::NavigateParams params(browser, url, content::PAGE_TRANSITION_TYPED);
98 params.tabstrip_index = 0;
99 params.disposition = NEW_FOREGROUND_TAB;
100 chrome::Navigate(¶ms);
101 CommitPendingLoad(¶ms.target_contents->GetController());
104 void BrowserWithTestWindowTest::CommitPendingLoad(
105 NavigationController* controller) {
106 if (!controller->GetPendingEntry())
107 return; // Nothing to commit.
109 RenderViewHost* old_rvh =
110 controller->GetWebContents()->GetRenderViewHost();
112 RenderViewHost* pending_rvh = RenderViewHostTester::GetPendingForController(
115 // Simulate the ShouldClose_ACK that is received from the current renderer
116 // for a cross-site navigation.
117 DCHECK_NE(old_rvh, pending_rvh);
118 RenderViewHostTester::For(old_rvh)->SendShouldCloseACK(true);
120 // Commit on the pending_rvh, if one exists.
121 RenderViewHost* test_rvh = pending_rvh ? pending_rvh : old_rvh;
122 RenderViewHostTester* test_rvh_tester = RenderViewHostTester::For(test_rvh);
124 // Simulate a SwapOut_ACK before the navigation commits.
126 RenderViewHostTester::For(old_rvh)->SimulateSwapOutACK();
128 // For new navigations, we need to send a larger page ID. For renavigations,
129 // we need to send the preexisting page ID. We can tell these apart because
130 // renavigations will have a pending_entry_index while new ones won't (they'll
131 // just have a standalong pending_entry that isn't in the list already).
132 if (controller->GetPendingEntryIndex() >= 0) {
133 test_rvh_tester->SendNavigateWithTransition(
134 controller->GetPendingEntry()->GetPageID(),
135 controller->GetPendingEntry()->GetURL(),
136 controller->GetPendingEntry()->GetTransitionType());
138 test_rvh_tester->SendNavigateWithTransition(
139 controller->GetWebContents()->
140 GetMaxPageIDForSiteInstance(test_rvh->GetSiteInstance()) + 1,
141 controller->GetPendingEntry()->GetURL(),
142 controller->GetPendingEntry()->GetTransitionType());
146 void BrowserWithTestWindowTest::NavigateAndCommit(
147 NavigationController* controller,
150 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string());
151 CommitPendingLoad(controller);
154 void BrowserWithTestWindowTest::NavigateAndCommitActiveTab(const GURL& url) {
155 NavigateAndCommit(&browser()->tab_strip_model()->GetActiveWebContents()->
160 void BrowserWithTestWindowTest::NavigateAndCommitActiveTabWithTitle(
161 Browser* navigating_browser,
163 const string16& title) {
164 NavigationController* controller = &navigating_browser->tab_strip_model()->
165 GetActiveWebContents()->GetController();
166 NavigateAndCommit(controller, url);
167 controller->GetActiveEntry()->SetTitle(title);
170 void BrowserWithTestWindowTest::DestroyBrowserAndProfile() {
171 if (browser_.get()) {
172 // Make sure we close all tabs, otherwise Browser isn't happy in its
174 browser()->tab_strip_model()->CloseAllTabs();
175 browser_.reset(NULL);
178 // Destroy the profile here - otherwise, if the profile is freed in the
179 // destructor, and a test subclass owns a resource that the profile depends
180 // on (such as g_browser_process()->local_state()) there's no way for the
181 // subclass to free it after the profile.
183 DestroyProfile(profile_);
187 TestingProfile* BrowserWithTestWindowTest::CreateProfile() {
188 return new TestingProfile();
191 void BrowserWithTestWindowTest::DestroyProfile(TestingProfile* profile) {
195 BrowserWindow* BrowserWithTestWindowTest::CreateBrowserWindow() {
196 return new TestBrowserWindow();