Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / test / base / browser_with_test_window_test.cc
blob324b596d07de99ecbdd06e2572cdf2a116860ac0
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/test/test_renderer_host.h"
18 #include "ui/base/page_transition_types.h"
20 #if defined(USE_AURA)
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"
25 #endif
27 #if defined(USE_ASH)
28 #include "ash/test/ash_test_helper.h"
29 #include "ash/test/ash_test_views_delegate.h"
30 #endif
32 #if defined(TOOLKIT_VIEWS)
33 #include "ui/views/test/test_views_delegate.h"
34 #endif
36 using content::NavigationController;
37 using content::RenderFrameHost;
38 using content::RenderFrameHostTester;
39 using content::WebContents;
41 BrowserWithTestWindowTest::BrowserWithTestWindowTest()
42 : browser_type_(Browser::TYPE_TABBED),
43 host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE),
44 hosted_app_(false) {
47 BrowserWithTestWindowTest::BrowserWithTestWindowTest(
48 Browser::Type browser_type,
49 chrome::HostDesktopType host_desktop_type,
50 bool hosted_app)
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());
79 #endif // USE_AURA
80 #if !defined(OS_CHROMEOS) && defined(TOOLKIT_VIEWS)
81 views_delegate_.reset(CreateViewsDelegate());
82 #endif
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();
109 #endif
110 testing::Test::TearDown();
112 // A Task is leaked if we don't destroy everything, then run the message
113 // loop.
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);
120 #endif
123 void BrowserWithTestWindowTest::AddTab(Browser* browser, const GURL& url) {
124 chrome::NavigateParams params(browser, url, ui::PAGE_TRANSITION_TYPED);
125 params.tabstrip_index = 0;
126 params.disposition = NEW_FOREGROUND_TAB;
127 chrome::Navigate(&params);
128 CommitPendingLoad(&params.target_contents->GetController());
131 void BrowserWithTestWindowTest::CommitPendingLoad(
132 NavigationController* controller) {
133 if (!controller->GetPendingEntry())
134 return; // Nothing to commit.
136 RenderFrameHost* old_rfh = controller->GetWebContents()->GetMainFrame();
138 RenderFrameHost* pending_rfh = RenderFrameHostTester::GetPendingForController(
139 controller);
140 if (pending_rfh) {
141 // Simulate the BeforeUnload_ACK that is received from the current renderer
142 // for a cross-site navigation.
143 DCHECK_NE(old_rfh, pending_rfh);
144 RenderFrameHostTester::For(old_rfh)->SendBeforeUnloadACK(true);
146 // Commit on the pending_rfh, if one exists.
147 RenderFrameHost* test_rfh = pending_rfh ? pending_rfh : old_rfh;
148 RenderFrameHostTester* test_rfh_tester = RenderFrameHostTester::For(test_rfh);
150 // Simulate a SwapOut_ACK before the navigation commits.
151 if (pending_rfh)
152 RenderFrameHostTester::For(old_rfh)->SimulateSwapOutACK();
154 // For new navigations, we need to send a larger page ID. For renavigations,
155 // we need to send the preexisting page ID. We can tell these apart because
156 // renavigations will have a pending_entry_index while new ones won't (they'll
157 // just have a standalong pending_entry that isn't in the list already).
158 if (controller->GetPendingEntryIndex() >= 0) {
159 test_rfh_tester->SendNavigateWithTransition(
160 controller->GetPendingEntry()->GetPageID(),
161 controller->GetPendingEntry()->GetURL(),
162 controller->GetPendingEntry()->GetTransitionType());
163 } else {
164 test_rfh_tester->SendNavigateWithTransition(
165 controller->GetWebContents()->GetMaxPageIDForSiteInstance(
166 test_rfh->GetSiteInstance()) + 1,
167 controller->GetPendingEntry()->GetURL(),
168 controller->GetPendingEntry()->GetTransitionType());
172 void BrowserWithTestWindowTest::NavigateAndCommit(
173 NavigationController* controller,
174 const GURL& url) {
175 controller->LoadURL(
176 url, content::Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
177 CommitPendingLoad(controller);
180 void BrowserWithTestWindowTest::NavigateAndCommitActiveTab(const GURL& url) {
181 NavigateAndCommit(&browser()->tab_strip_model()->GetActiveWebContents()->
182 GetController(),
183 url);
186 void BrowserWithTestWindowTest::NavigateAndCommitActiveTabWithTitle(
187 Browser* navigating_browser,
188 const GURL& url,
189 const base::string16& title) {
190 NavigationController* controller = &navigating_browser->tab_strip_model()->
191 GetActiveWebContents()->GetController();
192 NavigateAndCommit(controller, url);
193 controller->GetActiveEntry()->SetTitle(title);
196 void BrowserWithTestWindowTest::DestroyBrowserAndProfile() {
197 if (browser_.get()) {
198 // Make sure we close all tabs, otherwise Browser isn't happy in its
199 // destructor.
200 browser()->tab_strip_model()->CloseAllTabs();
201 browser_.reset(NULL);
203 window_.reset(NULL);
204 // Destroy the profile here - otherwise, if the profile is freed in the
205 // destructor, and a test subclass owns a resource that the profile depends
206 // on (such as g_browser_process()->local_state()) there's no way for the
207 // subclass to free it after the profile.
208 if (profile_)
209 DestroyProfile(profile_);
210 profile_ = NULL;
213 TestingProfile* BrowserWithTestWindowTest::CreateProfile() {
214 return new TestingProfile();
217 void BrowserWithTestWindowTest::DestroyProfile(TestingProfile* profile) {
218 delete profile;
221 BrowserWindow* BrowserWithTestWindowTest::CreateBrowserWindow() {
222 return new TestBrowserWindow();
225 Browser* BrowserWithTestWindowTest::CreateBrowser(
226 Profile* profile,
227 Browser::Type browser_type,
228 bool hosted_app,
229 chrome::HostDesktopType host_desktop_type,
230 BrowserWindow* browser_window) {
231 Browser::CreateParams params(profile, host_desktop_type);
232 if (hosted_app) {
233 params = Browser::CreateParams::CreateForApp("Test",
234 true /* trusted_source */,
235 gfx::Rect(),
236 profile,
237 host_desktop_type);
238 } else {
239 params.type = browser_type;
241 params.window = browser_window;
242 return new Browser(params);
245 #if !defined(OS_CHROMEOS) && defined(TOOLKIT_VIEWS)
246 views::ViewsDelegate* BrowserWithTestWindowTest::CreateViewsDelegate() {
247 #if defined(USE_ASH)
248 return new ash::test::AshTestViewsDelegate;
249 #else
250 return new views::TestViewsDelegate;
251 #endif
253 #endif