popup_blocker_browsertest.cc revision 58e6fbe4ee35d65e14b626c557d37565bf8ad179
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/strings/utf_string_conversions.h"
10#include "chrome/browser/autocomplete/autocomplete_match.h"
11#include "chrome/browser/autocomplete/autocomplete_result.h"
12#include "chrome/browser/chrome_notification_types.h"
13#include "chrome/browser/content_settings/host_content_settings_map.h"
14#include "chrome/browser/content_settings/tab_specific_content_settings.h"
15#include "chrome/browser/profiles/profile.h"
16#include "chrome/browser/search_engines/template_url_service_factory.h"
17#include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
18#include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
19#include "chrome/browser/ui/browser.h"
20#include "chrome/browser/ui/browser_commands.h"
21#include "chrome/browser/ui/browser_finder.h"
22#include "chrome/browser/ui/browser_window.h"
23#include "chrome/browser/ui/omnibox/location_bar.h"
24#include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
25#include "chrome/browser/ui/omnibox/omnibox_view.h"
26#include "chrome/browser/ui/tabs/tab_strip_model.h"
27#include "chrome/common/chrome_paths.h"
28#include "chrome/common/chrome_switches.h"
29#include "chrome/test/base/in_process_browser_test.h"
30#include "chrome/test/base/ui_test_utils.h"
31#include "content/public/browser/notification_registrar.h"
32#include "content/public/browser/notification_service.h"
33#include "content/public/browser/web_contents.h"
34#include "content/public/browser/web_contents_view.h"
35#include "content/public/common/url_constants.h"
36#include "content/public/test/browser_test_utils.h"
37#include "testing/gtest/include/gtest/gtest.h"
38
39using content::WebContents;
40
41namespace {
42
43static const base::FilePath::CharType* kTestDir =
44    FILE_PATH_LITERAL("popup_blocker");
45
46// Counts the number of RenderViewHosts created.
47class CountRenderViewHosts : public content::NotificationObserver {
48 public:
49  CountRenderViewHosts()
50      : count_(0) {
51    registrar_.Add(this,
52                   content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
53                   content::NotificationService::AllSources());
54  }
55  virtual ~CountRenderViewHosts() {}
56
57  int GetRenderViewHostCreatedCount() const { return count_; }
58
59 private:
60  virtual void Observe(int type,
61                       const content::NotificationSource& source,
62                       const content::NotificationDetails& details) OVERRIDE {
63    count_++;
64  }
65
66  content::NotificationRegistrar registrar_;
67
68  int count_;
69
70  DISALLOW_COPY_AND_ASSIGN(CountRenderViewHosts);
71};
72
73class PopupBlockerBrowserTest : public InProcessBrowserTest {
74 public:
75  PopupBlockerBrowserTest() {}
76
77  // Returns a url that shows one popup.
78  GURL GetTestURL() {
79    return ui_test_utils::GetTestUrl(
80      base::FilePath(kTestDir),
81      base::FilePath(FILE_PATH_LITERAL("popup-blocked-to-post-blank.html")));
82  }
83
84  std::vector<WebContents*> GetBlockedContents(Browser* browser) {
85    // Do a round trip to the renderer first to flush any in-flight IPCs to
86    // create a to-be-blocked window.
87    WebContents* tab = browser->tab_strip_model()->GetActiveWebContents();
88    CHECK(content::ExecuteScript(tab, std::string()));
89    BlockedContentTabHelper* blocked_content_tab_helper =
90        BlockedContentTabHelper::FromWebContents(tab);
91    std::vector<WebContents*> blocked_contents;
92    blocked_content_tab_helper->GetBlockedContents(&blocked_contents);
93    return blocked_contents;
94  }
95
96  void NavigateAndCheckPopupShown(Browser* browser, const GURL& url) {
97    content::WindowedNotificationObserver observer(
98        chrome::NOTIFICATION_TAB_ADDED,
99        content::NotificationService::AllSources());
100    ui_test_utils::NavigateToURL(browser, url);
101    observer.Wait();
102
103    ASSERT_EQ(2u, chrome::GetBrowserCount(browser->profile(),
104                                          browser->host_desktop_type()));
105
106    std::vector<WebContents*> blocked_contents = GetBlockedContents(browser);
107    ASSERT_TRUE(blocked_contents.empty());
108  }
109
110  void BasicTest(Browser* browser, const GURL& url) {
111    ui_test_utils::NavigateToURL(browser, url);
112
113    // If the popup blocker blocked the blank post, there should be only one
114    // tab in only one browser window and the URL of current tab must be equal
115    // to the original URL.
116    EXPECT_EQ(1u, chrome::GetBrowserCount(browser->profile(),
117                                          browser->host_desktop_type()));
118    EXPECT_EQ(1, browser->tab_strip_model()->count());
119    WebContents* web_contents =
120        browser->tab_strip_model()->GetActiveWebContents();
121    EXPECT_EQ(url, web_contents->GetURL());
122
123    std::vector<WebContents*> blocked_contents = GetBlockedContents(browser);
124    ASSERT_EQ(1u, blocked_contents.size());
125
126    content::WindowedNotificationObserver observer(
127        chrome::NOTIFICATION_TAB_ADDED,
128        content::NotificationService::AllSources());
129
130    BlockedContentTabHelper* blocked_content_tab_helper =
131        BlockedContentTabHelper::FromWebContents(web_contents);
132    blocked_content_tab_helper->LaunchForContents(blocked_contents[0]);
133
134    observer.Wait();
135  }
136};
137
138IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, PopupBlockedPostBlank) {
139  BasicTest(browser(), GetTestURL());
140}
141
142IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
143                       PopupBlockedPostBlankIncognito) {
144  BasicTest(CreateIncognitoBrowser(), GetTestURL());
145}
146
147IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
148                       PopupBlockedFakeClickOnAnchor) {
149  GURL url(ui_test_utils::GetTestUrl(
150      base::FilePath(kTestDir),
151      base::FilePath(FILE_PATH_LITERAL("popup-fake-click-on-anchor.html"))));
152  BasicTest(browser(), url);
153}
154
155IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, MultiplePopups) {
156  GURL url(ui_test_utils::GetTestUrl(base::FilePath(
157      kTestDir), base::FilePath(FILE_PATH_LITERAL("popup-many.html"))));
158  ui_test_utils::NavigateToURL(browser(), url);
159  std::vector<WebContents*> blocked_contents = GetBlockedContents(browser());
160  ASSERT_EQ(2u, blocked_contents.size());
161}
162
163// Verify that popups are launched on browser back button.
164IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
165                       AllowPopupThroughContentSetting) {
166  GURL url(GetTestURL());
167  browser()->profile()->GetHostContentSettingsMap()
168      ->SetContentSetting(ContentSettingsPattern::FromURL(url),
169                          ContentSettingsPattern::Wildcard(),
170                          CONTENT_SETTINGS_TYPE_POPUPS,
171                          std::string(),
172                          CONTENT_SETTING_ALLOW);
173
174  NavigateAndCheckPopupShown(browser(), url);
175}
176
177IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, PopupsLaunchWhenTabIsClosed) {
178  CommandLine::ForCurrentProcess()->AppendSwitch(
179      switches::kDisablePopupBlocking);
180  GURL url = ui_test_utils::GetTestUrl(
181      base::FilePath(kTestDir),
182      base::FilePath(FILE_PATH_LITERAL("popup-on-unload.html")));
183  ui_test_utils::NavigateToURL(browser(), url);
184
185  NavigateAndCheckPopupShown(browser(), GURL(content::kAboutBlankURL));
186}
187
188// Verify that when you unblock popup, the popup shows in history and omnibox.
189IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
190                       UnblockedPopupShowsInHistoryAndOmnibox) {
191  CommandLine::ForCurrentProcess()->AppendSwitch(
192      switches::kDisablePopupBlocking);
193  GURL url(GetTestURL());
194  NavigateAndCheckPopupShown(browser(), url);
195
196  std::string search_string =
197      "data:text/html,<title>Popup Success!</title>you should not see this "
198      "message if popup blocker is enabled";
199
200  ui_test_utils::HistoryEnumerator history(browser()->profile());
201  std::vector<GURL>& history_urls = history.urls();
202  ASSERT_EQ(2u, history_urls.size());
203  ASSERT_EQ(GURL(search_string), history_urls[0]);
204  ASSERT_EQ(url, history_urls[1]);
205
206  TemplateURLService* service = TemplateURLServiceFactory::GetForProfile(
207      browser()->profile());
208  ui_test_utils::WaitForTemplateURLServiceToLoad(service);
209  LocationBar* location_bar = browser()->window()->GetLocationBar();
210  ui_test_utils::SendToOmniboxAndSubmit(location_bar, search_string);
211  OmniboxEditModel* model = location_bar->GetLocationEntry()->model();
212  EXPECT_EQ(GURL(search_string), model->CurrentMatch(NULL).destination_url);
213  EXPECT_EQ(ASCIIToUTF16(search_string), model->CurrentMatch(NULL).contents);
214}
215
216class BetterPopupBlockerBrowserTest : public PopupBlockerBrowserTest {
217 public:
218  BetterPopupBlockerBrowserTest() {}
219  virtual ~BetterPopupBlockerBrowserTest() {}
220
221  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
222    PopupBlockerBrowserTest::SetUpCommandLine(command_line);
223    command_line->AppendSwitch(switches::kEnableBetterPopupBlocking);
224  }
225
226 private:
227  DISALLOW_COPY_AND_ASSIGN(BetterPopupBlockerBrowserTest);
228};
229
230IN_PROC_BROWSER_TEST_F(BetterPopupBlockerBrowserTest,
231                       BlockWebContentsCreation) {
232  CountRenderViewHosts counter;
233
234  ui_test_utils::NavigateToURL(browser(), GetTestURL());
235
236  // Wait until the request actually has hit the popup blocker. The
237  // NavigateToURL call above returns as soon as the main tab stopped loading
238  // which can happen before the popup request was processed.
239  WebContents* web_contents =
240      browser()->tab_strip_model()->GetActiveWebContents();
241  PopupBlockerTabHelper* popup_blocker_helper =
242      PopupBlockerTabHelper::FromWebContents(web_contents);
243  if (!popup_blocker_helper->GetBlockedPopupsCount()) {
244    content::WindowedNotificationObserver observer(
245        chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
246        content::NotificationService::AllSources());
247    observer.Wait();
248  }
249
250  // If the popup blocker blocked the blank post, there should be only one tab.
251  EXPECT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
252                                        browser()->host_desktop_type()));
253  EXPECT_EQ(1, browser()->tab_strip_model()->count());
254  EXPECT_EQ(GetTestURL(), web_contents->GetURL());
255
256  // And no new RVH created.
257  EXPECT_EQ(0, counter.GetRenderViewHostCreatedCount());
258
259  content::WindowedNotificationObserver observer(
260      chrome::NOTIFICATION_TAB_ADDED,
261      content::NotificationService::AllSources());
262
263  // Launch the blocked popup.
264  EXPECT_EQ(1u, popup_blocker_helper->GetBlockedPopupsCount());
265  std::map<int32, GURL> blocked_requests =
266      popup_blocker_helper->GetBlockedPopupRequests();
267  std::map<int32, GURL>::const_iterator iter = blocked_requests.begin();
268  popup_blocker_helper->ShowBlockedPopup(iter->first);
269
270  observer.Wait();
271}
272
273IN_PROC_BROWSER_TEST_F(BetterPopupBlockerBrowserTest,
274                       PopupBlockedFakeClickOnAnchorNoTarget) {
275  GURL url(ui_test_utils::GetTestUrl(
276      base::FilePath(kTestDir),
277      base::FilePath(FILE_PATH_LITERAL("popup-fake-click-on-anchor2.html"))));
278
279  CountRenderViewHosts counter;
280
281  ui_test_utils::NavigateToURL(browser(), url);
282
283  // If the popup blocker blocked the blank post, there should be only one tab.
284  EXPECT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
285                                        browser()->host_desktop_type()));
286  EXPECT_EQ(1, browser()->tab_strip_model()->count());
287  WebContents* web_contents =
288      browser()->tab_strip_model()->GetActiveWebContents();
289  EXPECT_EQ(url, web_contents->GetURL());
290
291  // And no new RVH created.
292  EXPECT_EQ(0, counter.GetRenderViewHostCreatedCount());
293
294  content::WindowedNotificationObserver observer(
295      chrome::NOTIFICATION_TAB_ADDED,
296      content::NotificationService::AllSources());
297
298  // Launch the blocked popup.
299  PopupBlockerTabHelper* popup_blocker_helper =
300      PopupBlockerTabHelper::FromWebContents(web_contents);
301  EXPECT_EQ(1u, popup_blocker_helper->GetBlockedPopupsCount());
302  std::map<int32, GURL> blocked_requests =
303      popup_blocker_helper->GetBlockedPopupRequests();
304  std::map<int32, GURL>::const_iterator iter = blocked_requests.begin();
305  popup_blocker_helper->ShowBlockedPopup(iter->first);
306
307  observer.Wait();
308}
309
310IN_PROC_BROWSER_TEST_F(BetterPopupBlockerBrowserTest, WindowFeatures) {
311  GURL url(ui_test_utils::GetTestUrl(
312      base::FilePath(kTestDir),
313      base::FilePath(FILE_PATH_LITERAL("popup-window-open.html"))));
314
315  CountRenderViewHosts counter;
316
317  ui_test_utils::NavigateToURL(browser(), url);
318
319  // If the popup blocker blocked the blank post, there should be only one tab.
320  EXPECT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
321                                        browser()->host_desktop_type()));
322  EXPECT_EQ(1, browser()->tab_strip_model()->count());
323  WebContents* web_contents =
324      browser()->tab_strip_model()->GetActiveWebContents();
325  EXPECT_EQ(url, web_contents->GetURL());
326
327  // And no new RVH created.
328  EXPECT_EQ(0, counter.GetRenderViewHostCreatedCount());
329
330  content::WindowedNotificationObserver observer(
331      chrome::NOTIFICATION_TAB_ADDED,
332      content::NotificationService::AllSources());
333  ui_test_utils::BrowserAddedObserver browser_observer;
334
335  // Launch the blocked popup.
336  PopupBlockerTabHelper* popup_blocker_helper =
337      PopupBlockerTabHelper::FromWebContents(web_contents);
338  EXPECT_EQ(1u, popup_blocker_helper->GetBlockedPopupsCount());
339  std::map<int32, GURL> blocked_requests =
340      popup_blocker_helper->GetBlockedPopupRequests();
341  std::map<int32, GURL>::const_iterator iter = blocked_requests.begin();
342  popup_blocker_helper->ShowBlockedPopup(iter->first);
343
344  observer.Wait();
345  Browser* new_browser = browser_observer.WaitForSingleNewBrowser();
346
347  // Check that the new popup has (roughly) the requested size.
348  web_contents = new_browser->tab_strip_model()->GetActiveWebContents();
349  gfx::Size window_size = web_contents->GetView()->GetContainerSize();
350  EXPECT_TRUE(349 <= window_size.width() && window_size.width() <= 351);
351  EXPECT_TRUE(249 <= window_size.height() && window_size.height() <= 251);
352}
353
354IN_PROC_BROWSER_TEST_F(BetterPopupBlockerBrowserTest, CorrectReferrer) {
355  GURL url(ui_test_utils::GetTestUrl(
356      base::FilePath(kTestDir),
357      base::FilePath(FILE_PATH_LITERAL("popup-referrer.html"))));
358
359  CountRenderViewHosts counter;
360
361  ui_test_utils::NavigateToURL(browser(), url);
362
363  // If the popup blocker blocked the blank post, there should be only one tab.
364  EXPECT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
365                                        browser()->host_desktop_type()));
366  EXPECT_EQ(1, browser()->tab_strip_model()->count());
367  WebContents* web_contents =
368      browser()->tab_strip_model()->GetActiveWebContents();
369  EXPECT_EQ(url, web_contents->GetURL());
370
371  // And no new RVH created.
372  EXPECT_EQ(0, counter.GetRenderViewHostCreatedCount());
373
374  content::WindowedNotificationObserver observer(
375      chrome::NOTIFICATION_TAB_ADDED,
376      content::NotificationService::AllSources());
377  ui_test_utils::BrowserAddedObserver browser_observer;
378
379  // Launch the blocked popup.
380  PopupBlockerTabHelper* popup_blocker_helper =
381      PopupBlockerTabHelper::FromWebContents(web_contents);
382  EXPECT_EQ(1u, popup_blocker_helper->GetBlockedPopupsCount());
383  std::map<int32, GURL> blocked_requests =
384      popup_blocker_helper->GetBlockedPopupRequests();
385  std::map<int32, GURL>::const_iterator iter = blocked_requests.begin();
386  popup_blocker_helper->ShowBlockedPopup(iter->first);
387
388  observer.Wait();
389  Browser* new_browser = browser_observer.WaitForSingleNewBrowser();
390
391  // Check that the referrer was correctly set.
392  web_contents = new_browser->tab_strip_model()->GetActiveWebContents();
393  base::string16 expected_title(base::ASCIIToUTF16("PASS"));
394  content::TitleWatcher title_watcher(web_contents, expected_title);
395  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
396}
397
398IN_PROC_BROWSER_TEST_F(BetterPopupBlockerBrowserTest, WindowFeaturesBarProps) {
399  GURL url(ui_test_utils::GetTestUrl(
400      base::FilePath(kTestDir),
401      base::FilePath(FILE_PATH_LITERAL("popup-windowfeatures.html"))));
402
403  CountRenderViewHosts counter;
404
405  ui_test_utils::NavigateToURL(browser(), url);
406
407  // If the popup blocker blocked the blank post, there should be only one tab.
408  EXPECT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
409                                        browser()->host_desktop_type()));
410  EXPECT_EQ(1, browser()->tab_strip_model()->count());
411  WebContents* web_contents =
412      browser()->tab_strip_model()->GetActiveWebContents();
413  EXPECT_EQ(url, web_contents->GetURL());
414
415  // And no new RVH created.
416  EXPECT_EQ(0, counter.GetRenderViewHostCreatedCount());
417
418  content::WindowedNotificationObserver observer(
419      chrome::NOTIFICATION_TAB_ADDED,
420      content::NotificationService::AllSources());
421  ui_test_utils::BrowserAddedObserver browser_observer;
422
423  // Launch the blocked popup.
424  PopupBlockerTabHelper* popup_blocker_helper =
425      PopupBlockerTabHelper::FromWebContents(web_contents);
426  EXPECT_EQ(1u, popup_blocker_helper->GetBlockedPopupsCount());
427  std::map<int32, GURL> blocked_requests =
428      popup_blocker_helper->GetBlockedPopupRequests();
429  std::map<int32, GURL>::const_iterator iter = blocked_requests.begin();
430  popup_blocker_helper->ShowBlockedPopup(iter->first);
431
432  observer.Wait();
433  Browser* new_browser = browser_observer.WaitForSingleNewBrowser();
434
435  // Check that the referrer was correctly set.
436  web_contents = new_browser->tab_strip_model()->GetActiveWebContents();
437  base::string16 expected_title(base::ASCIIToUTF16("PASS"));
438  content::TitleWatcher title_watcher(web_contents, expected_title);
439  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
440}
441
442}  // namespace
443