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