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