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 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 52 ExtensionContextMenuModel::~ExtensionContextMenuModel() { 53 } 54 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 73 bool ExtensionContextMenuModel::IsCommandIdChecked(int command_id) const { 74 return false; 75 } 76 77 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 101 bool ExtensionContextMenuModel::GetAcceleratorForCommandId( 102 int command_id, ui::Accelerator* accelerator) { 103 return false; 104 } 105 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 153 void ExtensionContextMenuModel::ExtensionDialogAccepted() { 154 if (GetExtension()) 155 profile_->GetExtensionService()->UninstallExtension(extension_id_, false, 156 NULL); 157 158 Release(); 159 } 160 161 void ExtensionContextMenuModel::ExtensionDialogCanceled() { 162 Release(); 163 } 164 165 const Extension* ExtensionContextMenuModel::GetExtension() const { 166 ExtensionService* extension_service = profile_->GetExtensionService(); 167 return extension_service->GetExtensionById(extension_id_, false); 168 } 169