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#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_KEYBINDING_REGISTRY_H_ 6#define CHROME_BROWSER_EXTENSIONS_EXTENSION_KEYBINDING_REGISTRY_H_ 7 8#include <list> 9#include <map> 10#include <string> 11 12#include "base/compiler_specific.h" 13#include "base/scoped_observer.h" 14#include "content/public/browser/notification_details.h" 15#include "content/public/browser/notification_observer.h" 16#include "content/public/browser/notification_registrar.h" 17#include "content/public/browser/notification_source.h" 18#include "extensions/browser/extension_registry_observer.h" 19 20namespace content { 21class BrowserContext; 22} 23 24namespace ui { 25class Accelerator; 26} 27 28namespace extensions { 29 30class ActiveTabPermissionGranter; 31class Extension; 32class ExtensionRegistry; 33 34// The ExtensionKeybindingRegistry is a class that handles the cross-platform 35// logic for keyboard accelerators. See platform-specific implementations for 36// implementation details for each platform. 37class ExtensionKeybindingRegistry : public content::NotificationObserver, 38 public ExtensionRegistryObserver { 39 public: 40 enum ExtensionFilter { 41 ALL_EXTENSIONS, 42 PLATFORM_APPS_ONLY 43 }; 44 45 class Delegate { 46 public: 47 // Gets the ActiveTabPermissionGranter for the active tab, if any. 48 // If there is no active tab then returns NULL. 49 virtual ActiveTabPermissionGranter* GetActiveTabPermissionGranter() = 0; 50 }; 51 52 // If |extension_filter| is not ALL_EXTENSIONS, only keybindings by 53 // by extensions that match the filter will be registered. 54 ExtensionKeybindingRegistry(content::BrowserContext* context, 55 ExtensionFilter extension_filter, 56 Delegate* delegate); 57 58 virtual ~ExtensionKeybindingRegistry(); 59 60 // Enables/Disables general shortcut handling in Chrome. Implemented in 61 // platform-specific ExtensionKeybindingsRegistry* files. 62 static void SetShortcutHandlingSuspended(bool suspended); 63 64 // Execute the command bound to |accelerator| and provided by the extension 65 // with |extension_id|, if it exists. 66 void ExecuteCommand(const std::string& extension_id, 67 const ui::Accelerator& accelerator); 68 69 protected: 70 // Add extension keybinding for the events defined by the |extension|. 71 // |command_name| is optional, but if not blank then only the command 72 // specified will be added. 73 virtual void AddExtensionKeybinding( 74 const Extension* extension, 75 const std::string& command_name) = 0; 76 // Remove extension bindings for |extension|. |command_name| is optional, 77 // but if not blank then only the command specified will be removed. 78 void RemoveExtensionKeybinding( 79 const Extension* extension, 80 const std::string& command_name); 81 // Overridden by platform specific implementations to provide additional 82 // unregistration (which varies between platforms). 83 virtual void RemoveExtensionKeybindingImpl( 84 const ui::Accelerator& accelerator, 85 const std::string& command_name) = 0; 86 87 // Make sure all extensions registered have keybindings added. 88 void Init(); 89 90 // Whether to ignore this command. Only browserAction commands and pageAction 91 // commands are currently ignored, since they are handled elsewhere. 92 bool ShouldIgnoreCommand(const std::string& command) const; 93 94 // Fire event targets which the specified |accelerator| is binding with. 95 // Returns true if we can find the appropriate event targets. 96 bool NotifyEventTargets(const ui::Accelerator& accelerator); 97 98 // Notifies appropriate parties that a command has been executed. 99 void CommandExecuted(const std::string& extension_id, 100 const std::string& command); 101 102 // Check whether the specified |accelerator| has been registered. 103 bool IsAcceleratorRegistered(const ui::Accelerator& accelerator) const; 104 105 // Add event target (extension_id, command name) to the target list of 106 // |accelerator|. Note that only media keys can have more than one event 107 // target. 108 void AddEventTarget(const ui::Accelerator& accelerator, 109 const std::string& extension_id, 110 const std::string& command_name); 111 112 // Get the first event target by the given |accelerator|. For a valid 113 // accelerator it should have only one event target, except for media keys. 114 // Returns true if we can find it, |extension_id| and |command_name| will be 115 // set to the right target; otherwise, false is returned and |extension_id|, 116 // |command_name| are unchanged. 117 bool GetFirstTarget(const ui::Accelerator& accelerator, 118 std::string* extension_id, 119 std::string* command_name) const; 120 121 // Returns true if the |event_targets_| is empty; otherwise returns false. 122 bool IsEventTargetsEmpty() const; 123 124 private: 125 // Overridden from content::NotificationObserver: 126 virtual void Observe(int type, 127 const content::NotificationSource& source, 128 const content::NotificationDetails& details) OVERRIDE; 129 130 // ExtensionRegistryObserver implementation. 131 virtual void OnExtensionLoaded(content::BrowserContext* browser_context, 132 const Extension* extension) OVERRIDE; 133 virtual void OnExtensionUnloaded( 134 content::BrowserContext* browser_context, 135 const Extension* extension, 136 UnloadedExtensionInfo::Reason reason) OVERRIDE; 137 138 // Returns true if the |extension| matches our extension filter. 139 bool ExtensionMatchesFilter(const extensions::Extension* extension); 140 141 // Execute commands for |accelerator|. If |extension_id| is empty, execute all 142 // commands bound to |accelerator|, otherwise execute only commands bound by 143 // the corresponding extension. Returns true if at least one command was 144 // executed. 145 bool ExecuteCommands(const ui::Accelerator& accelerator, 146 const std::string& extension_id); 147 148 // The content notification registrar for listening to extension events. 149 content::NotificationRegistrar registrar_; 150 151 content::BrowserContext* browser_context_; 152 153 // What extensions to register keybindings for. 154 ExtensionFilter extension_filter_; 155 156 // Weak pointer to our delegate. Not owned by us. Must outlive this class. 157 Delegate* delegate_; 158 159 // Maps an accelerator to a list of string pairs (extension id, command name) 160 // for commands that have been registered. This keeps track of the targets for 161 // the keybinding event (which named command to call in which extension). On 162 // GTK this map contains registration for pageAction and browserAction 163 // commands, whereas on other platforms it does not. Note that normal 164 // accelerator (which isn't media keys) has only one target, while the media 165 // keys can have more than one. 166 typedef std::list<std::pair<std::string, std::string> > TargetList; 167 typedef std::map<ui::Accelerator, TargetList> EventTargets; 168 EventTargets event_targets_; 169 170 // Listen to extension load, unloaded notifications. 171 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> 172 extension_registry_observer_; 173 174 DISALLOW_COPY_AND_ASSIGN(ExtensionKeybindingRegistry); 175}; 176 177} // namespace extensions 178 179#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_KEYBINDING_REGISTRY_H_ 180