OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/common/extensions/extension_commands.h" | |
6 | |
7 #include "base/memory/scoped_ptr.h" | |
8 #include "base/string_number_conversions.h" | |
9 #include "base/string_util.h" | |
10 #include "base/utf_string_conversions.h" | |
11 #include "base/values.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 | |
14 class ExtensionCommandsTest : public testing::Test { | |
15 }; | |
16 | |
17 TEST(ExtensionCommandsTest, ExtensionCommandParsing) { | |
18 const ui::Accelerator none = ui::Accelerator(); | |
19 const ui::Accelerator shift_f = ui::Accelerator(ui::VKEY_F, | |
20 ui::EF_SHIFT_DOWN); | |
21 const ui::Accelerator ctrl_f = ui::Accelerator(ui::VKEY_F, | |
22 ui::EF_CONTROL_DOWN); | |
23 const ui::Accelerator alt_f = ui::Accelerator(ui::VKEY_F, ui::EF_ALT_DOWN); | |
24 const ui::Accelerator ctrl_shift_f = | |
25 ui::Accelerator(ui::VKEY_F, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN); | |
26 const ui::Accelerator alt_shift_f = | |
27 ui::Accelerator(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN); | |
28 | |
29 const struct { | |
30 bool expected_result; | |
31 ui::Accelerator accelerator; | |
32 const char* command_name; | |
33 const char* key; | |
34 const char* description; | |
35 } kTests[] = { | |
36 // Negative test (one or more missing required fields). We don't need to | |
37 // test |command_name| being blank as it is used as a key in the manifest, | |
38 // so it can't be blank (and we CHECK() when it is). | |
39 { false, none, "command", "", "" }, | |
40 { false, none, "command", "Ctrl+f", "" }, | |
41 { false, none, "command", "", "description" }, | |
42 // Ctrl+Alt is not permitted, see MSDN link in comments in Parse function. | |
43 { false, none, "command", "Ctrl+Alt+F", "description" }, | |
44 // Unsupported shortcuts/too many, or missing modifier. | |
45 { false, none, "command", "A", "description" }, | |
46 { false, none, "command", "F10", "description" }, | |
47 { false, none, "command", "Ctrl+1", "description" }, | |
48 { false, none, "command", "Ctrl+F+G", "description" }, | |
49 { false, none, "command", "Ctrl+Alt+Shift+G", "description" }, | |
50 // Basic tests. | |
51 { true, ctrl_f, "command", "Ctrl+F", "description" }, | |
52 { true, shift_f, "command", "Shift+F", "description" }, | |
53 { true, alt_f, "command", "Alt+F", "description" }, | |
54 { true, ctrl_shift_f, "command", "Ctrl+Shift+F", "description" }, | |
55 { true, alt_shift_f, "command", "Alt+Shift+F", "description" }, | |
56 // Order tests. | |
57 { true, ctrl_f, "command", "F+Ctrl", "description" }, | |
58 { true, shift_f, "command", "F+Shift", "description" }, | |
59 { true, alt_f, "command", "F+Alt", "description" }, | |
60 { true, ctrl_shift_f, "command", "F+Ctrl+Shift", "description" }, | |
61 { true, ctrl_shift_f, "command", "F+Shift+Ctrl", "description" }, | |
62 { true, alt_shift_f, "command", "F+Alt+Shift", "description" }, | |
63 { true, alt_shift_f, "command", "F+Shift+Alt", "description" }, | |
64 // Case insensitivity is not OK. | |
65 { false, ctrl_f, "command", "Ctrl+f", "description" }, | |
66 { false, ctrl_f, "command", "cTrL+F", "description" }, | |
67 // Skipping description is OK for browser- and pageActions. | |
68 { true, ctrl_f, "_execute_browser_action", "Ctrl+F", "" }, | |
69 { true, ctrl_f, "_execute_page_action", "Ctrl+F", "" }, | |
70 }; | |
71 | |
72 // TODO(finnur): test Command/Options on Mac when implemented. | |
73 | |
74 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) { | |
75 // First parse the command as a simple string. | |
76 scoped_ptr<DictionaryValue> input(new DictionaryValue); | |
77 input->SetString("suggested_key", kTests[i].key); | |
78 input->SetString("description", kTests[i].description); | |
79 | |
80 SCOPED_TRACE(std::string("Command name: |") + kTests[i].command_name + | |
81 "| key: |" + kTests[i].key + | |
82 "| description: |" + kTests[i].description + | |
83 "| index: " + base::IntToString(i)); | |
84 | |
85 extensions::Command command; | |
86 string16 error; | |
87 bool result = | |
88 command.Parse(input.get(), kTests[i].command_name, i, &error); | |
89 | |
90 EXPECT_EQ(kTests[i].expected_result, result); | |
91 if (result) { | |
92 EXPECT_STREQ(kTests[i].description, | |
93 UTF16ToASCII(command.description()).c_str()); | |
94 EXPECT_STREQ(kTests[i].command_name, command.command_name().c_str()); | |
95 EXPECT_EQ(kTests[i].accelerator, command.accelerator()); | |
96 } | |
97 | |
98 // Now parse the command as a dictionary of multiple values. | |
99 input.reset(new DictionaryValue); | |
100 DictionaryValue* key_dict = new DictionaryValue(); | |
101 key_dict->SetString("default", kTests[i].key); | |
102 key_dict->SetString("windows", kTests[i].key); | |
103 key_dict->SetString("mac", kTests[i].key); | |
104 input->Set("suggested_key", key_dict); | |
105 input->SetString("description", kTests[i].description); | |
106 | |
107 result = command.Parse(input.get(), kTests[i].command_name, i, &error); | |
108 | |
109 EXPECT_EQ(kTests[i].expected_result, result); | |
110 if (result) { | |
111 EXPECT_STREQ(kTests[i].description, | |
112 UTF16ToASCII(command.description()).c_str()); | |
113 EXPECT_STREQ(kTests[i].command_name, command.command_name().c_str()); | |
114 EXPECT_EQ(kTests[i].accelerator, command.accelerator()); | |
115 } | |
116 } | |
117 } | |
118 | |
119 TEST(ExtensionCommandsTest, ExtensionCommandParsingFallback) { | |
120 std::string description = "desc"; | |
121 std::string command_name = "foo"; | |
122 | |
123 // Test that platform specific keys are honored on each platform, despite | |
124 // fallback being given. | |
125 scoped_ptr<DictionaryValue> input(new DictionaryValue); | |
126 DictionaryValue* key_dict = new DictionaryValue(); | |
127 key_dict->SetString("default", "Ctrl+Shift+D"); | |
128 key_dict->SetString("windows", "Ctrl+Shift+W"); | |
129 key_dict->SetString("mac", "Ctrl+Shift+M"); | |
130 key_dict->SetString("linux", "Ctrl+Shift+L"); | |
131 key_dict->SetString("chromeos", "Ctrl+Shift+C"); | |
132 input->Set("suggested_key", key_dict); | |
133 input->SetString("description", description); | |
134 | |
135 extensions::Command command; | |
136 string16 error; | |
137 EXPECT_TRUE(command.Parse(input.get(), command_name, 0, &error)); | |
138 EXPECT_STREQ(description.c_str(), | |
139 UTF16ToASCII(command.description()).c_str()); | |
140 EXPECT_STREQ(command_name.c_str(), command.command_name().c_str()); | |
141 | |
142 #if defined(OS_WIN) | |
143 ui::Accelerator accelerator(ui::VKEY_W, | |
144 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); | |
145 #elif defined(OS_MACOSX) | |
146 ui::Accelerator accelerator(ui::VKEY_M, | |
147 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); | |
148 #elif defined(OS_CHROMEOS) | |
149 ui::Accelerator accelerator(ui::VKEY_C, | |
150 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); | |
151 #elif defined(OS_LINUX) | |
152 ui::Accelerator accelerator(ui::VKEY_L, | |
153 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); | |
154 #else | |
155 ui::Accelerator accelerator(ui::VKEY_D, | |
156 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); | |
157 #endif | |
158 EXPECT_EQ(accelerator, command.accelerator()); | |
159 | |
160 // Misspell a platform. | |
161 key_dict->SetString("windosw", "Ctrl+M"); | |
162 EXPECT_FALSE(command.Parse(input.get(), command_name, 0, &error)); | |
163 EXPECT_TRUE(key_dict->Remove("windosw", NULL)); | |
164 | |
165 // Now remove platform specific keys (leaving just "default") and make sure | |
166 // every platform falls back to the default. | |
167 EXPECT_TRUE(key_dict->Remove("windows", NULL)); | |
168 EXPECT_TRUE(key_dict->Remove("mac", NULL)); | |
169 EXPECT_TRUE(key_dict->Remove("linux", NULL)); | |
170 EXPECT_TRUE(key_dict->Remove("chromeos", NULL)); | |
171 EXPECT_TRUE(command.Parse(input.get(), command_name, 0, &error)); | |
172 EXPECT_EQ(ui::VKEY_D, command.accelerator().key_code()); | |
173 | |
174 // Now remove "default", leaving no option but failure. Or, in the words of | |
175 // the immortal Adam Savage: "Failure is always an option". | |
176 EXPECT_TRUE(key_dict->Remove("default", NULL)); | |
177 EXPECT_FALSE(command.Parse(input.get(), command_name, 0, &error)); | |
178 | |
179 // Now add only a valid platform that we are not running on to make sure devs | |
180 // are notified of errors on other platforms. | |
181 #if defined(OS_WIN) | |
182 key_dict->SetString("mac", "Ctrl+Shift+M"); | |
183 #else | |
184 key_dict->SetString("windows", "Ctrl+Shift+W"); | |
185 #endif | |
186 EXPECT_FALSE(command.Parse(input.get(), command_name, 0, &error)); | |
187 | |
188 // Make sure Mac specific keys are not processed on other platforms. | |
189 #if !defined(OS_MACOSX) | |
190 key_dict->SetString("windows", "Command+Shift+M"); | |
191 EXPECT_FALSE(command.Parse(input.get(), command_name, 0, &error)); | |
192 key_dict->SetString("windows", "Options+Shift+M"); | |
193 EXPECT_FALSE(command.Parse(input.get(), command_name, 0, &error)); | |
194 #endif | |
195 } | |
OLD | NEW |