Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: chrome/common/extensions/command.cc

Issue 23445013: Parse media keys for named command in the manifest. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nit fix. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/common/extensions/command.h" 5 #include "chrome/common/extensions/command.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_split.h" 9 #include "base/strings/string_split.h"
10 #include "base/strings/string_util.h" 10 #include "base/strings/string_util.h"
(...skipping 11 matching lines...) Expand all
22 using extensions::ErrorUtils; 22 using extensions::ErrorUtils;
23 using extensions::Command; 23 using extensions::Command;
24 24
25 namespace { 25 namespace {
26 26
27 static const char kMissing[] = "Missing"; 27 static const char kMissing[] = "Missing";
28 28
29 static const char kCommandKeyNotSupported[] = 29 static const char kCommandKeyNotSupported[] =
30 "Command key is not supported. Note: Ctrl means Command on Mac"; 30 "Command key is not supported. Note: Ctrl means Command on Mac";
31 31
32 bool IsNamedCommand(const std::string& command_name) {
33 return command_name != values::kPageActionCommandEvent &&
34 command_name != values::kBrowserActionCommandEvent &&
35 command_name != values::kScriptBadgeCommandEvent;
36 }
37
38 bool DoesRequireModifier(const std::string& accelerator) {
39 return accelerator != values::kKeyMediaNextTrack &&
40 accelerator != values::kKeyMediaPlayPause &&
41 accelerator != values::kKeyMediaPrevTrack &&
42 accelerator != values::kKeyMediaStop;
43 }
44
32 ui::Accelerator ParseImpl(const std::string& accelerator, 45 ui::Accelerator ParseImpl(const std::string& accelerator,
33 const std::string& platform_key, 46 const std::string& platform_key,
34 int index, 47 int index,
48 bool should_parse_media_keys,
35 string16* error) { 49 string16* error) {
50 error->clear();
36 if (platform_key != values::kKeybindingPlatformWin && 51 if (platform_key != values::kKeybindingPlatformWin &&
37 platform_key != values::kKeybindingPlatformMac && 52 platform_key != values::kKeybindingPlatformMac &&
38 platform_key != values::kKeybindingPlatformChromeOs && 53 platform_key != values::kKeybindingPlatformChromeOs &&
39 platform_key != values::kKeybindingPlatformLinux && 54 platform_key != values::kKeybindingPlatformLinux &&
40 platform_key != values::kKeybindingPlatformDefault) { 55 platform_key != values::kKeybindingPlatformDefault) {
41 *error = ErrorUtils::FormatErrorMessageUTF16( 56 *error = ErrorUtils::FormatErrorMessageUTF16(
42 errors::kInvalidKeyBindingUnknownPlatform, 57 errors::kInvalidKeyBindingUnknownPlatform,
43 base::IntToString(index), 58 base::IntToString(index),
44 platform_key); 59 platform_key);
45 return ui::Accelerator(); 60 return ui::Accelerator();
46 } 61 }
47 62
48 std::vector<std::string> tokens; 63 std::vector<std::string> tokens;
49 base::SplitString(accelerator, '+', &tokens); 64 base::SplitString(accelerator, '+', &tokens);
50 if (tokens.size() < 2 || tokens.size() > 3) { 65 if (tokens.size() == 0 ||
66 (tokens.size() == 1 && DoesRequireModifier(accelerator)) ||
67 tokens.size() > 3) {
51 *error = ErrorUtils::FormatErrorMessageUTF16( 68 *error = ErrorUtils::FormatErrorMessageUTF16(
52 errors::kInvalidKeyBinding, 69 errors::kInvalidKeyBinding,
53 base::IntToString(index), 70 base::IntToString(index),
54 platform_key, 71 platform_key,
55 accelerator); 72 accelerator);
56 return ui::Accelerator(); 73 return ui::Accelerator();
57 } 74 }
58 75
59 // Now, parse it into an accelerator. 76 // Now, parse it into an accelerator.
60 int modifiers = ui::EF_NONE; 77 int modifiers = ui::EF_NONE;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 tokens[i] == values::kKeyUp || 109 tokens[i] == values::kKeyUp ||
93 tokens[i] == values::kKeyDown || 110 tokens[i] == values::kKeyDown ||
94 tokens[i] == values::kKeyLeft || 111 tokens[i] == values::kKeyLeft ||
95 tokens[i] == values::kKeyRight || 112 tokens[i] == values::kKeyRight ||
96 tokens[i] == values::kKeyIns || 113 tokens[i] == values::kKeyIns ||
97 tokens[i] == values::kKeyDel || 114 tokens[i] == values::kKeyDel ||
98 tokens[i] == values::kKeyHome || 115 tokens[i] == values::kKeyHome ||
99 tokens[i] == values::kKeyEnd || 116 tokens[i] == values::kKeyEnd ||
100 tokens[i] == values::kKeyPgUp || 117 tokens[i] == values::kKeyPgUp ||
101 tokens[i] == values::kKeyPgDwn || 118 tokens[i] == values::kKeyPgDwn ||
102 tokens[i] == values::kKeyTab) { 119 tokens[i] == values::kKeyTab ||
120 tokens[i] == values::kKeyMediaNextTrack ||
121 tokens[i] == values::kKeyMediaPlayPause ||
122 tokens[i] == values::kKeyMediaPrevTrack ||
123 tokens[i] == values::kKeyMediaStop) {
103 if (key != ui::VKEY_UNKNOWN) { 124 if (key != ui::VKEY_UNKNOWN) {
104 // Multiple key assignments. 125 // Multiple key assignments.
105 key = ui::VKEY_UNKNOWN; 126 key = ui::VKEY_UNKNOWN;
106 break; 127 break;
107 } 128 }
108 129
109 if (tokens[i] == values::kKeyComma) { 130 if (tokens[i] == values::kKeyComma) {
110 key = ui::VKEY_OEM_COMMA; 131 key = ui::VKEY_OEM_COMMA;
111 } else if (tokens[i] == values::kKeyPeriod) { 132 } else if (tokens[i] == values::kKeyPeriod) {
112 key = ui::VKEY_OEM_PERIOD; 133 key = ui::VKEY_OEM_PERIOD;
(...skipping 12 matching lines...) Expand all
125 } else if (tokens[i] == values::kKeyHome) { 146 } else if (tokens[i] == values::kKeyHome) {
126 key = ui::VKEY_HOME; 147 key = ui::VKEY_HOME;
127 } else if (tokens[i] == values::kKeyEnd) { 148 } else if (tokens[i] == values::kKeyEnd) {
128 key = ui::VKEY_END; 149 key = ui::VKEY_END;
129 } else if (tokens[i] == values::kKeyPgUp) { 150 } else if (tokens[i] == values::kKeyPgUp) {
130 key = ui::VKEY_PRIOR; 151 key = ui::VKEY_PRIOR;
131 } else if (tokens[i] == values::kKeyPgDwn) { 152 } else if (tokens[i] == values::kKeyPgDwn) {
132 key = ui::VKEY_NEXT; 153 key = ui::VKEY_NEXT;
133 } else if (tokens[i] == values::kKeyTab) { 154 } else if (tokens[i] == values::kKeyTab) {
134 key = ui::VKEY_TAB; 155 key = ui::VKEY_TAB;
156 } else if (tokens[i] == values::kKeyMediaNextTrack &&
157 should_parse_media_keys) {
158 key = ui::VKEY_MEDIA_NEXT_TRACK;
159 } else if (tokens[i] == values::kKeyMediaPlayPause &&
160 should_parse_media_keys) {
161 key = ui::VKEY_MEDIA_PLAY_PAUSE;
162 } else if (tokens[i] == values::kKeyMediaPrevTrack &&
163 should_parse_media_keys) {
164 key = ui::VKEY_MEDIA_PREV_TRACK;
165 } else if (tokens[i] == values::kKeyMediaStop &&
166 should_parse_media_keys) {
167 key = ui::VKEY_MEDIA_STOP;
135 } else if (tokens[i].size() == 1 && 168 } else if (tokens[i].size() == 1 &&
136 tokens[i][0] >= 'A' && tokens[i][0] <= 'Z') { 169 tokens[i][0] >= 'A' && tokens[i][0] <= 'Z') {
137 key = static_cast<ui::KeyboardCode>(ui::VKEY_A + (tokens[i][0] - 'A')); 170 key = static_cast<ui::KeyboardCode>(ui::VKEY_A + (tokens[i][0] - 'A'));
138 } else if (tokens[i].size() == 1 && 171 } else if (tokens[i].size() == 1 &&
139 tokens[i][0] >= '0' && tokens[i][0] <= '9') { 172 tokens[i][0] >= '0' && tokens[i][0] <= '9') {
140 key = static_cast<ui::KeyboardCode>(ui::VKEY_0 + (tokens[i][0] - '0')); 173 key = static_cast<ui::KeyboardCode>(ui::VKEY_0 + (tokens[i][0] - '0'));
141 } else { 174 } else {
142 key = ui::VKEY_UNKNOWN; 175 key = ui::VKEY_UNKNOWN;
143 break; 176 break;
144 } 177 }
145 } else { 178 } else {
146 *error = ErrorUtils::FormatErrorMessageUTF16( 179 *error = ErrorUtils::FormatErrorMessageUTF16(
147 errors::kInvalidKeyBinding, 180 errors::kInvalidKeyBinding,
148 base::IntToString(index), 181 base::IntToString(index),
149 platform_key, 182 platform_key,
150 accelerator); 183 accelerator);
151 return ui::Accelerator(); 184 return ui::Accelerator();
152 } 185 }
153 } 186 }
187
154 bool command = (modifiers & ui::EF_COMMAND_DOWN) != 0; 188 bool command = (modifiers & ui::EF_COMMAND_DOWN) != 0;
155 bool ctrl = (modifiers & ui::EF_CONTROL_DOWN) != 0; 189 bool ctrl = (modifiers & ui::EF_CONTROL_DOWN) != 0;
156 bool alt = (modifiers & ui::EF_ALT_DOWN) != 0; 190 bool alt = (modifiers & ui::EF_ALT_DOWN) != 0;
157 bool shift = (modifiers & ui::EF_SHIFT_DOWN) != 0; 191 bool shift = (modifiers & ui::EF_SHIFT_DOWN) != 0;
158 192
159 // We support Ctrl+foo, Alt+foo, Ctrl+Shift+foo, Alt+Shift+foo, but not 193 // We support Ctrl+foo, Alt+foo, Ctrl+Shift+foo, Alt+Shift+foo, but not
160 // Ctrl+Alt+foo and not Shift+foo either. For a more detailed reason why we 194 // Ctrl+Alt+foo and not Shift+foo either. For a more detailed reason why we
161 // don't support Ctrl+Alt+foo see this article: 195 // don't support Ctrl+Alt+foo see this article:
162 // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/29/101121.aspx. 196 // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/29/101121.aspx.
163 // On Mac Command can also be used in combination with Shift or on its own, 197 // On Mac Command can also be used in combination with Shift or on its own,
164 // as a modifier. 198 // as a modifier.
165 if (key == ui::VKEY_UNKNOWN || (ctrl && alt) || (command && alt) || 199 if (key == ui::VKEY_UNKNOWN || (ctrl && alt) || (command && alt) ||
166 (shift && !ctrl && !alt && !command)) { 200 (shift && !ctrl && !alt && !command)) {
167 *error = ErrorUtils::FormatErrorMessageUTF16( 201 *error = ErrorUtils::FormatErrorMessageUTF16(
168 errors::kInvalidKeyBinding, 202 errors::kInvalidKeyBinding,
169 base::IntToString(index), 203 base::IntToString(index),
170 platform_key, 204 platform_key,
171 accelerator); 205 accelerator);
172 return ui::Accelerator(); 206 return ui::Accelerator();
173 } 207 }
174 208
209 if ((key == ui::VKEY_MEDIA_NEXT_TRACK ||
210 key == ui::VKEY_MEDIA_PREV_TRACK ||
211 key == ui::VKEY_MEDIA_PLAY_PAUSE ||
212 key == ui::VKEY_MEDIA_STOP) &&
213 (shift || ctrl || alt || command)) {
214 *error = ErrorUtils::FormatErrorMessageUTF16(
215 errors::kInvalidKeyBindingMediaKeyWithModifier,
216 base::IntToString(index),
217 platform_key,
218 accelerator);
219 return ui::Accelerator();
220 }
221
175 return ui::Accelerator(key, modifiers); 222 return ui::Accelerator(key, modifiers);
176 } 223 }
177 224
178 // For Mac, we convert "Ctrl" to "Command" and "MacCtrl" to "Ctrl". Other 225 // For Mac, we convert "Ctrl" to "Command" and "MacCtrl" to "Ctrl". Other
179 // platforms leave the shortcut untouched. 226 // platforms leave the shortcut untouched.
180 std::string NormalizeShortcutSuggestion(const std::string& suggestion, 227 std::string NormalizeShortcutSuggestion(const std::string& suggestion,
181 const std::string& platform) { 228 const std::string& platform) {
182 bool normalize = false; 229 bool normalize = false;
183 if (platform == values::kKeybindingPlatformMac) { 230 if (platform == values::kKeybindingPlatformMac) {
184 normalize = true; 231 normalize = true;
(...skipping 22 matching lines...) Expand all
207 namespace extensions { 254 namespace extensions {
208 255
209 Command::Command() {} 256 Command::Command() {}
210 257
211 Command::Command(const std::string& command_name, 258 Command::Command(const std::string& command_name,
212 const string16& description, 259 const string16& description,
213 const std::string& accelerator) 260 const std::string& accelerator)
214 : command_name_(command_name), 261 : command_name_(command_name),
215 description_(description) { 262 description_(description) {
216 string16 error; 263 string16 error;
217 accelerator_ = ParseImpl(accelerator, CommandPlatform(), 0, &error); 264 accelerator_ = ParseImpl(accelerator, CommandPlatform(), 0,
265 IsNamedCommand(command_name), &error);
218 } 266 }
219 267
220 Command::~Command() {} 268 Command::~Command() {}
221 269
222 // static 270 // static
223 std::string Command::CommandPlatform() { 271 std::string Command::CommandPlatform() {
224 #if defined(OS_WIN) 272 #if defined(OS_WIN)
225 return values::kKeybindingPlatformWin; 273 return values::kKeybindingPlatformWin;
226 #elif defined(OS_MACOSX) 274 #elif defined(OS_MACOSX)
227 return values::kKeybindingPlatformMac; 275 return values::kKeybindingPlatformMac;
228 #elif defined(OS_CHROMEOS) 276 #elif defined(OS_CHROMEOS)
229 return values::kKeybindingPlatformChromeOs; 277 return values::kKeybindingPlatformChromeOs;
230 #elif defined(OS_LINUX) 278 #elif defined(OS_LINUX)
231 return values::kKeybindingPlatformLinux; 279 return values::kKeybindingPlatformLinux;
232 #else 280 #else
233 return ""; 281 return "";
234 #endif 282 #endif
235 } 283 }
236 284
237 // static 285 // static
238 ui::Accelerator Command::StringToAccelerator(const std::string& accelerator) { 286 ui::Accelerator Command::StringToAccelerator(const std::string& accelerator,
287 const std::string& command_name) {
239 string16 error; 288 string16 error;
240 Command command;
241 ui::Accelerator parsed = 289 ui::Accelerator parsed =
242 ParseImpl(accelerator, Command::CommandPlatform(), 0, &error); 290 ParseImpl(accelerator, Command::CommandPlatform(), 0,
291 IsNamedCommand(command_name), &error);
243 return parsed; 292 return parsed;
244 } 293 }
245 294
246 // static 295 // static
247 std::string Command::AcceleratorToString(const ui::Accelerator& accelerator) { 296 std::string Command::AcceleratorToString(const ui::Accelerator& accelerator) {
248 std::string shortcut; 297 std::string shortcut;
249 298
250 // Ctrl and Alt are mutually exclusive. 299 // Ctrl and Alt are mutually exclusive.
251 if (accelerator.IsCtrlDown()) 300 if (accelerator.IsCtrlDown())
252 shortcut += values::kKeyCtrl; 301 shortcut += values::kKeyCtrl;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 break; 354 break;
306 case ui::VKEY_PRIOR: 355 case ui::VKEY_PRIOR:
307 shortcut += values::kKeyPgUp; 356 shortcut += values::kKeyPgUp;
308 break; 357 break;
309 case ui::VKEY_NEXT: 358 case ui::VKEY_NEXT:
310 shortcut += values::kKeyPgDwn; 359 shortcut += values::kKeyPgDwn;
311 break; 360 break;
312 case ui::VKEY_TAB: 361 case ui::VKEY_TAB:
313 shortcut += values::kKeyTab; 362 shortcut += values::kKeyTab;
314 break; 363 break;
364 case ui::VKEY_MEDIA_NEXT_TRACK:
365 shortcut += values::kKeyMediaNextTrack;
366 break;
367 case ui::VKEY_MEDIA_PLAY_PAUSE:
368 shortcut += values::kKeyMediaPlayPause;
369 break;
370 case ui::VKEY_MEDIA_PREV_TRACK:
371 shortcut += values::kKeyMediaPrevTrack;
372 break;
373 case ui::VKEY_MEDIA_STOP:
374 shortcut += values::kKeyMediaStop;
375 break;
315 default: 376 default:
316 return ""; 377 return "";
317 } 378 }
318 } 379 }
319 return shortcut; 380 return shortcut;
320 } 381 }
321 382
322 bool Command::Parse(const base::DictionaryValue* command, 383 bool Command::Parse(const base::DictionaryValue* command,
323 const std::string& command_name, 384 const std::string& command_name,
324 int index, 385 int index,
325 string16* error) { 386 string16* error) {
326 DCHECK(!command_name.empty()); 387 DCHECK(!command_name.empty());
327 388
328 string16 description; 389 string16 description;
329 if (command_name != values::kPageActionCommandEvent && 390 if (IsNamedCommand(command_name)) {
330 command_name != values::kBrowserActionCommandEvent &&
331 command_name != values::kScriptBadgeCommandEvent) {
332 if (!command->GetString(keys::kDescription, &description) || 391 if (!command->GetString(keys::kDescription, &description) ||
333 description.empty()) { 392 description.empty()) {
334 *error = ErrorUtils::FormatErrorMessageUTF16( 393 *error = ErrorUtils::FormatErrorMessageUTF16(
335 errors::kInvalidKeyBindingDescription, 394 errors::kInvalidKeyBindingDescription,
336 base::IntToString(index)); 395 base::IntToString(index));
337 return false; 396 return false;
338 } 397 }
339 } 398 }
340 399
341 // We'll build up a map of platform-to-shortcut suggestions. 400 // We'll build up a map of platform-to-shortcut suggestions.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 471
413 // For developer convenience, we parse all the suggestions (and complain about 472 // For developer convenience, we parse all the suggestions (and complain about
414 // errors for platforms other than the current one) but use only what we need. 473 // errors for platforms other than the current one) but use only what we need.
415 std::map<const std::string, std::string>::const_iterator iter = 474 std::map<const std::string, std::string>::const_iterator iter =
416 suggestions.begin(); 475 suggestions.begin();
417 for ( ; iter != suggestions.end(); ++iter) { 476 for ( ; iter != suggestions.end(); ++iter) {
418 ui::Accelerator accelerator; 477 ui::Accelerator accelerator;
419 if (!iter->second.empty()) { 478 if (!iter->second.empty()) {
420 // Note that we pass iter->first to pretend we are on a platform we're not 479 // Note that we pass iter->first to pretend we are on a platform we're not
421 // on. 480 // on.
422 accelerator = ParseImpl(iter->second, iter->first, index, error); 481 accelerator = ParseImpl(iter->second, iter->first, index,
482 IsNamedCommand(command_name), error);
423 if (accelerator.key_code() == ui::VKEY_UNKNOWN) { 483 if (accelerator.key_code() == ui::VKEY_UNKNOWN) {
424 *error = ErrorUtils::FormatErrorMessageUTF16( 484 if (error->empty()) {
425 errors::kInvalidKeyBinding, 485 *error = ErrorUtils::FormatErrorMessageUTF16(
426 base::IntToString(index), 486 errors::kInvalidKeyBinding,
427 iter->first, 487 base::IntToString(index),
428 iter->second); 488 iter->first,
489 iter->second);
490 }
429 return false; 491 return false;
430 } 492 }
431 } 493 }
432 494
433 if (iter->first == key) { 495 if (iter->first == key) {
434 // This platform is our platform, so grab this key. 496 // This platform is our platform, so grab this key.
435 accelerator_ = accelerator; 497 accelerator_ = accelerator;
436 command_name_ = command_name; 498 command_name_ = command_name;
437 description_ = description; 499 description_ = description;
438 } 500 }
(...skipping 17 matching lines...) Expand all
456 extension_data->SetString("description", command_description); 518 extension_data->SetString("description", command_description);
457 extension_data->SetBoolean("active", active); 519 extension_data->SetBoolean("active", active);
458 extension_data->SetString("keybinding", accelerator().GetShortcutText()); 520 extension_data->SetString("keybinding", accelerator().GetShortcutText());
459 extension_data->SetString("command_name", command_name()); 521 extension_data->SetString("command_name", command_name());
460 extension_data->SetString("extension_id", extension->id()); 522 extension_data->SetString("extension_id", extension->id());
461 523
462 return extension_data; 524 return extension_data;
463 } 525 }
464 526
465 } // namespace extensions 527 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698