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