Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/commands/command_service.h" | 5 #include "chrome/browser/extensions/api/commands/command_service.h" |
| 6 | 6 |
| 7 #include <vector> | |
| 8 | |
| 7 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 8 #include "base/prefs/scoped_user_pref_update.h" | 10 #include "base/prefs/scoped_user_pref_update.h" |
| 11 #include "base/strings/string_split.h" | |
| 9 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 11 #include "chrome/browser/chrome_notification_types.h" | 14 #include "chrome/browser/chrome_notification_types.h" |
| 12 #include "chrome/browser/extensions/api/commands/commands.h" | 15 #include "chrome/browser/extensions/api/commands/commands.h" |
| 13 #include "chrome/browser/extensions/extension_commands_global_registry.h" | 16 #include "chrome/browser/extensions/extension_commands_global_registry.h" |
| 14 #include "chrome/browser/extensions/extension_function_registry.h" | 17 #include "chrome/browser/extensions/extension_function_registry.h" |
| 15 #include "chrome/browser/extensions/extension_keybinding_registry.h" | 18 #include "chrome/browser/extensions/extension_keybinding_registry.h" |
| 16 #include "chrome/browser/extensions/extension_service.h" | 19 #include "chrome/browser/extensions/extension_service.h" |
| 17 #include "chrome/browser/extensions/extension_system.h" | 20 #include "chrome/browser/extensions/extension_system.h" |
| 18 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
| 19 #include "chrome/browser/ui/accelerator_utils.h" | 22 #include "chrome/browser/ui/accelerator_utils.h" |
| 20 #include "chrome/common/extensions/api/commands/commands_handler.h" | 23 #include "chrome/common/extensions/api/commands/commands_handler.h" |
| 21 #include "chrome/common/pref_names.h" | 24 #include "chrome/common/pref_names.h" |
| 22 #include "components/user_prefs/pref_registry_syncable.h" | 25 #include "components/user_prefs/pref_registry_syncable.h" |
| 23 #include "content/public/browser/notification_details.h" | 26 #include "content/public/browser/notification_details.h" |
| 24 #include "content/public/browser/notification_service.h" | 27 #include "content/public/browser/notification_service.h" |
| 25 #include "extensions/common/feature_switch.h" | 28 #include "extensions/common/feature_switch.h" |
| 29 #include "extensions/common/manifest_constants.h" | |
| 26 | 30 |
| 27 using extensions::Extension; | 31 using extensions::Extension; |
| 28 using extensions::ExtensionPrefs; | 32 using extensions::ExtensionPrefs; |
| 29 | 33 |
| 30 namespace { | 34 namespace { |
| 31 | 35 |
| 32 const char kExtension[] = "extension"; | 36 const char kExtension[] = "extension"; |
| 33 const char kCommandName[] = "command_name"; | 37 const char kCommandName[] = "command_name"; |
| 34 const char kGlobal[] = "global"; | 38 const char kGlobal[] = "global"; |
| 35 | 39 |
| 36 // A preference that indicates that the initial keybindings for the given | 40 // A preference that indicates that the initial keybindings for the given |
| 37 // extension have been set. | 41 // extension have been set. |
| 38 const char kInitialBindingsHaveBeenAssigned[] = "initial_keybindings_set"; | 42 const char kInitialBindingsHaveBeenAssigned[] = "initial_keybindings_set"; |
| 39 | 43 |
| 40 std::string GetPlatformKeybindingKeyForAccelerator( | 44 std::string GetPlatformKeybindingKeyForAccelerator( |
| 41 const ui::Accelerator& accelerator) { | 45 const ui::Accelerator& accelerator, const std::string extension_id) { |
| 42 return extensions::Command::CommandPlatform() + ":" + | 46 std::string key = extensions::Command::CommandPlatform() + ":" + |
| 43 extensions::Command::AcceleratorToString(accelerator); | 47 extensions::Command::AcceleratorToString(accelerator); |
| 48 | |
| 49 // Media keys have a 1-to-many relationship with targets, unlike regular | |
| 50 // shortcut (1-to-1 relationship). That means two or more extensions can | |
| 51 // register for the same media key so the extension ID needs to be added to | |
| 52 // the key to make sure the key is unique. | |
| 53 if (extensions::CommandService::IsMediaKey(accelerator)) | |
| 54 key += ":" + extension_id; | |
| 55 | |
| 56 return key; | |
| 44 } | 57 } |
| 45 | 58 |
| 46 void SetInitialBindingsHaveBeenAssigned( | 59 void SetInitialBindingsHaveBeenAssigned( |
| 47 ExtensionPrefs* prefs, const std::string& extension_id) { | 60 ExtensionPrefs* prefs, const std::string& extension_id) { |
| 48 prefs->UpdateExtensionPref(extension_id, kInitialBindingsHaveBeenAssigned, | 61 prefs->UpdateExtensionPref(extension_id, kInitialBindingsHaveBeenAssigned, |
| 49 new base::FundamentalValue(true)); | 62 new base::FundamentalValue(true)); |
| 50 } | 63 } |
| 51 | 64 |
| 52 bool InitialBindingsHaveBeenAssigned( | 65 bool InitialBindingsHaveBeenAssigned( |
| 53 const ExtensionPrefs* prefs, const std::string& extension_id) { | 66 const ExtensionPrefs* prefs, const std::string& extension_id) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 103 // static | 116 // static |
| 104 ProfileKeyedAPIFactory<CommandService>* CommandService::GetFactoryInstance() { | 117 ProfileKeyedAPIFactory<CommandService>* CommandService::GetFactoryInstance() { |
| 105 return &g_factory.Get(); | 118 return &g_factory.Get(); |
| 106 } | 119 } |
| 107 | 120 |
| 108 // static | 121 // static |
| 109 CommandService* CommandService::Get(Profile* profile) { | 122 CommandService* CommandService::Get(Profile* profile) { |
| 110 return ProfileKeyedAPIFactory<CommandService>::GetForProfile(profile); | 123 return ProfileKeyedAPIFactory<CommandService>::GetForProfile(profile); |
| 111 } | 124 } |
| 112 | 125 |
| 126 // static | |
| 127 bool CommandService::IsMediaKey(const ui::Accelerator& accelerator) { | |
| 128 if (accelerator.modifiers() != 0) | |
| 129 return false; | |
| 130 | |
| 131 return (accelerator.key_code() == ui::VKEY_MEDIA_NEXT_TRACK || | |
| 132 accelerator.key_code() == ui::VKEY_MEDIA_PREV_TRACK || | |
| 133 accelerator.key_code() == ui::VKEY_MEDIA_PLAY_PAUSE || | |
| 134 accelerator.key_code() == ui::VKEY_MEDIA_STOP); | |
| 135 } | |
| 136 | |
| 113 bool CommandService::GetBrowserActionCommand( | 137 bool CommandService::GetBrowserActionCommand( |
| 114 const std::string& extension_id, | 138 const std::string& extension_id, |
| 115 QueryType type, | 139 QueryType type, |
| 116 extensions::Command* command, | 140 extensions::Command* command, |
| 117 bool* active) { | 141 bool* active) { |
| 118 return GetExtensionActionCommand( | 142 return GetExtensionActionCommand( |
| 119 extension_id, type, command, active, BROWSER_ACTION); | 143 extension_id, type, command, active, BROWSER_ACTION); |
| 120 } | 144 } |
| 121 | 145 |
| 122 bool CommandService::GetPageActionCommand( | 146 bool CommandService::GetPageActionCommand( |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 | 205 |
| 182 bool CommandService::AddKeybindingPref( | 206 bool CommandService::AddKeybindingPref( |
| 183 const ui::Accelerator& accelerator, | 207 const ui::Accelerator& accelerator, |
| 184 std::string extension_id, | 208 std::string extension_id, |
| 185 std::string command_name, | 209 std::string command_name, |
| 186 bool allow_overrides, | 210 bool allow_overrides, |
| 187 bool global) { | 211 bool global) { |
| 188 if (accelerator.key_code() == ui::VKEY_UNKNOWN) | 212 if (accelerator.key_code() == ui::VKEY_UNKNOWN) |
| 189 return false; | 213 return false; |
| 190 | 214 |
| 215 // Media Keys are allowed used by named command only. | |
|
Finnur
2013/11/18 14:14:54
s/used/for use/
zhchbin
2013/11/18 14:54:44
Done. Change to: "Media Keys are allowed to be use
| |
| 216 DCHECK(IsMediaKey(accelerator) && | |
|
Finnur
2013/11/18 14:14:54
That can't be right...
What happens when you add C
zhchbin
2013/11/18 14:54:44
I beat my head again....
| |
| 217 command_name != manifest_values::kPageActionCommandEvent && | |
| 218 command_name != manifest_values::kBrowserActionCommandEvent && | |
| 219 command_name != manifest_values::kScriptBadgeCommandEvent); | |
| 220 | |
| 191 DictionaryPrefUpdate updater(profile_->GetPrefs(), | 221 DictionaryPrefUpdate updater(profile_->GetPrefs(), |
| 192 prefs::kExtensionCommands); | 222 prefs::kExtensionCommands); |
| 193 base::DictionaryValue* bindings = updater.Get(); | 223 base::DictionaryValue* bindings = updater.Get(); |
| 194 | 224 |
| 195 std::string key = GetPlatformKeybindingKeyForAccelerator(accelerator); | 225 std::string key = GetPlatformKeybindingKeyForAccelerator(accelerator, |
| 226 extension_id); | |
| 196 | 227 |
| 197 if (!allow_overrides && bindings->HasKey(key)) | 228 if (!allow_overrides && bindings->HasKey(key)) |
| 198 return false; // Already taken. | 229 return false; // Already taken. |
| 199 | 230 |
| 200 base::DictionaryValue* keybinding = new base::DictionaryValue(); | 231 base::DictionaryValue* keybinding = new base::DictionaryValue(); |
| 201 keybinding->SetString(kExtension, extension_id); | 232 keybinding->SetString(kExtension, extension_id); |
| 202 keybinding->SetString(kCommandName, command_name); | 233 keybinding->SetString(kCommandName, command_name); |
| 203 keybinding->SetBoolean(kGlobal, global); | 234 keybinding->SetBoolean(kGlobal, global); |
| 204 | 235 |
| 205 bindings->Set(key, keybinding); | 236 bindings->Set(key, keybinding); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 if (extension != extension_id) | 310 if (extension != extension_id) |
| 280 continue; | 311 continue; |
| 281 std::string command_name; | 312 std::string command_name; |
| 282 item->GetString(kCommandName, &command_name); | 313 item->GetString(kCommandName, &command_name); |
| 283 if (command != command_name) | 314 if (command != command_name) |
| 284 continue; | 315 continue; |
| 285 bool global = false; | 316 bool global = false; |
| 286 if (FeatureSwitch::global_commands()->IsEnabled()) | 317 if (FeatureSwitch::global_commands()->IsEnabled()) |
| 287 item->GetBoolean(kGlobal, &global); | 318 item->GetBoolean(kGlobal, &global); |
| 288 | 319 |
| 320 // Format stored in Preferences is: "Platform:Shortcut[:ExtensionId]". | |
| 289 std::string shortcut = it.key(); | 321 std::string shortcut = it.key(); |
| 290 if (StartsWithASCII(shortcut, Command::CommandPlatform() + ":", true)) | 322 if (StartsWithASCII(shortcut, Command::CommandPlatform() + ":", true)) { |
| 291 shortcut = shortcut.substr(Command::CommandPlatform().length() + 1); | 323 std::vector<std::string> tokens; |
| 324 base::SplitString(shortcut, ':', &tokens); | |
| 325 CHECK(tokens.size() >= 2); | |
| 326 shortcut = tokens[1]; | |
| 327 } | |
| 292 | 328 |
| 293 return Command(command_name, string16(), shortcut, global); | 329 return Command(command_name, string16(), shortcut, global); |
| 294 } | 330 } |
| 295 | 331 |
| 296 return Command(); | 332 return Command(); |
| 297 } | 333 } |
| 298 | 334 |
| 299 void CommandService::AssignInitialKeybindings(const Extension* extension) { | 335 void CommandService::AssignInitialKeybindings(const Extension* extension) { |
| 300 const extensions::CommandMap* commands = | 336 const extensions::CommandMap* commands = |
| 301 CommandsInfo::GetNamedCommands(extension); | 337 CommandsInfo::GetNamedCommands(extension); |
| 302 if (!commands) | 338 if (!commands) |
| 303 return; | 339 return; |
| 304 | 340 |
| 305 ExtensionService* extension_service = | 341 ExtensionService* extension_service = |
| 306 ExtensionSystem::Get(profile_)->extension_service(); | 342 ExtensionSystem::Get(profile_)->extension_service(); |
| 307 ExtensionPrefs* extension_prefs = extension_service->extension_prefs(); | 343 ExtensionPrefs* extension_prefs = extension_service->extension_prefs(); |
| 308 if (InitialBindingsHaveBeenAssigned(extension_prefs, extension->id())) | 344 if (InitialBindingsHaveBeenAssigned(extension_prefs, extension->id())) |
| 309 return; | 345 return; |
| 310 SetInitialBindingsHaveBeenAssigned(extension_prefs, extension->id()); | 346 SetInitialBindingsHaveBeenAssigned(extension_prefs, extension->id()); |
| 311 | 347 |
| 312 extensions::CommandMap::const_iterator iter = commands->begin(); | 348 extensions::CommandMap::const_iterator iter = commands->begin(); |
| 313 for (; iter != commands->end(); ++iter) { | 349 for (; iter != commands->end(); ++iter) { |
| 314 if (!chrome::IsChromeAccelerator( | 350 // Make sure registered Chrome shortcuts cannot be automatically assigned |
| 315 iter->second.accelerator(), profile_) && | 351 // (overwritten) by extension developers. Media keys are an exception here. |
| 316 IsWhitelistedGlobalShortcut(iter->second)) { | 352 if ((!chrome::IsChromeAccelerator(iter->second.accelerator(), profile_) && |
| 353 IsWhitelistedGlobalShortcut(iter->second)) || | |
| 354 extensions::CommandService::IsMediaKey(iter->second.accelerator())) { | |
| 317 AddKeybindingPref(iter->second.accelerator(), | 355 AddKeybindingPref(iter->second.accelerator(), |
| 318 extension->id(), | 356 extension->id(), |
| 319 iter->second.command_name(), | 357 iter->second.command_name(), |
| 320 false, // Overwriting not allowed. | 358 false, // Overwriting not allowed. |
| 321 iter->second.global()); | 359 iter->second.global()); |
| 322 } | 360 } |
| 323 } | 361 } |
| 324 | 362 |
| 325 const extensions::Command* browser_action_command = | 363 const extensions::Command* browser_action_command = |
| 326 CommandsInfo::GetBrowserActionCommand(extension); | 364 CommandsInfo::GetBrowserActionCommand(extension); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 457 | 495 |
| 458 return true; | 496 return true; |
| 459 } | 497 } |
| 460 | 498 |
| 461 template <> | 499 template <> |
| 462 void ProfileKeyedAPIFactory<CommandService>::DeclareFactoryDependencies() { | 500 void ProfileKeyedAPIFactory<CommandService>::DeclareFactoryDependencies() { |
| 463 DependsOn(ExtensionCommandsGlobalRegistry::GetFactoryInstance()); | 501 DependsOn(ExtensionCommandsGlobalRegistry::GetFactoryInstance()); |
| 464 } | 502 } |
| 465 | 503 |
| 466 } // namespace extensions | 504 } // namespace extensions |
| OLD | NEW |