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"
22 #include "ui/compositor/compositor.h"
23 #include "ui/compositor/test/context_factories_for_test.h"
24 #include "ui/wm/core/default_activation_client.h"
28 #include "ash/test/ash_test_helper.h"
29 #include "ash/test/ash_test_views_delegate.h"
32 #if defined(TOOLKIT_VIEWS)
33 #include "ui/views/test/test_views_delegate.h"
36 using content::NavigationController
;
37 using content::RenderViewHost
;
38 using content::RenderViewHostTester
;
39 using content::WebContents
;
41 BrowserWithTestWindowTest::BrowserWithTestWindowTest()
42 : browser_type_(Browser::TYPE_TABBED
),
43 host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE
),
47 BrowserWithTestWindowTest::BrowserWithTestWindowTest(
48 Browser::Type browser_type
,
49 chrome::HostDesktopType host_desktop_type
,
51 : browser_type_(browser_type
),
52 host_desktop_type_(host_desktop_type
),
53 hosted_app_(hosted_app
) {
56 BrowserWithTestWindowTest::~BrowserWithTestWindowTest() {
59 void BrowserWithTestWindowTest::SetUp() {
60 testing::Test::SetUp();
61 #if defined(OS_CHROMEOS)
62 // TODO(jamescook): Windows Ash support. This will require refactoring
63 // AshTestHelper and AuraTestHelper so they can be used at the same time,
64 // perhaps by AshTestHelper owning an AuraTestHelper. Also, need to cleanup
65 // CreateViewsDelegate() below when cleanup done.
66 ash_test_helper_
.reset(new ash::test::AshTestHelper(
67 base::MessageLoopForUI::current()));
68 ash_test_helper_
->SetUp(true);
69 #elif defined(USE_AURA)
70 // The ContextFactory must exist before any Compositors are created.
71 bool enable_pixel_output
= false;
72 ui::ContextFactory
* context_factory
=
73 ui::InitializeContextFactoryForTests(enable_pixel_output
);
75 aura_test_helper_
.reset(new aura::test::AuraTestHelper(
76 base::MessageLoopForUI::current()));
77 aura_test_helper_
->SetUp(context_factory
);
78 new wm::DefaultActivationClient(aura_test_helper_
->root_window());
80 #if !defined(OS_CHROMEOS) && defined(TOOLKIT_VIEWS)
81 views_delegate_
.reset(CreateViewsDelegate());
84 // Subclasses can provide their own Profile.
85 profile_
= CreateProfile();
86 // Subclasses can provide their own test BrowserWindow. If they return NULL
87 // then Browser will create the a production BrowserWindow and the subclass
88 // is responsible for cleaning it up (usually by NativeWidget destruction).
89 window_
.reset(CreateBrowserWindow());
91 browser_
.reset(CreateBrowser(profile(), browser_type_
, hosted_app_
,
92 host_desktop_type_
, window_
.get()));
95 void BrowserWithTestWindowTest::TearDown() {
96 // Some tests end up posting tasks to the DB thread that must be completed
97 // before the profile can be destroyed and the test safely shut down.
98 base::RunLoop().RunUntilIdle();
100 // Reset the profile here because some profile keyed services (like the
101 // audio service) depend on test stubs that the helpers below will remove.
102 DestroyBrowserAndProfile();
104 #if defined(OS_CHROMEOS)
105 ash_test_helper_
->TearDown();
106 #elif defined(USE_AURA)
107 aura_test_helper_
->TearDown();
108 ui::TerminateContextFactoryForTests();
110 testing::Test::TearDown();
112 // A Task is leaked if we don't destroy everything, then run the message
114 base::MessageLoop::current()->PostTask(FROM_HERE
,
115 base::MessageLoop::QuitClosure());
116 base::MessageLoop::current()->Run();
118 #if defined(TOOLKIT_VIEWS)
119 views_delegate_
.reset(NULL
);
123 void BrowserWithTestWindowTest::AddTab(Browser
* browser
, const GURL
& url
) {
124 chrome::NavigateParams
params(browser
, url
, content::PAGE_TRANSITION_TYPED
);
125 params
.tabstrip_index
= 0;
126 params
.disposition
= NEW_FOREGROUND_TAB
;
127 chrome::Navigate(¶ms
);
128 CommitPendingLoad(¶ms
.target_contents
->GetController());
131 void BrowserWithTestWindowTest::CommitPendingLoad(
132 NavigationController
* controller
) {
133 if (!controller
->GetPendingEntry())
134 return; // Nothing to commit.
136 RenderViewHost
* old_rvh
=
137 controller
->GetWebContents()->GetRenderViewHost();
139 RenderViewHost
* pending_rvh
= RenderViewHostTester::GetPendingForController(
142 // Simulate the BeforeUnload_ACK that is received from the current renderer
143 // for a cross-site navigation.
144 DCHECK_NE(old_rvh
, pending_rvh
);
145 RenderViewHostTester::For(old_rvh
)->SendBeforeUnloadACK(true);
147 // Commit on the pending_rvh, if one exists.
148 RenderViewHost
* test_rvh
= pending_rvh
? pending_rvh
: old_rvh
;
149 RenderViewHostTester
* test_rvh_tester
= RenderViewHostTester::For(test_rvh
);
151 // Simulate a SwapOut_ACK before the navigation commits.
153 RenderViewHostTester::For(old_rvh
)->SimulateSwapOutACK();
155 // For new navigations, we need to send a larger page ID. For renavigations,
156 // we need to send the preexisting page ID. We can tell these apart because
157 // renavigations will have a pending_entry_index while new ones won't (they'll
158 // just have a standalong pending_entry that isn't in the list already).
159 if (controller
->GetPendingEntryIndex() >= 0) {
160 test_rvh_tester
->SendNavigateWithTransition(
161 controller
->GetPendingEntry()->GetPageID(),
162 controller
->GetPendingEntry()->GetURL(),
163 controller
->GetPendingEntry()->GetTransitionType());
165 test_rvh_tester
->SendNavigateWithTransition(
166 controller
->GetWebContents()->
167 GetMaxPageIDForSiteInstance(test_rvh
->GetSiteInstance()) + 1,
168 controller
->GetPendingEntry()->GetURL(),
169 controller
->GetPendingEntry()->GetTransitionType());
173 void BrowserWithTestWindowTest::NavigateAndCommit(
174 NavigationController
* controller
,
177 url
, content::Referrer(), content::PAGE_TRANSITION_LINK
, std::string());
178 CommitPendingLoad(controller
);
181 void BrowserWithTestWindowTest::NavigateAndCommitActiveTab(const GURL
& url
) {
182 NavigateAndCommit(&browser()->tab_strip_model()->GetActiveWebContents()->
187 void BrowserWithTestWindowTest::NavigateAndCommitActiveTabWithTitle(
188 Browser
* navigating_browser
,
190 const base::string16
& title
) {
191 NavigationController
* controller
= &navigating_browser
->tab_strip_model()->
192 GetActiveWebContents()->GetController();
193 NavigateAndCommit(controller
, url
);
194 controller
->GetActiveEntry()->SetTitle(title
);
197 void BrowserWithTestWindowTest::DestroyBrowserAndProfile() {
198 if (browser_
.get()) {
199 // Make sure we close all tabs, otherwise Browser isn't happy in its
201 browser()->tab_strip_model()->CloseAllTabs();
202 browser_
.reset(NULL
);
205 // Destroy the profile here - otherwise, if the profile is freed in the
206 // destructor, and a test subclass owns a resource that the profile depends
207 // on (such as g_browser_process()->local_state()) there's no way for the
208 // subclass to free it after the profile.
210 DestroyProfile(profile_
);
214 TestingProfile
* BrowserWithTestWindowTest::CreateProfile() {
215 return new TestingProfile();
218 void BrowserWithTestWindowTest::DestroyProfile(TestingProfile
* profile
) {
222 BrowserWindow
* BrowserWithTestWindowTest::CreateBrowserWindow() {
223 return new TestBrowserWindow();
226 Browser
* BrowserWithTestWindowTest::CreateBrowser(
228 Browser::Type browser_type
,
230 chrome::HostDesktopType host_desktop_type
,
231 BrowserWindow
* browser_window
) {
232 Browser::CreateParams
params(profile
, host_desktop_type
);
234 params
= Browser::CreateParams::CreateForApp("Test",
235 true /* trusted_source */,
240 params
.type
= browser_type
;
242 params
.window
= browser_window
;
243 return new Browser(params
);
246 #if !defined(OS_CHROMEOS) && defined(TOOLKIT_VIEWS)
247 views::ViewsDelegate
* BrowserWithTestWindowTest::CreateViewsDelegate() {
249 return new ash::test::AshTestViewsDelegate
;
251 return new views::TestViewsDelegate
;