command.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/command.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_manifest_constants.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/error_utils.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace errors = extension_manifest_errors; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace keys = extension_manifest_keys; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace values = extension_manifest_values; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::ErrorUtils; 23a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)using extensions::Command; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kMissing[] = "Missing"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kCommandKeyNotSupported[] = 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Command key is not supported. Note: Ctrl means Command on Mac"; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::Accelerator ParseImpl(const std::string& accelerator, 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& platform_key, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16* error) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (platform_key != values::kKeybindingPlatformWin && 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_key != values::kKeybindingPlatformMac && 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_key != values::kKeybindingPlatformChromeOs && 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_key != values::kKeybindingPlatformLinux && 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_key != values::kKeybindingPlatformDefault) { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errors::kInvalidKeyBindingUnknownPlatform, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::IntToString(index), 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_key); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::Accelerator(); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> tokens; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitString(accelerator, '+', &tokens); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tokens.size() < 2 || tokens.size() > 3) { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errors::kInvalidKeyBinding, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::IntToString(index), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_key, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accelerator); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::Accelerator(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now, parse it into an accelerator. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int modifiers = ui::EF_NONE; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::KeyboardCode key = ui::VKEY_UNKNOWN; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < tokens.size(); i++) { 63a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (tokens[i] == values::kKeyCtrl) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modifiers |= ui::EF_CONTROL_DOWN; 65a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyCommand) { 66a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (platform_key == values::kKeybindingPlatformMac) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either the developer specified Command+foo in the manifest for Mac or 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // they specified Ctrl and it got normalized to Command (to get Ctrl on 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mac the developer has to specify MacCtrl). Therefore we treat this 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as Command. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modifiers |= ui::EF_COMMAND_DOWN; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 73a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (platform_key == values::kKeybindingPlatformDefault) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we see "Command+foo" in the Default section it can mean two 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // things, depending on the platform: 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The developer specified "Ctrl+foo" for Default and it got normalized 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on Mac to "Command+foo". This is fine. Treat it as Command. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modifiers |= ui::EF_COMMAND_DOWN; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No other platform supports Command. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = ui::VKEY_UNKNOWN; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 85a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyAlt) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modifiers |= ui::EF_ALT_DOWN; 87a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyShift) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modifiers |= ui::EF_SHIFT_DOWN; 89a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i].size() == 1 || // A-Z, 0-9. 90a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyComma || 91a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyPeriod || 92a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyUp || 93a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyDown || 94a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyLeft || 95a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyRight || 96a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyIns || 97a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyDel || 98a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyHome || 99a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyEnd || 100a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyPgUp || 101a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyPgDwn || 102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] == values::kKeyTab) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key != ui::VKEY_UNKNOWN) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Multiple key assignments. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = ui::VKEY_UNKNOWN; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 108a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 109a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (tokens[i] == values::kKeyComma) { 110a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_OEM_COMMA; 111a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyPeriod) { 112a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_OEM_PERIOD; 113a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyUp) { 114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_UP; 115a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyDown) { 116a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_DOWN; 117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyLeft) { 118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_LEFT; 119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyRight) { 120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_RIGHT; 121a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyIns) { 122a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_INSERT; 123a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyDel) { 124a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_DELETE; 125a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyHome) { 126a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_HOME; 127a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyEnd) { 128a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_END; 129a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyPgUp) { 130a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_PRIOR; 131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyPgDwn) { 132a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_NEXT; 133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i] == values::kKeyTab) { 134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) key = ui::VKEY_TAB; 135a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i].size() == 1 && 136a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i][0] >= 'A' && tokens[i][0] <= 'Z') { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = static_cast<ui::KeyboardCode>(ui::VKEY_A + (tokens[i][0] - 'A')); 138a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (tokens[i].size() == 1 && 139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i][0] >= '0' && tokens[i][0] <= '9') { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = static_cast<ui::KeyboardCode>(ui::VKEY_0 + (tokens[i][0] - '0')); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = ui::VKEY_UNKNOWN; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errors::kInvalidKeyBinding, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::IntToString(index), 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_key, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accelerator); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::Accelerator(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool command = (modifiers & ui::EF_COMMAND_DOWN) != 0; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ctrl = (modifiers & ui::EF_CONTROL_DOWN) != 0; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool alt = (modifiers & ui::EF_ALT_DOWN) != 0; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool shift = (modifiers & ui::EF_SHIFT_DOWN) != 0; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We support Ctrl+foo, Alt+foo, Ctrl+Shift+foo, Alt+Shift+foo, but not 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ctrl+Alt+foo and not Shift+foo either. For a more detailed reason why we 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't support Ctrl+Alt+foo see this article: 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/29/101121.aspx. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On Mac Command can also be used in combination with Shift or on its own, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as a modifier. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key == ui::VKEY_UNKNOWN || (ctrl && alt) || (command && alt) || 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (shift && !ctrl && !alt && !command)) { 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errors::kInvalidKeyBinding, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::IntToString(index), 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_key, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accelerator); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::Accelerator(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::Accelerator(key, modifiers); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For Mac, we convert "Ctrl" to "Command" and "MacCtrl" to "Ctrl". Other 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// platforms leave the shortcut untouched. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string NormalizeShortcutSuggestion(const std::string& suggestion, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& platform) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool normalize = false; 183a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (platform == values::kKeybindingPlatformMac) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) normalize = true; 185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (platform == values::kKeybindingPlatformDefault) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) normalize = true; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!normalize) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return suggestion; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string key; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> tokens; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitString(suggestion, '+', &tokens); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < tokens.size(); i++) { 198a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (tokens[i] == values::kKeyCtrl) 199a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] = values::kKeyCommand; 200a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) else if (tokens[i] == values::kKeyMacCtrl) 201a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tokens[i] = values::kKeyCtrl; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return JoinString(tokens, '+'); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Command::Command() {} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Command::Command(const std::string& command_name, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& description, 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& accelerator) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : command_name_(command_name), 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) description_(description) { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 error; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accelerator_ = ParseImpl(accelerator, CommandPlatform(), 0, &error); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Command::~Command() {} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Command::CommandPlatform() { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return values::kKeybindingPlatformWin; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return values::kKeybindingPlatformMac; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_CHROMEOS) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return values::kKeybindingPlatformChromeOs; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return values::kKeybindingPlatformLinux; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ""; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::Accelerator Command::StringToAccelerator(const std::string& accelerator) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 error; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Command command; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::Accelerator parsed = 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseImpl(accelerator, Command::CommandPlatform(), 0, &error); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return parsed; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 247a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// static 248a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)std::string Command::AcceleratorToString(const ui::Accelerator& accelerator) { 249a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) std::string shortcut; 250a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 251a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Ctrl and Alt are mutually exclusive. 252a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (accelerator.IsCtrlDown()) 253a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyCtrl; 254a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) else if (accelerator.IsAltDown()) 255a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyAlt; 256a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!shortcut.empty()) 257a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeySeparator; 258a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 259a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (accelerator.IsCmdDown()) { 260a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyCommand; 261a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeySeparator; 262a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 263a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 264a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (accelerator.IsShiftDown()) { 265a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyShift; 266a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeySeparator; 267a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 268a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 269a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (accelerator.key_code() >= ui::VKEY_0 && 270a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) accelerator.key_code() <= ui::VKEY_9) { 271a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += '0' + (accelerator.key_code() - ui::VKEY_0); 272a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (accelerator.key_code() >= ui::VKEY_A && 273a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) accelerator.key_code() <= ui::VKEY_Z) { 274a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += 'A' + (accelerator.key_code() - ui::VKEY_A); 275a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else { 276a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) switch (accelerator.key_code()) { 277a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_OEM_COMMA: 278a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyComma; 279a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 280a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_OEM_PERIOD: 281a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyPeriod; 282a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 283a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_UP: 284a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyUp; 285a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 286a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_DOWN: 287a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyDown; 288a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 289a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_LEFT: 290a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyLeft; 291a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 292a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_RIGHT: 293a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyRight; 294a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 295a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_INSERT: 296a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyIns; 297a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 298a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_DELETE: 299a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyDel; 300a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 301a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_HOME: 302a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyHome; 303a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 304a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_END: 305a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyEnd; 306a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 307a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_PRIOR: 308a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyPgUp; 309a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 310a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_NEXT: 311a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyPgDwn; 312a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 313a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case ui::VKEY_TAB: 314a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) shortcut += values::kKeyTab; 315a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 316a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) default: 317a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return ""; 318a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 319a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 320a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return shortcut; 321a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 322a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool Command::Parse(const base::DictionaryValue* command, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& command_name, 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16* error) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!command_name.empty()); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) string16 description; 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (command_name != values::kPageActionCommandEvent && 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) command_name != values::kBrowserActionCommandEvent && 332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) command_name != values::kScriptBadgeCommandEvent) { 333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!command->GetString(keys::kDescription, &description) || 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) description.empty()) { 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) errors::kInvalidKeyBindingDescription, 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::IntToString(index)); 338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We'll build up a map of platform-to-shortcut suggestions. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<const std::string, std::string> SuggestionMap; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SuggestionMap suggestions; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First try to parse the |suggested_key| as a dictionary. 3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* suggested_key_dict; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command->GetDictionary(keys::kSuggestedKey, &suggested_key_dict)) { 3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (base::DictionaryValue::Iterator iter(*suggested_key_dict); 3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) !iter.IsAtEnd(); iter.Advance()) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For each item in the dictionary, extract the platforms specified. 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string suggested_key_string; 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (iter.value().GetAsString(&suggested_key_string) && 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !suggested_key_string.empty()) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Found a platform, add it to the suggestions list. 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) suggestions[iter.key()] = suggested_key_string; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errors::kInvalidKeyBinding, 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::IntToString(index), 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keys::kSuggestedKey, 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMissing); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No dictionary was found, fall back to using just a string, so developers 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't have to specify a dictionary if they just want to use one default 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for all platforms. 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string suggested_key_string; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command->GetString(keys::kSuggestedKey, &suggested_key_string) && 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !suggested_key_string.empty()) { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If only a single string is provided, it must be default for all. 374a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) suggestions[values::kKeybindingPlatformDefault] = suggested_key_string; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 376a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) suggestions[values::kKeybindingPlatformDefault] = ""; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Normalize the suggestions. 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SuggestionMap::iterator iter = suggestions.begin(); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != suggestions.end(); ++iter) { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Before we normalize Ctrl to Command we must detect when the developer 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // specified Command in the Default section, which will work on Mac after 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // normalization but only fail on other platforms when they try it out on 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other platforms, which is not what we want. 387a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (iter->first == values::kKeybindingPlatformDefault && 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->second.find("Command+") != std::string::npos) { 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errors::kInvalidKeyBinding, 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::IntToString(index), 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keys::kSuggestedKey, 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCommandKeyNotSupported); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suggestions[iter->first] = NormalizeShortcutSuggestion(iter->second, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->first); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string platform = CommandPlatform(); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string key = platform; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (suggestions.find(key) == suggestions.end()) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = values::kKeybindingPlatformDefault; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (suggestions.find(key) == suggestions.end()) { 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errors::kInvalidKeyBindingMissingPlatform, 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::IntToString(index), 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keys::kSuggestedKey, 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No platform specified and no fallback. Bail. 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For developer convenience, we parse all the suggestions (and complain about 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // errors for platforms other than the current one) but use only what we need. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<const std::string, std::string>::const_iterator iter = 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suggestions.begin(); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; iter != suggestions.end(); ++iter) { 419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ui::Accelerator accelerator; 420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!iter->second.empty()) { 421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Note that we pass iter->first to pretend we are on a platform we're not 422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // on. 423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) accelerator = ParseImpl(iter->second, iter->first, index, error); 424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (accelerator.key_code() == ui::VKEY_UNKNOWN) { 425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) errors::kInvalidKeyBinding, 427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::IntToString(index), 428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) iter->first, 429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) iter->second); 430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter->first == key) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This platform is our platform, so grab this key. 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accelerator_ = accelerator; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_name_ = command_name; 438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) description_ = description; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)base::DictionaryValue* Command::ToValue(const Extension* extension, 4457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool active) const { 4467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* extension_data = new base::DictionaryValue(); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 command_description; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command_name() == values::kBrowserActionCommandEvent || 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_name() == values::kPageActionCommandEvent || 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_name() == values::kScriptBadgeCommandEvent) { 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_description = 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_EXTENSION_COMMANDS_GENERIC_ACTIVATE); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_description = description(); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_data->SetString("description", command_description); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_data->SetBoolean("active", active); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_data->SetString("keybinding", accelerator().GetShortcutText()); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_data->SetString("command_name", command_name()); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_data->SetString("extension_id", extension->id()); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extension_data; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 467