Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / ui / blocked_content / popup_blocker_browsertest.cc
blob6bfcc9fd3cec925c177481f89841e419d9bbaa0c
1 // Copyright 2013 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 "base/command_line.h"
6 #include "base/files/file_path.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/path_service.h"
9 #include "base/run_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/content_settings/host_content_settings_map.h"
13 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/search_engines/template_url_service_factory.h"
16 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_commands.h"
19 #include "chrome/browser/ui/browser_finder.h"
20 #include "chrome/browser/ui/browser_window.h"
21 #include "chrome/browser/ui/location_bar/location_bar.h"
22 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
23 #include "chrome/browser/ui/omnibox/omnibox_view.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/common/chrome_paths.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/test/base/in_process_browser_test.h"
28 #include "chrome/test/base/test_switches.h"
29 #include "chrome/test/base/ui_test_utils.h"
30 #include "components/omnibox/autocomplete_match.h"
31 #include "components/omnibox/autocomplete_result.h"
32 #include "content/public/browser/notification_registrar.h"
33 #include "content/public/browser/notification_service.h"
34 #include "content/public/browser/render_frame_host.h"
35 #include "content/public/browser/web_contents.h"
36 #include "content/public/browser/web_contents_observer.h"
37 #include "content/public/common/url_constants.h"
38 #include "content/public/test/browser_test_utils.h"
39 #include "content/public/test/test_navigation_observer.h"
40 #include "net/dns/mock_host_resolver.h"
41 #include "net/test/embedded_test_server/embedded_test_server.h"
42 #include "testing/gtest/include/gtest/gtest.h"
44 using content::WebContents;
46 namespace {
48 // Counts the number of RenderViewHosts created.
49 class CountRenderViewHosts : public content::NotificationObserver {
50 public:
51 CountRenderViewHosts()
52 : count_(0) {
53 registrar_.Add(this,
54 content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
55 content::NotificationService::AllSources());
57 virtual ~CountRenderViewHosts() {}
59 int GetRenderViewHostCreatedCount() const { return count_; }
61 private:
62 virtual void Observe(int type,
63 const content::NotificationSource& source,
64 const content::NotificationDetails& details) override {
65 count_++;
68 content::NotificationRegistrar registrar_;
70 int count_;
72 DISALLOW_COPY_AND_ASSIGN(CountRenderViewHosts);
75 class CloseObserver : public content::WebContentsObserver {
76 public:
77 explicit CloseObserver(WebContents* contents)
78 : content::WebContentsObserver(contents) {}
80 void Wait() {
81 close_loop_.Run();
84 virtual void WebContentsDestroyed() override {
85 close_loop_.Quit();
88 private:
89 base::RunLoop close_loop_;
91 DISALLOW_COPY_AND_ASSIGN(CloseObserver);
94 class PopupBlockerBrowserTest : public InProcessBrowserTest {
95 public:
96 PopupBlockerBrowserTest() {}
97 virtual ~PopupBlockerBrowserTest() {}
99 virtual void SetUpOnMainThread() override {
100 InProcessBrowserTest::SetUpOnMainThread();
102 host_resolver()->AddRule("*", "127.0.0.1");
103 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
106 int GetBlockedContentsCount() {
107 // Do a round trip to the renderer first to flush any in-flight IPCs to
108 // create a to-be-blocked window.
109 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
110 CHECK(content::ExecuteScript(tab, std::string()));
111 PopupBlockerTabHelper* popup_blocker_helper =
112 PopupBlockerTabHelper::FromWebContents(tab);
113 return popup_blocker_helper->GetBlockedPopupsCount();
116 enum WhatToExpect {
117 ExpectPopup,
118 ExpectTab
121 enum ShouldCheckTitle {
122 CheckTitle,
123 DontCheckTitle
126 void NavigateAndCheckPopupShown(const GURL& url,
127 WhatToExpect what_to_expect) {
128 content::WindowedNotificationObserver observer(
129 chrome::NOTIFICATION_TAB_ADDED,
130 content::NotificationService::AllSources());
131 ui_test_utils::NavigateToURL(browser(), url);
132 observer.Wait();
134 if (what_to_expect == ExpectPopup) {
135 ASSERT_EQ(2u,
136 chrome::GetBrowserCount(browser()->profile(),
137 browser()->host_desktop_type()));
138 } else {
139 ASSERT_EQ(1u,
140 chrome::GetBrowserCount(browser()->profile(),
141 browser()->host_desktop_type()));
142 ASSERT_EQ(2, browser()->tab_strip_model()->count());
145 ASSERT_EQ(0, GetBlockedContentsCount());
148 // Navigates to the test indicated by |test_name| using |browser| which is
149 // expected to try to open a popup. Verifies that the popup was blocked and
150 // then opens the blocked popup. Once the popup stopped loading, verifies
151 // that the title of the page is "PASS" if |check_title| is set.
153 // If |what_to_expect| is ExpectPopup, the popup is expected to open a new
154 // window, or a background tab if it is false.
156 // Returns the WebContents of the launched popup.
157 WebContents* RunCheckTest(Browser* browser,
158 const std::string& test_name,
159 WhatToExpect what_to_expect,
160 ShouldCheckTitle check_title) {
161 GURL url(embedded_test_server()->GetURL(test_name));
163 CountRenderViewHosts counter;
165 ui_test_utils::NavigateToURL(browser, url);
167 // Since the popup blocker blocked the window.open, there should be only one
168 // tab.
169 EXPECT_EQ(1u, chrome::GetBrowserCount(browser->profile(),
170 browser->host_desktop_type()));
171 EXPECT_EQ(1, browser->tab_strip_model()->count());
172 WebContents* web_contents =
173 browser->tab_strip_model()->GetActiveWebContents();
174 EXPECT_EQ(url, web_contents->GetURL());
176 // And no new RVH created.
177 EXPECT_EQ(0, counter.GetRenderViewHostCreatedCount());
179 content::WindowedNotificationObserver observer(
180 chrome::NOTIFICATION_TAB_ADDED,
181 content::NotificationService::AllSources());
182 ui_test_utils::BrowserAddedObserver browser_observer;
184 // Launch the blocked popup.
185 PopupBlockerTabHelper* popup_blocker_helper =
186 PopupBlockerTabHelper::FromWebContents(web_contents);
187 if (!popup_blocker_helper->GetBlockedPopupsCount()) {
188 content::WindowedNotificationObserver observer(
189 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
190 content::NotificationService::AllSources());
191 observer.Wait();
193 EXPECT_EQ(1u, popup_blocker_helper->GetBlockedPopupsCount());
194 std::map<int32, GURL> blocked_requests =
195 popup_blocker_helper->GetBlockedPopupRequests();
196 std::map<int32, GURL>::const_iterator iter = blocked_requests.begin();
197 popup_blocker_helper->ShowBlockedPopup(iter->first);
199 observer.Wait();
200 Browser* new_browser;
201 if (what_to_expect == ExpectPopup) {
202 new_browser = browser_observer.WaitForSingleNewBrowser();
203 web_contents = new_browser->tab_strip_model()->GetActiveWebContents();
204 } else {
205 new_browser = browser;
206 EXPECT_EQ(2, browser->tab_strip_model()->count());
207 web_contents = browser->tab_strip_model()->GetWebContentsAt(1);
210 if (check_title == CheckTitle) {
211 // Check that the check passed.
212 base::string16 expected_title(base::ASCIIToUTF16("PASS"));
213 content::TitleWatcher title_watcher(web_contents, expected_title);
214 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
217 return web_contents;
220 private:
221 DISALLOW_COPY_AND_ASSIGN(PopupBlockerBrowserTest);
224 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
225 BlockWebContentsCreation) {
226 #if defined(OS_WIN) && defined(USE_ASH)
227 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
228 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
229 return;
230 #endif
232 RunCheckTest(
233 browser(),
234 "/popup_blocker/popup-blocked-to-post-blank.html",
235 ExpectPopup,
236 DontCheckTitle);
239 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
240 BlockWebContentsCreationIncognito) {
241 #if defined(OS_WIN) && defined(USE_ASH)
242 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
243 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
244 return;
245 #endif
247 RunCheckTest(
248 CreateIncognitoBrowser(),
249 "/popup_blocker/popup-blocked-to-post-blank.html",
250 ExpectPopup,
251 DontCheckTitle);
254 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
255 PopupBlockedFakeClickOnAnchor) {
256 #if defined(OS_WIN) && defined(USE_ASH)
257 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
258 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
259 return;
260 #endif
262 RunCheckTest(
263 browser(),
264 "/popup_blocker/popup-fake-click-on-anchor.html",
265 ExpectTab,
266 DontCheckTitle);
269 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
270 PopupBlockedFakeClickOnAnchorNoTarget) {
271 #if defined(OS_WIN) && defined(USE_ASH)
272 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
273 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
274 return;
275 #endif
277 RunCheckTest(
278 browser(),
279 "/popup_blocker/popup-fake-click-on-anchor2.html",
280 ExpectTab,
281 DontCheckTitle);
284 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, MultiplePopups) {
285 GURL url(embedded_test_server()->GetURL("/popup_blocker/popup-many.html"));
286 ui_test_utils::NavigateToURL(browser(), url);
287 ASSERT_EQ(2, GetBlockedContentsCount());
290 // Verify that popups are launched on browser back button.
291 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
292 AllowPopupThroughContentSetting) {
293 GURL url(embedded_test_server()->GetURL(
294 "/popup_blocker/popup-blocked-to-post-blank.html"));
295 browser()->profile()->GetHostContentSettingsMap()
296 ->SetContentSetting(ContentSettingsPattern::FromURL(url),
297 ContentSettingsPattern::Wildcard(),
298 CONTENT_SETTINGS_TYPE_POPUPS,
299 std::string(),
300 CONTENT_SETTING_ALLOW);
302 NavigateAndCheckPopupShown(url, ExpectTab);
305 // Verify that content settings are applied based on the top-level frame URL.
306 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
307 AllowPopupThroughContentSettingIFrame) {
308 GURL url(embedded_test_server()->GetURL("/popup_blocker/popup-frames.html"));
309 browser()->profile()->GetHostContentSettingsMap()
310 ->SetContentSetting(ContentSettingsPattern::FromURL(url),
311 ContentSettingsPattern::Wildcard(),
312 CONTENT_SETTINGS_TYPE_POPUPS,
313 std::string(),
314 CONTENT_SETTING_ALLOW);
316 // Popup from the iframe should be allowed since the top-level URL is
317 // whitelisted.
318 NavigateAndCheckPopupShown(url, ExpectTab);
320 // Whitelist iframe URL instead.
321 GURL::Replacements replace_host;
322 std::string host_str("www.a.com"); // Must stay in scope with replace_host
323 replace_host.SetHostStr(host_str);
324 GURL frame_url(embedded_test_server()
325 ->GetURL("/popup_blocker/popup-frames-iframe.html")
326 .ReplaceComponents(replace_host));
327 browser()->profile()->GetHostContentSettingsMap()->ClearSettingsForOneType(
328 CONTENT_SETTINGS_TYPE_POPUPS);
329 browser()->profile()->GetHostContentSettingsMap()
330 ->SetContentSetting(ContentSettingsPattern::FromURL(frame_url),
331 ContentSettingsPattern::Wildcard(),
332 CONTENT_SETTINGS_TYPE_POPUPS,
333 std::string(),
334 CONTENT_SETTING_ALLOW);
336 // Popup should be blocked.
337 ui_test_utils::NavigateToURL(browser(), url);
338 ASSERT_EQ(1, GetBlockedContentsCount());
341 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
342 PopupsLaunchWhenTabIsClosed) {
343 CommandLine::ForCurrentProcess()->AppendSwitch(
344 switches::kDisablePopupBlocking);
345 GURL url(
346 embedded_test_server()->GetURL("/popup_blocker/popup-on-unload.html"));
347 ui_test_utils::NavigateToURL(browser(), url);
349 NavigateAndCheckPopupShown(embedded_test_server()->GetURL("/popup_blocker/"),
350 ExpectPopup);
353 // Verify that when you unblock popup, the popup shows in history and omnibox.
354 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
355 UnblockedPopupShowsInHistoryAndOmnibox) {
356 CommandLine::ForCurrentProcess()->AppendSwitch(
357 switches::kDisablePopupBlocking);
358 GURL url(embedded_test_server()->GetURL(
359 "/popup_blocker/popup-blocked-to-post-blank.html"));
360 NavigateAndCheckPopupShown(url, ExpectTab);
362 std::string search_string =
363 "data:text/html,<title>Popup Success!</title>you should not see this "
364 "message if popup blocker is enabled";
366 ui_test_utils::HistoryEnumerator history(browser()->profile());
367 std::vector<GURL>& history_urls = history.urls();
368 ASSERT_EQ(2u, history_urls.size());
369 ASSERT_EQ(GURL(search_string), history_urls[0]);
370 ASSERT_EQ(url, history_urls[1]);
372 TemplateURLService* service = TemplateURLServiceFactory::GetForProfile(
373 browser()->profile());
374 ui_test_utils::WaitForTemplateURLServiceToLoad(service);
375 LocationBar* location_bar = browser()->window()->GetLocationBar();
376 ui_test_utils::SendToOmniboxAndSubmit(location_bar, search_string);
377 OmniboxEditModel* model = location_bar->GetOmniboxView()->model();
378 EXPECT_EQ(GURL(search_string), model->CurrentMatch(NULL).destination_url);
379 EXPECT_EQ(base::ASCIIToUTF16(search_string),
380 model->CurrentMatch(NULL).contents);
383 // This test fails on linux AURA with this change
384 // https://codereview.chromium.org/23903056
385 // BUG=https://code.google.com/p/chromium/issues/detail?id=295299
386 // TODO(ananta). Debug and fix this test.
387 #if defined(USE_AURA) && defined(OS_LINUX)
388 #define MAYBE_WindowFeatures DISABLED_WindowFeatures
389 #else
390 #define MAYBE_WindowFeatures WindowFeatures
391 #endif
392 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, MAYBE_WindowFeatures) {
393 WebContents* popup =
394 RunCheckTest(browser(),
395 "/popup_blocker/popup-window-open.html",
396 ExpectPopup,
397 DontCheckTitle);
399 // Check that the new popup has (roughly) the requested size.
400 gfx::Size window_size = popup->GetContainerBounds().size();
401 EXPECT_TRUE(349 <= window_size.width() && window_size.width() <= 351);
402 EXPECT_TRUE(249 <= window_size.height() && window_size.height() <= 251);
405 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, CorrectReferrer) {
406 RunCheckTest(browser(),
407 "/popup_blocker/popup-referrer.html",
408 ExpectPopup,
409 CheckTitle);
412 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, WindowFeaturesBarProps) {
413 RunCheckTest(browser(),
414 "/popup_blocker/popup-windowfeatures.html",
415 ExpectPopup,
416 CheckTitle);
419 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, SessionStorage) {
420 RunCheckTest(browser(),
421 "/popup_blocker/popup-sessionstorage.html",
422 ExpectPopup,
423 CheckTitle);
426 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, Opener) {
427 RunCheckTest(browser(),
428 "/popup_blocker/popup-opener.html",
429 ExpectPopup,
430 CheckTitle);
433 // Tests that the popup can still close itself after navigating. This tests that
434 // the openedByDOM bit is preserved across blocked popups.
435 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, ClosableAfterNavigation) {
436 // Open a popup.
437 WebContents* popup =
438 RunCheckTest(browser(),
439 "/popup_blocker/popup-opener.html",
440 ExpectPopup,
441 CheckTitle);
443 // Navigate it elsewhere.
444 content::TestNavigationObserver nav_observer(popup);
445 popup->GetMainFrame()->ExecuteJavaScript(
446 base::UTF8ToUTF16("location.href = '/empty.html'"));
447 nav_observer.Wait();
449 // Have it close itself.
450 CloseObserver close_observer(popup);
451 popup->GetMainFrame()->ExecuteJavaScript(
452 base::UTF8ToUTF16("window.close()"));
453 close_observer.Wait();
456 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, OpenerSuppressed) {
457 RunCheckTest(browser(),
458 "/popup_blocker/popup-openersuppressed.html",
459 ExpectTab,
460 CheckTitle);
463 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, ShiftClick) {
464 RunCheckTest(
465 browser(),
466 "/popup_blocker/popup-fake-click-on-anchor3.html",
467 ExpectPopup,
468 CheckTitle);
471 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, WebUI) {
472 WebContents* popup =
473 RunCheckTest(browser(),
474 "/popup_blocker/popup-webui.html",
475 ExpectPopup,
476 DontCheckTitle);
478 // Check that the new popup displays about:blank.
479 EXPECT_EQ(GURL(url::kAboutBlankURL), popup->GetURL());
482 // Verify that the renderer can't DOS the browser by creating arbitrarily many
483 // popups.
484 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, DenialOfService) {
485 GURL url(embedded_test_server()->GetURL("/popup_blocker/popup-dos.html"));
486 ui_test_utils::NavigateToURL(browser(), url);
487 ASSERT_EQ(25, GetBlockedContentsCount());
490 } // namespace