// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include "app/l10n_util.h" #include "base/file_path.h" #include "base/gfx/rect.h" #include "base/keyboard_codes.h" #include "chrome/browser/view_ids.h" #include "chrome/common/chrome_constants.h" #include "chrome/test/automation/automation_constants.h" #include "chrome/test/automation/browser_proxy.h" #include "chrome/test/automation/tab_proxy.h" #include "chrome/test/automation/window_proxy.h" #include "chrome/test/ui/ui_test.h" #include "grit/generated_resources.h" #include "net/base/net_util.h" #include "views/event.h" class BlockedPopupContainerInteractiveTest : public UITest { protected: BlockedPopupContainerInteractiveTest() { show_window_ = true; } virtual void SetUp() { UITest::SetUp(); browser_ = automation()->GetBrowserWindow(0); ASSERT_TRUE(browser_.get()); window_ = browser_->GetWindow(); ASSERT_TRUE(window_.get()); tab_ = browser_->GetTab(0); ASSERT_TRUE(tab_.get()); } void NavigateMainTabTo(const std::string& file_name) { FilePath filename(test_data_directory_); filename = filename.AppendASCII("constrained_files"); filename = filename.AppendASCII(file_name); ASSERT_TRUE(tab_->NavigateToURL(net::FilePathToFileURL(filename))); } void SimulateClickInCenterOf(const scoped_refptr& window) { gfx::Rect tab_view_bounds; ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_CONTAINER, &tab_view_bounds, true)); // Simulate a click of the actual link to force user_gesture to be // true; if we don't, the resulting popup will be constrained, which // isn't what we want to test. ASSERT_TRUE(window->SimulateOSClick(tab_view_bounds.CenterPoint(), views::Event::EF_LEFT_BUTTON_DOWN)); } scoped_refptr browser_; scoped_refptr window_; scoped_refptr tab_; }; TEST_F(BlockedPopupContainerInteractiveTest, TestOpenAndResizeTo) { NavigateMainTabTo("constrained_window_onload_resizeto.html"); SimulateClickInCenterOf(window_); ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000)); scoped_refptr popup_browser(automation()->GetBrowserWindow(1)); ASSERT_TRUE(popup_browser != NULL); scoped_refptr popup_window(popup_browser->GetWindow()); ASSERT_TRUE(popup_window != NULL); // Make sure we were created with the correct width and height. gfx::Rect rect; bool is_timeout = false; ASSERT_TRUE(popup_window->GetViewBoundsWithTimeout( VIEW_ID_TAB_CONTAINER, &rect, false, 1000, &is_timeout)); ASSERT_FALSE(is_timeout); EXPECT_EQ(300, rect.width()); EXPECT_EQ(320, rect.height()); #if defined(OS_LINUX) // It seems we have to wait a little bit for the widgets to spin up before // we can start clicking on them. PlatformThread::Sleep(500); #endif SimulateClickInCenterOf(popup_window); // No idea how to wait here other then sleeping. This timeout used to be // lower, then we started hitting it before it was done. :( PlatformThread::Sleep(5000); // The actual content will be LESS than (200, 200) because resizeTo // deals with a window's outer{Width,Height} instead of its // inner{Width,Height}. is_timeout = false; ASSERT_TRUE(popup_window->GetViewBoundsWithTimeout( VIEW_ID_TAB_CONTAINER, &rect, false, 1000, &is_timeout)); ASSERT_FALSE(is_timeout); EXPECT_LT(rect.height(), 200); #if defined(OS_LINUX) // On Linux we may run in an environment where there is no window frame. In // this case our width might be exactly 200. The height will still be less // because we have to show the location bar. EXPECT_LE(rect.width(), 200); #else EXPECT_LT(rect.width(), 200); #endif } // Helper function used to get the number of blocked popups out of the window // title. bool ParseCountOutOfTitle(const std::wstring& title, int* output) { // Since we will be reading the number of popup windows open by grabbing the // number out of the window title, and that format string is localized, we // need to find out the offset into that string. const wchar_t* placeholder = L"XXXX"; size_t offset = l10n_util::GetStringF(IDS_POPUPS_BLOCKED_COUNT, placeholder). find(placeholder); std::wstring number; while (offset < title.size() && iswdigit(title[offset])) { number += title[offset]; offset++; } return StringToInt(WideToUTF16(number), output); } // Tests that in the window.open() equivalent of a fork bomb, we stop building // windows. // Flaky, http://crbug.com/26692. TEST_F(BlockedPopupContainerInteractiveTest, FLAKY_DontSpawnEndlessPopups) { NavigateMainTabTo("infinite_popups.html"); SimulateClickInCenterOf(window_); ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000)); scoped_refptr popup_browser(automation()->GetBrowserWindow(1)); ASSERT_TRUE(popup_browser.get()); scoped_refptr popup_tab(popup_browser->GetTab(0)); ASSERT_TRUE(popup_tab.get()); // And now we spin, waiting to make sure that we don't spawn popup // windows endlessly. The current limit is 25, so allowing for possible race // conditions and one off errors, don't break out until we go over 30 popup // windows (in which case we are bork bork bork). const int kMaxPopupWindows = 30; int popup_window_count = 0; int new_popup_window_count = 0; int times_slept = 0; bool continuing = true; while (continuing && popup_window_count < kMaxPopupWindows) { ASSERT_TRUE(popup_tab->GetBlockedPopupCount(&new_popup_window_count)); if (new_popup_window_count == popup_window_count) { if (times_slept == 10) { continuing = false; } else { // Nothing intereseting is going on wait it out. PlatformThread::Sleep(automation::kSleepTime); times_slept++; } } else { times_slept = 0; } EXPECT_GE(new_popup_window_count, popup_window_count); EXPECT_LE(new_popup_window_count, kMaxPopupWindows); popup_window_count = new_popup_window_count; } } // Make sure that we refuse to close windows when a constrained popup is // displayed. TEST_F(BlockedPopupContainerInteractiveTest, FLAKY_WindowOpenWindowClosePopup) { NavigateMainTabTo("openclose_main.html"); SimulateClickInCenterOf(window_); ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 5000)); // Make sure we have a blocked popup notification scoped_refptr popup_browser(automation()->GetBrowserWindow(1)); ASSERT_TRUE(popup_browser.get()); scoped_refptr popup_window(popup_browser->GetWindow()); ASSERT_TRUE(popup_window.get()); scoped_refptr popup_tab(popup_browser->GetTab(0)); ASSERT_TRUE(popup_tab.get()); ASSERT_TRUE(popup_tab->WaitForBlockedPopupCountToChangeTo(1, 1000)); // Ensure we didn't close the first popup window. ASSERT_FALSE(automation()->WaitForWindowCountToBecome(1, 3000)); } TEST_F(BlockedPopupContainerInteractiveTest, BlockAlertFromBlockedPopup) { NavigateMainTabTo("block_alert.html"); // Wait for there to be an app modal dialog (and fail if it's shown). ASSERT_FALSE(automation()->WaitForAppModalDialog(4000)); // Ensure one browser window. int browser_window_count; ASSERT_TRUE(automation()->GetBrowserWindowCount(&browser_window_count)); ASSERT_EQ(1, browser_window_count); // Ensure one blocked popup window: the popup didn't escape. int popup_count = 0; ASSERT_TRUE(tab_->GetBlockedPopupCount(&popup_count)); ASSERT_EQ(1, popup_count); } TEST_F(BlockedPopupContainerInteractiveTest, ShowAlertFromNormalPopup) { NavigateMainTabTo("show_alert.html"); SimulateClickInCenterOf(window_); ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 5000)); scoped_refptr popup_browser(automation()->GetBrowserWindow(1)); ASSERT_TRUE(popup_browser.get()); scoped_refptr popup_window(popup_browser->GetWindow()); ASSERT_TRUE(popup_window.get()); scoped_refptr popup_tab(popup_browser->GetTab(0)); ASSERT_TRUE(popup_tab.get()); #if defined(OS_LINUX) // It seems we have to wait a little bit for the widgets to spin up before // we can start clicking on them. PlatformThread::Sleep(500); #endif SimulateClickInCenterOf(popup_window); // Wait for there to be an app modal dialog. ASSERT_TRUE(automation()->WaitForAppModalDialog(5000)); } // Make sure that window focus works while creating a popup window so that we // don't TEST_F(BlockedPopupContainerInteractiveTest, DontBreakOnBlur) { NavigateMainTabTo("window_blur_test.html"); SimulateClickInCenterOf(window_); // Wait for the popup window to open. ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000)); // We popup shouldn't be closed by the onblur handler. ASSERT_FALSE(automation()->WaitForWindowCountToBecome(1, 1500)); } // Tests that tab related keyboard accelerators are reserved by the app. class BrowserInteractiveTest : public UITest { }; TEST_F(BrowserInteractiveTest, ReserveKeyboardAccelerators) { const std::string kBadPage = ""; scoped_refptr browser(automation()->GetBrowserWindow(0)); browser->AppendTab(GURL("data:text/html," + kBadPage)); int tab_count = 0; ASSERT_TRUE(browser->GetTabCount(&tab_count)); ASSERT_EQ(tab_count, 2); int active_tab = 0; ASSERT_TRUE(browser->GetActiveTabIndex(&active_tab)); ASSERT_EQ(active_tab, 1); scoped_refptr window(browser->GetWindow()); ASSERT_TRUE(window->SimulateOSKeyPress( base::VKEY_TAB, views::Event::EF_CONTROL_DOWN)); ASSERT_TRUE(browser->WaitForTabToBecomeActive(0, action_max_timeout_ms())); #if !defined(OS_MACOSX) // see BrowserWindowCocoa::GetCommandId ASSERT_TRUE(browser->ActivateTab(1)); ASSERT_TRUE(window->SimulateOSKeyPress( base::VKEY_F4, views::Event::EF_CONTROL_DOWN)); ASSERT_TRUE(browser->WaitForTabCountToBecome(1, action_max_timeout_ms())); #endif }