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