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 "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