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