Infobar material design refresh: layout
[chromium-blink-merge.git] / chrome / browser / ui / browser_browsertest.cc
blob8602b698440fa5c0199e0401c487adb7458ad4dc
1 // Copyright 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 <string>
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/compiler_specific.h"
10 #include "base/files/file_path.h"
11 #include "base/location.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/sys_info.h"
17 #include "chrome/app/chrome_command_ids.h"
18 #include "chrome/browser/chrome_content_browser_client.h"
19 #include "chrome/browser/chrome_notification_types.h"
20 #include "chrome/browser/command_updater.h"
21 #include "chrome/browser/defaults.h"
22 #include "chrome/browser/devtools/devtools_window_testing.h"
23 #include "chrome/browser/extensions/extension_browsertest.h"
24 #include "chrome/browser/extensions/extension_service.h"
25 #include "chrome/browser/extensions/extension_util.h"
26 #include "chrome/browser/extensions/tab_helper.h"
27 #include "chrome/browser/first_run/first_run.h"
28 #include "chrome/browser/lifetime/application_lifetime.h"
29 #include "chrome/browser/prefs/incognito_mode_prefs.h"
30 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/browser/profiles/profile_info_cache.h"
32 #include "chrome/browser/profiles/profile_manager.h"
33 #include "chrome/browser/search/search.h"
34 #include "chrome/browser/sessions/session_service_factory.h"
35 #include "chrome/browser/ssl/connection_security.h"
36 #include "chrome/browser/translate/chrome_translate_client.h"
37 #include "chrome/browser/translate/cld_data_harness.h"
38 #include "chrome/browser/translate/cld_data_harness_factory.h"
39 #include "chrome/browser/ui/browser.h"
40 #include "chrome/browser/ui/browser_command_controller.h"
41 #include "chrome/browser/ui/browser_commands.h"
42 #include "chrome/browser/ui/browser_finder.h"
43 #include "chrome/browser/ui/browser_iterator.h"
44 #include "chrome/browser/ui/browser_navigator.h"
45 #include "chrome/browser/ui/browser_tabstrip.h"
46 #include "chrome/browser/ui/browser_ui_prefs.h"
47 #include "chrome/browser/ui/browser_window.h"
48 #include "chrome/browser/ui/extensions/app_launch_params.h"
49 #include "chrome/browser/ui/extensions/application_launch.h"
50 #include "chrome/browser/ui/host_desktop.h"
51 #include "chrome/browser/ui/startup/startup_browser_creator.h"
52 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
53 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
54 #include "chrome/browser/ui/tabs/tab_strip_model.h"
55 #include "chrome/common/chrome_switches.h"
56 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
57 #include "chrome/common/pref_names.h"
58 #include "chrome/common/url_constants.h"
59 #include "chrome/grit/chromium_strings.h"
60 #include "chrome/grit/generated_resources.h"
61 #include "chrome/test/base/in_process_browser_test.h"
62 #include "chrome/test/base/test_switches.h"
63 #include "chrome/test/base/ui_test_utils.h"
64 #include "components/app_modal/app_modal_dialog.h"
65 #include "components/app_modal/app_modal_dialog_queue.h"
66 #include "components/app_modal/javascript_app_modal_dialog.h"
67 #include "components/app_modal/native_app_modal_dialog.h"
68 #include "components/content_settings/core/browser/host_content_settings_map.h"
69 #include "components/sessions/base_session_service_test_helper.h"
70 #include "components/translate/core/browser/language_state.h"
71 #include "components/translate/core/common/language_detection_details.h"
72 #include "content/public/browser/favicon_status.h"
73 #include "content/public/browser/host_zoom_map.h"
74 #include "content/public/browser/interstitial_page.h"
75 #include "content/public/browser/interstitial_page_delegate.h"
76 #include "content/public/browser/navigation_entry.h"
77 #include "content/public/browser/notification_service.h"
78 #include "content/public/browser/render_frame_host.h"
79 #include "content/public/browser/render_process_host.h"
80 #include "content/public/browser/render_view_host.h"
81 #include "content/public/browser/render_widget_host_view.h"
82 #include "content/public/browser/resource_context.h"
83 #include "content/public/browser/security_style_explanation.h"
84 #include "content/public/browser/security_style_explanations.h"
85 #include "content/public/browser/web_contents.h"
86 #include "content/public/browser/web_contents_observer.h"
87 #include "content/public/common/frame_navigate_params.h"
88 #include "content/public/common/renderer_preferences.h"
89 #include "content/public/common/url_constants.h"
90 #include "content/public/test/browser_test_utils.h"
91 #include "content/public/test/test_navigation_observer.h"
92 #include "extensions/browser/extension_registry.h"
93 #include "extensions/browser/extension_system.h"
94 #include "extensions/browser/uninstall_reason.h"
95 #include "extensions/common/constants.h"
96 #include "extensions/common/extension.h"
97 #include "extensions/common/extension_set.h"
98 #include "net/base/net_errors.h"
99 #include "net/dns/mock_host_resolver.h"
100 #include "net/test/spawned_test_server/spawned_test_server.h"
101 #include "ui/base/l10n/l10n_util.h"
102 #include "ui/base/page_transition_types.h"
104 #if defined(OS_MACOSX)
105 #include "base/mac/mac_util.h"
106 #include "base/mac/scoped_nsautorelease_pool.h"
107 #include "chrome/browser/ui/cocoa/run_loop_testing.h"
108 #endif
110 #if defined(OS_WIN)
111 #include "base/i18n/rtl.h"
112 #include "chrome/browser/browser_process.h"
113 #endif
115 using app_modal::AppModalDialog;
116 using app_modal::AppModalDialogQueue;
117 using app_modal::JavaScriptAppModalDialog;
118 using base::ASCIIToUTF16;
119 using content::InterstitialPage;
120 using content::HostZoomMap;
121 using content::NavigationController;
122 using content::NavigationEntry;
123 using content::OpenURLParams;
124 using content::Referrer;
125 using content::WebContents;
126 using content::WebContentsObserver;
127 using extensions::Extension;
129 namespace {
131 enum CertificateStatus { VALID_CERTIFICATE, INVALID_CERTIFICATE };
133 const char* kBeforeUnloadHTML =
134 "<html><head><title>beforeunload</title></head><body>"
135 "<script>window.onbeforeunload=function(e){return 'foo'}</script>"
136 "</body></html>";
138 const char* kOpenNewBeforeUnloadPage =
139 "w=window.open(); w.onbeforeunload=function(e){return 'foo'};";
141 const base::FilePath::CharType* kBeforeUnloadFile =
142 FILE_PATH_LITERAL("beforeunload.html");
144 const base::FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html");
145 const base::FilePath::CharType* kTitle2File = FILE_PATH_LITERAL("title2.html");
147 const base::FilePath::CharType kDocRoot[] =
148 FILE_PATH_LITERAL("chrome/test/data");
150 // Given a page title, returns the expected window caption string.
151 base::string16 WindowCaptionFromPageTitle(const base::string16& page_title) {
152 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
153 // On Mac or ChromeOS, we don't want to suffix the page title with
154 // the application name.
155 if (page_title.empty())
156 return l10n_util::GetStringUTF16(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED);
157 return page_title;
158 #else
159 if (page_title.empty())
160 return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
162 return l10n_util::GetStringFUTF16(IDS_BROWSER_WINDOW_TITLE_FORMAT,
163 page_title);
164 #endif
167 // Returns the number of active RenderProcessHosts.
168 int CountRenderProcessHosts() {
169 int result = 0;
170 for (content::RenderProcessHost::iterator i(
171 content::RenderProcessHost::AllHostsIterator());
172 !i.IsAtEnd(); i.Advance())
173 ++result;
174 return result;
177 class MockTabStripModelObserver : public TabStripModelObserver {
178 public:
179 MockTabStripModelObserver() : closing_count_(0) {}
181 void TabClosingAt(TabStripModel* tab_strip_model,
182 WebContents* contents,
183 int index) override {
184 ++closing_count_;
187 int closing_count() const { return closing_count_; }
189 private:
190 int closing_count_;
192 DISALLOW_COPY_AND_ASSIGN(MockTabStripModelObserver);
195 // Causes the browser to swap processes on a redirect to an HTTPS URL.
196 class TransferHttpsRedirectsContentBrowserClient
197 : public chrome::ChromeContentBrowserClient {
198 public:
199 bool ShouldSwapProcessesForRedirect(
200 content::ResourceContext* resource_context,
201 const GURL& current_url,
202 const GURL& new_url) override {
203 return new_url.SchemeIs(url::kHttpsScheme);
207 // Used by CloseWithAppMenuOpen. Invokes CloseWindow on the supplied browser.
208 void CloseWindowCallback(Browser* browser) {
209 chrome::CloseWindow(browser);
212 // Used by CloseWithAppMenuOpen. Posts a CloseWindowCallback and shows the app
213 // menu.
214 void RunCloseWithAppMenuCallback(Browser* browser) {
215 // ShowAppMenu is modal under views. Schedule a task that closes the window.
216 base::MessageLoop::current()->task_runner()->PostTask(
217 FROM_HERE, base::Bind(&CloseWindowCallback, browser));
218 chrome::ShowAppMenu(browser);
221 // Displays "INTERSTITIAL" while the interstitial is attached.
222 // (InterstitialPage can be used in a test directly, but there would be no way
223 // to visually tell if it is showing or not.)
224 class TestInterstitialPage : public content::InterstitialPageDelegate {
225 public:
226 TestInterstitialPage(WebContents* tab, bool new_navigation, const GURL& url) {
227 interstitial_page_ = InterstitialPage::Create(
228 tab, new_navigation, url , this);
229 interstitial_page_->Show();
231 ~TestInterstitialPage() override {}
232 void Proceed() {
233 interstitial_page_->Proceed();
235 void DontProceed() {
236 interstitial_page_->DontProceed();
239 std::string GetHTMLContents() override { return "<h1>INTERSTITIAL</h1>"; }
241 private:
242 InterstitialPage* interstitial_page_; // Owns us.
245 class RenderViewSizeObserver : public content::WebContentsObserver {
246 public:
247 RenderViewSizeObserver(content::WebContents* web_contents,
248 BrowserWindow* browser_window)
249 : WebContentsObserver(web_contents),
250 browser_window_(browser_window) {
253 void GetSizeForRenderViewHost(
254 content::RenderViewHost* render_view_host,
255 gfx::Size* rwhv_create_size,
256 gfx::Size* rwhv_commit_size,
257 gfx::Size* wcv_commit_size) {
258 RenderViewSizes::const_iterator result = render_view_sizes_.end();
259 result = render_view_sizes_.find(render_view_host);
260 if (result != render_view_sizes_.end()) {
261 *rwhv_create_size = result->second.rwhv_create_size;
262 *rwhv_commit_size = result->second.rwhv_commit_size;
263 *wcv_commit_size = result->second.wcv_commit_size;
267 void set_wcv_resize_insets(const gfx::Size& wcv_resize_insets) {
268 wcv_resize_insets_ = wcv_resize_insets;
271 // Cache the size when RenderViewHost is first created.
272 void RenderViewCreated(content::RenderViewHost* render_view_host) override {
273 render_view_sizes_[render_view_host].rwhv_create_size =
274 render_view_host->GetView()->GetViewBounds().size();
277 // Enlarge WebContentsView by |wcv_resize_insets_| while the navigation entry
278 // is pending.
279 void DidStartNavigationToPendingEntry(
280 const GURL& url,
281 NavigationController::ReloadType reload_type) override {
282 if (wcv_resize_insets_.IsEmpty())
283 return;
284 // Resizing the main browser window by |wcv_resize_insets_| will
285 // automatically resize the WebContentsView by the same amount.
286 // Just resizing WebContentsView directly doesn't work on Linux, because the
287 // next automatic layout of the browser window will resize WebContentsView
288 // back to the previous size. To make it consistent, resize main browser
289 // window on all platforms.
290 gfx::Rect bounds(browser_window_->GetBounds());
291 gfx::Size size(bounds.size());
292 size.Enlarge(wcv_resize_insets_.width(), wcv_resize_insets_.height());
293 bounds.set_size(size);
294 browser_window_->SetBounds(bounds);
295 // Let the message loop run so that resize actually takes effect.
296 content::RunAllPendingInMessageLoop();
299 // Cache the sizes of RenderWidgetHostView and WebContentsView when the
300 // navigation entry is committed, which is before
301 // WebContentsDelegate::DidNavigateMainFramePostCommit is called.
302 void NavigationEntryCommitted(
303 const content::LoadCommittedDetails& details) override {
304 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
305 render_view_sizes_[rvh].rwhv_commit_size =
306 web_contents()->GetRenderWidgetHostView()->GetViewBounds().size();
307 render_view_sizes_[rvh].wcv_commit_size =
308 web_contents()->GetContainerBounds().size();
311 private:
312 struct Sizes {
313 gfx::Size rwhv_create_size; // Size of RenderWidgetHostView when created.
314 gfx::Size rwhv_commit_size; // Size of RenderWidgetHostView when committed.
315 gfx::Size wcv_commit_size; // Size of WebContentsView when committed.
318 typedef std::map<content::RenderViewHost*, Sizes> RenderViewSizes;
319 RenderViewSizes render_view_sizes_;
320 // Enlarge WebContentsView by this size insets in
321 // DidStartNavigationToPendingEntry.
322 gfx::Size wcv_resize_insets_;
323 BrowserWindow* browser_window_; // Weak ptr.
325 DISALLOW_COPY_AND_ASSIGN(RenderViewSizeObserver);
328 void ProceedThroughInterstitial(content::WebContents* web_contents) {
329 InterstitialPage* interstitial_page = web_contents->GetInterstitialPage();
330 ASSERT_TRUE(interstitial_page);
332 content::WindowedNotificationObserver observer(
333 content::NOTIFICATION_LOAD_STOP,
334 content::Source<NavigationController>(&web_contents->GetController()));
335 interstitial_page->Proceed();
336 observer.Wait();
339 bool GetFilePathWithHostAndPortReplacement(
340 const std::string& original_file_path,
341 const net::HostPortPair& host_port_pair,
342 std::string* replacement_path) {
343 std::vector<net::SpawnedTestServer::StringPair> replacement_text;
344 replacement_text.push_back(
345 make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString()));
346 return net::SpawnedTestServer::GetFilePathWithReplacements(
347 original_file_path, replacement_text, replacement_path);
350 // A WebContentsObserver useful for testing the SecurityStyleChanged()
351 // method: it keeps track of the latest security style and explanation
352 // that was fired.
353 class SecurityStyleTestObserver : public WebContentsObserver {
354 public:
355 explicit SecurityStyleTestObserver(content::WebContents* web_contents)
356 : content::WebContentsObserver(web_contents),
357 latest_security_style_(content::SECURITY_STYLE_UNKNOWN) {}
358 ~SecurityStyleTestObserver() override {}
360 void SecurityStyleChanged(content::SecurityStyle security_style,
361 const content::SecurityStyleExplanations&
362 security_style_explanations) override {
363 latest_security_style_ = security_style;
364 latest_explanations_ = security_style_explanations;
367 content::SecurityStyle latest_security_style() const {
368 return latest_security_style_;
371 const content::SecurityStyleExplanations& latest_explanations() const {
372 return latest_explanations_;
375 void ClearLatestSecurityStyleAndExplanations() {
376 latest_security_style_ = content::SECURITY_STYLE_UNKNOWN;
377 latest_explanations_ = content::SecurityStyleExplanations();
380 private:
381 content::SecurityStyle latest_security_style_;
382 content::SecurityStyleExplanations latest_explanations_;
384 DISALLOW_COPY_AND_ASSIGN(SecurityStyleTestObserver);
387 // Check that |observer|'s latest event was for an expired certificate
388 // and that it saw the proper SecurityStyle and explanations.
389 void CheckBrokenSecurityStyle(const SecurityStyleTestObserver& observer,
390 int error) {
391 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN,
392 observer.latest_security_style());
394 const content::SecurityStyleExplanations& expired_explanation =
395 observer.latest_explanations();
396 EXPECT_EQ(0u, expired_explanation.warning_explanations.size());
397 ASSERT_EQ(1u, expired_explanation.broken_explanations.size());
399 // Check that the summary and description are as expected.
400 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_CERTIFICATE_CHAIN_ERROR),
401 expired_explanation.broken_explanations[0].summary);
403 base::string16 error_string = base::UTF8ToUTF16(net::ErrorToString(error));
404 EXPECT_EQ(l10n_util::GetStringFUTF8(
405 IDS_CERTIFICATE_CHAIN_ERROR_DESCRIPTION_FORMAT, error_string),
406 expired_explanation.broken_explanations[0].description);
409 // Checks that the given |secure_explanations| contains appropriate
410 // an appropriate explanation if the certificate status is valid.
411 void CheckSecureExplanations(
412 const std::vector<content::SecurityStyleExplanation>& secure_explanations,
413 CertificateStatus cert_status) {
414 if (cert_status != VALID_CERTIFICATE) {
415 EXPECT_EQ(0u, secure_explanations.size());
416 return;
419 EXPECT_EQ(1u, secure_explanations.size());
420 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE),
421 secure_explanations[0].summary);
422 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE_DESCRIPTION),
423 secure_explanations[0].description);
426 } // namespace
428 class BrowserTest : public ExtensionBrowserTest {
429 protected:
430 // In RTL locales wrap the page title with RTL embedding characters so that it
431 // matches the value returned by GetWindowTitle().
432 base::string16 LocaleWindowCaptionFromPageTitle(
433 const base::string16& expected_title) {
434 base::string16 page_title = WindowCaptionFromPageTitle(expected_title);
435 #if defined(OS_WIN)
436 std::string locale = g_browser_process->GetApplicationLocale();
437 if (base::i18n::GetTextDirectionForLocale(locale.c_str()) ==
438 base::i18n::RIGHT_TO_LEFT) {
439 base::i18n::WrapStringWithLTRFormatting(&page_title);
442 return page_title;
443 #else
444 // Do we need to use the above code on POSIX as well?
445 return page_title;
446 #endif
449 // Returns the app extension aptly named "App Test".
450 const Extension* GetExtension() {
451 extensions::ExtensionRegistry* registry =
452 extensions::ExtensionRegistry::Get(browser()->profile());
453 for (const scoped_refptr<const extensions::Extension>& extension :
454 registry->enabled_extensions()) {
455 if (extension->name() == "App Test")
456 return extension.get();
458 NOTREACHED();
459 return NULL;
463 // Launch the app on a page with no title, check that the app title was set
464 // correctly.
465 IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) {
466 #if defined(OS_WIN) && defined(USE_ASH)
467 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
468 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
469 switches::kAshBrowserTests))
470 return;
471 #endif
473 ui_test_utils::NavigateToURL(
474 browser(), ui_test_utils::GetTestUrl(
475 base::FilePath(base::FilePath::kCurrentDirectory),
476 base::FilePath(kTitle1File)));
477 EXPECT_EQ(LocaleWindowCaptionFromPageTitle(ASCIIToUTF16("title1.html")),
478 browser()->GetWindowTitleForCurrentTab());
479 base::string16 tab_title;
480 ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
481 EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title);
484 // Check that a file:// URL displays the filename, but no path, with any ref or
485 // query parameters following it if the content does not have a <title> tag.
486 // Specifically verify the cases where the ref or query parameters have a '/'
487 // character in them. This is a regression test for
488 // https://crbug.com/503003.
489 IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitleFileUrl) {
490 #if defined(OS_WIN) && defined(USE_ASH)
491 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
492 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
493 switches::kAshBrowserTests))
494 return;
495 #endif
497 // Note that the host names used and the order of these cases are by design.
498 // There must be unique query parameters and references per case (i.e. the
499 // indexed foo*.com hosts) because if the same query parameter is repeated in
500 // a row, then the navigation may not actually happen, as it will only appear
501 // as a reference change. Additionally, cases with references first must
502 // appear after a query parameter case since otherwise it will not be a
503 // navigation.
504 struct {
505 std::string suffix;
506 std::string message;
507 } cases[]{
508 {"#https://foo1.com", "file:/// URL with slash in ref"},
509 {"?x=https://foo2.com", "file:/// URL with slash in query parameter"},
510 {"?x=https://foo3.com#https://foo3.com",
511 "file:/// URL with slashes in query parameter and ref"},
512 {"#https://foo4.com?x=https://foo4.com",
513 "file:/// URL with slashes in ref and query parameter"},
514 {"?x=https://foo6.com?x=https://foo6.com",
515 "file:/// URL with slashes in multiple query parameter"},
516 {"#https://foo5.com#https://foo5.com",
517 "file:/// URL with slashes in multiple refs"}};
519 GURL prefix_url = ui_test_utils::GetTestUrl(
520 base::FilePath(base::FilePath::kCurrentDirectory),
521 base::FilePath(kTitle1File));
522 base::string16 tab_title;
523 base::string16 test_title;
524 for (const auto& c : cases) {
525 SCOPED_TRACE(c.message);
526 GURL url(prefix_url.spec() + c.suffix);
527 test_title = ASCIIToUTF16("title1.html" + c.suffix);
528 content::TitleWatcher title_watcher(
529 browser()->tab_strip_model()->GetActiveWebContents(), test_title);
530 ui_test_utils::NavigateToURL(browser(), url);
531 EXPECT_EQ(test_title, title_watcher.WaitAndGetTitle());
535 // Launch the app, navigate to a page with a title, check that the app title
536 // was set correctly.
537 IN_PROC_BROWSER_TEST_F(BrowserTest, Title) {
538 #if defined(OS_WIN) && defined(USE_ASH)
539 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
540 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
541 switches::kAshBrowserTests))
542 return;
543 #endif
545 ui_test_utils::NavigateToURL(
546 browser(), ui_test_utils::GetTestUrl(
547 base::FilePath(base::FilePath::kCurrentDirectory),
548 base::FilePath(kTitle2File)));
549 const base::string16 test_title(ASCIIToUTF16("Title Of Awesomeness"));
550 EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title),
551 browser()->GetWindowTitleForCurrentTab());
552 base::string16 tab_title;
553 ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
554 EXPECT_EQ(test_title, tab_title);
557 IN_PROC_BROWSER_TEST_F(BrowserTest, JavascriptAlertActivatesTab) {
558 GURL url(ui_test_utils::GetTestUrl(base::FilePath(
559 base::FilePath::kCurrentDirectory), base::FilePath(kTitle1File)));
560 ui_test_utils::NavigateToURL(browser(), url);
561 AddTabAtIndex(0, url, ui::PAGE_TRANSITION_TYPED);
562 EXPECT_EQ(2, browser()->tab_strip_model()->count());
563 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
564 WebContents* second_tab = browser()->tab_strip_model()->GetWebContentsAt(1);
565 ASSERT_TRUE(second_tab);
566 second_tab->GetMainFrame()->ExecuteJavaScriptForTests(
567 ASCIIToUTF16("alert('Activate!');"));
568 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
569 alert->CloseModalDialog();
570 EXPECT_EQ(2, browser()->tab_strip_model()->count());
571 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
575 #if defined(OS_WIN) && !defined(NDEBUG)
576 // http://crbug.com/114859. Times out frequently on Windows.
577 #define MAYBE_ThirtyFourTabs DISABLED_ThirtyFourTabs
578 #else
579 #define MAYBE_ThirtyFourTabs ThirtyFourTabs
580 #endif
582 // Create 34 tabs and verify that a lot of processes have been created. The
583 // exact number of processes depends on the amount of memory. Previously we
584 // had a hard limit of 31 processes and this test is mainly directed at
585 // verifying that we don't crash when we pass this limit.
586 // Warning: this test can take >30 seconds when running on a slow (low
587 // memory?) Mac builder.
588 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_ThirtyFourTabs) {
589 GURL url(ui_test_utils::GetTestUrl(base::FilePath(
590 base::FilePath::kCurrentDirectory), base::FilePath(kTitle2File)));
592 // There is one initial tab.
593 const int kTabCount = 34;
594 for (int ix = 0; ix != (kTabCount - 1); ++ix) {
595 chrome::AddSelectedTabWithURL(browser(), url,
596 ui::PAGE_TRANSITION_TYPED);
598 EXPECT_EQ(kTabCount, browser()->tab_strip_model()->count());
600 // See GetMaxRendererProcessCount() in
601 // content/browser/renderer_host/render_process_host_impl.cc
602 // for the algorithm to decide how many processes to create.
603 const int kExpectedProcessCount =
604 #if defined(ARCH_CPU_64_BITS)
606 #else
608 #endif
609 if (base::SysInfo::AmountOfPhysicalMemoryMB() >= 2048) {
610 EXPECT_GE(CountRenderProcessHosts(), kExpectedProcessCount);
611 } else {
612 EXPECT_LT(CountRenderProcessHosts(), kExpectedProcessCount);
616 // Test that a browser-initiated navigation to an aborted URL load leaves around
617 // a pending entry if we start from the NTP but not from a normal page.
618 // See http://crbug.com/355537.
619 IN_PROC_BROWSER_TEST_F(BrowserTest, ClearPendingOnFailUnlessNTP) {
620 ASSERT_TRUE(test_server()->Start());
621 WebContents* web_contents =
622 browser()->tab_strip_model()->GetActiveWebContents();
623 GURL ntp_url(search::GetNewTabPageURL(browser()->profile()));
624 ui_test_utils::NavigateToURL(browser(), ntp_url);
626 // Navigate to a 204 URL (aborts with no content) on the NTP and make sure it
627 // sticks around so that the user can edit it.
628 GURL abort_url(test_server()->GetURL("nocontent"));
630 content::WindowedNotificationObserver stop_observer(
631 content::NOTIFICATION_LOAD_STOP,
632 content::Source<NavigationController>(
633 &web_contents->GetController()));
634 browser()->OpenURL(OpenURLParams(abort_url, Referrer(), CURRENT_TAB,
635 ui::PAGE_TRANSITION_TYPED, false));
636 stop_observer.Wait();
637 EXPECT_TRUE(web_contents->GetController().GetPendingEntry());
638 EXPECT_EQ(abort_url, web_contents->GetVisibleURL());
641 // Navigate to a real URL.
642 GURL real_url(test_server()->GetURL("title1.html"));
643 ui_test_utils::NavigateToURL(browser(), real_url);
644 EXPECT_EQ(real_url, web_contents->GetVisibleURL());
646 // Now navigating to a 204 URL should clear the pending entry.
648 content::WindowedNotificationObserver stop_observer(
649 content::NOTIFICATION_LOAD_STOP,
650 content::Source<NavigationController>(
651 &web_contents->GetController()));
652 browser()->OpenURL(OpenURLParams(abort_url, Referrer(), CURRENT_TAB,
653 ui::PAGE_TRANSITION_TYPED, false));
654 stop_observer.Wait();
655 EXPECT_FALSE(web_contents->GetController().GetPendingEntry());
656 EXPECT_EQ(real_url, web_contents->GetVisibleURL());
660 // Test for crbug.com/297289. Ensure that modal dialogs are closed when a
661 // cross-process navigation is ready to commit.
662 // Flaky test, see https://crbug.com/445155.
663 IN_PROC_BROWSER_TEST_F(BrowserTest, DISABLED_CrossProcessNavCancelsDialogs) {
664 ASSERT_TRUE(test_server()->Start());
665 host_resolver()->AddRule("www.example.com", "127.0.0.1");
666 GURL url(test_server()->GetURL("empty.html"));
667 ui_test_utils::NavigateToURL(browser(), url);
669 // Test this with multiple alert dialogs to ensure that we can navigate away
670 // even if the renderer tries to synchronously create more.
671 // See http://crbug.com/312490.
672 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
673 contents->GetMainFrame()->ExecuteJavaScriptForTests(
674 ASCIIToUTF16("alert('one'); alert('two');"));
675 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
676 EXPECT_TRUE(alert->IsValid());
677 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
678 EXPECT_TRUE(dialog_queue->HasActiveDialog());
680 // A cross-site navigation should force the dialog to close.
681 GURL url2("http://www.example.com/empty.html");
682 ui_test_utils::NavigateToURL(browser(), url2);
683 EXPECT_FALSE(dialog_queue->HasActiveDialog());
685 // Make sure input events still work in the renderer process.
686 EXPECT_FALSE(contents->GetRenderProcessHost()->IgnoreInputEvents());
689 // Make sure that dialogs are closed after a renderer process dies, and that
690 // subsequent navigations work. See http://crbug/com/343265.
691 IN_PROC_BROWSER_TEST_F(BrowserTest, SadTabCancelsDialogs) {
692 ASSERT_TRUE(test_server()->Start());
693 host_resolver()->AddRule("www.example.com", "127.0.0.1");
694 GURL beforeunload_url(test_server()->GetURL("files/beforeunload.html"));
695 ui_test_utils::NavigateToURL(browser(), beforeunload_url);
697 // Start a navigation to trigger the beforeunload dialog.
698 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
699 contents->GetMainFrame()->ExecuteJavaScriptForTests(
700 ASCIIToUTF16("window.location.href = 'data:text/html,foo'"));
701 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
702 EXPECT_TRUE(alert->IsValid());
703 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
704 EXPECT_TRUE(dialog_queue->HasActiveDialog());
706 // Crash the renderer process and ensure the dialog is gone.
707 content::RenderProcessHost* child_process = contents->GetRenderProcessHost();
708 content::RenderProcessHostWatcher crash_observer(
709 child_process,
710 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
711 child_process->Shutdown(0, false);
712 crash_observer.Wait();
713 EXPECT_FALSE(dialog_queue->HasActiveDialog());
715 // Make sure subsequent navigations work.
716 GURL url2("http://www.example.com/files/empty.html");
717 ui_test_utils::NavigateToURL(browser(), url2);
720 // Make sure that dialogs opened by subframes are closed when the process dies.
721 // See http://crbug.com/366510.
722 IN_PROC_BROWSER_TEST_F(BrowserTest, SadTabCancelsSubframeDialogs) {
723 // Navigate to an iframe that opens an alert dialog.
724 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
725 contents->GetMainFrame()->ExecuteJavaScriptForTests(
726 ASCIIToUTF16("window.location.href = 'data:text/html,"
727 "<iframe srcdoc=\"<script>alert(1)</script>\">'"));
728 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
729 EXPECT_TRUE(alert->IsValid());
730 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
731 EXPECT_TRUE(dialog_queue->HasActiveDialog());
733 // Crash the renderer process and ensure the dialog is gone.
734 content::RenderProcessHost* child_process = contents->GetRenderProcessHost();
735 content::RenderProcessHostWatcher crash_observer(
736 child_process,
737 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
738 child_process->Shutdown(0, false);
739 crash_observer.Wait();
740 EXPECT_FALSE(dialog_queue->HasActiveDialog());
742 // Make sure subsequent navigations work.
743 GURL url2("data:text/html,foo");
744 ui_test_utils::NavigateToURL(browser(), url2);
747 // Make sure modal dialogs within a guestview are closed when an interstitial
748 // page is showing. See crbug.com/482380.
749 IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialCancelsGuestViewDialogs) {
750 // Navigate to a PDF, which is loaded within a guestview.
751 ASSERT_TRUE(test_server()->Start());
752 GURL pdf_with_dialog(test_server()->GetURL("files/alert_dialog.pdf"));
753 ui_test_utils::NavigateToURL(browser(), pdf_with_dialog);
755 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
756 EXPECT_TRUE(alert->IsValid());
757 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
758 EXPECT_TRUE(dialog_queue->HasActiveDialog());
760 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
762 TestInterstitialPage* interstitial =
763 new TestInterstitialPage(contents, false, GURL());
764 content::WaitForInterstitialAttach(contents);
766 // The interstitial should have closed the dialog.
767 EXPECT_TRUE(contents->ShowingInterstitialPage());
768 EXPECT_FALSE(dialog_queue->HasActiveDialog());
770 interstitial->DontProceed();
773 // Test for crbug.com/22004. Reloading a page with a before unload handler and
774 // then canceling the dialog should not leave the throbber spinning.
775 IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) {
776 GURL url(std::string("data:text/html,") + kBeforeUnloadHTML);
777 ui_test_utils::NavigateToURL(browser(), url);
779 // Navigate to another page, but click cancel in the dialog. Make sure that
780 // the throbber stops spinning.
781 chrome::Reload(browser(), CURRENT_TAB);
782 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
783 alert->CloseModalDialog();
784 EXPECT_FALSE(
785 browser()->tab_strip_model()->GetActiveWebContents()->IsLoading());
787 // Clear the beforeunload handler so the test can easily exit.
788 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()->
789 ExecuteJavaScriptForTests(ASCIIToUTF16("onbeforeunload=null;"));
792 class RedirectObserver : public content::WebContentsObserver {
793 public:
794 explicit RedirectObserver(content::WebContents* web_contents)
795 : WebContentsObserver(web_contents) {
798 void DidNavigateAnyFrame(
799 content::RenderFrameHost* render_frame_host,
800 const content::LoadCommittedDetails& details,
801 const content::FrameNavigateParams& params) override {
802 params_ = params;
805 void WebContentsDestroyed() override {
806 // Make sure we don't close the tab while the observer is in scope.
807 // See http://crbug.com/314036.
808 FAIL() << "WebContents closed during navigation (http://crbug.com/314036).";
811 const content::FrameNavigateParams& params() const {
812 return params_;
815 private:
816 content::FrameNavigateParams params_;
818 DISALLOW_COPY_AND_ASSIGN(RedirectObserver);
821 // Ensure that a transferred cross-process navigation does not generate
822 // DidStopLoading events until the navigation commits. If it did, then
823 // ui_test_utils::NavigateToURL would proceed before the URL had committed.
824 // http://crbug.com/243957.
825 IN_PROC_BROWSER_TEST_F(BrowserTest, NoStopDuringTransferUntilCommit) {
826 // Create HTTP and HTTPS servers for a cross-site transition.
827 ASSERT_TRUE(test_server()->Start());
828 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
829 net::SpawnedTestServer::kLocalhost,
830 base::FilePath(kDocRoot));
831 ASSERT_TRUE(https_test_server.Start());
833 // Temporarily replace ContentBrowserClient with one that will cause a
834 // process swap on all redirects to HTTPS URLs.
835 TransferHttpsRedirectsContentBrowserClient new_client;
836 content::ContentBrowserClient* old_client =
837 SetBrowserClientForTesting(&new_client);
839 GURL init_url(test_server()->GetURL("files/title1.html"));
840 ui_test_utils::NavigateToURL(browser(), init_url);
842 // Navigate to a same-site page that redirects, causing a transfer.
843 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
845 // Create a RedirectObserver that goes away before we close the tab.
847 RedirectObserver redirect_observer(contents);
848 GURL dest_url(https_test_server.GetURL("files/title2.html"));
849 GURL redirect_url(test_server()->GetURL("server-redirect?" +
850 dest_url.spec()));
851 ui_test_utils::NavigateToURL(browser(), redirect_url);
853 // We should immediately see the new committed entry.
854 EXPECT_FALSE(contents->GetController().GetPendingEntry());
855 EXPECT_EQ(dest_url,
856 contents->GetController().GetLastCommittedEntry()->GetURL());
858 // We should keep track of the original request URL, redirect chain, and
859 // page transition type during a transfer, since these are necessary for
860 // history autocomplete to work.
861 EXPECT_EQ(redirect_url, contents->GetController().GetLastCommittedEntry()->
862 GetOriginalRequestURL());
863 EXPECT_EQ(2U, redirect_observer.params().redirects.size());
864 EXPECT_EQ(redirect_url, redirect_observer.params().redirects.at(0));
865 EXPECT_EQ(dest_url, redirect_observer.params().redirects.at(1));
866 EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
867 redirect_observer.params().transition, ui::PAGE_TRANSITION_TYPED));
870 // Restore previous browser client.
871 SetBrowserClientForTesting(old_client);
874 // Tests that a cross-process redirect will only cause the beforeunload
875 // handler to run once.
876 IN_PROC_BROWSER_TEST_F(BrowserTest, SingleBeforeUnloadAfterRedirect) {
877 // Create HTTP and HTTPS servers for a cross-site transition.
878 ASSERT_TRUE(test_server()->Start());
879 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
880 net::SpawnedTestServer::kLocalhost,
881 base::FilePath(kDocRoot));
882 ASSERT_TRUE(https_test_server.Start());
884 // Temporarily replace ContentBrowserClient with one that will cause a
885 // process swap on all redirects to HTTPS URLs.
886 TransferHttpsRedirectsContentBrowserClient new_client;
887 content::ContentBrowserClient* old_client =
888 SetBrowserClientForTesting(&new_client);
890 // Navigate to a page with a beforeunload handler.
891 GURL url(test_server()->GetURL("files/beforeunload.html"));
892 ui_test_utils::NavigateToURL(browser(), url);
894 // Navigate to a URL that redirects to another process and approve the
895 // beforeunload dialog that pops up.
896 content::WindowedNotificationObserver nav_observer(
897 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
898 content::NotificationService::AllSources());
899 GURL https_url(https_test_server.GetURL("files/title1.html"));
900 GURL redirect_url(test_server()->GetURL("server-redirect?" +
901 https_url.spec()));
902 browser()->OpenURL(OpenURLParams(redirect_url, Referrer(), CURRENT_TAB,
903 ui::PAGE_TRANSITION_TYPED, false));
904 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
905 EXPECT_TRUE(
906 static_cast<JavaScriptAppModalDialog*>(alert)->is_before_unload_dialog());
907 alert->native_dialog()->AcceptAppModalDialog();
908 nav_observer.Wait();
910 // Restore previous browser client.
911 SetBrowserClientForTesting(old_client);
914 // Test for crbug.com/80401. Canceling a before unload dialog should reset
915 // the URL to the previous page's URL.
916 IN_PROC_BROWSER_TEST_F(BrowserTest, CancelBeforeUnloadResetsURL) {
917 GURL url(ui_test_utils::GetTestUrl(base::FilePath(
918 base::FilePath::kCurrentDirectory), base::FilePath(kBeforeUnloadFile)));
919 ui_test_utils::NavigateToURL(browser(), url);
921 // Navigate to a page that triggers a cross-site transition.
922 ASSERT_TRUE(test_server()->Start());
923 GURL url2(test_server()->GetURL("files/title1.html"));
924 browser()->OpenURL(OpenURLParams(
925 url2, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
927 content::WindowedNotificationObserver host_destroyed_observer(
928 content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
929 content::NotificationService::AllSources());
931 // Cancel the dialog.
932 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
933 alert->CloseModalDialog();
934 EXPECT_FALSE(
935 browser()->tab_strip_model()->GetActiveWebContents()->IsLoading());
937 // Verify there are no pending history items after the dialog is cancelled.
938 // (see crbug.com/93858)
939 NavigationEntry* entry = browser()->tab_strip_model()->
940 GetActiveWebContents()->GetController().GetPendingEntry();
941 EXPECT_EQ(NULL, entry);
943 // Wait for the ShouldClose_ACK to arrive. We can detect it by waiting for
944 // the pending RVH to be destroyed.
945 host_destroyed_observer.Wait();
946 EXPECT_EQ(url, browser()->toolbar_model()->GetURL());
948 // Clear the beforeunload handler so the test can easily exit.
949 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()->
950 ExecuteJavaScriptForTests(ASCIIToUTF16("onbeforeunload=null;"));
953 // Test for crbug.com/11647. A page closed with window.close() should not have
954 // two beforeunload dialogs shown.
955 // http://crbug.com/410891
956 IN_PROC_BROWSER_TEST_F(BrowserTest,
957 DISABLED_SingleBeforeUnloadAfterWindowClose) {
958 browser()
959 ->tab_strip_model()
960 ->GetActiveWebContents()
961 ->GetMainFrame()
962 ->ExecuteJavaScriptWithUserGestureForTests(
963 ASCIIToUTF16(kOpenNewBeforeUnloadPage));
965 // Close the new window with JavaScript, which should show a single
966 // beforeunload dialog. Then show another alert, to make it easy to verify
967 // that a second beforeunload dialog isn't shown.
968 browser()
969 ->tab_strip_model()
970 ->GetWebContentsAt(0)
971 ->GetMainFrame()
972 ->ExecuteJavaScriptWithUserGestureForTests(
973 ASCIIToUTF16("w.close(); alert('bar');"));
974 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
975 alert->native_dialog()->AcceptAppModalDialog();
977 alert = ui_test_utils::WaitForAppModalDialog();
978 EXPECT_FALSE(static_cast<JavaScriptAppModalDialog*>(alert)->
979 is_before_unload_dialog());
980 alert->native_dialog()->AcceptAppModalDialog();
983 // BrowserTest.BeforeUnloadVsBeforeReload times out on Windows.
984 // http://crbug.com/130411
985 #if defined(OS_WIN)
986 #define MAYBE_BeforeUnloadVsBeforeReload DISABLED_BeforeUnloadVsBeforeReload
987 #else
988 #define MAYBE_BeforeUnloadVsBeforeReload BeforeUnloadVsBeforeReload
989 #endif
991 // Test that when a page has an onunload handler, reloading a page shows a
992 // different dialog than navigating to a different page.
993 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_BeforeUnloadVsBeforeReload) {
994 GURL url(std::string("data:text/html,") + kBeforeUnloadHTML);
995 ui_test_utils::NavigateToURL(browser(), url);
997 // Reload the page, and check that we get a "before reload" dialog.
998 chrome::Reload(browser(), CURRENT_TAB);
999 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
1000 EXPECT_TRUE(static_cast<JavaScriptAppModalDialog*>(alert)->is_reload());
1002 // Cancel the reload.
1003 alert->native_dialog()->CancelAppModalDialog();
1005 // Navigate to another url, and check that we get a "before unload" dialog.
1006 GURL url2(url::kAboutBlankURL);
1007 browser()->OpenURL(OpenURLParams(
1008 url2, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
1010 alert = ui_test_utils::WaitForAppModalDialog();
1011 EXPECT_FALSE(static_cast<JavaScriptAppModalDialog*>(alert)->is_reload());
1013 // Accept the navigation so we end up on a page without a beforeunload hook.
1014 alert->native_dialog()->AcceptAppModalDialog();
1017 // BeforeUnloadAtQuitWithTwoWindows is a regression test for
1018 // http://crbug.com/11842. It opens two windows, one of which has a
1019 // beforeunload handler and attempts to exit cleanly.
1020 class BeforeUnloadAtQuitWithTwoWindows : public InProcessBrowserTest {
1021 public:
1022 // This test is for testing a specific shutdown behavior. This mimics what
1023 // happens in InProcessBrowserTest::RunTestOnMainThread and QuitBrowsers, but
1024 // ensures that it happens through the single IDC_EXIT of the test.
1025 void TearDownOnMainThread() override {
1026 // Cycle both the MessageLoop and the Cocoa runloop twice to flush out any
1027 // Chrome work that generates Cocoa work. Do this twice since there are two
1028 // Browsers that must be closed.
1029 CycleRunLoops();
1030 CycleRunLoops();
1032 // Run the application event loop to completion, which will cycle the
1033 // native MessagePump on all platforms.
1034 base::MessageLoop::current()->task_runner()->PostTask(
1035 FROM_HERE, base::MessageLoop::QuitClosure());
1036 base::MessageLoop::current()->Run();
1038 // Take care of any remaining Cocoa work.
1039 CycleRunLoops();
1041 // At this point, quit should be for real now.
1042 ASSERT_EQ(0u, chrome::GetTotalBrowserCount());
1045 // A helper function that cycles the MessageLoop, and on Mac, the Cocoa run
1046 // loop. It also drains the NSAutoreleasePool.
1047 void CycleRunLoops() {
1048 content::RunAllPendingInMessageLoop();
1049 #if defined(OS_MACOSX)
1050 chrome::testing::NSRunLoopRunAllPending();
1051 AutoreleasePool()->Recycle();
1052 #endif
1056 // Disabled, http://crbug.com/159214 .
1057 IN_PROC_BROWSER_TEST_F(BeforeUnloadAtQuitWithTwoWindows,
1058 DISABLED_IfThisTestTimesOutItIndicatesFAILURE) {
1059 // In the first browser, set up a page that has a beforeunload handler.
1060 GURL url(std::string("data:text/html,") + kBeforeUnloadHTML);
1061 ui_test_utils::NavigateToURL(browser(), url);
1063 // Open a second browser window at about:blank.
1064 ui_test_utils::BrowserAddedObserver browser_added_observer;
1065 chrome::NewEmptyWindow(browser()->profile(), chrome::GetActiveDesktop());
1066 Browser* second_window = browser_added_observer.WaitForSingleNewBrowser();
1067 ui_test_utils::NavigateToURL(second_window, GURL(url::kAboutBlankURL));
1069 // Tell the application to quit. IDC_EXIT calls AttemptUserExit, which on
1070 // everything but ChromeOS allows unload handlers to block exit. On that
1071 // platform, though, it exits unconditionally. See the comment and bug ID
1072 // in AttemptUserExit() in application_lifetime.cc.
1073 #if defined(OS_CHROMEOS)
1074 chrome::AttemptExit();
1075 #else
1076 chrome::ExecuteCommand(second_window, IDC_EXIT);
1077 #endif
1079 // The beforeunload handler will run at exit, ensure it does, and then accept
1080 // it to allow shutdown to proceed.
1081 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
1082 ASSERT_TRUE(alert);
1083 EXPECT_TRUE(
1084 static_cast<JavaScriptAppModalDialog*>(alert)->is_before_unload_dialog());
1085 alert->native_dialog()->AcceptAppModalDialog();
1087 // But wait there's more! If this test times out, it likely means that the
1088 // browser has not been able to quit correctly, indicating there's a
1089 // regression of the bug noted above.
1092 // Test that scripts can fork a new renderer process for a cross-site popup,
1093 // based on http://www.google.com/chrome/intl/en/webmasters-faq.html#newtab.
1094 // The script must open a new tab, set its window.opener to null, and navigate
1095 // it to a cross-site URL. It should also work for meta-refreshes.
1096 // See http://crbug.com/93517.
1097 IN_PROC_BROWSER_TEST_F(BrowserTest, NullOpenerRedirectForksProcess) {
1098 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1099 switches::kDisablePopupBlocking);
1101 // Create http and https servers for a cross-site transition.
1102 ASSERT_TRUE(test_server()->Start());
1103 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
1104 net::SpawnedTestServer::kLocalhost,
1105 base::FilePath(kDocRoot));
1106 ASSERT_TRUE(https_test_server.Start());
1107 GURL http_url(test_server()->GetURL("files/title1.html"));
1108 GURL https_url(https_test_server.GetURL(std::string()));
1110 // Start with an http URL.
1111 ui_test_utils::NavigateToURL(browser(), http_url);
1112 WebContents* oldtab = browser()->tab_strip_model()->GetActiveWebContents();
1113 content::RenderProcessHost* process = oldtab->GetRenderProcessHost();
1115 // Now open a tab to a blank page, set its opener to null, and redirect it
1116 // cross-site.
1117 std::string redirect_popup = "w=window.open();";
1118 redirect_popup += "w.opener=null;";
1119 redirect_popup += "w.document.location=\"";
1120 redirect_popup += https_url.spec();
1121 redirect_popup += "\";";
1123 content::WindowedNotificationObserver popup_observer(
1124 chrome::NOTIFICATION_TAB_ADDED,
1125 content::NotificationService::AllSources());
1126 content::WindowedNotificationObserver nav_observer(
1127 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
1128 content::NotificationService::AllSources());
1129 oldtab->GetMainFrame()->
1130 ExecuteJavaScriptWithUserGestureForTests(ASCIIToUTF16(redirect_popup));
1132 // Wait for popup window to appear and finish navigating.
1133 popup_observer.Wait();
1134 ASSERT_EQ(2, browser()->tab_strip_model()->count());
1135 WebContents* newtab = browser()->tab_strip_model()->GetActiveWebContents();
1136 EXPECT_TRUE(newtab);
1137 EXPECT_NE(oldtab, newtab);
1138 nav_observer.Wait();
1139 ASSERT_TRUE(newtab->GetController().GetLastCommittedEntry());
1140 EXPECT_EQ(https_url.spec(),
1141 newtab->GetController().GetLastCommittedEntry()->GetURL().spec());
1143 // Popup window should not be in the opener's process.
1144 content::RenderProcessHost* popup_process =
1145 newtab->GetRenderProcessHost();
1146 EXPECT_NE(process, popup_process);
1148 // Now open a tab to a blank page, set its opener to null, and use a
1149 // meta-refresh to navigate it instead.
1150 std::string refresh_popup = "w=window.open();";
1151 refresh_popup += "w.opener=null;";
1152 refresh_popup += "w.document.write(";
1153 refresh_popup += "'<META HTTP-EQUIV=\"refresh\" content=\"0; url=";
1154 refresh_popup += https_url.spec();
1155 refresh_popup += "\">');w.document.close();";
1157 content::WindowedNotificationObserver popup_observer2(
1158 chrome::NOTIFICATION_TAB_ADDED,
1159 content::NotificationService::AllSources());
1160 content::WindowedNotificationObserver nav_observer2(
1161 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
1162 content::NotificationService::AllSources());
1163 oldtab->GetMainFrame()->
1164 ExecuteJavaScriptWithUserGestureForTests(ASCIIToUTF16(refresh_popup));
1166 // Wait for popup window to appear and finish navigating.
1167 popup_observer2.Wait();
1168 ASSERT_EQ(3, browser()->tab_strip_model()->count());
1169 WebContents* newtab2 = browser()->tab_strip_model()->GetActiveWebContents();
1170 EXPECT_TRUE(newtab2);
1171 EXPECT_NE(oldtab, newtab2);
1172 nav_observer2.Wait();
1173 ASSERT_TRUE(newtab2->GetController().GetLastCommittedEntry());
1174 EXPECT_EQ(https_url.spec(),
1175 newtab2->GetController().GetLastCommittedEntry()->GetURL().spec());
1177 // This popup window should also not be in the opener's process.
1178 content::RenderProcessHost* popup_process2 =
1179 newtab2->GetRenderProcessHost();
1180 EXPECT_NE(process, popup_process2);
1183 // Tests that other popup navigations that do not follow the steps at
1184 // http://www.google.com/chrome/intl/en/webmasters-faq.html#newtab will not
1185 // fork a new renderer process.
1186 IN_PROC_BROWSER_TEST_F(BrowserTest, OtherRedirectsDontForkProcess) {
1187 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1188 switches::kDisablePopupBlocking);
1190 // Create http and https servers for a cross-site transition.
1191 ASSERT_TRUE(test_server()->Start());
1192 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
1193 net::SpawnedTestServer::kLocalhost,
1194 base::FilePath(kDocRoot));
1195 ASSERT_TRUE(https_test_server.Start());
1196 GURL http_url(test_server()->GetURL("files/title1.html"));
1197 GURL https_url(https_test_server.GetURL(std::string()));
1199 // Start with an http URL.
1200 ui_test_utils::NavigateToURL(browser(), http_url);
1201 WebContents* oldtab = browser()->tab_strip_model()->GetActiveWebContents();
1202 content::RenderProcessHost* process = oldtab->GetRenderProcessHost();
1204 // Now open a tab to a blank page, set its opener to null, and redirect it
1205 // cross-site.
1206 std::string dont_fork_popup = "w=window.open();";
1207 dont_fork_popup += "w.document.location=\"";
1208 dont_fork_popup += https_url.spec();
1209 dont_fork_popup += "\";";
1211 content::WindowedNotificationObserver popup_observer(
1212 chrome::NOTIFICATION_TAB_ADDED,
1213 content::NotificationService::AllSources());
1214 content::WindowedNotificationObserver nav_observer(
1215 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
1216 content::NotificationService::AllSources());
1217 oldtab->GetMainFrame()->
1218 ExecuteJavaScriptWithUserGestureForTests(ASCIIToUTF16(dont_fork_popup));
1220 // Wait for popup window to appear and finish navigating.
1221 popup_observer.Wait();
1222 ASSERT_EQ(2, browser()->tab_strip_model()->count());
1223 WebContents* newtab = browser()->tab_strip_model()->GetActiveWebContents();
1224 EXPECT_TRUE(newtab);
1225 EXPECT_NE(oldtab, newtab);
1226 nav_observer.Wait();
1227 ASSERT_TRUE(newtab->GetController().GetLastCommittedEntry());
1228 EXPECT_EQ(https_url.spec(),
1229 newtab->GetController().GetLastCommittedEntry()->GetURL().spec());
1231 // Popup window should still be in the opener's process.
1232 content::RenderProcessHost* popup_process =
1233 newtab->GetRenderProcessHost();
1234 EXPECT_EQ(process, popup_process);
1236 // Same thing if the current tab tries to navigate itself.
1237 std::string navigate_str = "document.location=\"";
1238 navigate_str += https_url.spec();
1239 navigate_str += "\";";
1241 content::WindowedNotificationObserver nav_observer2(
1242 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
1243 content::NotificationService::AllSources());
1244 oldtab->GetMainFrame()->ExecuteJavaScriptWithUserGestureForTests(
1245 ASCIIToUTF16(navigate_str));
1246 nav_observer2.Wait();
1247 ASSERT_TRUE(oldtab->GetController().GetLastCommittedEntry());
1248 EXPECT_EQ(https_url.spec(),
1249 oldtab->GetController().GetLastCommittedEntry()->GetURL().spec());
1251 // Original window should still be in the original process.
1252 content::RenderProcessHost* new_process = newtab->GetRenderProcessHost();
1253 EXPECT_EQ(process, new_process);
1256 // Test that get_process_idle_time() returns reasonable values when compared
1257 // with time deltas measured locally.
1258 IN_PROC_BROWSER_TEST_F(BrowserTest, RenderIdleTime) {
1259 base::TimeTicks start = base::TimeTicks::Now();
1260 ui_test_utils::NavigateToURL(
1261 browser(), ui_test_utils::GetTestUrl(
1262 base::FilePath(base::FilePath::kCurrentDirectory),
1263 base::FilePath(kTitle1File)));
1264 content::RenderProcessHost::iterator it(
1265 content::RenderProcessHost::AllHostsIterator());
1266 for (; !it.IsAtEnd(); it.Advance()) {
1267 base::TimeDelta renderer_td =
1268 it.GetCurrentValue()->GetChildProcessIdleTime();
1269 base::TimeDelta browser_td = base::TimeTicks::Now() - start;
1270 EXPECT_TRUE(browser_td >= renderer_td);
1274 // Test IDC_CREATE_SHORTCUTS command is enabled for url scheme file, ftp, http
1275 // and https and disabled for chrome://, about:// etc.
1276 // TODO(pinkerton): Disable app-mode in the model until we implement it
1277 // on the Mac. http://crbug.com/13148
1278 #if !defined(OS_MACOSX)
1279 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFile) {
1280 CommandUpdater* command_updater =
1281 browser()->command_controller()->command_updater();
1283 static const base::FilePath::CharType* kEmptyFile =
1284 FILE_PATH_LITERAL("empty.html");
1285 GURL file_url(ui_test_utils::GetTestUrl(base::FilePath(
1286 base::FilePath::kCurrentDirectory), base::FilePath(kEmptyFile)));
1287 ASSERT_TRUE(file_url.SchemeIs(url::kFileScheme));
1288 ui_test_utils::NavigateToURL(browser(), file_url);
1289 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1292 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttp) {
1293 CommandUpdater* command_updater =
1294 browser()->command_controller()->command_updater();
1296 ASSERT_TRUE(test_server()->Start());
1297 GURL http_url(test_server()->GetURL(std::string()));
1298 ASSERT_TRUE(http_url.SchemeIs(url::kHttpScheme));
1299 ui_test_utils::NavigateToURL(browser(), http_url);
1300 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1303 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttps) {
1304 CommandUpdater* command_updater =
1305 browser()->command_controller()->command_updater();
1307 net::SpawnedTestServer test_server(net::SpawnedTestServer::TYPE_HTTPS,
1308 net::SpawnedTestServer::kLocalhost,
1309 base::FilePath(kDocRoot));
1310 ASSERT_TRUE(test_server.Start());
1311 GURL https_url(test_server.GetURL("/"));
1312 ASSERT_TRUE(https_url.SchemeIs(url::kHttpsScheme));
1313 ui_test_utils::NavigateToURL(browser(), https_url);
1314 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1317 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFtp) {
1318 CommandUpdater* command_updater =
1319 browser()->command_controller()->command_updater();
1321 net::SpawnedTestServer test_server(net::SpawnedTestServer::TYPE_FTP,
1322 net::SpawnedTestServer::kLocalhost,
1323 base::FilePath(kDocRoot));
1324 ASSERT_TRUE(test_server.Start());
1325 GURL ftp_url(test_server.GetURL(std::string()));
1326 ASSERT_TRUE(ftp_url.SchemeIs(url::kFtpScheme));
1327 ui_test_utils::NavigateToURL(browser(), ftp_url);
1328 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1331 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutInvalid) {
1332 CommandUpdater* command_updater =
1333 browser()->command_controller()->command_updater();
1335 // Urls that should not have shortcuts.
1336 GURL new_tab_url(chrome::kChromeUINewTabURL);
1337 ui_test_utils::NavigateToURL(browser(), new_tab_url);
1338 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1340 GURL history_url(chrome::kChromeUIHistoryURL);
1341 ui_test_utils::NavigateToURL(browser(), history_url);
1342 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1344 GURL blank_url(url::kAboutBlankURL);
1345 ui_test_utils::NavigateToURL(browser(), blank_url);
1346 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1349 // Change a tab into an application window.
1350 // DISABLED: http://crbug.com/72310
1351 IN_PROC_BROWSER_TEST_F(BrowserTest, DISABLED_ConvertTabToAppShortcut) {
1352 ASSERT_TRUE(test_server()->Start());
1353 GURL http_url(test_server()->GetURL(std::string()));
1354 ASSERT_TRUE(http_url.SchemeIs(url::kHttpScheme));
1356 ASSERT_EQ(1, browser()->tab_strip_model()->count());
1357 WebContents* initial_tab = browser()->tab_strip_model()->GetWebContentsAt(0);
1358 WebContents* app_tab = chrome::AddSelectedTabWithURL(
1359 browser(), http_url, ui::PAGE_TRANSITION_TYPED);
1360 ASSERT_EQ(2, browser()->tab_strip_model()->count());
1361 ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
1362 browser()->host_desktop_type()));
1364 // Normal tabs should accept load drops.
1365 EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops);
1366 EXPECT_TRUE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops);
1368 // Turn |app_tab| into a tab in an app panel.
1369 chrome::ConvertTabToAppWindow(browser(), app_tab);
1371 // The launch should have created a new browser.
1372 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
1373 browser()->host_desktop_type()));
1375 // Find the new browser.
1376 Browser* app_browser = NULL;
1377 for (chrome::BrowserIterator it; !it.done() && !app_browser; it.Next()) {
1378 if (*it != browser())
1379 app_browser = *it;
1381 ASSERT_TRUE(app_browser);
1383 // Check that the tab contents is in the new browser, and not in the old.
1384 ASSERT_EQ(1, browser()->tab_strip_model()->count());
1385 ASSERT_EQ(initial_tab, browser()->tab_strip_model()->GetWebContentsAt(0));
1387 // Check that the appliaction browser has a single tab, and that tab contains
1388 // the content that we app-ified.
1389 ASSERT_EQ(1, app_browser->tab_strip_model()->count());
1390 ASSERT_EQ(app_tab, app_browser->tab_strip_model()->GetWebContentsAt(0));
1392 // Normal tabs should accept load drops.
1393 EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops);
1395 // The tab in an app window should not.
1396 EXPECT_FALSE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops);
1399 #endif // !defined(OS_MACOSX)
1401 // Test RenderView correctly send back favicon url for web page that redirects
1402 // to an anchor in javascript body.onload handler.
1403 IN_PROC_BROWSER_TEST_F(BrowserTest,
1404 DISABLED_FaviconOfOnloadRedirectToAnchorPage) {
1405 ASSERT_TRUE(test_server()->Start());
1406 GURL url(test_server()->GetURL("files/onload_redirect_to_anchor.html"));
1407 GURL expected_favicon_url(test_server()->GetURL("files/test.png"));
1409 ui_test_utils::NavigateToURL(browser(), url);
1411 NavigationEntry* entry = browser()->tab_strip_model()->
1412 GetActiveWebContents()->GetController().GetLastCommittedEntry();
1413 EXPECT_EQ(expected_favicon_url.spec(), entry->GetFavicon().url.spec());
1416 #if defined(OS_MACOSX) || defined(OS_LINUX) || defined (OS_WIN)
1417 // http://crbug.com/83828. On Mac 10.6, the failure rate is 14%
1418 #define MAYBE_FaviconChange DISABLED_FaviconChange
1419 #else
1420 #define MAYBE_FaviconChange FaviconChange
1421 #endif
1422 // Test that an icon can be changed from JS.
1423 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_FaviconChange) {
1424 static const base::FilePath::CharType* kFile =
1425 FILE_PATH_LITERAL("onload_change_favicon.html");
1426 GURL file_url(ui_test_utils::GetTestUrl(base::FilePath(
1427 base::FilePath::kCurrentDirectory), base::FilePath(kFile)));
1428 ASSERT_TRUE(file_url.SchemeIs(url::kFileScheme));
1429 ui_test_utils::NavigateToURL(browser(), file_url);
1431 NavigationEntry* entry = browser()->tab_strip_model()->
1432 GetActiveWebContents()->GetController().GetLastCommittedEntry();
1433 static const base::FilePath::CharType* kIcon =
1434 FILE_PATH_LITERAL("test1.png");
1435 GURL expected_favicon_url(ui_test_utils::GetTestUrl(base::FilePath(
1436 base::FilePath::kCurrentDirectory), base::FilePath(kIcon)));
1437 EXPECT_EQ(expected_favicon_url.spec(), entry->GetFavicon().url.spec());
1440 // http://crbug.com/172336
1441 #if defined(OS_WIN)
1442 #define MAYBE_TabClosingWhenRemovingExtension \
1443 DISABLED_TabClosingWhenRemovingExtension
1444 #else
1445 #define MAYBE_TabClosingWhenRemovingExtension TabClosingWhenRemovingExtension
1446 #endif
1447 // Makes sure TabClosing is sent when uninstalling an extension that is an app
1448 // tab.
1449 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_TabClosingWhenRemovingExtension) {
1450 ASSERT_TRUE(test_server()->Start());
1451 host_resolver()->AddRule("www.example.com", "127.0.0.1");
1452 GURL url(test_server()->GetURL("empty.html"));
1453 TabStripModel* model = browser()->tab_strip_model();
1455 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
1457 const Extension* extension_app = GetExtension();
1459 ui_test_utils::NavigateToURL(browser(), url);
1461 WebContents* app_contents = WebContents::Create(
1462 WebContents::CreateParams(browser()->profile()));
1463 extensions::TabHelper::CreateForWebContents(app_contents);
1464 extensions::TabHelper* extensions_tab_helper =
1465 extensions::TabHelper::FromWebContents(app_contents);
1466 extensions_tab_helper->SetExtensionApp(extension_app);
1468 model->AddWebContents(app_contents, 0, ui::PageTransitionFromInt(0),
1469 TabStripModel::ADD_NONE);
1470 model->SetTabPinned(0, true);
1471 ui_test_utils::NavigateToURL(browser(), url);
1473 MockTabStripModelObserver observer;
1474 model->AddObserver(&observer);
1476 // Uninstall the extension and make sure TabClosing is sent.
1477 ExtensionService* service = extensions::ExtensionSystem::Get(
1478 browser()->profile())->extension_service();
1479 service->UninstallExtension(GetExtension()->id(),
1480 extensions::UNINSTALL_REASON_FOR_TESTING,
1481 base::Bind(&base::DoNothing),
1482 NULL);
1483 EXPECT_EQ(1, observer.closing_count());
1485 model->RemoveObserver(&observer);
1487 // There should only be one tab now.
1488 ASSERT_EQ(1, browser()->tab_strip_model()->count());
1491 // Open with --app-id=<id>, and see that an application tab opens by default.
1492 IN_PROC_BROWSER_TEST_F(BrowserTest, AppIdSwitch) {
1493 ASSERT_TRUE(test_server()->Start());
1495 // There should be one tab to start with.
1496 ASSERT_EQ(1, browser()->tab_strip_model()->count());
1498 // Load an app.
1499 host_resolver()->AddRule("www.example.com", "127.0.0.1");
1500 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
1501 const Extension* extension_app = GetExtension();
1503 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
1504 command_line.AppendSwitchASCII(switches::kAppId, extension_app->id());
1506 chrome::startup::IsFirstRun first_run = first_run::IsChromeFirstRun() ?
1507 chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN;
1508 StartupBrowserCreatorImpl launch(base::FilePath(), command_line, first_run);
1510 bool new_bookmark_apps_enabled = extensions::util::IsNewBookmarkAppsEnabled();
1512 // If the new bookmark app flow is enabled, the app should open as an tab.
1513 // Otherwise the app should open as an app window.
1514 EXPECT_EQ(!new_bookmark_apps_enabled,
1515 launch.OpenApplicationWindow(browser()->profile()));
1516 EXPECT_EQ(new_bookmark_apps_enabled,
1517 launch.OpenApplicationTab(browser()->profile()));
1519 // Check that a the number of browsers and tabs is correct.
1520 unsigned int expected_browsers = 1;
1521 int expected_tabs = 1;
1522 new_bookmark_apps_enabled ? expected_tabs++ : expected_browsers++;
1524 EXPECT_EQ(expected_browsers,
1525 chrome::GetBrowserCount(browser()->profile(),
1526 browser()->host_desktop_type()));
1527 EXPECT_EQ(expected_tabs, browser()->tab_strip_model()->count());
1530 // Open an app window and the dev tools window and ensure that the location
1531 // bar settings are correct.
1532 IN_PROC_BROWSER_TEST_F(BrowserTest, ShouldShowLocationBar) {
1533 ASSERT_TRUE(test_server()->Start());
1535 // Load an app.
1536 host_resolver()->AddRule("www.example.com", "127.0.0.1");
1537 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
1538 const Extension* extension_app = GetExtension();
1540 // Launch it in a window, as AppLauncherHandler::HandleLaunchApp() would.
1541 WebContents* app_window = OpenApplication(AppLaunchParams(
1542 browser()->profile(), extension_app, extensions::LAUNCH_CONTAINER_WINDOW,
1543 NEW_WINDOW, extensions::SOURCE_TEST));
1544 ASSERT_TRUE(app_window);
1546 DevToolsWindow* devtools_window =
1547 DevToolsWindowTesting::OpenDevToolsWindowSync(browser(), false);
1549 // The launch should have created a new app browser and a dev tools browser.
1550 ASSERT_EQ(3u,
1551 chrome::GetBrowserCount(browser()->profile(),
1552 browser()->host_desktop_type()));
1554 // Find the new browsers.
1555 Browser* app_browser = NULL;
1556 Browser* dev_tools_browser = NULL;
1557 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
1558 if (*it == browser()) {
1559 continue;
1560 } else if ((*it)->app_name() == DevToolsWindow::kDevToolsApp) {
1561 dev_tools_browser = *it;
1562 } else {
1563 app_browser = *it;
1566 ASSERT_TRUE(dev_tools_browser);
1567 ASSERT_TRUE(app_browser);
1568 ASSERT_TRUE(app_browser != browser());
1570 EXPECT_FALSE(
1571 dev_tools_browser->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR));
1573 // App windows can show location bars, for example when they navigate away
1574 // from their starting origin.
1575 EXPECT_TRUE(
1576 app_browser->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR));
1578 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools_window);
1581 // Tests that the CLD (Compact Language Detection) works properly.
1582 IN_PROC_BROWSER_TEST_F(BrowserTest, PageLanguageDetection) {
1583 scoped_ptr<test::CldDataHarness> cld_data_harness =
1584 test::CldDataHarnessFactory::Get()->CreateCldDataHarness();
1585 ASSERT_NO_FATAL_FAILURE(cld_data_harness->Init());
1586 ASSERT_TRUE(test_server()->Start());
1588 translate::LanguageDetectionDetails details;
1590 // Open a new tab with a page in English.
1591 AddTabAtIndex(0, GURL(test_server()->GetURL("files/english_page.html")),
1592 ui::PAGE_TRANSITION_TYPED);
1594 WebContents* current_web_contents =
1595 browser()->tab_strip_model()->GetActiveWebContents();
1596 ChromeTranslateClient* chrome_translate_client =
1597 ChromeTranslateClient::FromWebContents(current_web_contents);
1598 content::Source<WebContents> source(current_web_contents);
1600 ui_test_utils::WindowedNotificationObserverWithDetails<
1601 translate::LanguageDetectionDetails>
1602 en_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED,
1603 source);
1604 EXPECT_EQ("",
1605 chrome_translate_client->GetLanguageState().original_language());
1606 en_language_detected_signal.Wait();
1607 EXPECT_TRUE(en_language_detected_signal.GetDetailsFor(
1608 source.map_key(), &details));
1609 EXPECT_EQ("en", details.adopted_language);
1610 EXPECT_EQ("en",
1611 chrome_translate_client->GetLanguageState().original_language());
1613 // Now navigate to a page in French.
1614 ui_test_utils::WindowedNotificationObserverWithDetails<
1615 translate::LanguageDetectionDetails>
1616 fr_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED,
1617 source);
1618 ui_test_utils::NavigateToURL(
1619 browser(), GURL(test_server()->GetURL("files/french_page.html")));
1620 fr_language_detected_signal.Wait();
1621 details.adopted_language.clear();
1622 EXPECT_TRUE(fr_language_detected_signal.GetDetailsFor(
1623 source.map_key(), &details));
1624 EXPECT_EQ("fr", details.adopted_language);
1625 EXPECT_EQ("fr",
1626 chrome_translate_client->GetLanguageState().original_language());
1629 // Chromeos defaults to restoring the last session, so this test isn't
1630 // applicable.
1631 #if !defined(OS_CHROMEOS)
1632 #if defined(OS_MACOSX)
1633 // Crashy, http://crbug.com/38522
1634 #define RestorePinnedTabs DISABLED_RestorePinnedTabs
1635 #endif
1636 // Makes sure pinned tabs are restored correctly on start.
1637 IN_PROC_BROWSER_TEST_F(BrowserTest, RestorePinnedTabs) {
1638 ASSERT_TRUE(test_server()->Start());
1640 // Add a pinned tab.
1641 host_resolver()->AddRule("www.example.com", "127.0.0.1");
1642 GURL url(test_server()->GetURL("empty.html"));
1643 TabStripModel* model = browser()->tab_strip_model();
1644 ui_test_utils::NavigateToURL(browser(), url);
1645 model->SetTabPinned(0, true);
1647 // Add a non pinned tab.
1648 chrome::NewTab(browser());
1649 ui_test_utils::NavigateToURL(browser(), url);
1651 // Add another pinned tab.
1652 chrome::NewTab(browser());
1653 ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
1654 model->SetTabPinned(2, true);
1656 // Write out the pinned tabs.
1657 PinnedTabCodec::WritePinnedTabs(browser()->profile());
1659 // Simulate launching again.
1660 base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
1661 chrome::startup::IsFirstRun first_run = first_run::IsChromeFirstRun() ?
1662 chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN;
1663 StartupBrowserCreatorImpl launch(base::FilePath(), dummy, first_run);
1664 launch.profile_ = browser()->profile();
1665 launch.ProcessStartupURLs(std::vector<GURL>(),
1666 browser()->host_desktop_type());
1668 // The launch should have created a new browser.
1669 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
1670 browser()->host_desktop_type()));
1672 // Find the new browser.
1673 Browser* new_browser = NULL;
1674 for (chrome::BrowserIterator it; !it.done() && !new_browser; it.Next()) {
1675 if (*it != browser())
1676 new_browser = *it;
1678 ASSERT_TRUE(new_browser);
1679 ASSERT_TRUE(new_browser != browser());
1681 // We should get back an additional tab for the app, and another for the
1682 // default home page.
1683 ASSERT_EQ(3, new_browser->tab_strip_model()->count());
1685 // Make sure the state matches.
1686 TabStripModel* new_model = new_browser->tab_strip_model();
1687 EXPECT_TRUE(new_model->IsTabPinned(0));
1688 EXPECT_TRUE(new_model->IsTabPinned(1));
1689 EXPECT_FALSE(new_model->IsTabPinned(2));
1691 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
1692 new_model->GetWebContentsAt(2)->GetURL());
1694 #endif // !defined(OS_CHROMEOS)
1696 // This test verifies we don't crash when closing the last window and the app
1697 // menu is showing.
1698 IN_PROC_BROWSER_TEST_F(BrowserTest, CloseWithAppMenuOpen) {
1699 if (browser_defaults::kBrowserAliveWithNoWindows)
1700 return;
1702 // We need a message loop running for menus on windows.
1703 base::MessageLoop::current()->task_runner()->PostTask(
1704 FROM_HERE, base::Bind(&RunCloseWithAppMenuCallback, browser()));
1707 #if !defined(OS_MACOSX)
1708 IN_PROC_BROWSER_TEST_F(BrowserTest, OpenAppWindowLikeNtp) {
1709 ASSERT_TRUE(test_server()->Start());
1711 // Load an app
1712 host_resolver()->AddRule("www.example.com", "127.0.0.1");
1713 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
1714 const Extension* extension_app = GetExtension();
1716 // Launch it in a window, as AppLauncherHandler::HandleLaunchApp() would.
1717 WebContents* app_window = OpenApplication(AppLaunchParams(
1718 browser()->profile(), extension_app, extensions::LAUNCH_CONTAINER_WINDOW,
1719 NEW_WINDOW, extensions::SOURCE_TEST));
1720 ASSERT_TRUE(app_window);
1722 // Apps launched in a window from the NTP have an extensions tab helper but
1723 // do not have extension_app set in it.
1724 ASSERT_TRUE(extensions::TabHelper::FromWebContents(app_window));
1725 EXPECT_FALSE(
1726 extensions::TabHelper::FromWebContents(app_window)->extension_app());
1727 EXPECT_EQ(extensions::AppLaunchInfo::GetFullLaunchURL(extension_app),
1728 app_window->GetURL());
1730 // The launch should have created a new browser.
1731 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
1732 browser()->host_desktop_type()));
1734 // Find the new browser.
1735 Browser* new_browser = NULL;
1736 for (chrome::BrowserIterator it; !it.done() && !new_browser; it.Next()) {
1737 if (*it != browser())
1738 new_browser = *it;
1740 ASSERT_TRUE(new_browser);
1741 ASSERT_TRUE(new_browser != browser());
1743 EXPECT_TRUE(new_browser->is_app());
1745 // The browser's app name should include the extension's id.
1746 std::string app_name = new_browser->app_name_;
1747 EXPECT_NE(app_name.find(extension_app->id()), std::string::npos)
1748 << "Name " << app_name << " should contain id "<< extension_app->id();
1750 #endif // !defined(OS_MACOSX)
1752 // Makes sure the browser doesn't crash when
1753 // set_show_state(ui::SHOW_STATE_MAXIMIZED) has been invoked.
1754 IN_PROC_BROWSER_TEST_F(BrowserTest, StartMaximized) {
1755 Browser::Type types[] = { Browser::TYPE_TABBED, Browser::TYPE_POPUP };
1756 for (size_t i = 0; i < arraysize(types); ++i) {
1757 Browser::CreateParams params(types[i], browser()->profile(),
1758 browser()->host_desktop_type());
1759 params.initial_show_state = ui::SHOW_STATE_MAXIMIZED;
1760 AddBlankTabAndShow(new Browser(params));
1764 // Aura doesn't support minimized window. crbug.com/104571.
1765 #if defined(USE_AURA)
1766 #define MAYBE_StartMinimized DISABLED_StartMinimized
1767 #else
1768 #define MAYBE_StartMinimized StartMinimized
1769 #endif
1770 // Makes sure the browser doesn't crash when
1771 // set_show_state(ui::SHOW_STATE_MINIMIZED) has been invoked.
1772 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_StartMinimized) {
1773 Browser::Type types[] = { Browser::TYPE_TABBED, Browser::TYPE_POPUP };
1774 for (size_t i = 0; i < arraysize(types); ++i) {
1775 Browser::CreateParams params(types[i], browser()->profile(),
1776 browser()->host_desktop_type());
1777 params.initial_show_state = ui::SHOW_STATE_MINIMIZED;
1778 AddBlankTabAndShow(new Browser(params));
1782 // Makes sure the forward button is disabled immediately when navigating
1783 // forward to a slow-to-commit page.
1784 IN_PROC_BROWSER_TEST_F(BrowserTest, ForwardDisabledOnForward) {
1785 GURL blank_url(url::kAboutBlankURL);
1786 ui_test_utils::NavigateToURL(browser(), blank_url);
1788 ui_test_utils::NavigateToURL(
1789 browser(), ui_test_utils::GetTestUrl(
1790 base::FilePath(base::FilePath::kCurrentDirectory),
1791 base::FilePath(kTitle1File)));
1793 content::WindowedNotificationObserver back_nav_load_observer(
1794 content::NOTIFICATION_LOAD_STOP,
1795 content::Source<NavigationController>(
1796 &browser()->tab_strip_model()->GetActiveWebContents()->
1797 GetController()));
1798 chrome::GoBack(browser(), CURRENT_TAB);
1799 back_nav_load_observer.Wait();
1800 CommandUpdater* command_updater =
1801 browser()->command_controller()->command_updater();
1802 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_FORWARD));
1804 content::WindowedNotificationObserver forward_nav_load_observer(
1805 content::NOTIFICATION_LOAD_STOP,
1806 content::Source<NavigationController>(
1807 &browser()->tab_strip_model()->GetActiveWebContents()->
1808 GetController()));
1809 chrome::GoForward(browser(), CURRENT_TAB);
1810 // This check will happen before the navigation completes, since the browser
1811 // won't process the renderer's response until the Wait() call below.
1812 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_FORWARD));
1813 forward_nav_load_observer.Wait();
1816 // Makes sure certain commands are disabled when Incognito mode is forced.
1817 IN_PROC_BROWSER_TEST_F(BrowserTest, DisableMenuItemsWhenIncognitoIsForced) {
1818 CommandUpdater* command_updater =
1819 browser()->command_controller()->command_updater();
1820 // At the beginning, all commands are enabled.
1821 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1822 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW));
1823 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER));
1824 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1825 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1826 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1828 // Set Incognito to FORCED.
1829 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
1830 IncognitoModePrefs::FORCED);
1831 // Bookmarks & Settings commands should get disabled.
1832 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1833 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER));
1834 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1835 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1836 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1837 // New Incognito Window command, however, should be enabled.
1838 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW));
1840 // Create a new browser.
1841 Browser* new_browser =
1842 new Browser(Browser::CreateParams(
1843 browser()->profile()->GetOffTheRecordProfile(),
1844 browser()->host_desktop_type()));
1845 CommandUpdater* new_command_updater =
1846 new_browser->command_controller()->command_updater();
1847 // It should have Bookmarks & Settings commands disabled by default.
1848 EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1849 EXPECT_FALSE(new_command_updater->IsCommandEnabled(
1850 IDC_SHOW_BOOKMARK_MANAGER));
1851 EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1852 EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1853 EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_OPTIONS));
1854 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW));
1857 // Makes sure New Incognito Window command is disabled when Incognito mode is
1858 // not available.
1859 IN_PROC_BROWSER_TEST_F(BrowserTest,
1860 NoNewIncognitoWindowWhenIncognitoIsDisabled) {
1861 CommandUpdater* command_updater =
1862 browser()->command_controller()->command_updater();
1863 // Set Incognito to DISABLED.
1864 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
1865 IncognitoModePrefs::DISABLED);
1866 // Make sure New Incognito Window command is disabled. All remaining commands
1867 // should be enabled.
1868 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW));
1869 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1870 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER));
1871 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1872 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1873 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1875 // Create a new browser.
1876 Browser* new_browser =
1877 new Browser(Browser::CreateParams(browser()->profile(),
1878 browser()->host_desktop_type()));
1879 CommandUpdater* new_command_updater =
1880 new_browser->command_controller()->command_updater();
1881 EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW));
1882 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1883 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER));
1884 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1885 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1886 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_OPTIONS));
1889 // Makes sure Extensions and Settings commands are disabled in certain
1890 // circumstances even though normally they should stay enabled.
1891 IN_PROC_BROWSER_TEST_F(BrowserTest,
1892 DisableExtensionsAndSettingsWhenIncognitoIsDisabled) {
1893 CommandUpdater* command_updater =
1894 browser()->command_controller()->command_updater();
1895 // Disable extensions. This should disable Extensions menu.
1896 extensions::ExtensionSystem::Get(browser()->profile())->extension_service()->
1897 set_extensions_enabled(false);
1898 // Set Incognito to DISABLED.
1899 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
1900 IncognitoModePrefs::DISABLED);
1901 // Make sure Manage Extensions command is disabled.
1902 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1903 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1904 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER));
1905 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1906 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1908 // Create a popup (non-main-UI-type) browser. Settings command as well
1909 // as Extensions should be disabled.
1910 Browser* popup_browser = new Browser(
1911 Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(),
1912 browser()->host_desktop_type()));
1913 CommandUpdater* popup_command_updater =
1914 popup_browser->command_controller()->command_updater();
1915 EXPECT_FALSE(popup_command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1916 EXPECT_FALSE(popup_command_updater->IsCommandEnabled(IDC_OPTIONS));
1917 EXPECT_TRUE(popup_command_updater->IsCommandEnabled(
1918 IDC_SHOW_BOOKMARK_MANAGER));
1919 EXPECT_FALSE(popup_command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1922 // Makes sure Extensions and Settings commands are disabled in certain
1923 // circumstances even though normally they should stay enabled.
1924 IN_PROC_BROWSER_TEST_F(BrowserTest,
1925 DisableOptionsAndImportMenuItemsConsistently) {
1926 // Create a popup browser.
1927 Browser* popup_browser = new Browser(
1928 Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(),
1929 browser()->host_desktop_type()));
1930 CommandUpdater* command_updater =
1931 popup_browser->command_controller()->command_updater();
1932 // OPTIONS and IMPORT_SETTINGS are disabled for a non-normal UI.
1933 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1934 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1936 // Set Incognito to FORCED.
1937 IncognitoModePrefs::SetAvailability(popup_browser->profile()->GetPrefs(),
1938 IncognitoModePrefs::FORCED);
1939 // OPTIONS and IMPORT_SETTINGS are disabled when Incognito is forced.
1940 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1941 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1942 // Set Incognito to AVAILABLE.
1943 IncognitoModePrefs::SetAvailability(popup_browser->profile()->GetPrefs(),
1944 IncognitoModePrefs::ENABLED);
1945 // OPTIONS and IMPORT_SETTINGS are still disabled since it is a non-normal UI.
1946 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1947 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1950 namespace {
1952 void OnZoomLevelChanged(const base::Closure& callback,
1953 const HostZoomMap::ZoomLevelChange& host) {
1954 callback.Run();
1957 } // namespace
1959 #if defined(OS_WIN)
1960 // Flakes regularly on Windows XP
1961 // http://crbug.com/146040
1962 #define MAYBE_PageZoom DISABLED_PageZoom
1963 #else
1964 #define MAYBE_PageZoom PageZoom
1965 #endif
1967 namespace {
1969 int GetZoomPercent(const content::WebContents* contents,
1970 bool* enable_plus,
1971 bool* enable_minus) {
1972 int percent =
1973 ui_zoom::ZoomController::FromWebContents(contents)->GetZoomPercent();
1974 *enable_plus = percent < contents->GetMaximumZoomPercent();
1975 *enable_minus = percent > contents->GetMinimumZoomPercent();
1976 return percent;
1979 } // namespace
1981 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_PageZoom) {
1982 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
1983 bool enable_plus, enable_minus;
1986 scoped_refptr<content::MessageLoopRunner> loop_runner(
1987 new content::MessageLoopRunner);
1988 content::HostZoomMap::ZoomLevelChangedCallback callback(
1989 base::Bind(&OnZoomLevelChanged, loop_runner->QuitClosure()));
1990 scoped_ptr<content::HostZoomMap::Subscription> sub =
1991 content::HostZoomMap::GetDefaultForBrowserContext(
1992 browser()->profile())->AddZoomLevelChangedCallback(callback);
1993 chrome::Zoom(browser(), content::PAGE_ZOOM_IN);
1994 loop_runner->Run();
1995 sub.reset();
1996 EXPECT_EQ(GetZoomPercent(contents, &enable_plus, &enable_minus), 110);
1997 EXPECT_TRUE(enable_plus);
1998 EXPECT_TRUE(enable_minus);
2002 scoped_refptr<content::MessageLoopRunner> loop_runner(
2003 new content::MessageLoopRunner);
2004 content::HostZoomMap::ZoomLevelChangedCallback callback(
2005 base::Bind(&OnZoomLevelChanged, loop_runner->QuitClosure()));
2006 scoped_ptr<content::HostZoomMap::Subscription> sub =
2007 content::HostZoomMap::GetDefaultForBrowserContext(
2008 browser()->profile())->AddZoomLevelChangedCallback(callback);
2009 chrome::Zoom(browser(), content::PAGE_ZOOM_RESET);
2010 loop_runner->Run();
2011 sub.reset();
2012 EXPECT_EQ(GetZoomPercent(contents, &enable_plus, &enable_minus), 100);
2013 EXPECT_TRUE(enable_plus);
2014 EXPECT_TRUE(enable_minus);
2018 scoped_refptr<content::MessageLoopRunner> loop_runner(
2019 new content::MessageLoopRunner);
2020 content::HostZoomMap::ZoomLevelChangedCallback callback(
2021 base::Bind(&OnZoomLevelChanged, loop_runner->QuitClosure()));
2022 scoped_ptr<content::HostZoomMap::Subscription> sub =
2023 content::HostZoomMap::GetDefaultForBrowserContext(
2024 browser()->profile())->AddZoomLevelChangedCallback(callback);
2025 chrome::Zoom(browser(), content::PAGE_ZOOM_OUT);
2026 loop_runner->Run();
2027 sub.reset();
2028 EXPECT_EQ(GetZoomPercent(contents, &enable_plus, &enable_minus), 90);
2029 EXPECT_TRUE(enable_plus);
2030 EXPECT_TRUE(enable_minus);
2033 chrome::Zoom(browser(), content::PAGE_ZOOM_RESET);
2036 IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialCommandDisable) {
2037 ASSERT_TRUE(test_server()->Start());
2038 host_resolver()->AddRule("www.example.com", "127.0.0.1");
2039 GURL url(test_server()->GetURL("empty.html"));
2040 ui_test_utils::NavigateToURL(browser(), url);
2042 CommandUpdater* command_updater =
2043 browser()->command_controller()->command_updater();
2044 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_VIEW_SOURCE));
2045 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_PRINT));
2046 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SAVE_PAGE));
2047 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_ENCODING_MENU));
2048 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_DUPLICATE_TAB));
2050 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
2052 TestInterstitialPage* interstitial =
2053 new TestInterstitialPage(contents, false, GURL());
2054 content::WaitForInterstitialAttach(contents);
2056 EXPECT_TRUE(contents->ShowingInterstitialPage());
2058 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_VIEW_SOURCE));
2059 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_PRINT));
2060 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SAVE_PAGE));
2061 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_ENCODING_MENU));
2062 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_DUPLICATE_TAB));
2064 // Proceed and wait for interstitial to detach. This doesn't destroy
2065 // |contents|.
2066 interstitial->Proceed();
2067 content::WaitForInterstitialDetach(contents);
2068 // interstitial is deleted now.
2070 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_VIEW_SOURCE));
2071 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_PRINT));
2072 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SAVE_PAGE));
2073 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_ENCODING_MENU));
2074 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_DUPLICATE_TAB));
2077 // Ensure that creating an interstitial page closes any JavaScript dialogs
2078 // that were present on the previous page. See http://crbug.com/295695.
2079 IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialClosesDialogs) {
2080 ASSERT_TRUE(test_server()->Start());
2081 host_resolver()->AddRule("www.example.com", "127.0.0.1");
2082 GURL url(test_server()->GetURL("empty.html"));
2083 ui_test_utils::NavigateToURL(browser(), url);
2085 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
2086 contents->GetMainFrame()->ExecuteJavaScriptForTests(
2087 ASCIIToUTF16("alert('Dialog showing!');"));
2088 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
2089 EXPECT_TRUE(alert->IsValid());
2090 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
2091 EXPECT_TRUE(dialog_queue->HasActiveDialog());
2093 TestInterstitialPage* interstitial =
2094 new TestInterstitialPage(contents, false, GURL());
2095 content::WaitForInterstitialAttach(contents);
2097 // The interstitial should have closed the dialog.
2098 EXPECT_TRUE(contents->ShowingInterstitialPage());
2099 EXPECT_FALSE(dialog_queue->HasActiveDialog());
2101 // Don't proceed and wait for interstitial to detach. This doesn't destroy
2102 // |contents|.
2103 interstitial->DontProceed();
2104 content::WaitForInterstitialDetach(contents);
2105 // interstitial is deleted now.
2107 // Make sure input events still work in the renderer process.
2108 EXPECT_FALSE(contents->GetRenderProcessHost()->IgnoreInputEvents());
2112 IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialCloseTab) {
2113 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
2115 // Interstitial will delete itself when we close the tab.
2116 new TestInterstitialPage(contents, false, GURL());
2117 content::WaitForInterstitialAttach(contents);
2119 EXPECT_TRUE(contents->ShowingInterstitialPage());
2121 // Close the tab and wait for interstitial detach. This destroys |contents|.
2122 content::RunTaskAndWaitForInterstitialDetach(
2123 contents, base::Bind(&chrome::CloseTab, browser()));
2124 // interstitial is deleted now.
2127 class MockWebContentsObserver : public WebContentsObserver {
2128 public:
2129 explicit MockWebContentsObserver(WebContents* web_contents)
2130 : WebContentsObserver(web_contents),
2131 got_user_gesture_(false) {
2134 void DidGetUserGesture() override { got_user_gesture_ = true; }
2136 bool got_user_gesture() const {
2137 return got_user_gesture_;
2140 void set_got_user_gesture(bool got_it) {
2141 got_user_gesture_ = got_it;
2144 private:
2145 bool got_user_gesture_;
2147 DISALLOW_COPY_AND_ASSIGN(MockWebContentsObserver);
2150 IN_PROC_BROWSER_TEST_F(BrowserTest, UserGesturesReported) {
2151 // Regression test for http://crbug.com/110707. Also tests that a user
2152 // gesture is sent when a normal navigation (via e.g. the omnibox) is
2153 // performed.
2154 WebContents* web_contents =
2155 browser()->tab_strip_model()->GetActiveWebContents();
2156 MockWebContentsObserver mock_observer(web_contents);
2158 ASSERT_TRUE(test_server()->Start());
2159 GURL url(test_server()->GetURL("empty.html"));
2161 ui_test_utils::NavigateToURL(browser(), url);
2162 EXPECT_TRUE(mock_observer.got_user_gesture());
2164 mock_observer.set_got_user_gesture(false);
2165 chrome::Reload(browser(), CURRENT_TAB);
2166 EXPECT_TRUE(mock_observer.got_user_gesture());
2169 // TODO(ben): this test was never enabled. It has bit-rotted since being added.
2170 // It originally lived in browser_unittest.cc, but has been moved here to make
2171 // room for real browser unit tests.
2172 #if 0
2173 class BrowserTest2 : public InProcessBrowserTest {
2174 public:
2175 BrowserTest2() {
2176 host_resolver_proc_ = new net::RuleBasedHostResolverProc(NULL);
2177 // Avoid making external DNS lookups. In this test we don't need this
2178 // to succeed.
2179 host_resolver_proc_->AddSimulatedFailure("*.google.com");
2180 scoped_host_resolver_proc_.Init(host_resolver_proc_.get());
2183 private:
2184 scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_proc_;
2185 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc_;
2188 IN_PROC_BROWSER_TEST_F(BrowserTest2, NoTabsInPopups) {
2189 chrome::RegisterAppPrefs(L"Test");
2191 // We start with a normal browser with one tab.
2192 EXPECT_EQ(1, browser()->tab_strip_model()->count());
2194 // Open a popup browser with a single blank foreground tab.
2195 Browser* popup_browser = new Browser(
2196 Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile()));
2197 chrome::AddTabAt(popup_browser, GURL(), -1, true);
2198 EXPECT_EQ(1, popup_browser->tab_strip_model()->count());
2200 // Now try opening another tab in the popup browser.
2201 AddTabWithURLParams params1(url, ui::PAGE_TRANSITION_TYPED);
2202 popup_browser->AddTabWithURL(&params1);
2203 EXPECT_EQ(popup_browser, params1.target);
2205 // The popup should still only have one tab.
2206 EXPECT_EQ(1, popup_browser->tab_strip_model()->count());
2208 // The normal browser should now have two.
2209 EXPECT_EQ(2, browser()->tab_strip_model()->count());
2211 // Open an app frame browser with a single blank foreground tab.
2212 Browser* app_browser = new Browser(Browser::CreateParams::CreateForApp(
2213 L"Test", browser()->profile(), false));
2214 chrome::AddTabAt(app_browser, GURL(), -1, true);
2215 EXPECT_EQ(1, app_browser->tab_strip_model()->count());
2217 // Now try opening another tab in the app browser.
2218 AddTabWithURLParams params2(GURL(url::kAboutBlankURL),
2219 ui::PAGE_TRANSITION_TYPED);
2220 app_browser->AddTabWithURL(&params2);
2221 EXPECT_EQ(app_browser, params2.target);
2223 // The popup should still only have one tab.
2224 EXPECT_EQ(1, app_browser->tab_strip_model()->count());
2226 // The normal browser should now have three.
2227 EXPECT_EQ(3, browser()->tab_strip_model()->count());
2229 // Open an app frame popup browser with a single blank foreground tab.
2230 Browser* app_popup_browser = new Browser(Browser::CreateParams::CreateForApp(
2231 L"Test", browser()->profile(), false));
2232 chrome::AddTabAt(app_popup_browser, GURL(), -1, true);
2233 EXPECT_EQ(1, app_popup_browser->tab_strip_model()->count());
2235 // Now try opening another tab in the app popup browser.
2236 AddTabWithURLParams params3(GURL(url::kAboutBlankURL),
2237 ui::PAGE_TRANSITION_TYPED);
2238 app_popup_browser->AddTabWithURL(&params3);
2239 EXPECT_EQ(app_popup_browser, params3.target);
2241 // The popup should still only have one tab.
2242 EXPECT_EQ(1, app_popup_browser->tab_strip_model()->count());
2244 // The normal browser should now have four.
2245 EXPECT_EQ(4, browser()->tab_strip_model()->count());
2247 // Close the additional browsers.
2248 popup_browser->tab_strip_model()->CloseAllTabs();
2249 app_browser->tab_strip_model()->CloseAllTabs();
2250 app_popup_browser->tab_strip_model()->CloseAllTabs();
2252 #endif
2254 IN_PROC_BROWSER_TEST_F(BrowserTest, WindowOpenClose) {
2255 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2256 switches::kDisablePopupBlocking);
2257 GURL url = ui_test_utils::GetTestUrl(
2258 base::FilePath(), base::FilePath().AppendASCII("window.close.html"));
2260 base::string16 title = ASCIIToUTF16("Title Of Awesomeness");
2261 content::TitleWatcher title_watcher(
2262 browser()->tab_strip_model()->GetActiveWebContents(), title);
2263 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 2);
2264 EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
2267 // TODO(linux_aura) http://crbug.com/163931
2268 // Mac disabled: http://crbug.com/169820
2269 #if !defined(OS_MACOSX) && \
2270 !(defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA))
2271 IN_PROC_BROWSER_TEST_F(BrowserTest, FullscreenBookmarkBar) {
2272 #if defined(OS_WIN) && defined(USE_ASH)
2273 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
2274 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2275 switches::kAshBrowserTests))
2276 return;
2277 #endif
2279 chrome::ToggleBookmarkBar(browser());
2280 EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
2281 chrome::ToggleFullscreenMode(browser());
2282 EXPECT_TRUE(browser()->window()->IsFullscreen());
2283 #if defined(OS_MACOSX)
2284 EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
2285 #elif defined(OS_CHROMEOS)
2286 // TODO(jamescook): If immersive fullscreen is disabled by default, test
2287 // for BookmarkBar::HIDDEN.
2288 EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
2289 #else
2290 EXPECT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
2291 #endif
2293 #endif
2295 IN_PROC_BROWSER_TEST_F(BrowserTest, DisallowFileUrlUniversalAccessTest) {
2296 GURL url = ui_test_utils::GetTestUrl(
2297 base::FilePath(),
2298 base::FilePath().AppendASCII("fileurl_universalaccess.html"));
2300 base::string16 expected_title(ASCIIToUTF16("Disallowed"));
2301 content::TitleWatcher title_watcher(
2302 browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
2303 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("Allowed"));
2304 ui_test_utils::NavigateToURL(browser(), url);
2305 ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
2308 class KioskModeTest : public BrowserTest {
2309 public:
2310 KioskModeTest() {}
2312 void SetUpCommandLine(base::CommandLine* command_line) override {
2313 command_line->AppendSwitch(switches::kKioskMode);
2317 #if defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
2318 // Mac: http://crbug.com/103912
2319 // Linux: http://crbug.com/163931
2320 #define MAYBE_EnableKioskModeTest DISABLED_EnableKioskModeTest
2321 #else
2322 #define MAYBE_EnableKioskModeTest EnableKioskModeTest
2323 #endif
2324 IN_PROC_BROWSER_TEST_F(KioskModeTest, MAYBE_EnableKioskModeTest) {
2325 // Check if browser is in fullscreen mode.
2326 ASSERT_TRUE(browser()->window()->IsFullscreen());
2327 ASSERT_FALSE(browser()->window()->IsFullscreenBubbleVisible());
2330 #if defined(OS_WIN)
2331 // This test verifies that Chrome can be launched with a user-data-dir path
2332 // which contains non ASCII characters.
2333 class LaunchBrowserWithNonAsciiUserDatadir : public BrowserTest {
2334 public:
2335 LaunchBrowserWithNonAsciiUserDatadir() {}
2337 void SetUpCommandLine(base::CommandLine* command_line) override {
2338 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
2339 base::FilePath tmp_profile = temp_dir_.path().AppendASCII("tmp_profile");
2340 tmp_profile = tmp_profile.Append(L"Test Chrome G\u00E9raldine");
2342 ASSERT_TRUE(base::CreateDirectory(tmp_profile));
2343 command_line->AppendSwitchPath(switches::kUserDataDir, tmp_profile);
2346 base::ScopedTempDir temp_dir_;
2349 IN_PROC_BROWSER_TEST_F(LaunchBrowserWithNonAsciiUserDatadir,
2350 TestNonAsciiUserDataDir) {
2351 // Verify that the window is present.
2352 ASSERT_TRUE(browser());
2353 ASSERT_TRUE(browser()->profile());
2354 // Verify that the profile has been added correctly to the ProfileInfoCache.
2355 ASSERT_EQ(1u, g_browser_process->profile_manager()->
2356 GetProfileInfoCache().GetNumberOfProfiles());
2358 #endif // defined(OS_WIN)
2360 #if defined(OS_WIN)
2361 // This test verifies that Chrome can be launched with a user-data-dir path
2362 // which trailing slashes.
2363 class LaunchBrowserWithTrailingSlashDatadir : public BrowserTest {
2364 public:
2365 LaunchBrowserWithTrailingSlashDatadir() {}
2367 void SetUpCommandLine(base::CommandLine* command_line) override {
2368 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
2369 base::FilePath tmp_profile = temp_dir_.path().AppendASCII("tmp_profile");
2370 tmp_profile = tmp_profile.Append(L"Test Chrome\\");
2372 ASSERT_TRUE(base::CreateDirectory(tmp_profile));
2373 command_line->AppendSwitchPath(switches::kUserDataDir, tmp_profile);
2376 base::ScopedTempDir temp_dir_;
2379 IN_PROC_BROWSER_TEST_F(LaunchBrowserWithTrailingSlashDatadir,
2380 TestTrailingSlashUserDataDir) {
2381 // Verify that the window is present.
2382 ASSERT_TRUE(browser());
2383 ASSERT_TRUE(browser()->profile());
2384 // Verify that the profile has been added correctly to the ProfileInfoCache.
2385 ASSERT_EQ(1u, g_browser_process->profile_manager()->
2386 GetProfileInfoCache().GetNumberOfProfiles());
2388 #endif // defined(OS_WIN)
2390 // Tests to ensure that the browser continues running in the background after
2391 // the last window closes.
2392 class RunInBackgroundTest : public BrowserTest {
2393 public:
2394 RunInBackgroundTest() {}
2396 void SetUpCommandLine(base::CommandLine* command_line) override {
2397 command_line->AppendSwitch(switches::kKeepAliveForTest);
2401 IN_PROC_BROWSER_TEST_F(RunInBackgroundTest, RunInBackgroundBasicTest) {
2402 // Close the browser window, then open a new one - the browser should keep
2403 // running.
2404 Profile* profile = browser()->profile();
2405 EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
2406 content::WindowedNotificationObserver observer(
2407 chrome::NOTIFICATION_BROWSER_CLOSED,
2408 content::Source<Browser>(browser()));
2409 chrome::CloseWindow(browser());
2410 observer.Wait();
2411 EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
2413 ui_test_utils::BrowserAddedObserver browser_added_observer;
2414 chrome::NewEmptyWindow(profile, chrome::GetActiveDesktop());
2415 browser_added_observer.WaitForSingleNewBrowser();
2417 EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
2420 // Tests to ensure that the browser continues running in the background after
2421 // the last window closes.
2422 class NoStartupWindowTest : public BrowserTest {
2423 public:
2424 NoStartupWindowTest() {}
2426 void SetUpCommandLine(base::CommandLine* command_line) override {
2427 command_line->AppendSwitch(switches::kNoStartupWindow);
2428 command_line->AppendSwitch(switches::kKeepAliveForTest);
2431 // Returns true if any commands were processed.
2432 bool ProcessedAnyCommands(
2433 sessions::BaseSessionService* base_session_service) {
2434 sessions::BaseSessionServiceTestHelper test_helper(base_session_service);
2435 return test_helper.ProcessedAnyCommands();
2439 IN_PROC_BROWSER_TEST_F(NoStartupWindowTest, NoStartupWindowBasicTest) {
2440 #if defined(OS_WIN) && defined(USE_ASH)
2441 // kNoStartupWindow doesn't make sense in Metro+Ash.
2442 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2443 switches::kAshBrowserTests))
2444 return;
2445 #endif
2447 // No browser window should be started by default.
2448 EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
2450 // Starting a browser window should work just fine.
2451 ui_test_utils::BrowserAddedObserver browser_added_observer;
2452 CreateBrowser(ProfileManager::GetActiveUserProfile());
2453 browser_added_observer.WaitForSingleNewBrowser();
2455 EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
2458 // Chromeos needs to track app windows because it considers them to be part of
2459 // session state.
2460 #if !defined(OS_CHROMEOS)
2461 IN_PROC_BROWSER_TEST_F(NoStartupWindowTest, DontInitSessionServiceForApps) {
2462 #if defined(OS_WIN) && defined(USE_ASH)
2463 // kNoStartupWindow doesn't make sense in Metro+Ash.
2464 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2465 switches::kAshBrowserTests))
2466 return;
2467 #endif
2469 Profile* profile = ProfileManager::GetActiveUserProfile();
2471 SessionService* session_service =
2472 SessionServiceFactory::GetForProfile(profile);
2473 sessions::BaseSessionService* base_session_service =
2474 session_service->GetBaseSessionServiceForTest();
2475 ASSERT_FALSE(ProcessedAnyCommands(base_session_service));
2477 ui_test_utils::BrowserAddedObserver browser_added_observer;
2478 CreateBrowserForApp("blah", profile);
2479 browser_added_observer.WaitForSingleNewBrowser();
2481 ASSERT_FALSE(ProcessedAnyCommands(base_session_service));
2483 #endif // !defined(OS_CHROMEOS)
2485 // This test needs to be placed outside the anonymous namespace because we
2486 // need to access private type of Browser.
2487 class AppModeTest : public BrowserTest {
2488 public:
2489 AppModeTest() {}
2491 void SetUpCommandLine(base::CommandLine* command_line) override {
2492 GURL url = ui_test_utils::GetTestUrl(
2493 base::FilePath(), base::FilePath().AppendASCII("title1.html"));
2494 command_line->AppendSwitchASCII(switches::kApp, url.spec());
2498 IN_PROC_BROWSER_TEST_F(AppModeTest, EnableAppModeTest) {
2499 #if defined(OS_WIN) && defined(USE_ASH)
2500 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
2501 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2502 switches::kAshBrowserTests))
2503 return;
2504 #endif
2506 // Test that an application browser window loads correctly.
2508 // Verify the browser is in application mode.
2509 EXPECT_TRUE(browser()->is_app());
2512 // Confirm chrome://version contains some expected content.
2513 IN_PROC_BROWSER_TEST_F(BrowserTest, AboutVersion) {
2514 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL));
2515 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
2516 ASSERT_GT(ui_test_utils::FindInPage(tab, ASCIIToUTF16("WebKit"), true, true,
2517 NULL, NULL),
2519 ASSERT_GT(ui_test_utils::FindInPage(tab, ASCIIToUTF16("OS"), true, true,
2520 NULL, NULL),
2522 ASSERT_GT(ui_test_utils::FindInPage(tab, ASCIIToUTF16("JavaScript"), true,
2523 true, NULL, NULL),
2527 static const base::FilePath::CharType* kTestDir =
2528 FILE_PATH_LITERAL("click_modifier");
2529 static const char kFirstPageTitle[] = "First window";
2530 static const char kSecondPageTitle[] = "New window!";
2532 class ClickModifierTest : public InProcessBrowserTest {
2533 public:
2534 ClickModifierTest() {
2537 // Returns a url that opens a new window or tab when clicked, via javascript.
2538 GURL GetWindowOpenURL() {
2539 return ui_test_utils::GetTestUrl(
2540 base::FilePath(kTestDir),
2541 base::FilePath(FILE_PATH_LITERAL("window_open.html")));
2544 // Returns a url that follows a simple link when clicked, unless affected by
2545 // modifiers.
2546 GURL GetHrefURL() {
2547 return ui_test_utils::GetTestUrl(
2548 base::FilePath(kTestDir),
2549 base::FilePath(FILE_PATH_LITERAL("href.html")));
2552 base::string16 getFirstPageTitle() {
2553 return ASCIIToUTF16(kFirstPageTitle);
2556 base::string16 getSecondPageTitle() {
2557 return ASCIIToUTF16(kSecondPageTitle);
2560 // Loads our test page and simulates a single click using the supplied button
2561 // and modifiers. The click will cause either a navigation or the creation of
2562 // a new window or foreground or background tab. We verify that the expected
2563 // disposition occurs.
2564 void RunTest(Browser* browser,
2565 const GURL& url,
2566 int modifiers,
2567 blink::WebMouseEvent::Button button,
2568 WindowOpenDisposition disposition) {
2569 ui_test_utils::NavigateToURL(browser, url);
2570 EXPECT_EQ(1u, chrome::GetBrowserCount(browser->profile(),
2571 browser->host_desktop_type()));
2572 EXPECT_EQ(1, browser->tab_strip_model()->count());
2573 content::WebContents* web_contents =
2574 browser->tab_strip_model()->GetActiveWebContents();
2575 EXPECT_EQ(url, web_contents->GetURL());
2577 if (disposition == CURRENT_TAB) {
2578 content::WebContents* web_contents =
2579 browser->tab_strip_model()->GetActiveWebContents();
2580 content::TestNavigationObserver same_tab_observer(web_contents);
2581 SimulateMouseClick(web_contents, modifiers, button);
2582 same_tab_observer.Wait();
2583 EXPECT_EQ(1u, chrome::GetBrowserCount(browser->profile(),
2584 browser->host_desktop_type()));
2585 EXPECT_EQ(1, browser->tab_strip_model()->count());
2586 EXPECT_EQ(getSecondPageTitle(), web_contents->GetTitle());
2587 return;
2590 content::WindowedNotificationObserver observer(
2591 chrome::NOTIFICATION_TAB_ADDED,
2592 content::NotificationService::AllSources());
2593 SimulateMouseClick(web_contents, modifiers, button);
2594 observer.Wait();
2596 if (disposition == NEW_WINDOW) {
2597 EXPECT_EQ(2u, chrome::GetBrowserCount(browser->profile(),
2598 browser->host_desktop_type()));
2599 return;
2602 EXPECT_EQ(1u, chrome::GetBrowserCount(browser->profile(),
2603 browser->host_desktop_type()));
2604 EXPECT_EQ(2, browser->tab_strip_model()->count());
2605 web_contents = browser->tab_strip_model()->GetActiveWebContents();
2606 WaitForLoadStop(web_contents);
2607 if (disposition == NEW_FOREGROUND_TAB) {
2608 EXPECT_EQ(getSecondPageTitle(), web_contents->GetTitle());
2609 } else {
2610 ASSERT_EQ(NEW_BACKGROUND_TAB, disposition);
2611 EXPECT_EQ(getFirstPageTitle(), web_contents->GetTitle());
2615 private:
2616 DISALLOW_COPY_AND_ASSIGN(ClickModifierTest);
2619 // Tests for clicking on elements with handlers that run window.open.
2621 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenBasicClickTest) {
2622 int modifiers = 0;
2623 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2624 WindowOpenDisposition disposition = NEW_FOREGROUND_TAB;
2625 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2628 // TODO(ericu): Alt-click behavior on window.open is platform-dependent and not
2629 // well defined. Should we add tests so we know if it changes?
2631 // Shift-clicks open in a new window.
2632 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenShiftClickTest) {
2633 int modifiers = blink::WebInputEvent::ShiftKey;
2634 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2635 WindowOpenDisposition disposition = NEW_WINDOW;
2636 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2639 // Control-clicks open in a background tab.
2640 // On OSX meta [the command key] takes the place of control.
2641 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenControlClickTest) {
2642 #if defined(OS_MACOSX)
2643 int modifiers = blink::WebInputEvent::MetaKey;
2644 #else
2645 int modifiers = blink::WebInputEvent::ControlKey;
2646 #endif
2647 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2648 WindowOpenDisposition disposition = NEW_BACKGROUND_TAB;
2649 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2652 // Control-shift-clicks open in a foreground tab.
2653 // On OSX meta [the command key] takes the place of control.
2654 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenControlShiftClickTest) {
2655 #if defined(OS_MACOSX)
2656 int modifiers = blink::WebInputEvent::MetaKey;
2657 #else
2658 int modifiers = blink::WebInputEvent::ControlKey;
2659 #endif
2660 modifiers |= blink::WebInputEvent::ShiftKey;
2661 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2662 WindowOpenDisposition disposition = NEW_FOREGROUND_TAB;
2663 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2666 // Middle-clicks open in a background tab.
2667 #if defined(OS_LINUX)
2668 // http://crbug.com/396347
2669 #define MAYBE_WindowOpenMiddleClickTest DISABLED_WindowOpenMiddleClickTest
2670 #else
2671 #define MAYBE_WindowOpenMiddleClickTest WindowOpenMiddleClickTest
2672 #endif
2673 IN_PROC_BROWSER_TEST_F(ClickModifierTest, MAYBE_WindowOpenMiddleClickTest) {
2674 int modifiers = 0;
2675 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle;
2676 WindowOpenDisposition disposition = NEW_BACKGROUND_TAB;
2677 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2680 // Shift-middle-clicks open in a foreground tab.
2681 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenShiftMiddleClickTest) {
2682 int modifiers = blink::WebInputEvent::ShiftKey;
2683 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle;
2684 WindowOpenDisposition disposition = NEW_FOREGROUND_TAB;
2685 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2688 // Tests for clicking on normal links.
2690 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefBasicClickTest) {
2691 int modifiers = 0;
2692 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2693 WindowOpenDisposition disposition = CURRENT_TAB;
2694 RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2697 // TODO(ericu): Alt-click behavior on links is platform-dependent and not well
2698 // defined. Should we add tests so we know if it changes?
2700 // Shift-clicks open in a new window.
2701 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefShiftClickTest) {
2702 int modifiers = blink::WebInputEvent::ShiftKey;
2703 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2704 WindowOpenDisposition disposition = NEW_WINDOW;
2705 RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2708 // Control-clicks open in a background tab.
2709 // On OSX meta [the command key] takes the place of control.
2710 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefControlClickTest) {
2711 #if defined(OS_MACOSX)
2712 int modifiers = blink::WebInputEvent::MetaKey;
2713 #else
2714 int modifiers = blink::WebInputEvent::ControlKey;
2715 #endif
2716 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2717 WindowOpenDisposition disposition = NEW_BACKGROUND_TAB;
2718 RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2721 // Control-shift-clicks open in a foreground tab.
2722 // On OSX meta [the command key] takes the place of control.
2723 // http://crbug.com/396347
2724 IN_PROC_BROWSER_TEST_F(ClickModifierTest, DISABLED_HrefControlShiftClickTest) {
2725 #if defined(OS_MACOSX)
2726 int modifiers = blink::WebInputEvent::MetaKey;
2727 #else
2728 int modifiers = blink::WebInputEvent::ControlKey;
2729 #endif
2730 modifiers |= blink::WebInputEvent::ShiftKey;
2731 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2732 WindowOpenDisposition disposition = NEW_FOREGROUND_TAB;
2733 RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2736 // Middle-clicks open in a background tab.
2737 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefMiddleClickTest) {
2738 int modifiers = 0;
2739 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle;
2740 WindowOpenDisposition disposition = NEW_BACKGROUND_TAB;
2741 RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2744 // Shift-middle-clicks open in a foreground tab.
2745 // http://crbug.com/396347
2746 IN_PROC_BROWSER_TEST_F(ClickModifierTest, DISABLED_HrefShiftMiddleClickTest) {
2747 int modifiers = blink::WebInputEvent::ShiftKey;
2748 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle;
2749 WindowOpenDisposition disposition = NEW_FOREGROUND_TAB;
2750 RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2753 IN_PROC_BROWSER_TEST_F(BrowserTest, GetSizeForNewRenderView) {
2754 #if defined(OS_MACOSX) && !defined(OS_IOS)
2755 // TODO(erikchen): This behavior has regressed on OSX 10.7 and 10.8 and should
2756 // be fixed. http://crbug.com/503185
2757 if (base::mac::IsOSMountainLion() || base::mac::IsOSLion())
2758 return;
2759 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
2760 // The instant extended NTP has javascript that does not work with
2761 // ui_test_utils::NavigateToURL. The NTP rvh reloads when the browser tries
2762 // to navigate away from the page, which causes the WebContents to end up in
2763 // an inconsistent state. (is_loaded = true, last_commited_url=ntp,
2764 // visible_url=title1.html)
2765 browser()->profile()->GetPrefs()->SetBoolean(prefs::kWebKitJavascriptEnabled,
2766 false);
2767 ASSERT_TRUE(test_server()->Start());
2768 // Create an HTTPS server for cross-site transition.
2769 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
2770 net::SpawnedTestServer::kLocalhost,
2771 base::FilePath(kDocRoot));
2772 ASSERT_TRUE(https_test_server.Start());
2774 // Start with NTP.
2775 ui_test_utils::NavigateToURL(browser(), GURL("chrome://newtab"));
2776 ASSERT_EQ(BookmarkBar::DETACHED, browser()->bookmark_bar_state());
2777 WebContents* web_contents =
2778 browser()->tab_strip_model()->GetActiveWebContents();
2779 content::RenderViewHost* prev_rvh = web_contents->GetRenderViewHost();
2780 const int height_inset =
2781 browser()->window()->GetRenderViewHeightInsetWithDetachedBookmarkBar();
2782 const gfx::Size initial_wcv_size =
2783 web_contents->GetContainerBounds().size();
2784 RenderViewSizeObserver observer(web_contents, browser()->window());
2786 // Navigate to a non-NTP page, without resizing WebContentsView.
2787 ui_test_utils::NavigateToURL(browser(),
2788 test_server()->GetURL("files/title1.html"));
2789 ASSERT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
2790 // A new RenderViewHost should be created.
2791 EXPECT_NE(prev_rvh, web_contents->GetRenderViewHost());
2792 prev_rvh = web_contents->GetRenderViewHost();
2793 gfx::Size rwhv_create_size0, rwhv_commit_size0, wcv_commit_size0;
2794 observer.GetSizeForRenderViewHost(web_contents->GetRenderViewHost(),
2795 &rwhv_create_size0,
2796 &rwhv_commit_size0,
2797 &wcv_commit_size0);
2798 // The create height of RenderWidgetHostView should include the height inset.
2799 EXPECT_EQ(gfx::Size(initial_wcv_size.width(),
2800 initial_wcv_size.height() + height_inset),
2801 rwhv_create_size0);
2802 // When a navigation entry is committed, the size of RenderWidgetHostView
2803 // should be the same as when it was first created.
2804 EXPECT_EQ(rwhv_create_size0, rwhv_commit_size0);
2805 // Sizes of the current RenderWidgetHostView and WebContentsView should not
2806 // change before and after WebContentsDelegate::DidNavigateMainFramePostCommit
2807 // (implemented by Browser); we obtain the sizes before PostCommit via
2808 // WebContentsObserver::NavigationEntryCommitted (implemented by
2809 // RenderViewSizeObserver).
2810 EXPECT_EQ(rwhv_commit_size0,
2811 web_contents->GetRenderWidgetHostView()->GetViewBounds().size());
2812 // The behavior differs between OSX and views.
2813 // In OSX, the wcv does not change size until after the commit, when the
2814 // bookmark bar disappears (correct).
2815 // In views, the wcv changes size at commit time.
2816 #if defined(OS_MACOSX)
2817 EXPECT_EQ(gfx::Size(wcv_commit_size0.width(),
2818 wcv_commit_size0.height() + height_inset),
2819 web_contents->GetContainerBounds().size());
2820 #else
2821 EXPECT_EQ(wcv_commit_size0, web_contents->GetContainerBounds().size());
2822 #endif
2824 // Navigate to another non-NTP page, without resizing WebContentsView.
2825 ui_test_utils::NavigateToURL(browser(),
2826 https_test_server.GetURL("files/title2.html"));
2827 ASSERT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
2828 // A new RenderVieHost should be created.
2829 EXPECT_NE(prev_rvh, web_contents->GetRenderViewHost());
2830 gfx::Size rwhv_create_size1, rwhv_commit_size1, wcv_commit_size1;
2831 observer.GetSizeForRenderViewHost(web_contents->GetRenderViewHost(),
2832 &rwhv_create_size1,
2833 &rwhv_commit_size1,
2834 &wcv_commit_size1);
2835 EXPECT_EQ(rwhv_create_size1, rwhv_commit_size1);
2836 EXPECT_EQ(rwhv_commit_size1,
2837 web_contents->GetRenderWidgetHostView()->GetViewBounds().size());
2838 EXPECT_EQ(wcv_commit_size1, web_contents->GetContainerBounds().size());
2840 // Navigate from NTP to a non-NTP page, resizing WebContentsView while
2841 // navigation entry is pending.
2842 ui_test_utils::NavigateToURL(browser(), GURL("chrome://newtab"));
2843 gfx::Size wcv_resize_insets(1, 1);
2844 observer.set_wcv_resize_insets(wcv_resize_insets);
2845 ui_test_utils::NavigateToURL(browser(),
2846 test_server()->GetURL("files/title2.html"));
2847 ASSERT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
2848 gfx::Size rwhv_create_size2, rwhv_commit_size2, wcv_commit_size2;
2849 observer.GetSizeForRenderViewHost(web_contents->GetRenderViewHost(),
2850 &rwhv_create_size2,
2851 &rwhv_commit_size2,
2852 &wcv_commit_size2);
2854 // The behavior on OSX and Views is incorrect in this edge case, but they are
2855 // differently incorrect.
2856 // The behavior should be:
2857 // initial wcv size: (100,100) (to choose random numbers)
2858 // initial rwhv size: (100,140)
2859 // commit wcv size: (101, 101)
2860 // commit rwhv size: (101, 141)
2861 // final wcv size: (101, 141)
2862 // final rwhv size: (101, 141)
2864 // On OSX, the commit rwhv size is (101, 101)
2865 // On views, the commit wcv size is (101, 141)
2866 // All other sizes are correct.
2868 // The create height of RenderWidgetHostView should include the height inset.
2869 EXPECT_EQ(gfx::Size(initial_wcv_size.width(),
2870 initial_wcv_size.height() + height_inset),
2871 rwhv_create_size2);
2872 gfx::Size exp_commit_size(initial_wcv_size);
2874 #if defined(OS_MACOSX)
2875 exp_commit_size.Enlarge(wcv_resize_insets.width(),
2876 wcv_resize_insets.height());
2877 #else
2878 exp_commit_size.Enlarge(wcv_resize_insets.width(),
2879 wcv_resize_insets.height() + height_inset);
2880 #endif
2881 EXPECT_EQ(exp_commit_size, rwhv_commit_size2);
2882 EXPECT_EQ(exp_commit_size, wcv_commit_size2);
2883 gfx::Size exp_final_size(initial_wcv_size);
2884 exp_final_size.Enlarge(wcv_resize_insets.width(),
2885 wcv_resize_insets.height() + height_inset);
2886 EXPECT_EQ(exp_final_size,
2887 web_contents->GetRenderWidgetHostView()->GetViewBounds().size());
2888 EXPECT_EQ(exp_final_size, web_contents->GetContainerBounds().size());
2891 IN_PROC_BROWSER_TEST_F(BrowserTest, CanDuplicateTab) {
2892 GURL url(ui_test_utils::GetTestUrl(
2893 base::FilePath(base::FilePath::kCurrentDirectory),
2894 base::FilePath(kTitle1File)));
2895 ui_test_utils::NavigateToURL(browser(), url);
2897 AddTabAtIndex(0, url, ui::PAGE_TRANSITION_TYPED);
2899 int active_index = browser()->tab_strip_model()->active_index();
2900 EXPECT_EQ(0, active_index);
2902 EXPECT_TRUE(chrome::CanDuplicateTab(browser()));
2903 EXPECT_TRUE(chrome::CanDuplicateTabAt(browser(), 0));
2904 EXPECT_TRUE(chrome::CanDuplicateTabAt(browser(), 1));
2906 content::WebContents* web_contents =
2907 browser()->tab_strip_model()->GetActiveWebContents();
2909 TestInterstitialPage* interstitial =
2910 new TestInterstitialPage(web_contents, false, GURL());
2911 content::WaitForInterstitialAttach(web_contents);
2913 EXPECT_TRUE(web_contents->ShowingInterstitialPage());
2915 // Verify that the "Duplicate tab" command is disabled on interstitial
2916 // pages. Regression test for crbug.com/310812
2917 EXPECT_FALSE(chrome::CanDuplicateTab(browser()));
2918 EXPECT_FALSE(chrome::CanDuplicateTabAt(browser(), 0));
2919 EXPECT_TRUE(chrome::CanDuplicateTabAt(browser(), 1));
2921 // Don't proceed and wait for interstitial to detach. This doesn't
2922 // destroy |contents|.
2923 interstitial->DontProceed();
2924 content::WaitForInterstitialDetach(web_contents);
2925 // interstitial is deleted now.
2927 EXPECT_TRUE(chrome::CanDuplicateTab(browser()));
2928 EXPECT_TRUE(chrome::CanDuplicateTabAt(browser(), 0));
2929 EXPECT_TRUE(chrome::CanDuplicateTabAt(browser(), 1));
2932 // Tests that the WebContentsObserver::SecurityStyleChanged event fires
2933 // with the current style on HTTP, broken HTTPS, and valid HTTPS pages.
2934 IN_PROC_BROWSER_TEST_F(BrowserTest, SecurityStyleChangedObserver) {
2935 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
2936 net::SpawnedTestServer::kLocalhost,
2937 base::FilePath(kDocRoot));
2938 net::SpawnedTestServer https_test_server_expired(
2939 net::SpawnedTestServer::TYPE_HTTPS,
2940 net::SpawnedTestServer::SSLOptions(
2941 net::SpawnedTestServer::SSLOptions::CERT_EXPIRED),
2942 base::FilePath(kDocRoot));
2944 ASSERT_TRUE(https_test_server.Start());
2945 ASSERT_TRUE(https_test_server_expired.Start());
2946 ASSERT_TRUE(test_server()->Start());
2948 content::WebContents* web_contents =
2949 browser()->tab_strip_model()->GetActiveWebContents();
2950 SecurityStyleTestObserver observer(web_contents);
2952 // Visit an HTTP url.
2953 GURL http_url(test_server()->GetURL(std::string()));
2954 ui_test_utils::NavigateToURL(browser(), http_url);
2955 EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED,
2956 observer.latest_security_style());
2957 EXPECT_EQ(0u, observer.latest_explanations().warning_explanations.size());
2958 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size());
2959 EXPECT_EQ(0u, observer.latest_explanations().secure_explanations.size());
2960 EXPECT_FALSE(observer.latest_explanations().scheme_is_cryptographic);
2961 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content);
2962 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content);
2964 // Visit an (otherwise valid) HTTPS page that displays mixed content.
2965 std::string replacement_path;
2966 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
2967 "files/ssl/page_displays_insecure_content.html",
2968 test_server()->host_port_pair(), &replacement_path));
2970 GURL mixed_content_url(https_test_server.GetURL(replacement_path));
2971 ui_test_utils::NavigateToURL(browser(), mixed_content_url);
2972 EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED,
2973 observer.latest_security_style());
2975 const content::SecurityStyleExplanations& mixed_content_explanation =
2976 observer.latest_explanations();
2977 ASSERT_EQ(0u, mixed_content_explanation.warning_explanations.size());
2978 ASSERT_EQ(0u, mixed_content_explanation.broken_explanations.size());
2979 CheckSecureExplanations(mixed_content_explanation.secure_explanations,
2980 VALID_CERTIFICATE);
2981 EXPECT_TRUE(mixed_content_explanation.scheme_is_cryptographic);
2982 EXPECT_TRUE(mixed_content_explanation.displayed_insecure_content);
2983 EXPECT_FALSE(mixed_content_explanation.ran_insecure_content);
2984 EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED,
2985 mixed_content_explanation.displayed_insecure_content_style);
2986 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN,
2987 mixed_content_explanation.ran_insecure_content_style);
2989 // Visit a broken HTTPS url.
2990 GURL expired_url(https_test_server_expired.GetURL(std::string()));
2991 ui_test_utils::NavigateToURL(browser(), expired_url);
2993 // An interstitial should show, and an event for the lock icon on the
2994 // interstitial should fire.
2995 content::WaitForInterstitialAttach(web_contents);
2996 EXPECT_TRUE(web_contents->ShowingInterstitialPage());
2997 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID);
2998 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
2999 INVALID_CERTIFICATE);
3000 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
3001 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content);
3002 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content);
3004 // Before clicking through, navigate to a different page, and then go
3005 // back to the interstitial.
3006 GURL valid_https_url(https_test_server.GetURL(std::string()));
3007 ui_test_utils::NavigateToURL(browser(), valid_https_url);
3008 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED,
3009 observer.latest_security_style());
3010 EXPECT_EQ(0u, observer.latest_explanations().warning_explanations.size());
3011 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size());
3012 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
3013 VALID_CERTIFICATE);
3014 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
3015 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content);
3016 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content);
3018 // After going back to the interstitial, an event for a broken lock
3019 // icon should fire again.
3020 ui_test_utils::NavigateToURL(browser(), expired_url);
3021 content::WaitForInterstitialAttach(web_contents);
3022 EXPECT_TRUE(web_contents->ShowingInterstitialPage());
3023 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID);
3024 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
3025 INVALID_CERTIFICATE);
3026 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
3027 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content);
3028 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content);
3030 // Since the next expected style is the same as the previous, clear
3031 // the observer (to make sure that the event fires twice and we don't
3032 // just see the previous event's style).
3033 observer.ClearLatestSecurityStyleAndExplanations();
3035 // Other conditions cannot be tested on this host after clicking
3036 // through because once the interstitial is clicked through, all URLs
3037 // for this host will remain in a broken state.
3038 ProceedThroughInterstitial(web_contents);
3039 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID);
3040 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
3041 INVALID_CERTIFICATE);
3042 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
3043 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content);
3044 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content);
3047 // Visit a valid HTTPS page, then a broken HTTPS page, and then go back,
3048 // and test that the observed security style matches.
3049 IN_PROC_BROWSER_TEST_F(BrowserTest, SecurityStyleChangedObserverGoBack) {
3050 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
3051 net::SpawnedTestServer::kLocalhost,
3052 base::FilePath(kDocRoot));
3054 // Use a separate server to work around a mysterious SSL handshake
3055 // timeout when both requests go to the same server. See
3056 // https://crbug.com/515906.
3057 net::SpawnedTestServer https_test_server_expired(
3058 net::SpawnedTestServer::TYPE_HTTPS,
3059 net::SpawnedTestServer::SSLOptions(
3060 net::SpawnedTestServer::SSLOptions::CERT_EXPIRED),
3061 base::FilePath(kDocRoot));
3063 ASSERT_TRUE(https_test_server.Start());
3064 ASSERT_TRUE(https_test_server_expired.Start());
3066 content::WebContents* web_contents =
3067 browser()->tab_strip_model()->GetActiveWebContents();
3068 SecurityStyleTestObserver observer(web_contents);
3070 // Visit a valid HTTPS url.
3071 GURL valid_https_url(https_test_server.GetURL(std::string()));
3072 ui_test_utils::NavigateToURL(browser(), valid_https_url);
3073 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED,
3074 observer.latest_security_style());
3075 EXPECT_EQ(0u, observer.latest_explanations().warning_explanations.size());
3076 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size());
3077 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
3078 VALID_CERTIFICATE);
3079 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
3080 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content);
3081 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content);
3083 // Navigate to a bad HTTPS page on a different host, and then click
3084 // Back to verify that the previous good security style is seen again.
3085 GURL expired_https_url(https_test_server_expired.GetURL(std::string()));
3086 host_resolver()->AddRule("www.example_broken.test", "127.0.0.1");
3087 GURL::Replacements replace_host;
3088 replace_host.SetHostStr("www.example_broken.test");
3089 GURL https_url_different_host =
3090 expired_https_url.ReplaceComponents(replace_host);
3092 ui_test_utils::NavigateToURL(browser(), https_url_different_host);
3094 content::WaitForInterstitialAttach(web_contents);
3095 EXPECT_TRUE(web_contents->ShowingInterstitialPage());
3096 CheckBrokenSecurityStyle(observer, net::ERR_CERT_COMMON_NAME_INVALID);
3097 ProceedThroughInterstitial(web_contents);
3098 CheckBrokenSecurityStyle(observer, net::ERR_CERT_COMMON_NAME_INVALID);
3099 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
3100 INVALID_CERTIFICATE);
3101 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
3102 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content);
3103 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content);
3105 content::WindowedNotificationObserver back_nav_load_observer(
3106 content::NOTIFICATION_LOAD_STOP,
3107 content::Source<NavigationController>(&web_contents->GetController()));
3108 chrome::GoBack(browser(), CURRENT_TAB);
3109 back_nav_load_observer.Wait();
3111 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED,
3112 observer.latest_security_style());
3113 EXPECT_EQ(0u, observer.latest_explanations().warning_explanations.size());
3114 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size());
3115 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
3116 VALID_CERTIFICATE);
3117 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
3118 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content);
3119 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content);