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_API_COMMANDS_COMMAND_SERVICE_H_ 6 #define CHROME_BROWSER_EXTENSIONS_API_COMMANDS_COMMAND_SERVICE_H_ 7 8 #include <string> 9 10 #include "base/basictypes.h" 11 #include "chrome/browser/extensions/api/profile_keyed_api_factory.h" 12 #include "chrome/common/extensions/command.h" 13 #include "content/public/browser/notification_details.h" 14 #include "content/public/browser/notification_observer.h" 15 #include "content/public/browser/notification_registrar.h" 16 #include "content/public/browser/notification_source.h" 17 #include "extensions/common/extension.h" 18 19 class Profile; 20 21 namespace base { 22 class DictionaryValue; 23 } 24 25 namespace ui { 26 class Accelerator; 27 } 28 29 namespace user_prefs { 30 class PrefRegistrySyncable; 31 } 32 33 namespace extensions { 34 35 // This service keeps track of preferences related to extension commands 36 // (assigning initial keybindings on install and removing them on deletion 37 // and answers questions related to which commands are active. 38 class CommandService : public ProfileKeyedAPI, 39 public content::NotificationObserver { 40 public: 41 // An enum specifying whether to fetch all extension commands or only active 42 // ones. 43 enum QueryType { 44 ALL, 45 ACTIVE_ONLY, 46 }; 47 48 // An enum specifying whether the command is global in scope or not. Global 49 // commands -- unlike regular commands -- have a global keyboard hook 50 // associated with them (and therefore work when Chrome doesn't have focus). 51 enum CommandScope { 52 REGULAR, // Regular (non-globally scoped) command. 53 GLOBAL, // Global command (works when Chrome doesn't have focus) 54 ANY_SCOPE, // All commands, regardless of scope (used when querying). 55 }; 56 57 // Register prefs for keybinding. 58 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); 59 60 // Constructs a CommandService object for the given profile. 61 explicit CommandService(Profile* profile); 62 virtual ~CommandService(); 63 64 // ProfileKeyedAPI implementation. 65 static ProfileKeyedAPIFactory<CommandService>* GetFactoryInstance(); 66 67 // Convenience method to get the CommandService for a profile. 68 static CommandService* Get(Profile* profile); 69 70 // Return true if the specified accelerator is one of the following multimedia 71 // keys: Next Track key, Previous Track key, Stop Media key, Play/Pause Media 72 // key, without any modifiers. 73 static bool IsMediaKey(const ui::Accelerator& accelerator); 74 75 // Gets the command (if any) for the browser action of an extension given 76 // its |extension_id|. The function consults the master list to see if 77 // the command is active. Returns false if the extension has no browser 78 // action. Returns false if the command is not active and |type| requested 79 // is ACTIVE_ONLY. |command| contains the command found and |active| (if not 80 // NULL) contains whether |command| is active. 81 bool GetBrowserActionCommand(const std::string& extension_id, 82 QueryType type, 83 extensions::Command* command, 84 bool* active); 85 86 // Gets the command (if any) for the page action of an extension given 87 // its |extension_id|. The function consults the master list to see if 88 // the command is active. Returns false if the extension has no page 89 // action. Returns false if the command is not active and |type| requested 90 // is ACTIVE_ONLY. |command| contains the command found and |active| (if not 91 // NULL) contains whether |command| is active. 92 bool GetPageActionCommand(const std::string& extension_id, 93 QueryType type, 94 extensions::Command* command, 95 bool* active); 96 97 // Gets the command (if any) for the script badge of an extension given 98 // its |extension_id|. The function consults the master list to see if 99 // the command is active. Returns false if the extension has no script 100 // badge. Returns false if the command is not active and |type| requested 101 // is ACTIVE_ONLY. |command| contains the command found and |active| (if not 102 // NULL) contains whether |command| is active. 103 bool GetScriptBadgeCommand(const std::string& extension_id, 104 QueryType type, 105 extensions::Command* command, 106 bool* active); 107 108 // Gets the active command (if any) for the named commands of an extension 109 // given its |extension_id|. The function consults the master list to see if 110 // the command is active. Returns an empty map if the extension has no 111 // named commands of the right |scope| or no such active named commands when 112 // |type| requested is ACTIVE_ONLY. 113 bool GetNamedCommands(const std::string& extension_id, 114 QueryType type, 115 CommandScope scope, 116 extensions::CommandMap* command_map); 117 118 // Records a keybinding |accelerator| as active for an extension with id 119 // |extension_id| and command with the name |command_name|. If 120 // |allow_overrides| is false, the keybinding must be free for the change to 121 // be recorded (as determined by the master list in |user_prefs|). If 122 // |allow_overwrites| is true, any previously recorded keybinding for this 123 // |accelerator| will be overwritten. If |global| is true, the command will 124 // be registered as a global command (be active even when Chrome does not have 125 // focus. Returns true if the change was successfully recorded. 126 bool AddKeybindingPref(const ui::Accelerator& accelerator, 127 std::string extension_id, 128 std::string command_name, 129 bool allow_overrides, 130 bool global); 131 132 // Removes all keybindings for a given extension by its |extension_id|. 133 // |command_name| is optional and if specified, causes only the command with 134 // the name |command_name| to be removed. 135 void RemoveKeybindingPrefs(const std::string& extension_id, 136 const std::string& command_name); 137 138 // Update the keybinding prefs (for a command with a matching |extension_id| 139 // and |command_name|) to |keystroke|. If the command had another key assigned 140 // that key assignment will be removed. 141 void UpdateKeybindingPrefs(const std::string& extension_id, 142 const std::string& command_name, 143 const std::string& keystroke); 144 145 // Set the scope of the keybinding. If |global| is true, the keybinding works 146 // even when Chrome does not have focus. If the scope requested is already 147 // set, the function returns false, otherwise true. 148 bool SetScope(const std::string& extension_id, 149 const std::string& command_name, 150 bool global); 151 152 // Finds the command with the name |command_name| within an extension with id 153 // |extension_id| . Returns an empty Command object (with keycode 154 // VKEY_UNKNOWN) if the command is not found. 155 Command FindCommandByName(const std::string& extension_id, 156 const std::string& command); 157 158 // Overridden from content::NotificationObserver. 159 virtual void Observe(int type, 160 const content::NotificationSource& source, 161 const content::NotificationDetails& details) OVERRIDE; 162 163 private: 164 friend class ProfileKeyedAPIFactory<CommandService>; 165 166 // ProfileKeyedAPI implementation. 167 static const char* service_name() { 168 return "CommandService"; 169 } 170 static const bool kServiceRedirectedInIncognito = true; 171 172 // An enum specifying the types of icons that can have a command. 173 enum ExtensionActionType { 174 BROWSER_ACTION, 175 PAGE_ACTION, 176 SCRIPT_BADGE, 177 }; 178 179 // Assigns initial keybinding for a given |extension|'s page action, browser 180 // action and named commands. In each case, if the suggested keybinding is 181 // free, it will be taken by this extension. If not, that keybinding request 182 // is ignored. |user_pref| is the PrefService used to record the new 183 // keybinding assignment. 184 void AssignInitialKeybindings(const extensions::Extension* extension); 185 186 bool GetExtensionActionCommand(const std::string& extension_id, 187 QueryType query_type, 188 extensions::Command* command, 189 bool* active, 190 ExtensionActionType action_type); 191 192 // The content notification registrar for listening to extension events. 193 content::NotificationRegistrar registrar_; 194 195 // A weak pointer to the profile we are associated with. Not owned by us. 196 Profile* profile_; 197 198 DISALLOW_COPY_AND_ASSIGN(CommandService); 199 }; 200 201 template <> 202 void ProfileKeyedAPIFactory<CommandService>::DeclareFactoryDependencies(); 203 204 } // namespace extensions 205 206 #endif // CHROME_BROWSER_EXTENSIONS_API_COMMANDS_COMMAND_SERVICE_H_ 207