Home | History | Annotate | Download | only in commands
      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.
    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(content::BrowserContext* browser_context,
    189                                       const Extension* extension) OVERRIDE;
    190 
    191   // Updates keybindings for a given |extension|'s page action, browser action
    192   // and named commands. Assigns new keybindings and removes relinquished
    193   // keybindings if not changed by the user. In the case of adding keybindings,
    194   // if the suggested keybinding is free, it will be taken by this extension. If
    195   // not, the keybinding request is ignored.
    196   void UpdateKeybindings(const Extension* extension);
    197 
    198   // On update, removes keybindings that the extension previously suggested but
    199   // now no longer does, as long as the user has not modified them.
    200   void RemoveRelinquishedKeybindings(const Extension* extension);
    201 
    202   // Assigns keybindings that the extension suggests, as long as they are not
    203   // already assigned.
    204   void AssignKeybindings(const Extension* extension);
    205 
    206   // Checks if |extension| is permitted to automatically assign the
    207   // |accelerator| key.
    208   bool CanAutoAssign(const Command &command,
    209                      const Extension* extension);
    210 
    211   // Updates the record of |extension|'s most recent suggested command shortcut
    212   // keys in the preferences.
    213   void UpdateExtensionSuggestedCommandPrefs(const Extension* extension);
    214 
    215   // Remove suggested key command prefs that apply to commands that have been
    216   // removed.
    217   void RemoveDefunctExtensionSuggestedCommandPrefs(const Extension* extension);
    218 
    219   // Returns true if the user modified a command's shortcut key from the
    220   // |extension|-suggested value.
    221   bool IsCommandShortcutUserModified(const Extension* extension,
    222                                      const std::string& command_name);
    223 
    224   // Returns true if the extension is changing the binding of |command_name| on
    225   // install.
    226   bool IsKeybindingChanging(const Extension* extension,
    227                             const std::string& command_name);
    228 
    229   // Returns |extension|'s previous suggested key for |command_name| in the
    230   // preferences, or the empty string if none.
    231   std::string GetSuggestedKeyPref(const Extension* extension,
    232                                   const std::string& command_name);
    233 
    234   bool GetExtensionActionCommand(const std::string& extension_id,
    235                                  QueryType query_type,
    236                                  Command* command,
    237                                  bool* active,
    238                                  ExtensionCommandType action_type) const;
    239 
    240   // A weak pointer to the profile we are associated with. Not owned by us.
    241   Profile* profile_;
    242 
    243   ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
    244       extension_registry_observer_;
    245 
    246   DISALLOW_COPY_AND_ASSIGN(CommandService);
    247 };
    248 
    249 template <>
    250 void
    251     BrowserContextKeyedAPIFactory<CommandService>::DeclareFactoryDependencies();
    252 
    253 }  //  namespace extensions
    254 
    255 #endif  // CHROME_BROWSER_EXTENSIONS_API_COMMANDS_COMMAND_SERVICE_H_
    256