1// Copyright (c) 2012 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/api/extension_action/extension_action_api.h" 6#include "chrome/browser/extensions/extension_action.h" 7#include "chrome/browser/extensions/extension_action_icon_factory.h" 8#include "chrome/browser/extensions/extension_action_manager.h" 9#include "chrome/browser/extensions/extension_apitest.h" 10#include "chrome/browser/extensions/extension_service.h" 11#include "chrome/browser/extensions/extension_tab_util.h" 12#include "chrome/browser/profiles/profile.h" 13#include "chrome/browser/sessions/session_tab_helper.h" 14#include "chrome/browser/ui/browser.h" 15#include "chrome/browser/ui/browser_commands.h" 16#include "chrome/browser/ui/browser_window.h" 17#include "chrome/browser/ui/omnibox/location_bar.h" 18#include "chrome/browser/ui/tabs/tab_strip_model.h" 19#include "chrome/test/base/ui_test_utils.h" 20#include "content/public/browser/web_contents.h" 21#include "content/public/test/browser_test_utils.h" 22#include "extensions/browser/extension_system.h" 23#include "extensions/common/extension.h" 24 25using content::WebContents; 26 27namespace extensions { 28namespace { 29 30class PageActionApiTest : public ExtensionApiTest { 31 protected: 32 ExtensionAction* GetPageAction(const Extension& extension) { 33 return ExtensionActionManager::Get(browser()->profile())-> 34 GetPageAction(extension); 35 } 36}; 37 38IN_PROC_BROWSER_TEST_F(PageActionApiTest, Basic) { 39 ASSERT_TRUE(test_server()->Start()); 40 ASSERT_TRUE(RunExtensionTest("page_action/basics")) << message_; 41 const Extension* extension = GetSingleLoadedExtension(); 42 ASSERT_TRUE(extension) << message_; 43 { 44 // Tell the extension to update the page action state. 45 ResultCatcher catcher; 46 ui_test_utils::NavigateToURL(browser(), 47 GURL(extension->GetResourceURL("update.html"))); 48 ASSERT_TRUE(catcher.GetNextResult()); 49 } 50 51 // Test that we received the changes. 52 int tab_id = SessionTabHelper::FromWebContents( 53 browser()->tab_strip_model()->GetActiveWebContents())->session_id().id(); 54 ExtensionAction* action = GetPageAction(*extension); 55 ASSERT_TRUE(action); 56 EXPECT_EQ("Modified", action->GetTitle(tab_id)); 57 58 { 59 // Simulate the page action being clicked. 60 ResultCatcher catcher; 61 int tab_id = ExtensionTabUtil::GetTabId( 62 browser()->tab_strip_model()->GetActiveWebContents()); 63 ExtensionActionAPI::PageActionExecuted( 64 browser()->profile(), *action, tab_id, std::string(), 0); 65 EXPECT_TRUE(catcher.GetNextResult()); 66 } 67 68 { 69 // Tell the extension to update the page action state again. 70 ResultCatcher catcher; 71 ui_test_utils::NavigateToURL(browser(), 72 GURL(extension->GetResourceURL("update2.html"))); 73 ASSERT_TRUE(catcher.GetNextResult()); 74 } 75 76 // We should not be creating icons asynchronously, so we don't need an 77 // observer. 78 ExtensionActionIconFactory icon_factory(profile(), extension, action, NULL); 79 80 // Test that we received the changes. 81 tab_id = SessionTabHelper::FromWebContents( 82 browser()->tab_strip_model()->GetActiveWebContents())->session_id().id(); 83 EXPECT_FALSE(icon_factory.GetIcon(tab_id).IsEmpty()); 84} 85 86// Test that calling chrome.pageAction.setPopup() can enable a popup. 87IN_PROC_BROWSER_TEST_F(PageActionApiTest, AddPopup) { 88 // Load the extension, which has no default popup. 89 ASSERT_TRUE(RunExtensionTest("page_action/add_popup")) << message_; 90 const Extension* extension = GetSingleLoadedExtension(); 91 ASSERT_TRUE(extension) << message_; 92 93 int tab_id = ExtensionTabUtil::GetTabId( 94 browser()->tab_strip_model()->GetActiveWebContents()); 95 96 ExtensionAction* page_action = GetPageAction(*extension); 97 ASSERT_TRUE(page_action) 98 << "Page action test extension should have a page action."; 99 100 ASSERT_FALSE(page_action->HasPopup(tab_id)); 101 102 // Simulate the page action being clicked. The resulting event should 103 // install a page action popup. 104 { 105 ResultCatcher catcher; 106 ExtensionActionAPI::PageActionExecuted( 107 browser()->profile(), *page_action, tab_id, std::string(), 1); 108 ASSERT_TRUE(catcher.GetNextResult()); 109 } 110 111 ASSERT_TRUE(page_action->HasPopup(tab_id)) 112 << "Clicking on the page action should have caused a popup to be added."; 113 114 ASSERT_STREQ("/a_popup.html", 115 page_action->GetPopupUrl(tab_id).path().c_str()); 116 117 // Now change the popup from a_popup.html to a_second_popup.html . 118 // Load a page which removes the popup using chrome.pageAction.setPopup(). 119 { 120 ResultCatcher catcher; 121 ui_test_utils::NavigateToURL( 122 browser(), 123 GURL(extension->GetResourceURL("change_popup.html"))); 124 ASSERT_TRUE(catcher.GetNextResult()); 125 } 126 127 ASSERT_TRUE(page_action->HasPopup(tab_id)); 128 ASSERT_STREQ("/another_popup.html", 129 page_action->GetPopupUrl(tab_id).path().c_str()); 130} 131 132// Test that calling chrome.pageAction.setPopup() can remove a popup. 133IN_PROC_BROWSER_TEST_F(PageActionApiTest, RemovePopup) { 134 // Load the extension, which has a page action with a default popup. 135 ASSERT_TRUE(RunExtensionTest("page_action/remove_popup")) << message_; 136 const Extension* extension = GetSingleLoadedExtension(); 137 ASSERT_TRUE(extension) << message_; 138 139 int tab_id = ExtensionTabUtil::GetTabId( 140 browser()->tab_strip_model()->GetActiveWebContents()); 141 142 ExtensionAction* page_action = GetPageAction(*extension); 143 ASSERT_TRUE(page_action) 144 << "Page action test extension should have a page action."; 145 146 ASSERT_TRUE(page_action->HasPopup(tab_id)) 147 << "Expect a page action popup before the test removes it."; 148 149 // Load a page which removes the popup using chrome.pageAction.setPopup(). 150 { 151 ResultCatcher catcher; 152 ui_test_utils::NavigateToURL( 153 browser(), 154 GURL(extension->GetResourceURL("remove_popup.html"))); 155 ASSERT_TRUE(catcher.GetNextResult()); 156 } 157 158 ASSERT_FALSE(page_action->HasPopup(tab_id)) 159 << "Page action popup should have been removed."; 160} 161 162// Tests old-style pageActions API that is deprecated but we don't want to 163// break. 164IN_PROC_BROWSER_TEST_F(PageActionApiTest, OldPageActions) { 165 ASSERT_TRUE(RunExtensionTestAllowOldManifestVersion("page_action/old_api")) << 166 message_; 167 const Extension* extension = GetSingleLoadedExtension(); 168 ASSERT_TRUE(extension) << message_; 169 170 // Have the extension enable the page action. 171 { 172 ResultCatcher catcher; 173 ui_test_utils::NavigateToURL(browser(), 174 GURL(extension->GetResourceURL("page.html"))); 175 ASSERT_TRUE(catcher.GetNextResult()); 176 } 177 178 // Simulate the page action being clicked. 179 { 180 ResultCatcher catcher; 181 int tab_id = ExtensionTabUtil::GetTabId( 182 browser()->tab_strip_model()->GetActiveWebContents()); 183 ExtensionAction* page_action = GetPageAction(*extension); 184 ExtensionActionAPI::PageActionExecuted( 185 browser()->profile(), *page_action, tab_id, std::string(), 1); 186 EXPECT_TRUE(catcher.GetNextResult()); 187 } 188} 189 190// Tests popups in page actions. 191// Flaky on the trybots. See http://crbug.com/96725. 192IN_PROC_BROWSER_TEST_F(PageActionApiTest, DISABLED_ShowPageActionPopup) { 193 ASSERT_TRUE(RunExtensionTest("page_action/popup")) << message_; 194 const Extension* extension = GetSingleLoadedExtension(); 195 ASSERT_TRUE(extension) << message_; 196 197 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1)); 198 199 { 200 ResultCatcher catcher; 201 LocationBarTesting* location_bar = 202 browser()->window()->GetLocationBar()->GetLocationBarForTesting(); 203 location_bar->TestPageActionPressed(0); 204 ASSERT_TRUE(catcher.GetNextResult()); 205 } 206} 207 208// Test http://crbug.com/57333: that two page action extensions using the same 209// icon for the page action icon and the extension icon do not crash. 210IN_PROC_BROWSER_TEST_F(PageActionApiTest, TestCrash57333) { 211 // Load extension A. 212 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("page_action") 213 .AppendASCII("crash_57333") 214 .AppendASCII("Extension1"))); 215 // Load extension B. 216 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("page_action") 217 .AppendASCII("crash_57333") 218 .AppendASCII("Extension2"))); 219} 220 221IN_PROC_BROWSER_TEST_F(PageActionApiTest, Getters) { 222 ASSERT_TRUE(RunExtensionTest("page_action/getters")) << message_; 223 const Extension* extension = GetSingleLoadedExtension(); 224 ASSERT_TRUE(extension) << message_; 225 226 ResultCatcher catcher; 227 ui_test_utils::NavigateToURL(browser(), 228 GURL(extension->GetResourceURL("update.html"))); 229 ASSERT_TRUE(catcher.GetNextResult()); 230} 231 232// Verify triggering page action. 233IN_PROC_BROWSER_TEST_F(PageActionApiTest, TestTriggerPageAction) { 234 ASSERT_TRUE(test_server()->Start()); 235 236 ASSERT_TRUE(RunExtensionTest("trigger_actions/page_action")) << message_; 237 const Extension* extension = GetSingleLoadedExtension(); 238 ASSERT_TRUE(extension) << message_; 239 240 // Page action icon is displayed when a tab is created. 241 ui_test_utils::NavigateToURL(browser(), 242 test_server()->GetURL("files/simple.html")); 243 chrome::NewTab(browser()); 244 browser()->tab_strip_model()->ActivateTabAt(0, true); 245 246 ExtensionAction* page_action = GetPageAction(*extension); 247 ASSERT_TRUE(page_action); 248 249 { 250 // Simulate the page action being clicked. 251 ResultCatcher catcher; 252 int tab_id = ExtensionTabUtil::GetTabId( 253 browser()->tab_strip_model()->GetActiveWebContents()); 254 ExtensionActionAPI::PageActionExecuted( 255 browser()->profile(), *page_action, tab_id, std::string(), 0); 256 EXPECT_TRUE(catcher.GetNextResult()); 257 } 258 259 WebContents* tab = 260 browser()->tab_strip_model()->GetActiveWebContents(); 261 EXPECT_TRUE(tab != NULL); 262 263 // Verify that the browser action turned the background color red. 264 const std::string script = 265 "window.domAutomationController.send(document.body.style." 266 "backgroundColor);"; 267 std::string result; 268 EXPECT_TRUE(content::ExecuteScriptAndExtractString(tab, script, &result)); 269 EXPECT_EQ(result, "red"); 270} 271 272} // namespace 273} // namespace extensions 274