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) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 9b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/extensions/api/extension_action/extension_action_api.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action_manager.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_system.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/management_policy.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/chrome_pages.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/manifest_url_handler.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::OpenURLParams; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::Referrer; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ExtensionContextMenuModel::ExtensionContextMenuModel(const Extension* extension, 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Browser* browser, 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PopupDelegate* delegate) 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : SimpleMenuModel(this), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_id_(extension->id()), 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_(browser), 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(browser->profile()), 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_(delegate) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitMenu(extension); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode) && 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddSeparator(ui::NORMAL_SEPARATOR); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddItemWithStringId(INSPECT_POPUP, IDS_EXTENSION_ACTION_INSPECT_POPUP); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ExtensionContextMenuModel::ExtensionContextMenuModel(const Extension* extension, 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Browser* browser) 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : SimpleMenuModel(this), 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_id_(extension->id()), 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_(browser), 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(browser->profile()), 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_(NULL) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitMenu(extension); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionContextMenuModel::IsCommandIdChecked(int command_id) const { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionContextMenuModel::IsCommandIdEnabled(int command_id) const { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = this->GetExtension(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command_id == CONFIGURE) { 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ManifestURL::GetOptionsPage(extension).spec().length() > 0; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (command_id == NAME) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The NAME links to the Homepage URL. If the extension doesn't have a 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // homepage, we just disable this menu item. 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return extensions::ManifestURL::GetHomepageURL(extension).is_valid(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (command_id == INSPECT_POPUP) { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* web_contents = 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_->tab_strip_model()->GetActiveWebContents(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!web_contents) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extension_action_ && 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_action_->HasPopup(SessionID::IdForTab(web_contents)); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (command_id == UNINSTALL) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some extension types can not be uninstalled. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extensions::ExtensionSystem::Get( 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_)->management_policy()->UserMayModifySettings(extension, NULL); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionContextMenuModel::GetAcceleratorForCommandId( 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int command_id, ui::Accelerator* accelerator) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionContextMenuModel::ExecuteCommand(int command_id, 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int event_flags) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = GetExtension(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (command_id) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case NAME: { 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OpenURLParams params(extensions::ManifestURL::GetHomepageURL(extension), 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Referrer(), NEW_FOREGROUND_TAB, 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::PAGE_TRANSITION_LINK, false); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_->OpenURL(params); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CONFIGURE: 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!extensions::ManifestURL::GetOptionsPage(extension).is_empty()); 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExtensionTabUtil::OpenOptionsPage(extension, browser_); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HIDE: { 118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) extensions::ExtensionActionAPI::SetBrowserActionVisibility( 119b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) extensions::ExtensionSystem::Get(profile_)-> 120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) extension_service()->extension_prefs(), 121b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) extension->id(), 122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) false); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case UNINSTALL: { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddRef(); // Balanced in Accepted() and Canceled() 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_uninstall_dialog_.reset( 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionUninstallDialog::Create(profile_, browser_, this)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_uninstall_dialog_->ConfirmUninstall(extension); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MANAGE: { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::ShowExtensions(browser_, extension->id()); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case INSPECT_POPUP: { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->InspectPopup(extension_action_); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unknown option"; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionContextMenuModel::ExtensionUninstallAccepted() { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (GetExtension()) { 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ExtensionSystem::Get(profile_)->extension_service()-> 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UninstallExtension(extension_id_, false, NULL); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionContextMenuModel::ExtensionUninstallCanceled() { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionContextMenuModel::~ExtensionContextMenuModel() {} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionContextMenuModel::InitMenu(const Extension* extension) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(extension); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionActionManager* extension_action_manager = 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionActionManager::Get(profile_); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_action_ = extension_action_manager->GetBrowserAction(*extension); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension_action_) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_action_ = extension_action_manager->GetPageAction(*extension); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string extension_name = extension->name(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ampersands need to be escaped to avoid being treated like 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mnemonics in the menu. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReplaceChars(extension_name, "&", "&&", &extension_name); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddItem(NAME, UTF8ToUTF16(extension_name)); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddSeparator(ui::NORMAL_SEPARATOR); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddItemWithStringId(CONFIGURE, IDS_EXTENSIONS_OPTIONS_MENU_ITEM); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddItem(UNINSTALL, l10n_util::GetStringUTF16(IDS_EXTENSIONS_UNINSTALL)); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension_action_manager->GetBrowserAction(*extension)) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddItemWithStringId(HIDE, IDS_EXTENSIONS_HIDE_BUTTON); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddSeparator(ui::NORMAL_SEPARATOR); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddItemWithStringId(MANAGE, IDS_MANAGE_EXTENSION); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Extension* ExtensionContextMenuModel::GetExtension() const { 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionService* extension_service = 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ExtensionSystem::Get(profile_)->extension_service(); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extension_service->GetExtensionById(extension_id_, false); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 188