OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_context_menu_model.h" | 5 #include "chrome/browser/extensions/extension_context_menu_model.h" |
6 | 6 |
7 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" | 7 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" |
8 #include "chrome/browser/extensions/extension_service.h" | 8 #include "chrome/browser/extensions/extension_service.h" |
9 #include "chrome/browser/extensions/extension_service_test_base.h" | 9 #include "chrome/browser/extensions/extension_service_test_base.h" |
10 #include "chrome/browser/extensions/menu_manager.h" | 10 #include "chrome/browser/extensions/menu_manager.h" |
11 #include "chrome/browser/extensions/menu_manager_factory.h" | 11 #include "chrome/browser/extensions/menu_manager_factory.h" |
12 #include "chrome/browser/ui/browser.h" | 12 #include "chrome/browser/ui/browser.h" |
13 #include "chrome/browser/ui/host_desktop.h" | 13 #include "chrome/browser/ui/host_desktop.h" |
14 #include "chrome/common/extensions/api/context_menus.h" | 14 #include "chrome/common/extensions/api/context_menus.h" |
15 #include "chrome/grit/chromium_strings.h" | 15 #include "chrome/grit/chromium_strings.h" |
16 #include "chrome/grit/generated_resources.h" | 16 #include "chrome/grit/generated_resources.h" |
17 #include "chrome/test/base/test_browser_window.h" | 17 #include "chrome/test/base/test_browser_window.h" |
18 #include "chrome/test/base/testing_profile.h" | 18 #include "chrome/test/base/testing_profile.h" |
19 #include "components/crx_file/id_util.h" | 19 #include "components/crx_file/id_util.h" |
20 #include "extensions/browser/extension_system.h" | 20 #include "extensions/browser/extension_system.h" |
21 #include "extensions/browser/test_management_policy.h" | 21 #include "extensions/browser/test_management_policy.h" |
22 #include "extensions/common/extension_builder.h" | 22 #include "extensions/common/extension_builder.h" |
23 #include "extensions/common/feature_switch.h" | 23 #include "extensions/common/feature_switch.h" |
24 #include "extensions/common/manifest.h" | 24 #include "extensions/common/manifest.h" |
25 #include "extensions/common/manifest_constants.h" | 25 #include "extensions/common/manifest_constants.h" |
| 26 #include "extensions/common/manifest_handlers/options_page_info.h" |
26 #include "extensions/common/value_builder.h" | 27 #include "extensions/common/value_builder.h" |
27 #include "testing/gtest/include/gtest/gtest.h" | 28 #include "testing/gtest/include/gtest/gtest.h" |
28 #include "ui/base/l10n/l10n_util.h" | 29 #include "ui/base/l10n/l10n_util.h" |
| 30 #include "ui/gfx/image/image.h" |
29 | 31 |
30 namespace extensions { | 32 namespace extensions { |
31 | 33 |
32 namespace { | 34 namespace { |
33 | 35 |
34 // Build an extension to pass to the menu constructor, with the an action | 36 // Build an extension to pass to the menu constructor, with the an action |
35 // specified by |action_key|. | 37 // specified by |action_key|. |
36 scoped_refptr<const Extension> BuildExtension(const std::string& name, | 38 scoped_refptr<const Extension> BuildExtension(const std::string& name, |
37 const char* action_key, | 39 const char* action_key, |
38 Manifest::Location location) { | 40 Manifest::Location location) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 // Returns the number of extension menu items that show up in |model|. | 88 // Returns the number of extension menu items that show up in |model|. |
87 int CountExtensionItems(ExtensionContextMenuModel* model); | 89 int CountExtensionItems(ExtensionContextMenuModel* model); |
88 | 90 |
89 private: | 91 private: |
90 int cur_id_; | 92 int cur_id_; |
91 }; | 93 }; |
92 | 94 |
93 ExtensionContextMenuModelTest::ExtensionContextMenuModelTest() : cur_id_(0) { | 95 ExtensionContextMenuModelTest::ExtensionContextMenuModelTest() : cur_id_(0) { |
94 } | 96 } |
95 | 97 |
96 | |
97 void ExtensionContextMenuModelTest::AddContextItemAndRefreshModel( | 98 void ExtensionContextMenuModelTest::AddContextItemAndRefreshModel( |
98 MenuManager* manager, | 99 MenuManager* manager, |
99 const Extension* extension, | 100 const Extension* extension, |
100 MenuItem::Context context, | 101 MenuItem::Context context, |
101 ExtensionContextMenuModel* model) { | 102 ExtensionContextMenuModel* model) { |
102 MenuItem::Type type = MenuItem::NORMAL; | 103 MenuItem::Type type = MenuItem::NORMAL; |
103 MenuItem::ContextList contexts(context); | 104 MenuItem::ContextList contexts(context); |
104 const MenuItem::ExtensionKey key(extension->id()); | 105 const MenuItem::ExtensionKey key(extension->id()); |
105 MenuItem::Id id(false, key); | 106 MenuItem::Id id(false, key); |
106 id.uid = ++cur_id_; | 107 id.uid = ++cur_id_; |
(...skipping 15 matching lines...) Expand all Loading... |
122 int ExtensionContextMenuModelTest::CountExtensionItems( | 123 int ExtensionContextMenuModelTest::CountExtensionItems( |
123 ExtensionContextMenuModel* model) { | 124 ExtensionContextMenuModel* model) { |
124 return model->extension_items_count_; | 125 return model->extension_items_count_; |
125 } | 126 } |
126 | 127 |
127 // Tests that applicable menu items are disabled when a ManagementPolicy | 128 // Tests that applicable menu items are disabled when a ManagementPolicy |
128 // prohibits them. | 129 // prohibits them. |
129 TEST_F(ExtensionContextMenuModelTest, RequiredInstallationsDisablesItems) { | 130 TEST_F(ExtensionContextMenuModelTest, RequiredInstallationsDisablesItems) { |
130 InitializeEmptyExtensionService(); | 131 InitializeEmptyExtensionService(); |
131 | 132 |
132 // First, test that a component extension cannot be uninstalled by the | 133 // Test that management policy can determine whether or not policy-installed |
133 // standard management policy. | 134 // extensions can be installed/uninstalled. |
134 scoped_refptr<const Extension> extension = | 135 scoped_refptr<const Extension> extension = |
135 BuildExtension("component", | 136 BuildExtension("extension", |
136 manifest_keys::kBrowserAction, | 137 manifest_keys::kPageAction, |
137 Manifest::COMPONENT); | 138 Manifest::EXTERNAL_POLICY); |
138 ASSERT_TRUE(extension.get()); | 139 ASSERT_TRUE(extension.get()); |
139 service()->AddExtension(extension.get()); | 140 service()->AddExtension(extension.get()); |
140 | 141 |
141 scoped_ptr<Browser> browser = CreateBrowser(profile()); | 142 scoped_ptr<Browser> browser = CreateBrowser(profile()); |
| 143 scoped_refptr<ExtensionContextMenuModel> menu( |
| 144 new ExtensionContextMenuModel(extension.get(), browser.get())); |
| 145 |
| 146 ExtensionSystem* system = ExtensionSystem::Get(profile()); |
| 147 system->management_policy()->UnregisterAllProviders(); |
| 148 |
| 149 // Uninstallation should be, by default, enabled. |
| 150 ASSERT_TRUE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::UNINSTALL)); |
| 151 |
| 152 TestManagementPolicyProvider policy_provider( |
| 153 TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS); |
| 154 system->management_policy()->RegisterProvider(&policy_provider); |
| 155 |
| 156 // If there's a policy provider that requires the extension stay enabled, then |
| 157 // uninstallation should be disabled. |
| 158 ASSERT_FALSE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::UNINSTALL)); |
| 159 |
| 160 // Don't leave |policy_provider| dangling. |
| 161 system->management_policy()->UnregisterProvider(&policy_provider); |
| 162 } |
| 163 |
| 164 // Tests the context menu for a component extension. |
| 165 TEST_F(ExtensionContextMenuModelTest, ComponentExtensionContextMenu) { |
| 166 InitializeEmptyExtensionService(); |
| 167 |
| 168 std::string name("component"); |
| 169 scoped_ptr<base::DictionaryValue> manifest = |
| 170 DictionaryBuilder().Set("name", name) |
| 171 .Set("version", "1") |
| 172 .Set("manifest_version", 2) |
| 173 .Set("browser_action", DictionaryBuilder().Pass()) |
| 174 .Build(); |
| 175 |
| 176 scoped_refptr<const Extension> extension = |
| 177 ExtensionBuilder().SetManifest(make_scoped_ptr(manifest->DeepCopy())) |
| 178 .SetID(crx_file::id_util::GenerateId("component")) |
| 179 .SetLocation(Manifest::COMPONENT) |
| 180 .Build(); |
| 181 service()->AddExtension(extension.get()); |
| 182 |
| 183 scoped_ptr<Browser> browser = CreateBrowser(profile()); |
142 | 184 |
143 scoped_refptr<ExtensionContextMenuModel> menu( | 185 scoped_refptr<ExtensionContextMenuModel> menu( |
144 new ExtensionContextMenuModel(extension.get(), browser.get())); | 186 new ExtensionContextMenuModel(extension.get(), browser.get())); |
145 | 187 |
146 // Uninstallation should be disabled. | 188 // A component extension's context menu should not include options for |
147 EXPECT_FALSE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::UNINSTALL)); | 189 // managing extensions or removing it, and should only include an option for |
| 190 // the options page if the extension has one (which this one doesn't). |
| 191 EXPECT_EQ(-1, |
| 192 menu->GetIndexOfCommandId(ExtensionContextMenuModel::CONFIGURE)); |
| 193 EXPECT_EQ(-1, |
| 194 menu->GetIndexOfCommandId(ExtensionContextMenuModel::UNINSTALL)); |
| 195 EXPECT_EQ(-1, menu->GetIndexOfCommandId(ExtensionContextMenuModel::MANAGE)); |
| 196 // The "name" option should be present, but not enabled for component |
| 197 // extensions. |
| 198 EXPECT_NE(-1, menu->GetIndexOfCommandId(ExtensionContextMenuModel::NAME)); |
| 199 EXPECT_FALSE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::NAME)); |
148 | 200 |
149 // Also test that management policy can determine whether or not | 201 // Check that a component extension with an options page does have the options |
150 // policy-installed extensions can be installed/uninstalled. | 202 // menu item, and it is enabled. |
151 extension = BuildExtension("extension", | 203 manifest->SetString("options_page", "options_page.html"); |
152 manifest_keys::kPageAction, | 204 extension = |
153 Manifest::INTERNAL); | 205 ExtensionBuilder().SetManifest(manifest.Pass()) |
154 ASSERT_TRUE(extension.get()); | 206 .SetID(crx_file::id_util::GenerateId("component_opts")) |
| 207 .SetLocation(Manifest::COMPONENT) |
| 208 .Build(); |
| 209 menu = new ExtensionContextMenuModel(extension.get(), browser.get()); |
155 service()->AddExtension(extension.get()); | 210 service()->AddExtension(extension.get()); |
156 | 211 EXPECT_TRUE(extensions::OptionsPageInfo::HasOptionsPage(extension.get())); |
157 menu = new ExtensionContextMenuModel(extension.get(), browser.get()); | 212 EXPECT_NE(-1, |
158 | 213 menu->GetIndexOfCommandId(ExtensionContextMenuModel::CONFIGURE)); |
159 ExtensionSystem* system = ExtensionSystem::Get(profile()); | 214 EXPECT_TRUE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::CONFIGURE)); |
160 system->management_policy()->UnregisterAllProviders(); | |
161 | |
162 // Actions should be enabled. | |
163 ASSERT_TRUE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::UNINSTALL)); | |
164 | |
165 TestManagementPolicyProvider policy_provider( | |
166 TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS); | |
167 system->management_policy()->RegisterProvider(&policy_provider); | |
168 | |
169 // Now the actions are disabled. | |
170 ASSERT_FALSE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::UNINSTALL)); | |
171 | |
172 // Don't leave |policy_provider| dangling. | |
173 system->management_policy()->UnregisterProvider(&policy_provider); | |
174 } | 215 } |
175 | 216 |
176 TEST_F(ExtensionContextMenuModelTest, ExtensionItemTest) { | 217 TEST_F(ExtensionContextMenuModelTest, ExtensionItemTest) { |
177 InitializeEmptyExtensionService(); | 218 InitializeEmptyExtensionService(); |
178 scoped_refptr<const Extension> extension = | 219 scoped_refptr<const Extension> extension = |
179 BuildExtension("extension", | 220 BuildExtension("extension", |
180 manifest_keys::kPageAction, | 221 manifest_keys::kPageAction, |
181 Manifest::INTERNAL); | 222 Manifest::INTERNAL); |
182 ASSERT_TRUE(extension.get()); | 223 ASSERT_TRUE(extension.get()); |
183 service()->AddExtension(extension.get()); | 224 service()->AddExtension(extension.get()); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 browser_action.get(), | 354 browser_action.get(), |
314 browser.get(), | 355 browser.get(), |
315 ExtensionContextMenuModel::TRANSITIVELY_VISIBLE, | 356 ExtensionContextMenuModel::TRANSITIVELY_VISIBLE, |
316 nullptr); | 357 nullptr); |
317 index = GetCommandIndex(menu, visibility_command); | 358 index = GetCommandIndex(menu, visibility_command); |
318 EXPECT_NE(-1, index); | 359 EXPECT_NE(-1, index); |
319 EXPECT_EQ(redesign_keep_string, menu->GetLabelAt(index)); | 360 EXPECT_EQ(redesign_keep_string, menu->GetLabelAt(index)); |
320 } | 361 } |
321 | 362 |
322 } // namespace extensions | 363 } // namespace extensions |
OLD | NEW |