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
20 enum MenuEntries {
21 NAME = 0,
22 CONFIGURE,
23 HIDE,
24 DISABLE,
25 UNINSTALL,
26 MANAGE,
27 INSPECT_POPUP
28 };
29
ExtensionContextMenuModel(const Extension * extension,Browser * browser,PopupDelegate * delegate)30 ExtensionContextMenuModel::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
~ExtensionContextMenuModel()52 ExtensionContextMenuModel::~ExtensionContextMenuModel() {
53 }
54
InitCommonCommands()55 void 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
IsCommandIdChecked(int command_id) const73 bool ExtensionContextMenuModel::IsCommandIdChecked(int command_id) const {
74 return false;
75 }
76
IsCommandIdEnabled(int command_id) const77 bool 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
GetAcceleratorForCommandId(int command_id,ui::Accelerator * accelerator)101 bool ExtensionContextMenuModel::GetAcceleratorForCommandId(
102 int command_id, ui::Accelerator* accelerator) {
103 return false;
104 }
105
ExecuteCommand(int command_id)106 void 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
ExtensionDialogAccepted()153 void ExtensionContextMenuModel::ExtensionDialogAccepted() {
154 if (GetExtension())
155 profile_->GetExtensionService()->UninstallExtension(extension_id_, false,
156 NULL);
157
158 Release();
159 }
160
ExtensionDialogCanceled()161 void ExtensionContextMenuModel::ExtensionDialogCanceled() {
162 Release();
163 }
164
GetExtension() const165 const Extension* ExtensionContextMenuModel::GetExtension() const {
166 ExtensionService* extension_service = profile_->GetExtensionService();
167 return extension_service->GetExtensionById(extension_id_, false);
168 }
169