browser_action_apitest.cc revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
1// Copyright (c) 2010 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 "build/build_config.h" 6 7#if defined(TOOLKIT_GTK) 8#include <gtk/gtk.h> 9#endif 10 11#include "chrome/browser/browser_window.h" 12#include "chrome/browser/extensions/browser_action_test_util.h" 13#include "chrome/browser/extensions/extension_apitest.h" 14#include "chrome/browser/extensions/extension_browser_event_router.h" 15#include "chrome/browser/extensions/extension_tabs_module.h" 16#include "chrome/browser/extensions/extensions_service.h" 17#include "chrome/browser/profile.h" 18#include "chrome/browser/tab_contents/tab_contents.h" 19#include "chrome/browser/ui/browser.h" 20#include "chrome/common/chrome_switches.h" 21#include "chrome/common/extensions/extension_action.h" 22#include "chrome/common/url_constants.h" 23#include "chrome/test/ui_test_utils.h" 24#include "gfx/rect.h" 25#include "gfx/size.h" 26 27class BrowserActionApiTest : public ExtensionApiTest { 28 public: 29 BrowserActionApiTest() {} 30 virtual ~BrowserActionApiTest() {} 31 32 protected: 33 BrowserActionTestUtil GetBrowserActionsBar() { 34 return BrowserActionTestUtil(browser()); 35 } 36 37 bool OpenPopup(int index) { 38 ResultCatcher catcher; 39 GetBrowserActionsBar().Press(index); 40 ui_test_utils::WaitForNotification( 41 NotificationType::EXTENSION_POPUP_VIEW_READY); 42 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 43 return GetBrowserActionsBar().HasPopup(); 44 } 45}; 46 47IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, Basic) { 48 ASSERT_TRUE(test_server()->Start()); 49 ASSERT_TRUE(RunExtensionTest("browser_action/basics")) << message_; 50 const Extension* extension = GetSingleLoadedExtension(); 51 ASSERT_TRUE(extension) << message_; 52 53 // Test that there is a browser action in the toolbar. 54 ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); 55 56 // Tell the extension to update the browser action state. 57 ResultCatcher catcher; 58 ui_test_utils::NavigateToURL(browser(), 59 GURL(extension->GetResourceURL("update.html"))); 60 ASSERT_TRUE(catcher.GetNextResult()); 61 62 // Test that we received the changes. 63 ExtensionAction* action = extension->browser_action(); 64 ASSERT_EQ("Modified", action->GetTitle(ExtensionAction::kDefaultTabId)); 65 ASSERT_EQ("badge", action->GetBadgeText(ExtensionAction::kDefaultTabId)); 66 ASSERT_EQ(SkColorSetARGB(255, 255, 255, 255), 67 action->GetBadgeBackgroundColor(ExtensionAction::kDefaultTabId)); 68 69 // Simulate the browser action being clicked. 70 ui_test_utils::NavigateToURL(browser(), 71 test_server()->GetURL("files/extensions/test_file.txt")); 72 73 ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted( 74 browser()->profile(), action->extension_id(), browser()); 75 76 // Verify the command worked. 77 TabContents* tab = browser()->GetSelectedTabContents(); 78 bool result = false; 79 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 80 tab->render_view_host(), L"", 81 L"setInterval(function(){" 82 L" if(document.body.bgColor == 'red'){" 83 L" window.domAutomationController.send(true)}}, 100)", 84 &result)); 85 ASSERT_TRUE(result); 86} 87 88IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, DynamicBrowserAction) { 89 ASSERT_TRUE(RunExtensionTest("browser_action/no_icon")) << message_; 90 const Extension* extension = GetSingleLoadedExtension(); 91 ASSERT_TRUE(extension) << message_; 92 93 // Test that there is a browser action in the toolbar and that it has no icon. 94 ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); 95 EXPECT_FALSE(GetBrowserActionsBar().HasIcon(0)); 96 97 // Tell the extension to update the icon using setIcon({imageData:...}). 98 ResultCatcher catcher; 99 ui_test_utils::NavigateToURL(browser(), 100 GURL(extension->GetResourceURL("update.html"))); 101 ASSERT_TRUE(catcher.GetNextResult()); 102 103 // Test that we received the changes. 104 EXPECT_TRUE(GetBrowserActionsBar().HasIcon(0)); 105 106 // Tell the extension to update using setIcon({path:...}); 107 ui_test_utils::NavigateToURL(browser(), 108 GURL(extension->GetResourceURL("update2.html"))); 109 ASSERT_TRUE(catcher.GetNextResult()); 110 111 // Test that we received the changes. 112 EXPECT_TRUE(GetBrowserActionsBar().HasIcon(0)); 113 114 // TODO(aa): Would be nice here to actually compare that the pixels change. 115} 116 117IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, TabSpecificBrowserActionState) { 118 ASSERT_TRUE(RunExtensionTest("browser_action/tab_specific_state")) << 119 message_; 120 const Extension* extension = GetSingleLoadedExtension(); 121 ASSERT_TRUE(extension) << message_; 122 123 // Test that there is a browser action in the toolbar and that it has an icon. 124 ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); 125 EXPECT_TRUE(GetBrowserActionsBar().HasIcon(0)); 126 127 // Execute the action, its title should change. 128 ResultCatcher catcher; 129 GetBrowserActionsBar().Press(0); 130 ASSERT_TRUE(catcher.GetNextResult()); 131 EXPECT_EQ("Showing icon 2", GetBrowserActionsBar().GetTooltip(0)); 132 133 // Open a new tab, the title should go back. 134 browser()->NewTab(); 135 EXPECT_EQ("hi!", GetBrowserActionsBar().GetTooltip(0)); 136 137 // Go back to first tab, changed title should reappear. 138 browser()->SelectTabContentsAt(0, true); 139 EXPECT_EQ("Showing icon 2", GetBrowserActionsBar().GetTooltip(0)); 140 141 // Reload that tab, default title should come back. 142 ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); 143 EXPECT_EQ("hi!", GetBrowserActionsBar().GetTooltip(0)); 144} 145 146IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionPopup) { 147 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII( 148 "browser_action/popup"))); 149 BrowserActionTestUtil actions_bar = GetBrowserActionsBar(); 150 const Extension* extension = GetSingleLoadedExtension(); 151 ASSERT_TRUE(extension) << message_; 152 153 // The extension's popup's size grows by |growFactor| each click. 154 const int growFactor = 500; 155 gfx::Size minSize = BrowserActionTestUtil::GetMinPopupSize(); 156 gfx::Size middleSize = gfx::Size(growFactor, growFactor); 157 gfx::Size maxSize = BrowserActionTestUtil::GetMaxPopupSize(); 158 159 // Ensure that two clicks will exceed the maximum allowed size. 160 ASSERT_GT(minSize.height() + growFactor * 2, maxSize.height()); 161 ASSERT_GT(minSize.width() + growFactor * 2, maxSize.width()); 162 163 // Simulate a click on the browser action and verify the size of the resulting 164 // popup. The first one tries to be 0x0, so it should be the min values. 165 ASSERT_TRUE(OpenPopup(0)); 166 EXPECT_EQ(minSize, actions_bar.GetPopupBounds().size()); 167 EXPECT_TRUE(actions_bar.HidePopup()); 168 169 ASSERT_TRUE(OpenPopup(0)); 170 EXPECT_EQ(middleSize, actions_bar.GetPopupBounds().size()); 171 EXPECT_TRUE(actions_bar.HidePopup()); 172 173 // One more time, but this time it should be constrained by the max values. 174 ASSERT_TRUE(OpenPopup(0)); 175 EXPECT_EQ(maxSize, actions_bar.GetPopupBounds().size()); 176 EXPECT_TRUE(actions_bar.HidePopup()); 177} 178 179// Test that calling chrome.browserAction.setPopup() can enable and change 180// a popup. 181IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionAddPopup) { 182 ASSERT_TRUE(RunExtensionTest("browser_action/add_popup")) << message_; 183 const Extension* extension = GetSingleLoadedExtension(); 184 ASSERT_TRUE(extension) << message_; 185 186 int tab_id = ExtensionTabUtil::GetTabId(browser()->GetSelectedTabContents()); 187 188 ExtensionAction* browser_action = extension->browser_action(); 189 ASSERT_TRUE(browser_action) 190 << "Browser action test extension should have a browser action."; 191 192 ASSERT_FALSE(browser_action->HasPopup(tab_id)); 193 ASSERT_FALSE(browser_action->HasPopup(ExtensionAction::kDefaultTabId)); 194 195 // Simulate a click on the browser action icon. The onClicked handler 196 // will add a popup. 197 { 198 ResultCatcher catcher; 199 GetBrowserActionsBar().Press(0); 200 ASSERT_TRUE(catcher.GetNextResult()); 201 } 202 203 // The call to setPopup in background.html set a tab id, so the 204 // current tab's setting should have changed, but the default setting 205 // should not have changed. 206 ASSERT_TRUE(browser_action->HasPopup(tab_id)) 207 << "Clicking on the browser action should have caused a popup to " 208 << "be added."; 209 ASSERT_FALSE(browser_action->HasPopup(ExtensionAction::kDefaultTabId)) 210 << "Clicking on the browser action should not have set a default " 211 << "popup."; 212 213 ASSERT_STREQ("/a_popup.html", 214 browser_action->GetPopupUrl(tab_id).path().c_str()); 215 216 // Now change the popup from a_popup.html to another_popup.html by loading 217 // a page which removes the popup using chrome.browserAction.setPopup(). 218 { 219 ResultCatcher catcher; 220 ui_test_utils::NavigateToURL( 221 browser(), 222 GURL(extension->GetResourceURL("change_popup.html"))); 223 ASSERT_TRUE(catcher.GetNextResult()); 224 } 225 226 // The call to setPopup in change_popup.html did not use a tab id, 227 // so the default setting should have changed as well as the current tab. 228 ASSERT_TRUE(browser_action->HasPopup(tab_id)); 229 ASSERT_TRUE(browser_action->HasPopup(ExtensionAction::kDefaultTabId)); 230 ASSERT_STREQ("/another_popup.html", 231 browser_action->GetPopupUrl(tab_id).path().c_str()); 232} 233 234// Test that calling chrome.browserAction.setPopup() can remove a popup. 235IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionRemovePopup) { 236 // Load the extension, which has a browser action with a default popup. 237 ASSERT_TRUE(RunExtensionTest("browser_action/remove_popup")) << message_; 238 const Extension* extension = GetSingleLoadedExtension(); 239 ASSERT_TRUE(extension) << message_; 240 241 int tab_id = ExtensionTabUtil::GetTabId(browser()->GetSelectedTabContents()); 242 243 ExtensionAction* browser_action = extension->browser_action(); 244 ASSERT_TRUE(browser_action) 245 << "Browser action test extension should have a browser action."; 246 247 ASSERT_TRUE(browser_action->HasPopup(tab_id)) 248 << "Expect a browser action popup before the test removes it."; 249 ASSERT_TRUE(browser_action->HasPopup(ExtensionAction::kDefaultTabId)) 250 << "Expect a browser action popup is the default for all tabs."; 251 252 // Load a page which removes the popup using chrome.browserAction.setPopup(). 253 { 254 ResultCatcher catcher; 255 ui_test_utils::NavigateToURL( 256 browser(), 257 GURL(extension->GetResourceURL("remove_popup.html"))); 258 ASSERT_TRUE(catcher.GetNextResult()); 259 } 260 261 ASSERT_FALSE(browser_action->HasPopup(tab_id)) 262 << "Browser action popup should have been removed."; 263 ASSERT_TRUE(browser_action->HasPopup(ExtensionAction::kDefaultTabId)) 264 << "Browser action popup default should not be changed by setting " 265 << "a specific tab id."; 266} 267 268IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoBasic) { 269 ASSERT_TRUE(test_server()->Start()); 270 271 ASSERT_TRUE(RunExtensionTest("browser_action/basics")) << message_; 272 const Extension* extension = GetSingleLoadedExtension(); 273 ASSERT_TRUE(extension) << message_; 274 275 // Test that there is a browser action in the toolbar. 276 ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); 277 278 // Open an incognito window and test that the browser action isn't there by 279 // default. 280 Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile(); 281 Browser* incognito_browser = Browser::Create(incognito_profile); 282 283 ASSERT_EQ(0, 284 BrowserActionTestUtil(incognito_browser).NumberOfBrowserActions()); 285 286 // Now enable the extension in incognito mode, and test that the browser 287 // action shows up. Note that we don't update the existing window at the 288 // moment, so we just create a new one. 289 browser()->profile()->GetExtensionsService()->extension_prefs()-> 290 SetIsIncognitoEnabled(extension->id(), true); 291 292 incognito_browser->CloseWindow(); 293 incognito_browser = Browser::Create(incognito_profile); 294 ASSERT_EQ(1, 295 BrowserActionTestUtil(incognito_browser).NumberOfBrowserActions()); 296 297 // TODO(mpcomplete): simulate a click and have it do the right thing in 298 // incognito. 299} 300 301IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoDragging) { 302 ExtensionsService* service = browser()->profile()->GetExtensionsService(); 303 304 // The tooltips for each respective browser action. 305 const char kTooltipA[] = "Make this page red"; 306 const char kTooltipB[] = "grow"; 307 const char kTooltipC[] = "Test setPopup()"; 308 309 const size_t size_before = service->extensions()->size(); 310 311 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII( 312 "browser_action/basics"))); 313 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII( 314 "browser_action/popup"))); 315 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII( 316 "browser_action/add_popup"))); 317 318 // Test that there are 3 browser actions in the toolbar. 319 ASSERT_EQ(size_before + 3, service->extensions()->size()); 320 ASSERT_EQ(3, GetBrowserActionsBar().NumberOfBrowserActions()); 321 322 // Now enable 2 of the extensions in incognito mode, and test that the browser 323 // actions show up. 324 service->extension_prefs()->SetIsIncognitoEnabled( 325 service->extensions()->at(size_before)->id(), true); 326 service->extension_prefs()->SetIsIncognitoEnabled( 327 service->extensions()->at(size_before + 2)->id(), true); 328 329 Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile(); 330 Browser* incognito_browser = Browser::Create(incognito_profile); 331 BrowserActionTestUtil incognito_bar(incognito_browser); 332 333 // Navigate just to have a tab in this window, otherwise wonky things happen. 334 ui_test_utils::OpenURLOffTheRecord(browser()->profile(), 335 GURL(chrome::kChromeUIExtensionsURL)); 336 337 ASSERT_EQ(2, incognito_bar.NumberOfBrowserActions()); 338 339 // Ensure that the browser actions are in the right order (ABC). 340 EXPECT_EQ(kTooltipA, GetBrowserActionsBar().GetTooltip(0)); 341 EXPECT_EQ(kTooltipB, GetBrowserActionsBar().GetTooltip(1)); 342 EXPECT_EQ(kTooltipC, GetBrowserActionsBar().GetTooltip(2)); 343 344 EXPECT_EQ(kTooltipA, incognito_bar.GetTooltip(0)); 345 EXPECT_EQ(kTooltipC, incognito_bar.GetTooltip(1)); 346 347 // Now rearrange them and ensure that they are rearranged correctly in both 348 // regular and incognito mode. 349 350 // ABC -> CAB 351 service->toolbar_model()->MoveBrowserAction( 352 service->extensions()->at(size_before + 2), 0); 353 354 EXPECT_EQ(kTooltipC, GetBrowserActionsBar().GetTooltip(0)); 355 EXPECT_EQ(kTooltipA, GetBrowserActionsBar().GetTooltip(1)); 356 EXPECT_EQ(kTooltipB, GetBrowserActionsBar().GetTooltip(2)); 357 358 EXPECT_EQ(kTooltipC, incognito_bar.GetTooltip(0)); 359 EXPECT_EQ(kTooltipA, incognito_bar.GetTooltip(1)); 360 361 // CAB -> CBA 362 service->toolbar_model()->MoveBrowserAction( 363 service->extensions()->at(size_before + 1), 1); 364 365 EXPECT_EQ(kTooltipC, GetBrowserActionsBar().GetTooltip(0)); 366 EXPECT_EQ(kTooltipB, GetBrowserActionsBar().GetTooltip(1)); 367 EXPECT_EQ(kTooltipA, GetBrowserActionsBar().GetTooltip(2)); 368 369 EXPECT_EQ(kTooltipC, incognito_bar.GetTooltip(0)); 370 EXPECT_EQ(kTooltipA, incognito_bar.GetTooltip(1)); 371} 372