1// Copyright 2014 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 "base/memory/scoped_ptr.h" 6#include "base/run_loop.h" 7#include "base/strings/stringprintf.h" 8#include "chrome/browser/extensions/api/extension_action/extension_action_api.h" 9#include "chrome/browser/extensions/extension_action.h" 10#include "chrome/browser/extensions/extension_action_manager.h" 11#include "chrome/browser/extensions/extension_browsertest.h" 12#include "chrome/browser/extensions/extension_service.h" 13#include "chrome/browser/extensions/test_extension_dir.h" 14#include "chrome/browser/sessions/session_tab_helper.h" 15#include "chrome/browser/ui/browser.h" 16#include "chrome/browser/ui/browser_window.h" 17#include "chrome/browser/ui/location_bar/location_bar.h" 18#include "chrome/browser/ui/tabs/tab_strip_model.h" 19#include "extensions/common/extension.h" 20#include "extensions/common/extension_builder.h" 21#include "extensions/common/feature_switch.h" 22#include "extensions/common/value_builder.h" 23#include "extensions/test/extension_test_message_listener.h" 24 25namespace { 26 27const char kBackgroundScriptSource[] = 28 "chrome.pageAction.onClicked.addListener(function() {\n" 29 " chrome.test.sendMessage('clicked');\n" 30 "});\n" 31 "chrome.test.sendMessage('registered');\n"; 32const char kManifestSource[] = 33 "{" 34 " \"name\": \"%s\"," 35 " \"version\": \"1.0\"," 36 " \"manifest_version\": 2," 37 " \"background\": { \"scripts\": [\"background.js\"] }," 38 " \"page_action\": { }" 39 "}"; 40 41} // namespace 42 43class LocationBarBrowserTest : public ExtensionBrowserTest { 44 public: 45 LocationBarBrowserTest() {} 46 virtual ~LocationBarBrowserTest() {} 47 48 protected: 49 virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE; 50 51 // Load an extension with a PageAction that sends a message when clicked. 52 const extensions::Extension* LoadPageActionExtension( 53 extensions::TestExtensionDir* dir); 54 55 private: 56 scoped_ptr<extensions::FeatureSwitch::ScopedOverride> enable_override_; 57 58 DISALLOW_COPY_AND_ASSIGN(LocationBarBrowserTest); 59}; 60 61void LocationBarBrowserTest::SetUpCommandLine(base::CommandLine* command_line) { 62 // In order to let a vanilla extension override the bookmark star, we have to 63 // enable the switch. 64 enable_override_.reset(new extensions::FeatureSwitch::ScopedOverride( 65 extensions::FeatureSwitch::enable_override_bookmarks_ui(), true)); 66 ExtensionBrowserTest::SetUpCommandLine(command_line); 67} 68 69const extensions::Extension* LocationBarBrowserTest::LoadPageActionExtension( 70 extensions::TestExtensionDir* dir) { 71 DCHECK(dir); 72 73 dir->WriteManifest(base::StringPrintf(kManifestSource, "page_action1")); 74 dir->WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundScriptSource); 75 76 ExtensionTestMessageListener registered_listener("registered", false); 77 const extensions::Extension* extension = LoadExtension(dir->unpacked_path()); 78 registered_listener.WaitUntilSatisfied(); 79 80 return extension; 81} 82 83// Test that page actions show up properly in the location bar. Since the 84// page action logic is more fully tested as part of the extensions system, this 85// only needs to check that they are displayed and clicking on them triggers 86// the action. 87// TODO(devlin): This flakily times out on Mac. crbug.com/410866 88#if defined(OS_MACOSX) 89#define MAYBE_PageActionUITest DISABLED_PageActionUITeset 90#else 91#define MAYBE_PageActionUITest PageActionUITest 92#endif 93IN_PROC_BROWSER_TEST_F(LocationBarBrowserTest, MAYBE_PageActionUITest) { 94 LocationBarTesting* location_bar = 95 browser()->window()->GetLocationBar()->GetLocationBarForTesting(); 96 97 // At the start, no page actions should exist. 98 EXPECT_EQ(0, location_bar->PageActionCount()); 99 EXPECT_EQ(0, location_bar->PageActionVisibleCount()); 100 101 // Load two extensions with page actions. 102 extensions::TestExtensionDir test_dir1; 103 const extensions::Extension* page_action1 = 104 LoadPageActionExtension(&test_dir1); 105 ASSERT_TRUE(page_action1); 106 107 extensions::TestExtensionDir test_dir2; 108 const extensions::Extension* page_action2 = 109 LoadPageActionExtension(&test_dir2); 110 ASSERT_TRUE(page_action2); 111 112 // Now there should be two page actions, but neither should be visible. 113 EXPECT_EQ(2, location_bar->PageActionCount()); 114 EXPECT_EQ(0, location_bar->PageActionVisibleCount()); 115 116 // Make the first page action visible. 117 ExtensionAction* action = extensions::ExtensionActionManager::Get( 118 profile())->GetPageAction(*page_action1); 119 content::WebContents* tab = 120 browser()->tab_strip_model()->GetActiveWebContents(); 121 int tab_id = SessionTabHelper::IdForTab(tab); 122 action->SetIsVisible(tab_id, true); 123 extensions::ExtensionActionAPI::Get(profile())->NotifyChange( 124 action, tab, profile()); 125 126 // Verify that only one action is visible and that it's the proper one. 127 EXPECT_EQ(2, location_bar->PageActionCount()); 128 EXPECT_EQ(1, location_bar->PageActionVisibleCount()); 129 EXPECT_EQ(action, location_bar->GetVisiblePageAction(0u)); 130 131 // Trigger the visible page action, and ensure it executes. 132 ExtensionTestMessageListener clicked_listener("clicked", false); 133 clicked_listener.set_extension_id(page_action1->id()); 134 location_bar->TestPageActionPressed(0u); 135 EXPECT_TRUE(clicked_listener.WaitUntilSatisfied()); 136} 137 138// Test that installing an extension that overrides the bookmark star 139// successfully hides the star. 140IN_PROC_BROWSER_TEST_F(LocationBarBrowserTest, 141 ExtensionCanOverrideBookmarkStar) { 142 LocationBarTesting* location_bar = 143 browser()->window()->GetLocationBar()->GetLocationBarForTesting(); 144 // By default, we should show the star. 145 EXPECT_TRUE(location_bar->GetBookmarkStarVisibility()); 146 147 // Create and install an extension that overrides the bookmark star. 148 extensions::DictionaryBuilder chrome_ui_overrides; 149 chrome_ui_overrides.Set( 150 "bookmarks_ui", 151 extensions::DictionaryBuilder().SetBoolean("remove_button", true)); 152 scoped_refptr<const extensions::Extension> extension = 153 extensions::ExtensionBuilder(). 154 SetManifest(extensions::DictionaryBuilder(). 155 Set("name", "overrides star"). 156 Set("manifest_version", 2). 157 Set("version", "0.1"). 158 Set("description", "override the star"). 159 Set("chrome_ui_overrides", 160 chrome_ui_overrides.Pass())).Build(); 161 extension_service()->AddExtension(extension.get()); 162 163 // The star should now be hidden. 164 EXPECT_FALSE(location_bar->GetBookmarkStarVisibility()); 165} 166 167class LocationBarBrowserTestWithRedesign : public LocationBarBrowserTest { 168 public: 169 LocationBarBrowserTestWithRedesign() {} 170 virtual ~LocationBarBrowserTestWithRedesign() {} 171 172 private: 173 virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE; 174 175 scoped_ptr<extensions::FeatureSwitch::ScopedOverride> enable_redesign_; 176 177 DISALLOW_COPY_AND_ASSIGN(LocationBarBrowserTestWithRedesign); 178}; 179 180void LocationBarBrowserTestWithRedesign::SetUpCommandLine( 181 base::CommandLine* command_line) { 182 LocationBarBrowserTest::SetUpCommandLine(command_line); 183 enable_redesign_.reset(new extensions::FeatureSwitch::ScopedOverride( 184 extensions::FeatureSwitch::extension_action_redesign(), true)); 185} 186 187// Test that page actions are not displayed in the location bar if the 188// extension action redesign switch is enabled. 189IN_PROC_BROWSER_TEST_F(LocationBarBrowserTestWithRedesign, 190 PageActionUITestWithRedesign) { 191 LocationBarTesting* location_bar = 192 browser()->window()->GetLocationBar()->GetLocationBarForTesting(); 193 EXPECT_EQ(0, location_bar->PageActionCount()); 194 EXPECT_EQ(0, location_bar->PageActionVisibleCount()); 195 196 // Load an extension with a page action. 197 extensions::TestExtensionDir test_dir1; 198 const extensions::Extension* page_action1 = 199 LoadPageActionExtension(&test_dir1); 200 ASSERT_TRUE(page_action1); 201 202 // We should still have no page actions. 203 EXPECT_EQ(0, location_bar->PageActionCount()); 204 EXPECT_EQ(0, location_bar->PageActionVisibleCount()); 205 206 // Set the page action to be visible. 207 ExtensionAction* action = extensions::ExtensionActionManager::Get( 208 profile())->GetPageAction(*page_action1); 209 content::WebContents* tab = 210 browser()->tab_strip_model()->GetActiveWebContents(); 211 int tab_id = SessionTabHelper::IdForTab(tab); 212 action->SetIsVisible(tab_id, true); 213 extensions::ExtensionActionAPI::Get(profile())->NotifyChange( 214 action, tab, profile()); 215 216 // We should still have no page actions. 217 EXPECT_EQ(0, location_bar->PageActionCount()); 218 EXPECT_EQ(0, location_bar->PageActionVisibleCount()); 219} 220