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/common/extensions/extension.h" | 5 #include "chrome/common/extensions/extension.h" |
6 | 6 |
7 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/json/json_file_value_serializer.h" | 10 #include "base/json/json_file_value_serializer.h" |
(...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
938 bool expected_result; | 938 bool expected_result; |
939 ui::Accelerator accelerator; | 939 ui::Accelerator accelerator; |
940 const char* command_name; | 940 const char* command_name; |
941 const char* key; | 941 const char* key; |
942 const char* description; | 942 const char* description; |
943 } kTests[] = { | 943 } kTests[] = { |
944 // Negative test (one or more missing required fields). We don't need to | 944 // Negative test (one or more missing required fields). We don't need to |
945 // test |command_name| being blank as it is used as a key in the manifest, | 945 // test |command_name| being blank as it is used as a key in the manifest, |
946 // so it can't be blank (and we DCHECK when it is). | 946 // so it can't be blank (and we DCHECK when it is). |
947 { false, None, "command", "", "" }, | 947 { false, None, "command", "", "" }, |
948 { false, None, "command", "ctrl+f", "" }, | 948 { false, None, "command", "Ctrl+f", "" }, |
949 { false, None, "command", "", "description" }, | 949 { false, None, "command", "", "description" }, |
950 // Ctrl+Alt is not permitted, see MSDN link in comments in Parse function. | 950 // Ctrl+Alt is not permitted, see MSDN link in comments in Parse function. |
951 { false, None, "command", "Ctrl+Alt+F", "description" }, | 951 { false, None, "command", "Ctrl+Alt+F", "description" }, |
952 // Unsupported shortcuts/too many. | 952 // Unsupported shortcuts/too many, or missing modifier. |
953 { false, None, "command", "F10", "description" }, | 953 { false, None, "command", "A", "description" }, |
954 { false, None, "command", "Ctrl+1", "description" }, | 954 { false, None, "command", "F10", "description" }, |
955 { false, None, "command", "Ctrl+F+G", "description" }, | 955 { false, None, "command", "Ctrl+1", "description" }, |
| 956 { false, None, "command", "Ctrl+F+G", "description" }, |
| 957 { false, None, "command", "Ctrl+Alt+Shift+G", "description" }, |
956 // Basic tests. | 958 // Basic tests. |
957 { true, CtrlF, "command", "Ctrl+F", "description" }, | 959 { true, CtrlF, "command", "Ctrl+F", "description" }, |
958 { true, ShiftF, "command", "Shift+F", "description" }, | 960 { true, ShiftF, "command", "Shift+F", "description" }, |
959 { true, AltF, "command", "Alt+F", "description" }, | 961 { true, AltF, "command", "Alt+F", "description" }, |
960 { true, CtrlShiftF, "command", "Ctrl+Shift+F", "description" }, | 962 { true, CtrlShiftF, "command", "Ctrl+Shift+F", "description" }, |
961 { true, AltShiftF, "command", "Alt+Shift+F", "description" }, | 963 { true, AltShiftF, "command", "Alt+Shift+F", "description" }, |
962 // Order tests. | 964 // Order tests. |
963 { true, CtrlF, "command", "F+Ctrl", "description" }, | 965 { true, CtrlF, "command", "F+Ctrl", "description" }, |
964 { true, ShiftF, "command", "F+Shift", "description" }, | 966 { true, ShiftF, "command", "F+Shift", "description" }, |
965 { true, AltF, "command", "F+Alt", "description" }, | 967 { true, AltF, "command", "F+Alt", "description" }, |
966 { true, CtrlShiftF, "command", "F+Ctrl+Shift", "description" }, | 968 { true, CtrlShiftF, "command", "F+Ctrl+Shift", "description" }, |
967 { true, CtrlShiftF, "command", "F+Shift+Ctrl", "description" }, | 969 { true, CtrlShiftF, "command", "F+Shift+Ctrl", "description" }, |
968 { true, AltShiftF, "command", "F+Alt+Shift", "description" }, | 970 { true, AltShiftF, "command", "F+Alt+Shift", "description" }, |
969 { true, AltShiftF, "command", "F+Shift+Alt", "description" }, | 971 { true, AltShiftF, "command", "F+Shift+Alt", "description" }, |
970 // Case insensitivity is OK. | 972 // Case insensitivity is not OK. |
971 { true, CtrlF, "command", "Ctrl+F", "description" }, | 973 { false, CtrlF, "command", "Ctrl+f", "description" }, |
972 { true, CtrlF, "command", "cTrL+f", "description" }, | 974 { false, CtrlF, "command", "cTrL+F", "description" }, |
973 // Extra spaces are fine. | |
974 { true, CtrlShiftF, "command", " Ctrl + Shift +F", "description" }, | |
975 // Minus is equivalent to plus. | |
976 { true, CtrlShiftF, "command", "Ctrl+Shift-F", "description" }, | |
977 // Skipping description is OK for browser- and pageActions. | 975 // Skipping description is OK for browser- and pageActions. |
978 { true, CtrlF, "browserAction", "Ctrl+F", "" }, | 976 { true, CtrlF, "_execute_browser_action", "Ctrl+F", "" }, |
979 { true, CtrlF, "pageAction", "Ctrl+F", "" }, | 977 { true, CtrlF, "_execute_page_action", "Ctrl+F", "" }, |
980 }; | 978 }; |
981 | 979 |
982 // TODO(finnur): test Command/Options on Mac when implemented. | 980 // TODO(finnur): test Command/Options on Mac when implemented. |
983 | 981 |
984 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) { | 982 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) { |
| 983 // First parse the command as a simple string. |
985 scoped_ptr<DictionaryValue> command(new DictionaryValue); | 984 scoped_ptr<DictionaryValue> command(new DictionaryValue); |
986 command->SetString("key", kTests[i].key); | 985 command->SetString("suggested_key", kTests[i].key); |
987 command->SetString("description", kTests[i].description); | 986 command->SetString("description", kTests[i].description); |
988 | 987 |
| 988 SCOPED_TRACE(std::string("Command name: |") + kTests[i].command_name + |
| 989 "| key: |" + kTests[i].key + |
| 990 "| description: |" + kTests[i].description + |
| 991 "| index: " + base::IntToString(i)); |
| 992 |
989 Extension::ExtensionKeybinding keybinding; | 993 Extension::ExtensionKeybinding keybinding; |
990 string16 error; | 994 string16 error; |
991 bool result = | 995 bool result = |
992 keybinding.Parse(command.get(), kTests[i].command_name, i, &error); | 996 keybinding.Parse(command.get(), kTests[i].command_name, i, &error); |
993 | 997 |
994 SCOPED_TRACE(std::string("Command name: |") + kTests[i].command_name + | 998 EXPECT_EQ(kTests[i].expected_result, result); |
995 "| key: |" + kTests[i].key + | 999 if (result) { |
996 "| description: |" + kTests[i].description + | 1000 EXPECT_STREQ(kTests[i].description, keybinding.description().c_str()); |
997 "| index: " + base::IntToString(i)); | 1001 EXPECT_STREQ(kTests[i].command_name, keybinding.command_name().c_str()); |
| 1002 EXPECT_EQ(kTests[i].accelerator, keybinding.accelerator()); |
| 1003 } |
| 1004 |
| 1005 // Now parse the command as a dictionary of multiple values. |
| 1006 command.reset(new DictionaryValue); |
| 1007 DictionaryValue* key_dict = new DictionaryValue(); |
| 1008 key_dict->SetString("default", kTests[i].key); |
| 1009 key_dict->SetString("windows", kTests[i].key); |
| 1010 key_dict->SetString("mac", kTests[i].key); |
| 1011 command->Set("suggested_key", key_dict); |
| 1012 command->SetString("description", kTests[i].description); |
| 1013 |
| 1014 result = keybinding.Parse(command.get(), kTests[i].command_name, i, &error); |
998 | 1015 |
999 EXPECT_EQ(kTests[i].expected_result, result); | 1016 EXPECT_EQ(kTests[i].expected_result, result); |
1000 if (result) { | 1017 if (result) { |
1001 EXPECT_STREQ(kTests[i].description, keybinding.description().c_str()); | 1018 EXPECT_STREQ(kTests[i].description, keybinding.description().c_str()); |
1002 EXPECT_STREQ(kTests[i].command_name, keybinding.command_name().c_str()); | 1019 EXPECT_STREQ(kTests[i].command_name, keybinding.command_name().c_str()); |
1003 EXPECT_EQ(kTests[i].accelerator, keybinding.accelerator()); | 1020 EXPECT_EQ(kTests[i].accelerator, keybinding.accelerator()); |
1004 } | 1021 } |
1005 } | 1022 } |
1006 } | 1023 } |
1007 | 1024 |
| 1025 TEST(ExtensionTest, ExtensionKeybindingParsingFallback) { |
| 1026 std::string description = "desc"; |
| 1027 std::string command_name = "foo"; |
| 1028 |
| 1029 // Test that platform specific keys are honored on each platform, despite |
| 1030 // fallback being given. |
| 1031 scoped_ptr<DictionaryValue> command(new DictionaryValue); |
| 1032 DictionaryValue* key_dict = new DictionaryValue(); |
| 1033 key_dict->SetString("default", "Ctrl+Shift+D"); |
| 1034 key_dict->SetString("windows", "Ctrl+Shift+W"); |
| 1035 key_dict->SetString("mac", "Ctrl+Shift+M"); |
| 1036 key_dict->SetString("linux", "Ctrl+Shift+L"); |
| 1037 key_dict->SetString("chromeos", "Ctrl+Shift+C"); |
| 1038 command->Set("suggested_key", key_dict); |
| 1039 command->SetString("description", description); |
| 1040 |
| 1041 Extension::ExtensionKeybinding keybinding; |
| 1042 string16 error; |
| 1043 EXPECT_TRUE(keybinding.Parse(command.get(), command_name, 0, &error)); |
| 1044 EXPECT_STREQ(description.c_str(), keybinding.description().c_str()); |
| 1045 EXPECT_STREQ(command_name.c_str(), keybinding.command_name().c_str()); |
| 1046 |
| 1047 #if defined(OS_WIN) |
| 1048 ui::Accelerator accelerator(ui::VKEY_W, true, true, false); |
| 1049 #elif defined(OS_MACOSX) |
| 1050 ui::Accelerator accelerator(ui::VKEY_M, true, true, false); |
| 1051 #elif defined(OS_CHROMEOS) |
| 1052 ui::Accelerator accelerator(ui::VKEY_C, true, true, false); |
| 1053 #elif defined(OS_LINUX) |
| 1054 ui::Accelerator accelerator(ui::VKEY_L, true, true, false); |
| 1055 #else |
| 1056 ui::Accelerator accelerator(ui::VKEY_D, true, true, false); |
| 1057 #endif |
| 1058 EXPECT_EQ(accelerator, keybinding.accelerator()); |
| 1059 |
| 1060 // Misspell a platform. |
| 1061 key_dict->SetString("windosw", "Ctrl+M"); |
| 1062 EXPECT_FALSE(keybinding.Parse(command.get(), command_name, 0, &error)); |
| 1063 EXPECT_TRUE(key_dict->Remove("windosw", NULL)); |
| 1064 |
| 1065 // Now remove platform specific keys (leaving just "default") and make sure |
| 1066 // every platform falls back to the default. |
| 1067 EXPECT_TRUE(key_dict->Remove("windows", NULL)); |
| 1068 EXPECT_TRUE(key_dict->Remove("mac", NULL)); |
| 1069 EXPECT_TRUE(key_dict->Remove("linux", NULL)); |
| 1070 EXPECT_TRUE(key_dict->Remove("chromeos", NULL)); |
| 1071 EXPECT_TRUE(keybinding.Parse(command.get(), command_name, 0, &error)); |
| 1072 EXPECT_EQ(ui::VKEY_D, keybinding.accelerator().key_code()); |
| 1073 |
| 1074 // Now remove "default", leaving no option but failure. Or, in the words of |
| 1075 // the immortal Adam Savage: "Failure is always an option". |
| 1076 EXPECT_TRUE(key_dict->Remove("default", NULL)); |
| 1077 EXPECT_FALSE(keybinding.Parse(command.get(), command_name, 0, &error)); |
| 1078 |
| 1079 // Now add only a valid platform that we are not running on to make sure devs |
| 1080 // are notified of errors on other platforms. |
| 1081 #if defined(OS_WIN) |
| 1082 key_dict->SetString("mac", "Ctrl+Shift+M"); |
| 1083 #else |
| 1084 key_dict->SetString("windows", "Ctrl+Shift+W"); |
| 1085 #endif |
| 1086 EXPECT_FALSE(keybinding.Parse(command.get(), command_name, 0, &error)); |
| 1087 |
| 1088 // Make sure Mac specific keys are not processed on other platforms. |
| 1089 #if !defined(OS_MACOSX) |
| 1090 key_dict->SetString("windows", "Command+Shift+M"); |
| 1091 EXPECT_FALSE(keybinding.Parse(command.get(), command_name, 0, &error)); |
| 1092 key_dict->SetString("windows", "Options+Shift+M"); |
| 1093 EXPECT_FALSE(keybinding.Parse(command.get(), command_name, 0, &error)); |
| 1094 #endif |
| 1095 } |
| 1096 |
1008 // These last 2 tests don't make sense on Chrome OS, where extension plugins | 1097 // These last 2 tests don't make sense on Chrome OS, where extension plugins |
1009 // are not allowed. | 1098 // are not allowed. |
1010 #if !defined(OS_CHROMEOS) | 1099 #if !defined(OS_CHROMEOS) |
1011 TEST(ExtensionTest, GetSyncTypeExtensionWithPlugin) { | 1100 TEST(ExtensionTest, GetSyncTypeExtensionWithPlugin) { |
1012 scoped_refptr<Extension> extension( | 1101 scoped_refptr<Extension> extension( |
1013 MakeSyncTestExtension(EXTENSION, GURL(), GURL(), | 1102 MakeSyncTestExtension(EXTENSION, GURL(), GURL(), |
1014 Extension::INTERNAL, 1, FilePath())); | 1103 Extension::INTERNAL, 1, FilePath())); |
1015 if (extension) | 1104 if (extension) |
1016 EXPECT_EQ(extension->GetSyncType(), Extension::SYNC_TYPE_NONE); | 1105 EXPECT_EQ(extension->GetSyncType(), Extension::SYNC_TYPE_NONE); |
1017 } | 1106 } |
1018 | 1107 |
1019 TEST(ExtensionTest, GetSyncTypeExtensionWithTwoPlugins) { | 1108 TEST(ExtensionTest, GetSyncTypeExtensionWithTwoPlugins) { |
1020 scoped_refptr<Extension> extension( | 1109 scoped_refptr<Extension> extension( |
1021 MakeSyncTestExtension(EXTENSION, GURL(), GURL(), | 1110 MakeSyncTestExtension(EXTENSION, GURL(), GURL(), |
1022 Extension::INTERNAL, 2, FilePath())); | 1111 Extension::INTERNAL, 2, FilePath())); |
1023 if (extension) | 1112 if (extension) |
1024 EXPECT_EQ(extension->GetSyncType(), Extension::SYNC_TYPE_NONE); | 1113 EXPECT_EQ(extension->GetSyncType(), Extension::SYNC_TYPE_NONE); |
1025 } | 1114 } |
1026 #endif // !defined(OS_CHROMEOS) | 1115 #endif // !defined(OS_CHROMEOS) |
OLD | NEW |