• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/scoped_observer.h"
12 #include "chrome/common/extensions/command.h"
13 #include "extensions/browser/browser_context_keyed_api_factory.h"
14 #include "extensions/browser/extension_registry_observer.h"
15 #include "extensions/common/extension.h"
16 
17 class Profile;
18 
19 namespace base {
20 class DictionaryValue;
21 }
22 
23 namespace content {
24 class BrowserContext;
25 }
26 
27 namespace ui {
28 class Accelerator;
29 }
30 
31 namespace user_prefs {
32 class PrefRegistrySyncable;
33 }
34 
35 namespace extensions {
36 class ExtensionRegistry;
37 
38 // This service keeps track of preferences related to extension commands
39 // (assigning initial keybindings on install and removing them on deletion
40 // and answers questions related to which commands are active.
41 class CommandService : public BrowserContextKeyedAPI,
42                        public ExtensionRegistryObserver {
43  public:
44   // An enum specifying whether to fetch all extension commands or only active
45   // ones.
46   enum QueryType {
47     ALL,
48     ACTIVE_ONLY,
49   };
50 
51   // An enum specifying whether the command is global in scope or not. Global
52   // commands -- unlike regular commands -- have a global keyboard hook
53   // associated with them (and therefore work when Chrome doesn't have focus).
54   enum CommandScope {
55     REGULAR,    // Regular (non-globally scoped) command.
56     GLOBAL,     // Global command (works when Chrome doesn't have focus)
57     ANY_SCOPE,  // All commands, regardless of scope (used when querying).
58   };
59 
60   // An enum specifying the types of commands that can be used by an extension.
61   enum ExtensionCommandType {
62     NAMED,
63     BROWSER_ACTION,
64     PAGE_ACTION
65   };
66 
67   // Register prefs for keybinding.
68   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
69 
70   // Constructs a CommandService object for the given profile.
71   explicit CommandService(content::BrowserContext* context);
72   virtual ~CommandService();
73 
74   // BrowserContextKeyedAPI implementation.
75   static BrowserContextKeyedAPIFactory<CommandService>* GetFactoryInstance();
76 
77   // Convenience method to get the CommandService for a profile.
78   static CommandService* Get(content::BrowserContext* context);
79 
80   // Returns true if |extension| is permitted to and does remove the bookmark
81   // shortcut key.
82   static bool RemovesBookmarkShortcut(const Extension* extension);
83 
84   // Returns true if |extension| is permitted to and does remove the bookmark
85   // open pages shortcut key.
86   static bool RemovesBookmarkOpenPagesShortcut(const Extension* extension);
87 
88   // Gets the command (if any) for the browser action of an extension given
89   // its |extension_id|. The function consults the master list to see if
90   // the command is active. Returns false if the extension has no browser
91   // action. Returns false if the command is not active and |type| requested
92   // is ACTIVE_ONLY. |command| contains the command found and |active| (if not
93   // NULL) contains whether |command| is active.
94   bool GetBrowserActionCommand(const std::string& extension_id,
95                                QueryType type,
96                                Command* command,
97                                bool* active) const;
98 
99   // Gets the command (if any) for the page action of an extension given
100   // its |extension_id|. The function consults the master list to see if
101   // the command is active. Returns false if the extension has no page
102   // action. Returns false if the command is not active and |type| requested
103   // is ACTIVE_ONLY. |command| contains the command found and |active| (if not
104   // NULL) contains whether |command| is active.
105   bool GetPageActionCommand(const std::string& extension_id,
106                             QueryType type,
107                             Command* command,
108                             bool* active) const;
109 
110   // Gets the active named commands (if any) for the extension with
111   // |extension_id|. The function consults the master list to see if the
112   // commands are active. Returns an empty map if the extension has no named
113   // commands of the right |scope| or no such active named commands when |type|
114   // requested is ACTIVE_ONLY.
115   bool GetNamedCommands(const std::string& extension_id,
116                         QueryType type,
117                         CommandScope scope,
118                         CommandMap* command_map) const;
119 
120   // Records a keybinding |accelerator| as active for an extension with id
121   // |extension_id| and command with the name |command_name|. If
122   // |allow_overrides| is false, the keybinding must be free for the change to
123   // be recorded (as determined by the master list in |user_prefs|). If
124   // |allow_overwrites| is true, any previously recorded keybinding for this
125   // |accelerator| will be overwritten. If |global| is true, the command will
126   // be registered as a global command (be active even when Chrome does not have
127   // focus. Returns true if the change was successfully recorded.
128   bool AddKeybindingPref(const ui::Accelerator& accelerator,
129                          std::string extension_id,
130                          std::string command_name,
131                          bool allow_overrides,
132                          bool global);
133 
134   // Removes all keybindings for a given extension by its |extension_id|.
135   // |command_name| is optional and if specified, causes only the command with
136   // the name |command_name| to be removed.
137   void RemoveKeybindingPrefs(const std::string& extension_id,
138                              const std::string& command_name);
139 
140   // Update the keybinding prefs (for a command with a matching |extension_id|
141   // and |command_name|) to |keystroke|. If the command had another key assigned
142   // that key assignment will be removed.
143   void UpdateKeybindingPrefs(const std::string& extension_id,
144                              const std::string& command_name,
145                              const std::string& keystroke);
146 
147   // Set the scope of the keybinding. If |global| is true, the keybinding works
148   // even when Chrome does not have focus. If the scope requested is already
149   // set, the function returns false, otherwise true.
150   bool SetScope(const std::string& extension_id,
151                 const std::string& command_name,
152                 bool global);
153 
154   // Finds the command with the name |command_name| within an extension with id
155   // |extension_id| . Returns an empty Command object (with keycode
156   // VKEY_UNKNOWN) if the command is not found.
157   Command FindCommandByName(const std::string& extension_id,
158                             const std::string& command) const;
159 
160   // If the extension with |extension_id| binds a command to |accelerator|,
161   // returns true and assigns *|command| and *|command_type| to the command and
162   // its type if non-NULL.
163   bool GetBoundExtensionCommand(const std::string& extension_id,
164                                 const ui::Accelerator& accelerator,
165                                 Command* command,
166                                 ExtensionCommandType* command_type) const;
167 
168   // Returns true if |extension| is permitted to and does override the bookmark
169   // shortcut key.
170   bool OverridesBookmarkShortcut(const Extension* extension) const;
171 
172  private:
173   friend class BrowserContextKeyedAPIFactory<CommandService>;
174 
175   // BrowserContextKeyedAPI implementation.
service_name()176   static const char* service_name() {
177     return "CommandService";
178   }
179   static const bool kServiceRedirectedInIncognito = true;
180 
181   // ExtensionRegistryObserver.
182   virtual void OnExtensionWillBeInstalled(
183       content::BrowserContext* browser_context,
184       const Extension* extension,
185       bool is_update,
186       bool from_ephemeral,
187       const std::string& old_name) OVERRIDE;
188   virtual void OnExtensionUninstalled(
189       content::BrowserContext* browser_context,
190       const Extension* extension,
191       extensions::UninstallReason reason) OVERRIDE;
192 
193   // Updates keybindings for a given |extension|'s page action, browser action
194   // and named commands. Assigns new keybindings and removes relinquished
195   // keybindings if not changed by the user. In the case of adding keybindings,
196   // if the suggested keybinding is free, it will be taken by this extension. If
197   // not, the keybinding request is ignored.
198   void UpdateKeybindings(const Extension* extension);
199 
200   // On update, removes keybindings that the extension previously suggested but
201   // now no longer does, as long as the user has not modified them.
202   void RemoveRelinquishedKeybindings(const Extension* extension);
203 
204   // Assigns keybindings that the extension suggests, as long as they are not
205   // already assigned.
206   void AssignKeybindings(const Extension* extension);
207 
208   // Checks if |extension| is permitted to automatically assign the
209   // |accelerator| key.
210   bool CanAutoAssign(const Command &command,
211                      const Extension* extension);
212 
213   // Updates the record of |extension|'s most recent suggested command shortcut
214   // keys in the preferences.
215   void UpdateExtensionSuggestedCommandPrefs(const Extension* extension);
216 
217   // Remove suggested key command prefs that apply to commands that have been
218   // removed.
219   void RemoveDefunctExtensionSuggestedCommandPrefs(const Extension* extension);
220 
221   // Returns true if the user modified a command's shortcut key from the
222   // |extension|-suggested value.
223   bool IsCommandShortcutUserModified(const Extension* extension,
224                                      const std::string& command_name);
225 
226   // Returns true if the extension is changing the binding of |command_name| on
227   // install.
228   bool IsKeybindingChanging(const Extension* extension,
229                             const std::string& command_name);
230 
231   // Returns |extension|'s previous suggested key for |command_name| in the
232   // preferences, or the empty string if none.
233   std::string GetSuggestedKeyPref(const Extension* extension,
234                                   const std::string& command_name);
235 
236   bool GetExtensionActionCommand(const std::string& extension_id,
237                                  QueryType query_type,
238                                  Command* command,
239                                  bool* active,
240                                  ExtensionCommandType action_type) const;
241 
242   // A weak pointer to the profile we are associated with. Not owned by us.
243   Profile* profile_;
244 
245   ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
246       extension_registry_observer_;
247 
248   DISALLOW_COPY_AND_ASSIGN(CommandService);
249 };
250 
251 template <>
252 void
253     BrowserContextKeyedAPIFactory<CommandService>::DeclareFactoryDependencies();
254 
255 }  //  namespace extensions
256 
257 #endif  // CHROME_BROWSER_EXTENSIONS_API_COMMANDS_COMMAND_SERVICE_H_
258