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/command.h" | 5 #include "chrome/common/extensions/command.h" |
6 | 6 |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
11 #include "base/values.h" | 11 #include "base/values.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
13 | 13 |
14 class CommandTest : public testing::Test { | 14 class CommandTest : public testing::Test { |
15 }; | 15 }; |
16 | 16 |
17 typedef const struct { | |
18 bool expected_result; | |
19 ui::Accelerator accelerator; | |
20 const char* command_name; | |
21 const char* key; | |
22 const char* description; | |
23 } ConstCommandsTestData; | |
24 | |
25 void CheckExpectations(ConstCommandsTestData data, | |
26 int i, | |
27 bool skip_simple_parse, | |
28 bool platform_default, | |
29 bool windows, | |
30 bool mac, | |
31 bool chromeos) { | |
32 scoped_ptr<base::DictionaryValue> input(new base::DictionaryValue); | |
33 extensions::Command command; | |
34 base::string16 error; | |
35 | |
36 // First parse the command as a simple string. | |
37 if (!skip_simple_parse) { | |
38 input->SetString("suggested_key", data.key); | |
39 input->SetString("description", data.description); | |
40 | |
41 SCOPED_TRACE(std::string("Command name: |") + data.command_name + | |
42 "| key: |" + data.key + "| description: |" + data.description + | |
43 "| index: " + base::IntToString(i)); | |
44 | |
45 bool result = command.Parse(input.get(), data.command_name, i, &error); | |
46 | |
47 EXPECT_EQ(data.expected_result, result); | |
48 if (result) { | |
49 EXPECT_STREQ(data.description, | |
50 base::UTF16ToASCII(command.description()).c_str()); | |
51 EXPECT_STREQ(data.command_name, command.command_name().c_str()); | |
52 EXPECT_EQ(data.accelerator, command.accelerator()); | |
53 } | |
54 } | |
55 | |
56 // Now parse the command as a dictionary of multiple values. | |
57 if (data.key[0] != '\0') { | |
58 input.reset(new base::DictionaryValue); | |
59 base::DictionaryValue* key_dict = new base::DictionaryValue(); | |
60 | |
61 if (platform_default) | |
62 key_dict->SetString("default", data.key); | |
63 if (windows) | |
64 key_dict->SetString("windows", data.key); | |
65 if (mac) | |
66 key_dict->SetString("mac", data.key); | |
67 if (chromeos) | |
68 key_dict->SetString("chromeos", data.key); | |
69 | |
70 input->Set("suggested_key", key_dict); | |
71 input->SetString("description", data.description); | |
72 | |
73 bool result = command.Parse(input.get(), data.command_name, i, &error); | |
74 | |
75 EXPECT_EQ(data.expected_result, result); | |
76 if (result) { | |
77 EXPECT_STREQ(data.description, | |
78 base::UTF16ToASCII(command.description()).c_str()); | |
79 EXPECT_STREQ(data.command_name, command.command_name().c_str()); | |
80 EXPECT_EQ(data.accelerator, command.accelerator()); | |
81 } | |
82 } | |
83 } | |
Finnur
2014/08/21 11:18:11
Same here. Version we reviewed before is more up-t
David Tseng
2014/08/21 16:17:56
Acknowledged.
| |
84 | |
17 TEST(CommandTest, ExtensionCommandParsing) { | 85 TEST(CommandTest, ExtensionCommandParsing) { |
18 const ui::Accelerator none = ui::Accelerator(); | 86 const ui::Accelerator none = ui::Accelerator(); |
19 const ui::Accelerator shift_f = ui::Accelerator(ui::VKEY_F, | 87 const ui::Accelerator shift_f = ui::Accelerator(ui::VKEY_F, |
20 ui::EF_SHIFT_DOWN); | 88 ui::EF_SHIFT_DOWN); |
21 #if defined(OS_MACOSX) | 89 #if defined(OS_MACOSX) |
22 int ctrl = ui::EF_COMMAND_DOWN; | 90 int ctrl = ui::EF_COMMAND_DOWN; |
23 #else | 91 #else |
24 int ctrl = ui::EF_CONTROL_DOWN; | 92 int ctrl = ui::EF_CONTROL_DOWN; |
25 #endif | 93 #endif |
26 | 94 |
(...skipping 18 matching lines...) Expand all Loading... | |
45 const ui::Accelerator ctrl_pgdwn = ui::Accelerator(ui::VKEY_NEXT, ctrl); | 113 const ui::Accelerator ctrl_pgdwn = ui::Accelerator(ui::VKEY_NEXT, ctrl); |
46 const ui::Accelerator next_track = | 114 const ui::Accelerator next_track = |
47 ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE); | 115 ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE); |
48 const ui::Accelerator prev_track = | 116 const ui::Accelerator prev_track = |
49 ui::Accelerator(ui::VKEY_MEDIA_PREV_TRACK, ui::EF_NONE); | 117 ui::Accelerator(ui::VKEY_MEDIA_PREV_TRACK, ui::EF_NONE); |
50 const ui::Accelerator play_pause = | 118 const ui::Accelerator play_pause = |
51 ui::Accelerator(ui::VKEY_MEDIA_PLAY_PAUSE, ui::EF_NONE); | 119 ui::Accelerator(ui::VKEY_MEDIA_PLAY_PAUSE, ui::EF_NONE); |
52 const ui::Accelerator stop = | 120 const ui::Accelerator stop = |
53 ui::Accelerator(ui::VKEY_MEDIA_STOP, ui::EF_NONE); | 121 ui::Accelerator(ui::VKEY_MEDIA_STOP, ui::EF_NONE); |
54 | 122 |
55 const struct { | 123 ConstCommandsTestData kTests[] = { |
56 bool expected_result; | 124 // Negative test (one or more missing required fields). We don't need to |
57 ui::Accelerator accelerator; | 125 // test |command_name| being blank as it is used as a key in the manifest, |
58 const char* command_name; | 126 // so it can't be blank (and we CHECK() when it is). A blank shortcut is |
59 const char* key; | 127 // permitted. |
60 const char* description; | 128 {false, none, "command", "", ""}, |
61 } kTests[] = { | 129 {false, none, "command", "Ctrl+f", ""}, |
62 // Negative test (one or more missing required fields). We don't need to | 130 // Ctrl+Alt is not permitted, see MSDN link in comments in Parse function. |
63 // test |command_name| being blank as it is used as a key in the manifest, | 131 {false, none, "command", "Ctrl+Alt+F", "description"}, |
64 // so it can't be blank (and we CHECK() when it is). A blank shortcut is | 132 // Unsupported shortcuts/too many, or missing modifier. |
65 // permitted. | 133 {false, none, "command", "A", "description"}, |
66 { false, none, "command", "", "" }, | 134 {false, none, "command", "F10", "description"}, |
67 { false, none, "command", "Ctrl+f", "" }, | 135 {false, none, "command", "Ctrl+F+G", "description"}, |
68 // Ctrl+Alt is not permitted, see MSDN link in comments in Parse function. | 136 {false, none, "command", "Ctrl+Alt+Shift+G", "description"}, |
69 { false, none, "command", "Ctrl+Alt+F", "description" }, | 137 // Shift on its own is not supported. |
70 // Unsupported shortcuts/too many, or missing modifier. | 138 {false, shift_f, "command", "Shift+F", "description"}, |
71 { false, none, "command", "A", "description" }, | 139 {false, shift_f, "command", "F+Shift", "description"}, |
72 { false, none, "command", "F10", "description" }, | 140 // Basic tests. |
73 { false, none, "command", "Ctrl+F+G", "description" }, | 141 {true, none, "command", "", "description"}, |
74 { false, none, "command", "Ctrl+Alt+Shift+G", "description" }, | 142 {true, ctrl_f, "command", "Ctrl+F", "description"}, |
75 // Shift on its own is not supported. | 143 {true, alt_f, "command", "Alt+F", "description"}, |
76 { false, shift_f, "command", "Shift+F", "description" }, | 144 {true, ctrl_shift_f, "command", "Ctrl+Shift+F", "description"}, |
77 { false, shift_f, "command", "F+Shift", "description" }, | 145 {true, alt_shift_f, "command", "Alt+Shift+F", "description"}, |
78 // Basic tests. | 146 {true, ctrl_1, "command", "Ctrl+1", "description"}, |
79 { true, none, "command", "", "description" }, | 147 // Shortcut token order tests. |
80 { true, ctrl_f, "command", "Ctrl+F", "description" }, | 148 {true, ctrl_f, "command", "F+Ctrl", "description"}, |
81 { true, alt_f, "command", "Alt+F", "description" }, | 149 {true, alt_f, "command", "F+Alt", "description"}, |
82 { true, ctrl_shift_f, "command", "Ctrl+Shift+F", "description" }, | 150 {true, ctrl_shift_f, "command", "F+Ctrl+Shift", "description"}, |
83 { true, alt_shift_f, "command", "Alt+Shift+F", "description" }, | 151 {true, ctrl_shift_f, "command", "F+Shift+Ctrl", "description"}, |
84 { true, ctrl_1, "command", "Ctrl+1", "description" }, | 152 {true, alt_shift_f, "command", "F+Alt+Shift", "description"}, |
85 // Shortcut token order tests. | 153 {true, alt_shift_f, "command", "F+Shift+Alt", "description"}, |
86 { true, ctrl_f, "command", "F+Ctrl", "description" }, | 154 // Case insensitivity is not OK. |
87 { true, alt_f, "command", "F+Alt", "description" }, | 155 {false, ctrl_f, "command", "Ctrl+f", "description"}, |
88 { true, ctrl_shift_f, "command", "F+Ctrl+Shift", "description" }, | 156 {false, ctrl_f, "command", "cTrL+F", "description"}, |
89 { true, ctrl_shift_f, "command", "F+Shift+Ctrl", "description" }, | 157 // Skipping description is OK for browser- and pageActions. |
90 { true, alt_shift_f, "command", "F+Alt+Shift", "description" }, | 158 {true, ctrl_f, "_execute_browser_action", "Ctrl+F", ""}, |
91 { true, alt_shift_f, "command", "F+Shift+Alt", "description" }, | 159 {true, ctrl_f, "_execute_page_action", "Ctrl+F", ""}, |
92 // Case insensitivity is not OK. | 160 // Home, End, Arrow keys, etc. |
93 { false, ctrl_f, "command", "Ctrl+f", "description" }, | 161 {true, ctrl_comma, "_execute_browser_action", "Ctrl+Comma", ""}, |
94 { false, ctrl_f, "command", "cTrL+F", "description" }, | 162 {true, ctrl_dot, "_execute_browser_action", "Ctrl+Period", ""}, |
95 // Skipping description is OK for browser- and pageActions. | 163 {true, ctrl_left, "_execute_browser_action", "Ctrl+Left", ""}, |
96 { true, ctrl_f, "_execute_browser_action", "Ctrl+F", "" }, | 164 {true, ctrl_right, "_execute_browser_action", "Ctrl+Right", ""}, |
97 { true, ctrl_f, "_execute_page_action", "Ctrl+F", "" }, | 165 {true, ctrl_up, "_execute_browser_action", "Ctrl+Up", ""}, |
98 // Home, End, Arrow keys, etc. | 166 {true, ctrl_down, "_execute_browser_action", "Ctrl+Down", ""}, |
99 { true, ctrl_comma, "_execute_browser_action", "Ctrl+Comma", "" }, | 167 {true, ctrl_ins, "_execute_browser_action", "Ctrl+Insert", ""}, |
100 { true, ctrl_dot, "_execute_browser_action", "Ctrl+Period", "" }, | 168 {true, ctrl_del, "_execute_browser_action", "Ctrl+Delete", ""}, |
101 { true, ctrl_left, "_execute_browser_action", "Ctrl+Left", "" }, | 169 {true, ctrl_home, "_execute_browser_action", "Ctrl+Home", ""}, |
102 { true, ctrl_right, "_execute_browser_action", "Ctrl+Right", "" }, | 170 {true, ctrl_end, "_execute_browser_action", "Ctrl+End", ""}, |
103 { true, ctrl_up, "_execute_browser_action", "Ctrl+Up", "" }, | 171 {true, ctrl_pgup, "_execute_browser_action", "Ctrl+PageUp", ""}, |
104 { true, ctrl_down, "_execute_browser_action", "Ctrl+Down", "" }, | 172 {true, ctrl_pgdwn, "_execute_browser_action", "Ctrl+PageDown", ""}, |
105 { true, ctrl_ins, "_execute_browser_action", "Ctrl+Insert", "" }, | 173 // Media keys. |
106 { true, ctrl_del, "_execute_browser_action", "Ctrl+Delete", "" }, | 174 {true, next_track, "command", "MediaNextTrack", "description"}, |
107 { true, ctrl_home, "_execute_browser_action", "Ctrl+Home", "" }, | 175 {true, play_pause, "command", "MediaPlayPause", "description"}, |
108 { true, ctrl_end, "_execute_browser_action", "Ctrl+End", "" }, | 176 {true, prev_track, "command", "MediaPrevTrack", "description"}, |
109 { true, ctrl_pgup, "_execute_browser_action", "Ctrl+PageUp", "" }, | 177 {true, stop, "command", "MediaStop", "description"}, |
110 { true, ctrl_pgdwn, "_execute_browser_action", "Ctrl+PageDown", "" }, | 178 {false, none, "_execute_browser_action", "MediaNextTrack", ""}, |
111 // Media keys. | 179 {false, none, "_execute_page_action", "MediaPrevTrack", ""}, |
112 { true, next_track, "command", "MediaNextTrack", "description" }, | 180 {false, none, "command", "Ctrl+Shift+MediaPrevTrack", "description"}, |
113 { true, play_pause, "command", "MediaPlayPause", "description" }, | |
114 { true, prev_track, "command", "MediaPrevTrack", "description" }, | |
115 { true, stop, "command", "MediaStop", "description" }, | |
116 { false, none, "_execute_browser_action", "MediaNextTrack", "" }, | |
117 { false, none, "_execute_page_action", "MediaPrevTrack", "" }, | |
118 { false, none, "command", "Ctrl+Shift+MediaPrevTrack", "description" }, | |
119 }; | 181 }; |
120 | 182 |
121 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) { | 183 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) { |
122 // First parse the command as a simple string. | 184 CheckExpectations(kTests[i], false, i, true, true, true, true); |
123 scoped_ptr<base::DictionaryValue> input(new base::DictionaryValue); | |
124 input->SetString("suggested_key", kTests[i].key); | |
125 input->SetString("description", kTests[i].description); | |
126 | |
127 SCOPED_TRACE(std::string("Command name: |") + kTests[i].command_name + | |
128 "| key: |" + kTests[i].key + | |
129 "| description: |" + kTests[i].description + | |
130 "| index: " + base::IntToString(i)); | |
131 | |
132 extensions::Command command; | |
133 base::string16 error; | |
134 bool result = | |
135 command.Parse(input.get(), kTests[i].command_name, i, &error); | |
136 | |
137 EXPECT_EQ(kTests[i].expected_result, result); | |
138 if (result) { | |
139 EXPECT_STREQ(kTests[i].description, | |
140 base::UTF16ToASCII(command.description()).c_str()); | |
141 EXPECT_STREQ(kTests[i].command_name, command.command_name().c_str()); | |
142 EXPECT_EQ(kTests[i].accelerator, command.accelerator()); | |
143 } | |
144 | |
145 // Now parse the command as a dictionary of multiple values. | |
146 if (kTests[i].key[0] != '\0') { | |
147 input.reset(new base::DictionaryValue); | |
148 base::DictionaryValue* key_dict = new base::DictionaryValue(); | |
149 key_dict->SetString("default", kTests[i].key); | |
150 key_dict->SetString("windows", kTests[i].key); | |
151 key_dict->SetString("mac", kTests[i].key); | |
152 input->Set("suggested_key", key_dict); | |
153 input->SetString("description", kTests[i].description); | |
154 | |
155 result = command.Parse(input.get(), kTests[i].command_name, i, &error); | |
156 | |
157 EXPECT_EQ(kTests[i].expected_result, result); | |
158 if (result) { | |
159 EXPECT_STREQ(kTests[i].description, | |
160 base::UTF16ToASCII(command.description()).c_str()); | |
161 EXPECT_STREQ(kTests[i].command_name, command.command_name().c_str()); | |
162 EXPECT_EQ(kTests[i].accelerator, command.accelerator()); | |
163 } | |
164 } | |
165 } | 185 } |
166 } | 186 } |
167 | 187 |
168 TEST(CommandTest, ExtensionCommandParsingFallback) { | 188 TEST(CommandTest, ExtensionCommandParsingFallback) { |
169 std::string description = "desc"; | 189 std::string description = "desc"; |
170 std::string command_name = "foo"; | 190 std::string command_name = "foo"; |
171 | 191 |
172 // Test that platform specific keys are honored on each platform, despite | 192 // Test that platform specific keys are honored on each platform, despite |
173 // fallback being given. | 193 // fallback being given. |
174 scoped_ptr<base::DictionaryValue> input(new base::DictionaryValue); | 194 scoped_ptr<base::DictionaryValue> input(new base::DictionaryValue); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 key_dict->SetString("windows", "Ctrl+Shift+W"); | 261 key_dict->SetString("windows", "Ctrl+Shift+W"); |
242 #endif | 262 #endif |
243 EXPECT_FALSE(command.Parse(input.get(), command_name, 0, &error)); | 263 EXPECT_FALSE(command.Parse(input.get(), command_name, 0, &error)); |
244 | 264 |
245 // Make sure Mac specific keys are not processed on other platforms. | 265 // Make sure Mac specific keys are not processed on other platforms. |
246 #if !defined(OS_MACOSX) | 266 #if !defined(OS_MACOSX) |
247 key_dict->SetString("windows", "Command+Shift+M"); | 267 key_dict->SetString("windows", "Command+Shift+M"); |
248 EXPECT_FALSE(command.Parse(input.get(), command_name, 0, &error)); | 268 EXPECT_FALSE(command.Parse(input.get(), command_name, 0, &error)); |
249 #endif | 269 #endif |
250 } | 270 } |
271 | |
272 TEST(CommandTest, ExtensionCommandParsingPlatformSpecific) { | |
273 ui::Accelerator search_shift_z(ui::VKEY_Z, | |
274 ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN); | |
275 | |
276 ConstCommandsTestData kChromeOsTests[] = { | |
277 {true, search_shift_z, "command", "Search+Shift+Z", "description"}, | |
278 {false, search_shift_z, "command", "Command+Shift+Z", "description"}, | |
279 }; | |
280 | |
281 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kChromeOsTests); ++i) { | |
282 // Search is only valid on Chrome OS and default platforms. | |
283 CheckExpectations(kChromeOsTests[i], i, false, true, false, false, true); | |
284 } | |
285 | |
286 ConstCommandsTestData kNonChromeOsSearchTests[] = { | |
287 {false, search_shift_z, "command", "Search+Shift+Z", "description"}, | |
288 }; | |
289 | |
290 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNonChromeOsSearchTests); ++i) { | |
291 // Make sure dictionary parsing fails on Windows and Mac. | |
292 CheckExpectations( | |
293 kNonChromeOsSearchTests[i], i, true, false, true, true, false); | |
294 } | |
295 } | |
OLD | NEW |