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/location.h"
8 #include "base/run_loop.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "chrome/browser/profiles/profile_destroyer.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_navigator.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/test/base/testing_profile.h"
16 #include "content/public/browser/navigation_controller.h"
17 #include "content/public/browser/navigation_entry.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/test/test_renderer_host.h"
20 #include "ui/base/page_transition_types.h"
22 #if defined(OS_CHROMEOS)
23 #include "ash/test/ash_test_helper.h"
24 #elif defined(TOOLKIT_VIEWS)
25 #include "ui/views/test/scoped_views_test_helper.h"
28 #if defined(TOOLKIT_VIEWS)
29 #include "chrome/browser/ui/views/chrome_constrained_window_views_client.h"
30 #include "components/constrained_window/constrained_window_views.h"
33 using content::NavigationController
;
34 using content::RenderFrameHost
;
35 using content::RenderFrameHostTester
;
36 using content::WebContents
;
38 BrowserWithTestWindowTest::BrowserWithTestWindowTest()
39 : browser_type_(Browser::TYPE_TABBED
),
40 host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE
),
44 BrowserWithTestWindowTest::BrowserWithTestWindowTest(
45 Browser::Type browser_type
,
46 chrome::HostDesktopType host_desktop_type
,
48 : browser_type_(browser_type
),
49 host_desktop_type_(host_desktop_type
),
50 hosted_app_(hosted_app
) {
53 BrowserWithTestWindowTest::~BrowserWithTestWindowTest() {
56 void BrowserWithTestWindowTest::SetUp() {
57 testing::Test::SetUp();
58 #if defined(OS_CHROMEOS)
59 // TODO(jamescook): Windows Ash support. This will require refactoring
60 // AshTestHelper and AuraTestHelper so they can be used at the same time,
61 // perhaps by AshTestHelper owning an AuraTestHelper.
62 ash_test_helper_
.reset(new ash::test::AshTestHelper(
63 base::MessageLoopForUI::current()));
64 ash_test_helper_
->SetUp(true);
65 #elif defined(TOOLKIT_VIEWS)
66 views_test_helper_
.reset(new views::ScopedViewsTestHelper());
68 #if defined(TOOLKIT_VIEWS)
69 SetConstrainedWindowViewsClient(CreateChromeConstrainedWindowViewsClient());
72 // Subclasses can provide their own Profile.
73 profile_
= CreateProfile();
74 // Subclasses can provide their own test BrowserWindow. If they return NULL
75 // then Browser will create the a production BrowserWindow and the subclass
76 // is responsible for cleaning it up (usually by NativeWidget destruction).
77 window_
.reset(CreateBrowserWindow());
79 browser_
.reset(CreateBrowser(profile(), browser_type_
, hosted_app_
,
80 host_desktop_type_
, window_
.get()));
83 void BrowserWithTestWindowTest::TearDown() {
84 // Some tests end up posting tasks to the DB thread that must be completed
85 // before the profile can be destroyed and the test safely shut down.
86 base::RunLoop().RunUntilIdle();
88 // Reset the profile here because some profile keyed services (like the
89 // audio service) depend on test stubs that the helpers below will remove.
90 DestroyBrowserAndProfile();
92 #if defined(TOOLKIT_VIEWS)
93 constrained_window::SetConstrainedWindowViewsClient(nullptr);
96 #if defined(OS_CHROMEOS)
97 ash_test_helper_
->TearDown();
98 #elif defined(TOOLKIT_VIEWS)
99 views_test_helper_
.reset();
102 testing::Test::TearDown();
104 // A Task is leaked if we don't destroy everything, then run the message
106 base::ThreadTaskRunnerHandle::Get()->PostTask(
107 FROM_HERE
, base::MessageLoop::QuitClosure());
108 base::MessageLoop::current()->Run();
111 gfx::NativeWindow
BrowserWithTestWindowTest::GetContext() {
112 #if defined(OS_CHROMEOS)
113 return ash_test_helper_
->CurrentContext();
114 #elif defined(TOOLKIT_VIEWS)
115 return views_test_helper_
->GetContext();
121 void BrowserWithTestWindowTest::AddTab(Browser
* browser
, const GURL
& url
) {
122 chrome::NavigateParams
params(browser
, url
, ui::PAGE_TRANSITION_TYPED
);
123 params
.tabstrip_index
= 0;
124 params
.disposition
= NEW_FOREGROUND_TAB
;
125 chrome::Navigate(¶ms
);
126 CommitPendingLoad(¶ms
.target_contents
->GetController());
129 void BrowserWithTestWindowTest::CommitPendingLoad(
130 NavigationController
* controller
) {
131 if (!controller
->GetPendingEntry())
132 return; // Nothing to commit.
134 RenderFrameHost
* old_rfh
= controller
->GetWebContents()->GetMainFrame();
136 RenderFrameHost
* pending_rfh
= RenderFrameHostTester::GetPendingForController(
139 // Simulate the BeforeUnload_ACK that is received from the current renderer
140 // for a cross-site navigation.
141 DCHECK_NE(old_rfh
, pending_rfh
);
142 RenderFrameHostTester::For(old_rfh
)->SendBeforeUnloadACK(true);
144 // Commit on the pending_rfh, if one exists.
145 RenderFrameHost
* test_rfh
= pending_rfh
? pending_rfh
: old_rfh
;
146 RenderFrameHostTester
* test_rfh_tester
= RenderFrameHostTester::For(test_rfh
);
148 // Simulate a SwapOut_ACK before the navigation commits.
150 RenderFrameHostTester::For(old_rfh
)->SimulateSwapOutACK();
152 // For new navigations, we need to send a larger page ID. For renavigations,
153 // we need to send the preexisting page ID. We can tell these apart because
154 // renavigations will have a pending_entry_index while new ones won't (they'll
155 // just have a standalong pending_entry that isn't in the list already).
156 if (controller
->GetPendingEntryIndex() >= 0) {
157 test_rfh_tester
->SendNavigateWithTransition(
158 controller
->GetPendingEntry()->GetPageID(),
159 controller
->GetPendingEntry()->GetUniqueID(),
161 controller
->GetPendingEntry()->GetURL(),
162 controller
->GetPendingEntry()->GetTransitionType());
164 test_rfh_tester
->SendNavigateWithTransition(
165 controller
->GetWebContents()->GetMaxPageIDForSiteInstance(
166 test_rfh
->GetSiteInstance()) + 1,
167 controller
->GetPendingEntry()->GetUniqueID(),
169 controller
->GetPendingEntry()->GetURL(),
170 controller
->GetPendingEntry()->GetTransitionType());
174 void BrowserWithTestWindowTest::NavigateAndCommit(
175 NavigationController
* controller
,
178 url
, content::Referrer(), ui::PAGE_TRANSITION_LINK
, std::string());
179 CommitPendingLoad(controller
);
182 void BrowserWithTestWindowTest::NavigateAndCommitActiveTab(const GURL
& url
) {
183 NavigateAndCommit(&browser()->tab_strip_model()->GetActiveWebContents()->
188 void BrowserWithTestWindowTest::NavigateAndCommitActiveTabWithTitle(
189 Browser
* navigating_browser
,
191 const base::string16
& title
) {
192 NavigationController
* controller
= &navigating_browser
->tab_strip_model()->
193 GetActiveWebContents()->GetController();
194 NavigateAndCommit(controller
, url
);
195 controller
->GetActiveEntry()->SetTitle(title
);
198 void BrowserWithTestWindowTest::DestroyBrowserAndProfile() {
199 if (browser_
.get()) {
200 // Make sure we close all tabs, otherwise Browser isn't happy in its
202 browser()->tab_strip_model()->CloseAllTabs();
203 browser_
.reset(NULL
);
206 // Destroy the profile here - otherwise, if the profile is freed in the
207 // destructor, and a test subclass owns a resource that the profile depends
208 // on (such as g_browser_process()->local_state()) there's no way for the
209 // subclass to free it after the profile.
211 DestroyProfile(profile_
);
215 TestingProfile
* BrowserWithTestWindowTest::CreateProfile() {
216 return new TestingProfile();
219 void BrowserWithTestWindowTest::DestroyProfile(TestingProfile
* profile
) {
223 BrowserWindow
* BrowserWithTestWindowTest::CreateBrowserWindow() {
224 return new TestBrowserWindow();
227 Browser
* BrowserWithTestWindowTest::CreateBrowser(
229 Browser::Type browser_type
,
231 chrome::HostDesktopType host_desktop_type
,
232 BrowserWindow
* browser_window
) {
233 Browser::CreateParams
params(profile
, host_desktop_type
);
235 params
= Browser::CreateParams::CreateForApp("Test",
236 true /* trusted_source */,
241 params
.type
= browser_type
;
243 params
.window
= browser_window
;
244 return new Browser(params
);