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 #if defined(TOOLKIT_VIEWS)
29 #include "ui/views/test/test_views_delegate.h"
32 using content::NavigationController;
33 using content::RenderViewHost;
34 using content::RenderViewHostTester;
35 using content::WebContents;
37 BrowserWithTestWindowTest::BrowserWithTestWindowTest()
38 : browser_type_(Browser::TYPE_TABBED),
39 host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE),
43 BrowserWithTestWindowTest::BrowserWithTestWindowTest(
44 Browser::Type browser_type,
45 chrome::HostDesktopType host_desktop_type,
47 : browser_type_(browser_type),
48 host_desktop_type_(host_desktop_type),
49 hosted_app_(hosted_app) {
52 BrowserWithTestWindowTest::~BrowserWithTestWindowTest() {
55 void BrowserWithTestWindowTest::SetUp() {
56 testing::Test::SetUp();
57 #if defined(OS_CHROMEOS)
58 // TODO(jamescook): Windows Ash support. This will require refactoring
59 // AshTestHelper and AuraTestHelper so they can be used at the same time,
60 // perhaps by AshTestHelper owning an AuraTestHelper.
61 ash_test_helper_.reset(new ash::test::AshTestHelper(
62 base::MessageLoopForUI::current()));
63 ash_test_helper_->SetUp(true);
64 #elif defined(USE_AURA)
65 aura_test_helper_.reset(new aura::test::AuraTestHelper(
66 base::MessageLoopForUI::current()));
67 bool allow_test_contexts = true;
68 aura_test_helper_->SetUp(allow_test_contexts);
70 #if defined(TOOLKIT_VIEWS)
71 views_delegate_.reset(CreateViewsDelegate());
72 views::ViewsDelegate::views_delegate = views_delegate_.get();
75 // Subclasses can provide their own Profile.
76 profile_ = CreateProfile();
77 // Subclasses can provide their own test BrowserWindow. If they return NULL
78 // then Browser will create the a production BrowserWindow and the subclass
79 // is responsible for cleaning it up (usually by NativeWidget destruction).
80 window_.reset(CreateBrowserWindow());
82 browser_.reset(CreateBrowser(profile(), browser_type_, hosted_app_,
83 host_desktop_type_, window_.get()));
86 void BrowserWithTestWindowTest::TearDown() {
87 // Some tests end up posting tasks to the DB thread that must be completed
88 // before the profile can be destroyed and the test safely shut down.
89 base::RunLoop().RunUntilIdle();
91 // Reset the profile here because some profile keyed services (like the
92 // audio service) depend on test stubs that the helpers below will remove.
93 DestroyBrowserAndProfile();
95 #if defined(OS_CHROMEOS)
96 ash_test_helper_->TearDown();
97 #elif defined(USE_AURA)
98 aura_test_helper_->TearDown();
100 testing::Test::TearDown();
102 // A Task is leaked if we don't destroy everything, then run the message
104 base::MessageLoop::current()->PostTask(FROM_HERE,
105 base::MessageLoop::QuitClosure());
106 base::MessageLoop::current()->Run();
108 #if defined(TOOLKIT_VIEWS)
109 views::ViewsDelegate::views_delegate = NULL;
110 views_delegate_.reset(NULL);
114 void BrowserWithTestWindowTest::AddTab(Browser* browser, const GURL& url) {
115 chrome::NavigateParams params(browser, url, content::PAGE_TRANSITION_TYPED);
116 params.tabstrip_index = 0;
117 params.disposition = NEW_FOREGROUND_TAB;
118 chrome::Navigate(¶ms);
119 CommitPendingLoad(¶ms.target_contents->GetController());
122 void BrowserWithTestWindowTest::CommitPendingLoad(
123 NavigationController* controller) {
124 if (!controller->GetPendingEntry())
125 return; // Nothing to commit.
127 RenderViewHost* old_rvh =
128 controller->GetWebContents()->GetRenderViewHost();
130 RenderViewHost* pending_rvh = RenderViewHostTester::GetPendingForController(
133 // Simulate the ShouldClose_ACK that is received from the current renderer
134 // for a cross-site navigation.
135 DCHECK_NE(old_rvh, pending_rvh);
136 RenderViewHostTester::For(old_rvh)->SendShouldCloseACK(true);
138 // Commit on the pending_rvh, if one exists.
139 RenderViewHost* test_rvh = pending_rvh ? pending_rvh : old_rvh;
140 RenderViewHostTester* test_rvh_tester = RenderViewHostTester::For(test_rvh);
142 // Simulate a SwapOut_ACK before the navigation commits.
144 RenderViewHostTester::For(old_rvh)->SimulateSwapOutACK();
146 // For new navigations, we need to send a larger page ID. For renavigations,
147 // we need to send the preexisting page ID. We can tell these apart because
148 // renavigations will have a pending_entry_index while new ones won't (they'll
149 // just have a standalong pending_entry that isn't in the list already).
150 if (controller->GetPendingEntryIndex() >= 0) {
151 test_rvh_tester->SendNavigateWithTransition(
152 controller->GetPendingEntry()->GetPageID(),
153 controller->GetPendingEntry()->GetURL(),
154 controller->GetPendingEntry()->GetTransitionType());
156 test_rvh_tester->SendNavigateWithTransition(
157 controller->GetWebContents()->
158 GetMaxPageIDForSiteInstance(test_rvh->GetSiteInstance()) + 1,
159 controller->GetPendingEntry()->GetURL(),
160 controller->GetPendingEntry()->GetTransitionType());
164 void BrowserWithTestWindowTest::NavigateAndCommit(
165 NavigationController* controller,
168 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string());
169 CommitPendingLoad(controller);
172 void BrowserWithTestWindowTest::NavigateAndCommitActiveTab(const GURL& url) {
173 NavigateAndCommit(&browser()->tab_strip_model()->GetActiveWebContents()->
178 void BrowserWithTestWindowTest::NavigateAndCommitActiveTabWithTitle(
179 Browser* navigating_browser,
181 const base::string16& title) {
182 NavigationController* controller = &navigating_browser->tab_strip_model()->
183 GetActiveWebContents()->GetController();
184 NavigateAndCommit(controller, url);
185 controller->GetActiveEntry()->SetTitle(title);
188 void BrowserWithTestWindowTest::DestroyBrowserAndProfile() {
189 if (browser_.get()) {
190 // Make sure we close all tabs, otherwise Browser isn't happy in its
192 browser()->tab_strip_model()->CloseAllTabs();
193 browser_.reset(NULL);
196 // Destroy the profile here - otherwise, if the profile is freed in the
197 // destructor, and a test subclass owns a resource that the profile depends
198 // on (such as g_browser_process()->local_state()) there's no way for the
199 // subclass to free it after the profile.
201 DestroyProfile(profile_);
205 TestingProfile* BrowserWithTestWindowTest::CreateProfile() {
206 return new TestingProfile();
209 void BrowserWithTestWindowTest::DestroyProfile(TestingProfile* profile) {
213 BrowserWindow* BrowserWithTestWindowTest::CreateBrowserWindow() {
214 return new TestBrowserWindow();
217 Browser* BrowserWithTestWindowTest::CreateBrowser(
219 Browser::Type browser_type,
221 chrome::HostDesktopType host_desktop_type,
222 BrowserWindow* browser_window) {
223 Browser::CreateParams params(profile, host_desktop_type);
224 params.type = browser_type;
225 params.window = browser_window;
227 params.app_name = "Test";
228 return new Browser(params);
231 #if defined(TOOLKIT_VIEWS)
232 views::ViewsDelegate* BrowserWithTestWindowTest::CreateViewsDelegate() {
233 return new views::TestViewsDelegate;