blob: 754be302435ae7710c3607e28fb3228ec1b8daa5 [file] [log] [blame]
// 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 <string>
#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<WindowProxy>& 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<BrowserProxy> browser_;
scoped_refptr<WindowProxy> window_;
scoped_refptr<TabProxy> tab_;
};
TEST_F(BlockedPopupContainerInteractiveTest, TestOpenAndResizeTo) {
NavigateMainTabTo("constrained_window_onload_resizeto.html");
SimulateClickInCenterOf(window_);
ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));
scoped_refptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
ASSERT_TRUE(popup_browser != NULL);
scoped_refptr<WindowProxy> 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<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
ASSERT_TRUE(popup_browser.get());
scoped_refptr<TabProxy> 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<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
ASSERT_TRUE(popup_browser.get());
scoped_refptr<WindowProxy> popup_window(popup_browser->GetWindow());
ASSERT_TRUE(popup_window.get());
scoped_refptr<TabProxy> 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<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
ASSERT_TRUE(popup_browser.get());
scoped_refptr<WindowProxy> popup_window(popup_browser->GetWindow());
ASSERT_TRUE(popup_window.get());
scoped_refptr<TabProxy> 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 =
"<html><script>"
"document.onkeydown = function() {"
" event.preventDefault();"
" return false;"
"}"
"</script></html>";
scoped_refptr<BrowserProxy> 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<WindowProxy> 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_W, views::Event::EF_CONTROL_DOWN));
ASSERT_TRUE(browser->WaitForTabCountToBecome(1, action_max_timeout_ms()));
#endif
}