1 // Copyright (c) 2012 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_keybinding_registry.h" 6 7 #include "base/values.h" 8 #include "chrome/browser/chrome_notification_types.h" 9 #include "chrome/browser/extensions/active_tab_permission_granter.h" 10 #include "chrome/browser/extensions/event_router.h" 11 #include "chrome/browser/extensions/extension_service.h" 12 #include "chrome/browser/extensions/extension_system.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/common/extensions/extension_manifest_constants.h" 15 #include "chrome/common/extensions/extension_set.h" 16 17 namespace extensions { 18 19 ExtensionKeybindingRegistry::ExtensionKeybindingRegistry( 20 Profile* profile, ExtensionFilter extension_filter, Delegate* delegate) 21 : profile_(profile), 22 extension_filter_(extension_filter), 23 delegate_(delegate) { 24 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 25 content::Source<Profile>(profile->GetOriginalProfile())); 26 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 27 content::Source<Profile>(profile->GetOriginalProfile())); 28 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_COMMAND_ADDED, 29 content::Source<Profile>(profile->GetOriginalProfile())); 30 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_COMMAND_REMOVED, 31 content::Source<Profile>(profile->GetOriginalProfile())); 32 } 33 34 ExtensionKeybindingRegistry::~ExtensionKeybindingRegistry() { 35 } 36 37 void ExtensionKeybindingRegistry::Init() { 38 ExtensionService* service = 39 extensions::ExtensionSystem::Get(profile_)->extension_service(); 40 if (!service) 41 return; // ExtensionService can be null during testing. 42 43 const ExtensionSet* extensions = service->extensions(); 44 ExtensionSet::const_iterator iter = extensions->begin(); 45 for (; iter != extensions->end(); ++iter) 46 if (ExtensionMatchesFilter(iter->get())) 47 AddExtensionKeybinding(iter->get(), std::string()); 48 } 49 50 bool ExtensionKeybindingRegistry::ShouldIgnoreCommand( 51 const std::string& command) const { 52 return command == extension_manifest_values::kPageActionCommandEvent || 53 command == extension_manifest_values::kBrowserActionCommandEvent || 54 command == extension_manifest_values::kScriptBadgeCommandEvent; 55 } 56 57 void ExtensionKeybindingRegistry::CommandExecuted( 58 const std::string& extension_id, const std::string& command) { 59 ExtensionService* service = 60 ExtensionSystem::Get(profile_)->extension_service(); 61 62 const Extension* extension = service->extensions()->GetByID(extension_id); 63 if (!extension) 64 return; 65 66 // Grant before sending the event so that the permission is granted before 67 // the extension acts on the command. 68 ActiveTabPermissionGranter* granter = 69 delegate_->GetActiveTabPermissionGranter(); 70 if (granter) 71 granter->GrantIfRequested(extension); 72 73 scoped_ptr<base::ListValue> args(new base::ListValue()); 74 args->Append(Value::CreateStringValue(command)); 75 76 scoped_ptr<Event> event(new Event("commands.onCommand", args.Pass())); 77 event->restrict_to_profile = profile_; 78 event->user_gesture = EventRouter::USER_GESTURE_ENABLED; 79 ExtensionSystem::Get(profile_)->event_router()-> 80 DispatchEventToExtension(extension_id, event.Pass()); 81 } 82 83 void ExtensionKeybindingRegistry::Observe( 84 int type, 85 const content::NotificationSource& source, 86 const content::NotificationDetails& details) { 87 switch (type) { 88 case chrome::NOTIFICATION_EXTENSION_LOADED: { 89 const extensions::Extension* extension = 90 content::Details<const extensions::Extension>(details).ptr(); 91 if (ExtensionMatchesFilter(extension)) 92 AddExtensionKeybinding(extension, std::string()); 93 break; 94 } 95 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { 96 const extensions::Extension* extension = 97 content::Details<UnloadedExtensionInfo>(details)->extension; 98 if (ExtensionMatchesFilter(extension)) 99 RemoveExtensionKeybinding(extension, std::string()); 100 break; 101 } 102 case chrome::NOTIFICATION_EXTENSION_COMMAND_ADDED: 103 case chrome::NOTIFICATION_EXTENSION_COMMAND_REMOVED: { 104 std::pair<const std::string, const std::string>* payload = 105 content::Details<std::pair<const std::string, const std::string> >( 106 details).ptr(); 107 108 const extensions::Extension* extension = 109 ExtensionSystem::Get(profile_)->extension_service()-> 110 extensions()->GetByID(payload->first); 111 // During install and uninstall the extension won't be found. We'll catch 112 // those events above, with the LOADED/UNLOADED, so we ignore this event. 113 if (!extension) 114 return; 115 116 if (ExtensionMatchesFilter(extension)) { 117 if (type == chrome::NOTIFICATION_EXTENSION_COMMAND_ADDED) 118 AddExtensionKeybinding(extension, payload->second); 119 else 120 RemoveExtensionKeybinding(extension, payload->second); 121 } 122 break; 123 } 124 default: 125 NOTREACHED(); 126 break; 127 } 128 } 129 130 bool ExtensionKeybindingRegistry::ExtensionMatchesFilter( 131 const extensions::Extension* extension) 132 { 133 switch (extension_filter_) { 134 case ALL_EXTENSIONS: 135 return true; 136 case PLATFORM_APPS_ONLY: 137 return extension->is_platform_app(); 138 default: 139 NOTREACHED(); 140 } 141 return false; 142 } 143 144 } // namespace extensions 145