OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 <stddef.h> | |
6 | |
7 #include <set> | |
8 | |
9 #include "build/build_config.h" | |
10 #include "chrome/app/chrome_command_ids.h" | |
11 #include "chrome/browser/global_keyboard_shortcuts_mac.h" | |
12 #include "chrome/browser/ui/views/accelerator_table.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 #include "ui/events/event_constants.h" | |
15 #include "ui/events/keycodes/keyboard_code_conversion_mac.h" | |
16 | |
17 namespace chrome { | |
18 | |
19 // Vefifies that only the whitelisted accelerators could have Control key | |
20 // modifier, while running on macOS. | |
21 TEST(AcceleratorTableTest, CheckMacOSControlAccelerators) { | |
22 // Only the accelerators that also work in Cocoa browser are allowed to appear | |
23 // on this whitelist. | |
24 const std::set<int> whitelisted_control_shortcuts = { | |
25 IDC_SELECT_NEXT_TAB, | |
26 IDC_SELECT_PREVIOUS_TAB, | |
27 IDC_FULLSCREEN, | |
28 }; | |
29 | |
30 const std::vector<AcceleratorMapping> accelerator_list(GetAcceleratorList()); | |
31 | |
32 // Control modifier is rarely used on Mac, and all valid uses must be | |
33 // whitelisted. | |
34 for (const auto& entry : accelerator_list) { | |
35 if (whitelisted_control_shortcuts.count(entry.command_id)) | |
36 continue; | |
37 EXPECT_FALSE(entry.modifiers & ui::EF_CONTROL_DOWN) | |
38 << "Found non-whitelisted accelerator that contains Control " | |
39 "modifier: " << entry.command_id; | |
40 } | |
41 | |
42 // Test that whitelist is not outdated. | |
43 for (const auto& whitelist_entry : whitelisted_control_shortcuts) { | |
44 const auto entry = | |
45 std::find_if(accelerator_list.begin(), accelerator_list.end(), | |
46 [whitelist_entry](const AcceleratorMapping& a) { | |
47 return a.command_id == whitelist_entry && | |
48 a.modifiers & ui::EF_CONTROL_DOWN; | |
49 }); | |
50 EXPECT_TRUE(entry != accelerator_list.end()) | |
51 << "Whitelisted accelerator not found in the actual list: " | |
52 << whitelist_entry; | |
53 } | |
54 } | |
55 | |
56 // Verifies that Alt-only (or with just Shift) accelerators are not present in | |
57 // the list. | |
58 TEST(AcceleratorTableTest, CheckMacOSAltAccelerators) { | |
59 const int kNonShiftMask = | |
60 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN; | |
61 for (const auto& entry : GetAcceleratorList()) { | |
62 EXPECT_FALSE((entry.modifiers & kNonShiftMask) == ui::EF_ALT_DOWN) | |
63 << "Found accelerator that uses solely Alt modifier: " | |
64 << entry.command_id; | |
65 } | |
66 } | |
67 | |
68 // Vefifies that accelerator filtering works correctly and we have an | |
69 // alternative shortcut for each filtered-out accelerator. | |
70 TEST(AcceleratorTableTest, CheckMacOSFilteredOutAcceleratorsHaveAlternatives) { | |
71 // It's okay not to have an alternative accelerator for these commands as | |
72 // there's no alternative for them in the Cocoa browser. | |
73 const std::set<int> whitelisted_unique_shortcuts = { | |
74 IDC_FOCUS_TOOLBAR, | |
75 IDC_FOCUS_BOOKMARKS, | |
76 IDC_FOCUS_INFOBARS, | |
77 IDC_SHOW_APP_MENU, | |
78 }; | |
79 | |
80 const std::vector<AcceleratorMapping> accelerator_list(GetAcceleratorList()); | |
81 const std::vector<AcceleratorMapping> full_accelerator_list( | |
82 GetUnfilteredAcceleratorListForTesting()); | |
83 | |
84 // Ensure that we still have alternative mappings for all filtered-out | |
85 // accelerators. | |
86 std::vector<AcceleratorMapping> filtered_list(full_accelerator_list); | |
87 auto remove_start = | |
88 std::remove_if(filtered_list.begin(), filtered_list.end(), | |
89 [&accelerator_list](const AcceleratorMapping& m1) { | |
90 // Remove all accelerators that are present in |accelerator_list| | |
91 return std::find_if(accelerator_list.begin(), accelerator_list.end(), | |
92 [&m1](const AcceleratorMapping& m2) { | |
93 return m1.command_id == m2.command_id && | |
94 m1.keycode == m2.keycode && | |
95 m1.modifiers == m2.modifiers; | |
96 }) != accelerator_list.end(); | |
97 }); | |
98 filtered_list.erase(remove_start, filtered_list.end()); | |
99 EXPECT_GT(filtered_list.size(), 1u); | |
100 | |
101 for (const auto& removed_entry : filtered_list) { | |
102 if (whitelisted_unique_shortcuts.count(removed_entry.command_id)) | |
103 continue; | |
104 | |
105 const auto entry = | |
106 std::find_if(accelerator_list.begin(), accelerator_list.end(), | |
107 [&removed_entry](const AcceleratorMapping& m) { | |
108 return removed_entry.command_id == m.command_id; | |
109 }); | |
110 EXPECT_TRUE(entry != accelerator_list.end()) | |
111 << "Filtered command doesn't have an alternative mapping: " | |
112 << removed_entry.command_id; | |
113 } | |
114 | |
115 for (const auto& whitelist_entry : whitelisted_unique_shortcuts) { | |
116 const auto entry = | |
117 std::find_if(filtered_list.begin(), filtered_list.end(), | |
118 [&whitelist_entry](const AcceleratorMapping& m) { | |
119 return whitelist_entry == m.command_id; | |
120 }); | |
121 EXPECT_TRUE(entry != filtered_list.end()) | |
122 << "Whitelisted accelerator not found in the filtered-out list: " | |
123 << whitelist_entry; | |
124 } | |
125 } | |
126 | |
127 namespace { | |
128 | |
129 static void VerifyTable( | |
130 const KeyboardShortcutData* (*get_keyboard_shortcut_table)(size_t*), | |
131 const std::string& table_name) { | |
132 const std::vector<AcceleratorMapping> accelerator_list(GetAcceleratorList()); | |
133 | |
134 size_t num_shortcuts = 0; | |
135 const KeyboardShortcutData *it = get_keyboard_shortcut_table(&num_shortcuts); | |
136 for (size_t i = 0; i < num_shortcuts; ++i, ++it) { | |
137 int modifiers = 0; | |
138 if (it->command_key) | |
139 modifiers |= ui::EF_COMMAND_DOWN; | |
140 if (it->shift_key) | |
141 modifiers |= ui::EF_SHIFT_DOWN; | |
142 if (it->cntrl_key) | |
143 modifiers |= ui::EF_CONTROL_DOWN; | |
144 if (it->opt_key) | |
145 modifiers |= ui::EF_ALT_DOWN; | |
146 | |
147 for (const auto& entry : accelerator_list) { | |
148 unichar character; | |
149 unichar shifted_character; | |
150 const int vkey_code = ui::MacKeyCodeForWindowsKeyCode( | |
151 entry.keycode, entry.modifiers, &shifted_character, &character); | |
152 | |
153 if (it->vkey_code) { | |
154 if (modifiers == entry.modifiers && it->vkey_code == vkey_code && | |
155 it->chrome_command == entry.command_id) { | |
156 EXPECT_TRUE(false) << "Duplicate command: " << entry.command_id | |
157 << " in table " << table_name; | |
158 } | |
159 } else { | |
160 if (modifiers == entry.modifiers && | |
161 (it->key_char == character || it->key_char == shifted_character) && | |
162 it->chrome_command == entry.command_id) { | |
163 EXPECT_TRUE(false) << "Duplicate command: " << entry.command_id | |
164 << " in table " << table_name; | |
165 } | |
166 } | |
167 } | |
168 } | |
169 } | |
170 | |
171 } // namespace | |
172 | |
173 // Verifies that we're not processing any duplicate accelerators in | |
174 // global_keyboard_shortcuts_mac.mm functions. | |
175 TEST(AcceleratorTableTest, CheckNoDuplicatesGlobalKeyboardShortcutsMac) { | |
176 // VerifyTable(GetWindowKeyboardShortcutTable, "WindowKeyboardShortcutTable"); | |
tapted
2016/10/26 08:40:47
We don't commit commented-out code. I'm guessing t
themblsha
2016/10/26 17:10:03
Yep, I should remove it in the final version. Idea
themblsha
2016/10/28 17:32:22
With the split now all the tables are always used
| |
177 // VerifyTable(GetDelayedWindowKeyboardShortcutTable, | |
178 // "DelayedWindowKeyboardShortcutTable"); | |
179 // VerifyTable(GetBrowserKeyboardShortcutTable, | |
180 // "BrowserKeyboardShortcutTable"); | |
181 VerifyTable(GetMacViewsKeyboardShortcutTable, | |
182 "MacViewsKeyboardShortcutTable"); | |
183 } | |
184 | |
185 } // namespace chrome | |
OLD | NEW |