15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_context_menu_model.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/extensions/extension_service_test_base.h"
106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/browser/extensions/menu_manager.h"
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/browser/extensions/menu_manager_factory.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/common/extensions/api/context_menus.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/test_browser_window.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_profile.h"
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h"
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/test_management_policy.h"
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension_builder.h"
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/common/feature_switch.h"
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/common/manifest_constants.h"
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/value_builder.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace {
3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Build an extension to pass to the menu constructor, with the an action
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// specified by |action_key|.
3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)scoped_refptr<const Extension> BuildExtension(const std::string& name,
3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                              const char* action_key) {
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return ExtensionBuilder()
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      .SetManifest(DictionaryBuilder()
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                       .Set("name", name)
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                       .Set("version", "1")
4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                       .Set("manifest_version", 2)
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                       .Set(action_key, DictionaryBuilder().Pass()))
4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      .SetID(crx_file::id_util::GenerateId(name))
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      .Build();
4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Create a Browser for the ExtensionContextMenuModel to use.
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)scoped_ptr<Browser> CreateBrowser(Profile* profile) {
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  Browser::CreateParams params(profile, chrome::GetActiveDesktop());
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  TestBrowserWindow test_window;
5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  params.window = &test_window;
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return scoped_ptr<Browser>(new Browser(params));
5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Returns the index of the given |command_id| in the given |menu|, or -1 if it
5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// is not found.
5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)int GetCommandIndex(const scoped_refptr<ExtensionContextMenuModel> menu,
5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         int command_id) {
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int item_count = menu->GetItemCount();
6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (int i = 0; i < item_count; ++i) {
6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (menu->GetCommandIdAt(i) == command_id)
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return i;
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return -1;
6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // namespace
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionContextMenuModelTest : public ExtensionServiceTestBase {
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public:
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ExtensionContextMenuModelTest();
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Creates an extension menu item for |extension| with the given |context|
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // and adds it to |manager|. Refreshes |model| to show new item.
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void AddContextItemAndRefreshModel(MenuManager* manager,
7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                     const Extension* extension,
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                     MenuItem::Context context,
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                     ExtensionContextMenuModel* model);
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Reinitializes the given |model|.
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void RefreshMenu(ExtensionContextMenuModel* model);
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Returns the number of extension menu items that show up in |model|.
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int CountExtensionItems(ExtensionContextMenuModel* model);
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private:
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int cur_id_;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ExtensionContextMenuModelTest::ExtensionContextMenuModelTest() : cur_id_(0) {
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ExtensionContextMenuModelTest::AddContextItemAndRefreshModel(
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    MenuManager* manager,
9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const Extension* extension,
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    MenuItem::Context context,
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ExtensionContextMenuModel* model) {
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  MenuItem::Type type = MenuItem::NORMAL;
1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  MenuItem::ContextList contexts(context);
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const MenuItem::ExtensionKey key(extension->id());
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  MenuItem::Id id(false, key);
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  id.uid = ++cur_id_;
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  manager->AddContextItem(extension,
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          new MenuItem(id,
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       "test",
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       false,  // checked
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       true,   // enabled
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       type,
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       contexts));
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  RefreshMenu(model);
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ExtensionContextMenuModelTest::RefreshMenu(
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ExtensionContextMenuModel* model) {
1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  model->InitMenu(model->GetExtension());
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)int ExtensionContextMenuModelTest::CountExtensionItems(
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ExtensionContextMenuModel* model) {
1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return model->extension_items_count_;
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that applicable menu items are disabled when a ManagementPolicy
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prohibits them.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionContextMenuModelTest, PolicyDisablesItems) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeEmptyExtensionService();
12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<const Extension> extension =
12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      BuildExtension("extension", manifest_keys::kPageAction);
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(extension.get());
13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  service()->AddExtension(extension.get());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_ptr<Browser> browser = CreateBrowser(profile());
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ExtensionContextMenuModel> menu(
13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      new ExtensionContextMenuModel(extension.get(), browser.get()));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtensionSystem* system = ExtensionSystem::Get(profile());
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system->management_policy()->UnregisterAllProviders();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Actions should be enabled.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::UNINSTALL));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  TestManagementPolicyProvider policy_provider(
14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system->management_policy()->RegisterProvider(&policy_provider);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now the actions are disabled.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(menu->IsCommandIdEnabled(ExtensionContextMenuModel::UNINSTALL));
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't leave |policy_provider| dangling.
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  system->management_policy()->UnregisterAllProviders();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)TEST_F(ExtensionContextMenuModelTest, ExtensionItemTest) {
1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  InitializeEmptyExtensionService();
15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<const Extension> extension =
15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      BuildExtension("extension", manifest_keys::kPageAction);
1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ASSERT_TRUE(extension.get());
16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  service()->AddExtension(extension.get());
1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_ptr<Browser> browser = CreateBrowser(profile());
1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Create a MenuManager for adding context items.
1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  MenuManager* manager = static_cast<MenuManager*>(
1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      (MenuManagerFactory::GetInstance()->SetTestingFactoryAndUse(
16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          profile(),
1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          &MenuManagerFactory::BuildServiceInstanceForTesting)));
1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ASSERT_TRUE(manager);
1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_refptr<ExtensionContextMenuModel> menu(
17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      new ExtensionContextMenuModel(extension.get(), browser.get()));
1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // There should be no extension items yet.
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(0, CountExtensionItems(menu.get()));
1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Add a browser action menu item for |extension| to |manager|.
1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  AddContextItemAndRefreshModel(
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      manager, extension.get(), MenuItem::BROWSER_ACTION, menu.get());
1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Since |extension| has a page action, the browser action menu item should
1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // not be present.
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(0, CountExtensionItems(menu.get()));
1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Add a page action menu item and reset the context menu.
1866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  AddContextItemAndRefreshModel(
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      manager, extension.get(), MenuItem::PAGE_ACTION, menu.get());
1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // The page action item should be present because |extension| has a page
1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // action.
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(1, CountExtensionItems(menu.get()));
1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Create more page action items to test top level menu item limitations.
1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  for (int i = 0; i < api::context_menus::ACTION_MENU_TOP_LEVEL_LIMIT; ++i)
1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    AddContextItemAndRefreshModel(
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        manager, extension.get(), MenuItem::PAGE_ACTION, menu.get());
1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // The menu should only have a limited number of extension items, since they
1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // are all top level items, and we limit the number of top level extension
2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // items.
2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_EQ(api::context_menus::ACTION_MENU_TOP_LEVEL_LIMIT,
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            CountExtensionItems(menu.get()));
2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  AddContextItemAndRefreshModel(
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      manager, extension.get(), MenuItem::PAGE_ACTION, menu.get());
2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Adding another top level item should not increase the count.
2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_EQ(api::context_menus::ACTION_MENU_TOP_LEVEL_LIMIT,
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            CountExtensionItems(menu.get()));
2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Test that the "show" and "hide" menu items appear correctly in the extension
21303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// context menu.
21403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_F(ExtensionContextMenuModelTest, ExtensionContextMenuShowAndHide) {
21503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  InitializeEmptyExtensionService();
21603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<const Extension> page_action =
21703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      BuildExtension("page_action_extension", manifest_keys::kPageAction);
21803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_TRUE(page_action.get());
21903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<const Extension> browser_action =
22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      BuildExtension("browser_action_extension", manifest_keys::kBrowserAction);
22103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_TRUE(browser_action.get());
22203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
22303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  service()->AddExtension(page_action.get());
22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  service()->AddExtension(browser_action.get());
22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_ptr<Browser> browser = CreateBrowser(profile());
22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<ExtensionContextMenuModel> menu(
22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      new ExtensionContextMenuModel(page_action.get(), browser.get()));
23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // For laziness.
23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const ExtensionContextMenuModel::MenuEntries visibility_command =
23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      ExtensionContextMenuModel::TOGGLE_VISIBILITY;
23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::string16 hide_string =
23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_EXTENSIONS_HIDE_BUTTON);
23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::string16 show_string =
23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_BUTTON);
23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int index = GetCommandIndex(menu, visibility_command);
24103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Without the toolbar redesign switch, page action menus shouldn't have a
24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // visibility option.
24303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_EQ(-1, index);
24403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  menu = new ExtensionContextMenuModel(browser_action.get(), browser.get());
24603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  index = GetCommandIndex(menu, visibility_command);
24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Browser actions should have the visibility option.
24803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_NE(-1, index);
24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Enabling the toolbar redesign switch should give page actions the button.
25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  FeatureSwitch::ScopedOverride enable_toolbar_redesign(
25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      FeatureSwitch::extension_action_redesign(), true);
25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  menu = new ExtensionContextMenuModel(page_action.get(), browser.get());
25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  index = GetCommandIndex(menu, visibility_command);
25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_NE(-1, index);
25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Next, we test the command label.
25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  menu = new ExtensionContextMenuModel(browser_action.get(), browser.get());
25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  index = GetCommandIndex(menu, visibility_command);
26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // By default, browser actions should be visible (and therefore the button
26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // should be to hide).
26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(ExtensionActionAPI::GetBrowserActionVisibility(
26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                  prefs, browser_action->id()));
26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_EQ(hide_string, menu->GetLabelAt(index));
26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Hide the browser action. This should mean the string is "show".
26703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtensionActionAPI::SetBrowserActionVisibility(
26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      prefs, browser_action->id(), false);
26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  menu = new ExtensionContextMenuModel(browser_action.get(), browser.get());
27003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  index = GetCommandIndex(menu, visibility_command);
27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_NE(-1, index);
27203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_EQ(show_string, menu->GetLabelAt(index));
27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
27403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
276