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.
5 #ifndef CHROME_BROWSER_EXTENSIONS_API_COMMANDS_COMMAND_SERVICE_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_COMMANDS_COMMAND_SERVICE_H_
10 #include "base/basictypes.h"
11 #include "base/observer_list.h"
12 #include "base/scoped_observer.h"
13 #include "chrome/common/extensions/command.h"
14 #include "extensions/browser/browser_context_keyed_api_factory.h"
15 #include "extensions/browser/extension_registry_observer.h"
16 #include "extensions/common/extension.h"
21 class DictionaryValue
;
32 namespace user_prefs
{
33 class PrefRegistrySyncable
;
36 namespace extensions
{
37 class ExtensionRegistry
;
39 // This service keeps track of preferences related to extension commands
40 // (assigning initial keybindings on install and removing them on deletion
41 // and answers questions related to which commands are active.
42 class CommandService
: public BrowserContextKeyedAPI
,
43 public ExtensionRegistryObserver
{
45 // An enum specifying which extension commands to fetch. There are effectively
46 // four options: all, active, suggested, and inactive. Only the first three
47 // appear in the enum since there hasn't been a need for 'inactive' yet.
49 // 'Inactive' means no key is bound. It might be because 1) a key wasn't
50 // specified (suggested) or 2) it was not granted (key already taken).
52 // SUGGESTED covers developer-assigned keys that may or may not have been
53 // granted. Reasons for not granting include permission denied/key already
56 // ACTIVE means developer-assigned keys that were granted or user-assigned
59 // ALL is all of the above.
66 // An enum specifying whether the command is global in scope or not. Global
67 // commands -- unlike regular commands -- have a global keyboard hook
68 // associated with them (and therefore work when Chrome doesn't have focus).
70 REGULAR
, // Regular (non-globally scoped) command.
71 GLOBAL
, // Global command (works when Chrome doesn't have focus)
72 ANY_SCOPE
, // All commands, regardless of scope (used when querying).
75 // An enum specifying the types of commands that can be used by an extension.
76 enum ExtensionCommandType
{
84 // Called when an extension command is added.
85 virtual void OnExtensionCommandAdded(const std::string
& extension_id
,
86 const Command
& command
) {}
88 // Called when an extension command is removed.
89 virtual void OnExtensionCommandRemoved(const std::string
& extension_id
,
90 const Command
& command
) {}
92 virtual ~Observer() {}
95 // Register prefs for keybinding.
96 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable
* registry
);
98 // Constructs a CommandService object for the given profile.
99 explicit CommandService(content::BrowserContext
* context
);
100 ~CommandService() override
;
102 // BrowserContextKeyedAPI implementation.
103 static BrowserContextKeyedAPIFactory
<CommandService
>* GetFactoryInstance();
105 // Convenience method to get the CommandService for a profile.
106 static CommandService
* Get(content::BrowserContext
* context
);
108 // Returns true if |extension| is permitted to and does remove the bookmark
110 static bool RemovesBookmarkShortcut(const Extension
* extension
);
112 // Returns true if |extension| is permitted to and does remove the bookmark
113 // open pages shortcut key.
114 static bool RemovesBookmarkOpenPagesShortcut(const Extension
* extension
);
116 // Gets the command (if any) for the browser action of an extension given
117 // its |extension_id|. The function consults the master list to see if
118 // the command is active. Returns false if the extension has no browser
119 // action. Returns false if the command is not active and |type| requested
120 // is ACTIVE. |command| contains the command found and |active| (if not
121 // NULL) contains whether |command| is active.
122 bool GetBrowserActionCommand(const std::string
& extension_id
,
127 // Gets the command (if any) for the page action of an extension given
128 // its |extension_id|. The function consults the master list to see if
129 // the command is active. Returns false if the extension has no page
130 // action. Returns false if the command is not active and |type| requested
131 // is ACTIVE. |command| contains the command found and |active| (if not
132 // NULL) contains whether |command| is active.
133 bool GetPageActionCommand(const std::string
& extension_id
,
138 // Gets the active named commands (if any) for the extension with
139 // |extension_id|. The function consults the master list to see if the
140 // commands are active. Returns an empty map if the extension has no named
141 // commands of the right |scope| or no such active named commands when |type|
142 // requested is ACTIVE.
143 bool GetNamedCommands(const std::string
& extension_id
,
146 CommandMap
* command_map
) const;
148 // Records a keybinding |accelerator| as active for an extension with id
149 // |extension_id| and command with the name |command_name|. If
150 // |allow_overrides| is false, the keybinding must be free for the change to
151 // be recorded (as determined by the master list in |user_prefs|). If
152 // |allow_overwrites| is true, any previously recorded keybinding for this
153 // |accelerator| will be overwritten. If |global| is true, the command will
154 // be registered as a global command (be active even when Chrome does not have
155 // focus. Returns true if the change was successfully recorded.
156 bool AddKeybindingPref(const ui::Accelerator
& accelerator
,
157 const std::string
& extension_id
,
158 const std::string
& command_name
,
159 bool allow_overrides
,
162 // Removes all keybindings for a given extension by its |extension_id|.
163 // |command_name| is optional and if specified, causes only the command with
164 // the name |command_name| to be removed.
165 void RemoveKeybindingPrefs(const std::string
& extension_id
,
166 const std::string
& command_name
);
168 // Update the keybinding prefs (for a command with a matching |extension_id|
169 // and |command_name|) to |keystroke|. If the command had another key assigned
170 // that key assignment will be removed.
171 void UpdateKeybindingPrefs(const std::string
& extension_id
,
172 const std::string
& command_name
,
173 const std::string
& keystroke
);
175 // Set the scope of the keybinding. If |global| is true, the keybinding works
176 // even when Chrome does not have focus. If the scope requested is already
177 // set, the function returns false, otherwise true.
178 bool SetScope(const std::string
& extension_id
,
179 const std::string
& command_name
,
182 // Finds the command with the name |command_name| within an extension with id
183 // |extension_id| . Returns an empty Command object (with keycode
184 // VKEY_UNKNOWN) if the command is not found.
185 Command
FindCommandByName(const std::string
& extension_id
,
186 const std::string
& command
) const;
188 // If the extension with |extension_id| suggests the assignment of a command
189 // to |accelerator|, returns true and assigns the command to *|command|. Also
190 // assigns the type to *|command_type| if non-null.
191 bool GetSuggestedExtensionCommand(const std::string
& extension_id
,
192 const ui::Accelerator
& accelerator
,
194 ExtensionCommandType
* command_type
) const;
196 // Returns true if |extension| requests to override the bookmark shortcut key
197 // and should be allowed to do so.
198 bool RequestsBookmarkShortcutOverride(const Extension
* extension
) const;
200 void AddObserver(Observer
* observer
);
201 void RemoveObserver(Observer
* observer
);
204 friend class BrowserContextKeyedAPIFactory
<CommandService
>;
206 // BrowserContextKeyedAPI implementation.
207 static const char* service_name() {
208 return "CommandService";
210 static const bool kServiceRedirectedInIncognito
= true;
212 // ExtensionRegistryObserver.
213 void OnExtensionWillBeInstalled(content::BrowserContext
* browser_context
,
214 const Extension
* extension
,
217 const std::string
& old_name
) override
;
218 void OnExtensionUninstalled(content::BrowserContext
* browser_context
,
219 const Extension
* extension
,
220 extensions::UninstallReason reason
) override
;
222 // Updates keybindings for a given |extension|'s page action, browser action
223 // and named commands. Assigns new keybindings and removes relinquished
224 // keybindings if not changed by the user. In the case of adding keybindings,
225 // if the suggested keybinding is free, it will be taken by this extension. If
226 // not, the keybinding request is ignored.
227 void UpdateKeybindings(const Extension
* extension
);
229 // On update, removes keybindings that the extension previously suggested but
230 // now no longer does, as long as the user has not modified them.
231 void RemoveRelinquishedKeybindings(const Extension
* extension
);
233 // Assigns keybindings that the extension suggests, as long as they are not
235 void AssignKeybindings(const Extension
* extension
);
237 // Checks if |extension| is permitted to automatically assign the
238 // |accelerator| key.
239 bool CanAutoAssign(const Command
&command
,
240 const Extension
* extension
);
242 // Updates the record of |extension|'s most recent suggested command shortcut
243 // keys in the preferences.
244 void UpdateExtensionSuggestedCommandPrefs(const Extension
* extension
);
246 // Remove suggested key command prefs that apply to commands that have been
248 void RemoveDefunctExtensionSuggestedCommandPrefs(const Extension
* extension
);
250 // Returns true if the user modified a command's shortcut key from the
251 // |extension|-suggested value.
252 bool IsCommandShortcutUserModified(const Extension
* extension
,
253 const std::string
& command_name
);
255 // Returns true if the extension is changing the binding of |command_name| on
257 bool IsKeybindingChanging(const Extension
* extension
,
258 const std::string
& command_name
);
260 // Returns |extension|'s previous suggested key for |command_name| in the
261 // preferences, or the empty string if none.
262 std::string
GetSuggestedKeyPref(const Extension
* extension
,
263 const std::string
& command_name
);
265 bool GetExtensionActionCommand(const std::string
& extension_id
,
266 QueryType query_type
,
269 ExtensionCommandType action_type
) const;
271 // A weak pointer to the profile we are associated with. Not owned by us.
274 ScopedObserver
<ExtensionRegistry
, ExtensionRegistryObserver
>
275 extension_registry_observer_
;
277 base::ObserverList
<Observer
> observers_
;
279 DISALLOW_COPY_AND_ASSIGN(CommandService
);
284 BrowserContextKeyedAPIFactory
<CommandService
>::DeclareFactoryDependencies();
286 } // namespace extensions
288 #endif // CHROME_BROWSER_EXTENSIONS_API_COMMANDS_COMMAND_SERVICE_H_