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