1// Copyright (c) 2011 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/extension_context_menu_model.h"
6
7#include "base/utf_string_conversions.h"
8#include "chrome/browser/extensions/extension_service.h"
9#include "chrome/browser/extensions/extension_tabs_module.h"
10#include "chrome/browser/prefs/pref_service.h"
11#include "chrome/browser/profiles/profile.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/common/extensions/extension.h"
14#include "chrome/common/extensions/extension_action.h"
15#include "chrome/common/extensions/extension_constants.h"
16#include "chrome/common/pref_names.h"
17#include "chrome/common/url_constants.h"
18#include "grit/generated_resources.h"
19
20enum MenuEntries {
21  NAME = 0,
22  CONFIGURE,
23  HIDE,
24  DISABLE,
25  UNINSTALL,
26  MANAGE,
27  INSPECT_POPUP
28};
29
30ExtensionContextMenuModel::ExtensionContextMenuModel(
31    const Extension* extension,
32    Browser* browser,
33    PopupDelegate* delegate)
34    : ALLOW_THIS_IN_INITIALIZER_LIST(SimpleMenuModel(this)),
35      extension_id_(extension->id()),
36      browser_(browser),
37      profile_(browser->profile()),
38      delegate_(delegate) {
39  extension_action_ = extension->browser_action();
40  if (!extension_action_)
41    extension_action_ = extension->page_action();
42
43  InitCommonCommands();
44
45  if (profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode) &&
46      delegate_) {
47    AddSeparator();
48    AddItemWithStringId(INSPECT_POPUP, IDS_EXTENSION_ACTION_INSPECT_POPUP);
49  }
50}
51
52ExtensionContextMenuModel::~ExtensionContextMenuModel() {
53}
54
55void ExtensionContextMenuModel::InitCommonCommands() {
56  const Extension* extension = GetExtension();
57
58  // The extension pointer should only be null if the extension was uninstalled,
59  // and since the menu just opened, it should still be installed.
60  DCHECK(extension);
61
62  AddItem(NAME, UTF8ToUTF16(extension->name()));
63  AddSeparator();
64  AddItemWithStringId(CONFIGURE, IDS_EXTENSIONS_OPTIONS);
65  AddItemWithStringId(DISABLE, IDS_EXTENSIONS_DISABLE);
66  AddItemWithStringId(UNINSTALL, IDS_EXTENSIONS_UNINSTALL);
67  if (extension->browser_action())
68    AddItemWithStringId(HIDE, IDS_EXTENSIONS_HIDE_BUTTON);
69  AddSeparator();
70  AddItemWithStringId(MANAGE, IDS_MANAGE_EXTENSIONS);
71}
72
73bool ExtensionContextMenuModel::IsCommandIdChecked(int command_id) const {
74  return false;
75}
76
77bool ExtensionContextMenuModel::IsCommandIdEnabled(int command_id) const {
78  const Extension* extension = this->GetExtension();
79  if (!extension)
80    return false;
81
82  if (command_id == CONFIGURE) {
83    return extension->options_url().spec().length() > 0;
84  } else if (command_id == NAME) {
85    // The NAME links to the Homepage URL. If the extension doesn't have a
86    // homepage, we just disable this menu item.
87    return extension->GetHomepageURL().is_valid();
88  } else if (command_id == INSPECT_POPUP) {
89    TabContents* contents = browser_->GetSelectedTabContents();
90    if (!contents)
91      return false;
92
93    return extension_action_->HasPopup(ExtensionTabUtil::GetTabId(contents));
94  } else if (command_id == DISABLE || command_id == UNINSTALL) {
95    // Some extension types can not be disabled or uninstalled.
96    return Extension::UserMayDisable(extension->location());
97  }
98  return true;
99}
100
101bool ExtensionContextMenuModel::GetAcceleratorForCommandId(
102    int command_id, ui::Accelerator* accelerator) {
103  return false;
104}
105
106void ExtensionContextMenuModel::ExecuteCommand(int command_id) {
107  const Extension* extension = GetExtension();
108  if (!extension)
109    return;
110
111  switch (command_id) {
112    case NAME: {
113      browser_->OpenURL(extension->GetHomepageURL(), GURL(),
114                        NEW_FOREGROUND_TAB, PageTransition::LINK);
115      break;
116    }
117    case CONFIGURE:
118      DCHECK(!extension->options_url().is_empty());
119      profile_->GetExtensionProcessManager()->OpenOptionsPage(extension,
120                                                              browser_);
121      break;
122    case HIDE: {
123      ExtensionService* extension_service = profile_->GetExtensionService();
124      extension_service->SetBrowserActionVisibility(extension, false);
125      break;
126    }
127    case DISABLE: {
128      ExtensionService* extension_service = profile_->GetExtensionService();
129      extension_service->DisableExtension(extension_id_);
130      break;
131    }
132    case UNINSTALL: {
133      AddRef();  // Balanced in Accepted() and Canceled()
134      extension_uninstall_dialog_.reset(new ExtensionUninstallDialog(profile_));
135      extension_uninstall_dialog_->ConfirmUninstall(this, extension);
136      break;
137    }
138    case MANAGE: {
139      browser_->OpenURL(GURL(chrome::kChromeUIExtensionsURL), GURL(),
140                        SINGLETON_TAB, PageTransition::LINK);
141      break;
142    }
143    case INSPECT_POPUP: {
144      delegate_->InspectPopup(extension_action_);
145      break;
146    }
147    default:
148     NOTREACHED() << "Unknown option";
149     break;
150  }
151}
152
153void ExtensionContextMenuModel::ExtensionDialogAccepted() {
154  if (GetExtension())
155    profile_->GetExtensionService()->UninstallExtension(extension_id_, false,
156                                                        NULL);
157
158  Release();
159}
160
161void ExtensionContextMenuModel::ExtensionDialogCanceled() {
162  Release();
163}
164
165const Extension* ExtensionContextMenuModel::GetExtension() const {
166  ExtensionService* extension_service = profile_->GetExtensionService();
167  return extension_service->GetExtensionById(extension_id_, false);
168}
169