1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
|
// Copyright 2013 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 "chrome/browser/extensions/browser_action_test_util.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/notification_service.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/permissions/permissions_data.h"
#if defined(OS_WIN)
#include "ui/views/win/hwnd_util.h"
#endif
namespace extensions {
namespace {
// chrome.browserAction API tests that interact with the UI in such a way that
// they cannot be run concurrently (i.e. openPopup API tests that require the
// window be focused/active).
class BrowserActionInteractiveTest : public ExtensionApiTest {
public:
BrowserActionInteractiveTest() {}
virtual ~BrowserActionInteractiveTest() {}
protected:
// Function to control whether to run popup tests for the current platform.
// These tests require RunExtensionSubtest to work as expected and the browser
// window to able to be made active automatically. Returns false for platforms
// where these conditions are not met.
bool ShouldRunPopupTest() {
// TODO(justinlin): http://crbug.com/177163
#if defined(OS_WIN) && !defined(NDEBUG)
return false;
#elif defined(OS_MACOSX)
// TODO(justinlin): Browser window do not become active on Mac even when
// Activate() is called on them. Enable when/if it's possible to fix.
return false;
#else
return true;
#endif
}
// Open an extension popup via the chrome.browserAction.openPopup API.
void OpenExtensionPopupViaAPI() {
// Setup the notification observer to wait for the popup to finish loading.
content::WindowedNotificationObserver frame_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
// Show first popup in first window and expect it to have loaded.
ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
"open_popup_succeeds.html")) << message_;
frame_observer.Wait();
EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
}
};
// Tests opening a popup using the chrome.browserAction.openPopup API. This test
// opens a popup in the starting window, closes the popup, creates a new window
// and opens a popup in the new window. Both popups should succeed in opening.
IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, TestOpenPopup) {
if (!ShouldRunPopupTest())
return;
BrowserActionTestUtil browserActionBar = BrowserActionTestUtil(browser());
// Setup extension message listener to wait for javascript to finish running.
ExtensionTestMessageListener listener("ready", true);
{
OpenExtensionPopupViaAPI();
EXPECT_TRUE(browserActionBar.HasPopup());
browserActionBar.HidePopup();
}
EXPECT_TRUE(listener.WaitUntilSatisfied());
Browser* new_browser = NULL;
{
content::WindowedNotificationObserver frame_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
// Open a new window.
new_browser = chrome::FindBrowserWithWebContents(
browser()->OpenURL(content::OpenURLParams(
GURL("about:"), content::Referrer(), NEW_WINDOW,
content::PAGE_TRANSITION_TYPED, false)));
#if defined(OS_WIN)
// Hide all the buttons to test that it opens even when browser action is
// in the overflow bucket.
// TODO(justinlin): Implement for other platforms.
browserActionBar.SetIconVisibilityCount(0);
#endif
frame_observer.Wait();
}
EXPECT_TRUE(new_browser != NULL);
// Flaky on non-aura linux http://crbug.com/309749
#if !(defined(OS_LINUX) && !defined(USE_AURA))
ResultCatcher catcher;
{
content::WindowedNotificationObserver frame_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
// Show second popup in new window.
listener.Reply("");
frame_observer.Wait();
EXPECT_TRUE(BrowserActionTestUtil(new_browser).HasPopup());
}
ASSERT_TRUE(catcher.GetNextResult()) << message_;
#endif
}
// Tests opening a popup in an incognito window.
IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, TestOpenPopupIncognito) {
if (!ShouldRunPopupTest())
return;
content::WindowedNotificationObserver frame_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
"open_popup_succeeds.html",
kFlagEnableIncognito | kFlagUseIncognito))
<< message_;
frame_observer.Wait();
// Non-Aura Linux uses a singleton for the popup, so it looks like all windows
// have popups if there is any popup open.
#if !(defined(OS_LINUX) && !defined(USE_AURA))
// Starting window does not have a popup.
EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
#endif
// Incognito window should have a popup.
EXPECT_TRUE(BrowserActionTestUtil(BrowserList::GetInstance(
chrome::GetActiveDesktop())->GetLastActive()).HasPopup());
}
#if defined(OS_LINUX)
#define MAYBE_TestOpenPopupDoesNotCloseOtherPopups DISABLED_TestOpenPopupDoesNotCloseOtherPopups
#else
#define MAYBE_TestOpenPopupDoesNotCloseOtherPopups TestOpenPopupDoesNotCloseOtherPopups
#endif
// Tests if there is already a popup open (by a user click or otherwise), that
// the openPopup API does not override it.
IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
MAYBE_TestOpenPopupDoesNotCloseOtherPopups) {
if (!ShouldRunPopupTest())
return;
// Load a first extension that can open a popup.
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"browser_action/popup")));
const Extension* extension = GetSingleLoadedExtension();
ASSERT_TRUE(extension) << message_;
ExtensionTestMessageListener listener("ready", true);
// Load the test extension which will do nothing except notifyPass() to
// return control here.
ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
"open_popup_fails.html")) << message_;
EXPECT_TRUE(listener.WaitUntilSatisfied());
content::WindowedNotificationObserver frame_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
// Open popup in the first extension.
BrowserActionTestUtil(browser()).Press(0);
frame_observer.Wait();
EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
ResultCatcher catcher;
// Return control to javascript to validate that opening a popup fails now.
listener.Reply("");
ASSERT_TRUE(catcher.GetNextResult()) << message_;
}
// Test that openPopup does not grant tab permissions like for browser action
// clicks if the activeTab permission is set.
IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
TestOpenPopupDoesNotGrantTabPermissions) {
if (!ShouldRunPopupTest())
return;
OpenExtensionPopupViaAPI();
ExtensionService* service = extensions::ExtensionSystem::Get(
browser()->profile())->extension_service();
ASSERT_FALSE(
service->GetExtensionById(last_loaded_extension_id(), false)
->permissions_data()
->HasAPIPermissionForTab(
SessionID::IdForTab(
browser()->tab_strip_model()->GetActiveWebContents()),
APIPermission::kTab));
}
// Test that the extension popup is closed when the browser window is clicked.
IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, BrowserClickClosesPopup1) {
if (!ShouldRunPopupTest())
return;
// Open an extension popup via the chrome.browserAction.openPopup API.
content::WindowedNotificationObserver frame_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
"open_popup_succeeds.html")) << message_;
frame_observer.Wait();
EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
// Click on the omnibox to close the extension popup.
ui_test_utils::ClickOnView(browser(), VIEW_ID_OMNIBOX);
EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
}
// Test that the extension popup is closed when the browser window is clicked.
IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, BrowserClickClosesPopup2) {
if (!ShouldRunPopupTest())
return;
// Load a first extension that can open a popup.
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"browser_action/popup")));
const Extension* extension = GetSingleLoadedExtension();
ASSERT_TRUE(extension) << message_;
// Open an extension popup by clicking the browser action button.
content::WindowedNotificationObserver frame_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
BrowserActionTestUtil(browser()).Press(0);
frame_observer.Wait();
EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
// Click on the omnibox to close the extension popup.
ui_test_utils::ClickOnView(browser(), VIEW_ID_OMNIBOX);
EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
}
// Test that the extension popup is closed on browser tab switches.
IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, TabSwitchClosesPopup) {
if (!ShouldRunPopupTest())
return;
// Add a second tab to the browser and open an extension popup.
chrome::NewTab(browser());
ASSERT_EQ(2, browser()->tab_strip_model()->count());
OpenExtensionPopupViaAPI();
// Press CTRL+TAB to change active tabs, the extension popup should close.
ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
browser(), ui::VKEY_TAB, true, false, false, false));
EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
}
#if defined(TOOLKIT_VIEWS)
// Test closing the browser while inspecting an extension popup with dev tools.
IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, CloseBrowserWithDevTools) {
if (!ShouldRunPopupTest())
return;
// Load a first extension that can open a popup.
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"browser_action/popup")));
const Extension* extension = GetSingleLoadedExtension();
ASSERT_TRUE(extension) << message_;
// Open an extension popup by clicking the browser action button.
content::WindowedNotificationObserver frame_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
BrowserActionTestUtil(browser()).InspectPopup(0);
frame_observer.Wait();
EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
// Close the browser window, this should not cause a crash.
chrome::CloseWindow(browser());
}
#endif // TOOLKIT_VIEWS
#if defined(OS_WIN)
// Test that forcibly closing the browser and popup HWND does not cause a crash.
IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, DestroyHWNDDoesNotCrash) {
if (!ShouldRunPopupTest())
return;
OpenExtensionPopupViaAPI();
BrowserActionTestUtil test_util(browser());
const gfx::NativeView view = test_util.GetPopupNativeView();
EXPECT_NE(static_cast<gfx::NativeView>(NULL), view);
const HWND hwnd = views::HWNDForNativeView(view);
EXPECT_EQ(hwnd,
views::HWNDForNativeView(browser()->window()->GetNativeWindow()));
EXPECT_EQ(TRUE, ::IsWindow(hwnd));
// Create a new browser window to prevent the message loop from terminating.
Browser* new_browser = chrome::FindBrowserWithWebContents(
browser()->OpenURL(content::OpenURLParams(
GURL("about:"), content::Referrer(), NEW_WINDOW,
content::PAGE_TRANSITION_TYPED, false)));
// Forcibly closing the browser HWND should not cause a crash.
EXPECT_EQ(TRUE, ::CloseWindow(hwnd));
EXPECT_EQ(TRUE, ::DestroyWindow(hwnd));
EXPECT_EQ(FALSE, ::IsWindow(hwnd));
}
#endif // OS_WIN
} // namespace
} // namespace extensions
|