Prevent chrome://net-internals/#export from flickering
[chromium-blink-merge.git] / chrome / browser / extensions / extension_context_menu_model_unittest.cc
blob16fb6959e5f16f54ce39ab696b0ac43f10958027
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.
5 #include "chrome/browser/extensions/extension_context_menu_model.h"
7 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
8 #include "chrome/browser/extensions/extension_service.h"
9 #include "chrome/browser/extensions/extension_service_test_base.h"
10 #include "chrome/browser/extensions/menu_manager.h"
11 #include "chrome/browser/extensions/menu_manager_factory.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/host_desktop.h"
14 #include "chrome/common/extensions/api/context_menus.h"
15 #include "chrome/grit/generated_resources.h"
16 #include "chrome/test/base/test_browser_window.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "components/crx_file/id_util.h"
19 #include "extensions/browser/extension_prefs.h"
20 #include "extensions/browser/extension_system.h"
21 #include "extensions/browser/test_management_policy.h"
22 #include "extensions/common/extension_builder.h"
23 #include "extensions/common/feature_switch.h"
24 #include "extensions/common/manifest.h"
25 #include "extensions/common/manifest_constants.h"
26 #include "extensions/common/value_builder.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "ui/base/l10n/l10n_util.h"
30 namespace extensions {
32 namespace {
34 // Build an extension to pass to the menu constructor, with the an action
35 // specified by |action_key|.
36 scoped_refptr<const Extension> BuildExtension(const std::string& name,
37 const char* action_key,
38 Manifest::Location location) {
39 return ExtensionBuilder()
40 .SetManifest(DictionaryBuilder()
41 .Set("name", name)
42 .Set("version", "1")
43 .Set("manifest_version", 2)
44 .Set(action_key, DictionaryBuilder().Pass()))
45 .SetID(crx_file::id_util::GenerateId(name))
46 .SetLocation(location)
47 .Build();
50 // Create a Browser for the ExtensionContextMenuModel to use.
51 scoped_ptr<Browser> CreateBrowser(Profile* profile) {
52 Browser::CreateParams params(profile, chrome::GetActiveDesktop());
53 TestBrowserWindow test_window;
54 params.window = &test_window;
55 return scoped_ptr<Browser>(new Browser(params));
58 // Returns the index of the given |command_id| in the given |menu|, or -1 if it
59 // is not found.
60 int GetCommandIndex(const scoped_refptr<ExtensionContextMenuModel> menu,
61 int command_id) {
62 int item_count = menu->GetItemCount();
63 for (int i = 0; i < item_count; ++i) {
64 if (menu->GetCommandIdAt(i) == command_id)
65 return i;
67 return -1;
70 } // namespace
72 class ExtensionContextMenuModelTest : public ExtensionServiceTestBase {
73 public:
74 ExtensionContextMenuModelTest();
76 // Creates an extension menu item for |extension| with the given |context|
77 // and adds it to |manager|. Refreshes |model| to show new item.
78 void AddContextItemAndRefreshModel(MenuManager* manager,
79 const Extension* extension,
80 MenuItem::Context context,
81 ExtensionContextMenuModel* model);
83 // Reinitializes the given |model|.
84 void RefreshMenu(ExtensionContextMenuModel* model);
86 // Returns the number of extension menu items that show up in |model|.
87 int CountExtensionItems(ExtensionContextMenuModel* model);
89 private:
90 int cur_id_;
93 ExtensionContextMenuModelTest::ExtensionContextMenuModelTest() : cur_id_(0) {
97 void ExtensionContextMenuModelTest::AddContextItemAndRefreshModel(
98 MenuManager* manager,
99 const Extension* extension,
100 MenuItem::Context context,
101 ExtensionContextMenuModel* model) {
102 MenuItem::Type type = MenuItem::NORMAL;
103 MenuItem::ContextList contexts(context);
104 const MenuItem::ExtensionKey key(extension->id());
105 MenuItem::Id id(false, key);
106 id.uid = ++cur_id_;
107 manager->AddContextItem(extension,
108 new MenuItem(id,
109 "test",
110 false, // checked
111 true, // enabled
112 type,
113 contexts));
114 RefreshMenu(model);
117 void ExtensionContextMenuModelTest::RefreshMenu(
118 ExtensionContextMenuModel* model) {
119 model->InitMenu(model->GetExtension());
122 int ExtensionContextMenuModelTest::CountExtensionItems(
123 ExtensionContextMenuModel* model) {
124 return model->extension_items_count_;
127 // Tests that applicable menu items are disabled when a ManagementPolicy
128 // prohibits them.
129 TEST_F(ExtensionContextMenuModelTest, RequiredInstallationsDisablesItems) {
130 InitializeEmptyExtensionService();
132 // First, test that a component extension cannot be uninstalled by the
133 // standard management policy.
134 scoped_refptr<const Extension> extension =
135 BuildExtension("component",
136 manifest_keys::kBrowserAction,
137 Manifest::COMPONENT);
138 ASSERT_TRUE(extension.get());
139 service()->AddExtension(extension.get());
141 scoped_ptr<Browser> browser = CreateBrowser(profile());
143 scoped_refptr<ExtensionContextMenuModel> menu(
144 new ExtensionContextMenuModel(extension.get(), browser.get()));
146 // Uninstallation should be disabled.
147 EXPECT_FALSE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::UNINSTALL));
149 // Also test that management policy can determine whether or not
150 // policy-installed extensions can be installed/uninstalled.
151 extension = BuildExtension("extension",
152 manifest_keys::kPageAction,
153 Manifest::INTERNAL);
154 ASSERT_TRUE(extension.get());
155 service()->AddExtension(extension.get());
157 menu = new ExtensionContextMenuModel(extension.get(), browser.get());
159 ExtensionSystem* system = ExtensionSystem::Get(profile());
160 system->management_policy()->UnregisterAllProviders();
162 // Actions should be enabled.
163 ASSERT_TRUE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::UNINSTALL));
165 TestManagementPolicyProvider policy_provider(
166 TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
167 system->management_policy()->RegisterProvider(&policy_provider);
169 // Now the actions are disabled.
170 ASSERT_FALSE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::UNINSTALL));
172 // Don't leave |policy_provider| dangling.
173 system->management_policy()->UnregisterProvider(&policy_provider);
176 TEST_F(ExtensionContextMenuModelTest, ExtensionItemTest) {
177 InitializeEmptyExtensionService();
178 scoped_refptr<const Extension> extension =
179 BuildExtension("extension",
180 manifest_keys::kPageAction,
181 Manifest::INTERNAL);
182 ASSERT_TRUE(extension.get());
183 service()->AddExtension(extension.get());
185 scoped_ptr<Browser> browser = CreateBrowser(profile());
187 // Create a MenuManager for adding context items.
188 MenuManager* manager = static_cast<MenuManager*>(
189 (MenuManagerFactory::GetInstance()->SetTestingFactoryAndUse(
190 profile(),
191 &MenuManagerFactory::BuildServiceInstanceForTesting)));
192 ASSERT_TRUE(manager);
194 scoped_refptr<ExtensionContextMenuModel> menu(
195 new ExtensionContextMenuModel(extension.get(), browser.get()));
197 // There should be no extension items yet.
198 EXPECT_EQ(0, CountExtensionItems(menu.get()));
200 // Add a browser action menu item for |extension| to |manager|.
201 AddContextItemAndRefreshModel(
202 manager, extension.get(), MenuItem::BROWSER_ACTION, menu.get());
204 // Since |extension| has a page action, the browser action menu item should
205 // not be present.
206 EXPECT_EQ(0, CountExtensionItems(menu.get()));
208 // Add a page action menu item and reset the context menu.
209 AddContextItemAndRefreshModel(
210 manager, extension.get(), MenuItem::PAGE_ACTION, menu.get());
212 // The page action item should be present because |extension| has a page
213 // action.
214 EXPECT_EQ(1, CountExtensionItems(menu.get()));
216 // Create more page action items to test top level menu item limitations.
217 for (int i = 0; i < api::context_menus::ACTION_MENU_TOP_LEVEL_LIMIT; ++i)
218 AddContextItemAndRefreshModel(
219 manager, extension.get(), MenuItem::PAGE_ACTION, menu.get());
221 // The menu should only have a limited number of extension items, since they
222 // are all top level items, and we limit the number of top level extension
223 // items.
224 EXPECT_EQ(api::context_menus::ACTION_MENU_TOP_LEVEL_LIMIT,
225 CountExtensionItems(menu.get()));
227 AddContextItemAndRefreshModel(
228 manager, extension.get(), MenuItem::PAGE_ACTION, menu.get());
230 // Adding another top level item should not increase the count.
231 EXPECT_EQ(api::context_menus::ACTION_MENU_TOP_LEVEL_LIMIT,
232 CountExtensionItems(menu.get()));
235 // Test that the "show" and "hide" menu items appear correctly in the extension
236 // context menu.
237 TEST_F(ExtensionContextMenuModelTest, ExtensionContextMenuShowAndHide) {
238 InitializeEmptyExtensionService();
239 scoped_refptr<const Extension> page_action =
240 BuildExtension("page_action_extension",
241 manifest_keys::kPageAction,
242 Manifest::INTERNAL);
243 ASSERT_TRUE(page_action.get());
244 scoped_refptr<const Extension> browser_action =
245 BuildExtension("browser_action_extension",
246 manifest_keys::kBrowserAction,
247 Manifest::INTERNAL);
248 ASSERT_TRUE(browser_action.get());
250 service()->AddExtension(page_action.get());
251 service()->AddExtension(browser_action.get());
253 scoped_ptr<Browser> browser = CreateBrowser(profile());
255 scoped_refptr<ExtensionContextMenuModel> menu(
256 new ExtensionContextMenuModel(page_action.get(), browser.get()));
258 // For laziness.
259 const ExtensionContextMenuModel::MenuEntries visibility_command =
260 ExtensionContextMenuModel::TOGGLE_VISIBILITY;
261 base::string16 hide_string =
262 l10n_util::GetStringUTF16(IDS_EXTENSIONS_HIDE_BUTTON);
263 base::string16 show_string =
264 l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_BUTTON);
265 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
267 int index = GetCommandIndex(menu, visibility_command);
268 // Without the toolbar redesign switch, page action menus shouldn't have a
269 // visibility option.
270 EXPECT_EQ(-1, index);
272 menu = new ExtensionContextMenuModel(browser_action.get(), browser.get());
273 index = GetCommandIndex(menu, visibility_command);
274 // Browser actions should have the visibility option.
275 EXPECT_NE(-1, index);
277 // Enabling the toolbar redesign switch should give page actions the button.
278 FeatureSwitch::ScopedOverride enable_toolbar_redesign(
279 FeatureSwitch::extension_action_redesign(), true);
280 menu = new ExtensionContextMenuModel(page_action.get(), browser.get());
281 index = GetCommandIndex(menu, visibility_command);
282 EXPECT_NE(-1, index);
284 // Next, we test the command label.
285 menu = new ExtensionContextMenuModel(browser_action.get(), browser.get());
286 index = GetCommandIndex(menu, visibility_command);
287 // By default, browser actions should be visible (and therefore the button
288 // should be to hide).
289 EXPECT_TRUE(ExtensionActionAPI::GetBrowserActionVisibility(
290 prefs, browser_action->id()));
291 EXPECT_EQ(hide_string, menu->GetLabelAt(index));
293 // Hide the browser action. This should mean the string is "show".
294 ExtensionActionAPI::SetBrowserActionVisibility(
295 prefs, browser_action->id(), false);
296 menu = new ExtensionContextMenuModel(browser_action.get(), browser.get());
297 index = GetCommandIndex(menu, visibility_command);
298 EXPECT_NE(-1, index);
299 EXPECT_EQ(show_string, menu->GetLabelAt(index));
302 } // namespace extensions