Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: chrome/browser/ui/views/accelerator_table_unittest_mac.mm

Issue 2074643003: MacViews: Views accelerators table should match the Cocoa one. (Closed) Base URL: ssh://bitbucket.browser.yandex-team.ru/chromium/src.git@master
Patch Set: Fix spelling in a comment. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 #import "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 #import "ui/events/keycodes/keyboard_code_conversion_mac.h"
16
17 namespace {
tapted 2016/11/01 00:22:50 nit: nest this inside `namespace chrome {` and rem
Peter Kasting 2016/11/01 00:46:21 Note that we're trying to kill the chrome namespac
themblsha 2016/11/01 14:36:25 Is there a crbug for that? I don't feel that I com
Peter Kasting 2016/11/01 18:20:59 Right, you got it. Here's the bug: https://bugs.c
18
19 // operator< inside anonymous namespace will cause compile-time errors.
tapted 2016/11/01 00:22:50 Yeah - it needs to satisfy the requirements of Koe
Peter Kasting 2016/11/01 00:46:22 Can we supply a lambda to the std::set template?
20 struct AcceleratorMappingComparator {
21 bool operator()(const chrome::AcceleratorMapping& lhs,
22 const chrome::AcceleratorMapping& rhs) {
23 return std::tie(lhs.command_id, lhs.keycode, lhs.modifiers) <
24 std::tie(rhs.command_id, rhs.keycode, rhs.modifiers);
25 }
26 };
27
28 using AcceleratorMappingSet =
29 std::set<chrome::AcceleratorMapping, AcceleratorMappingComparator>;
30
31 // If we try to initialize std::set(GetAcceleratorList().begin(),
32 // GetAcceleratorList().end()) we'll crash as we'll get two different copies of
33 // the same vector data.
Peter Kasting 2016/11/01 00:46:22 Nit: I think you could omit this comment (and the
themblsha 2016/11/01 14:36:24 Did it using a lambda. But not sure what's the bes
Peter Kasting 2016/11/01 18:20:59 You mean, storing the comparator lambda in an auto
themblsha 2016/11/02 17:31:37 auto AcceleratorMappingComparator = [](const
Peter Kasting 2016/11/02 17:51:28 It's pretty much a tossup for me. I might tweak a
34 AcceleratorMappingSet FromVector(
35 const std::vector<chrome::AcceleratorMapping>& v) {
36 return AcceleratorMappingSet(v.begin(), v.end());
37 }
38
39 } // namespace
40
41 namespace chrome {
42
43 // Vefifies that only the whitelisted accelerators could have Control key
44 // modifier, while running on macOS.
45 TEST(AcceleratorTableTest, CheckMacOSControlAccelerators) {
46 // Only the accelerators that also work in Cocoa browser are allowed to appear
47 // on this whitelist.
48 const std::set<int> whitelisted_control_shortcuts = {
49 IDC_SELECT_NEXT_TAB,
50 IDC_SELECT_PREVIOUS_TAB,
51 IDC_FULLSCREEN,
52 };
53
54 const std::vector<AcceleratorMapping> accelerator_list(GetAcceleratorList());
55
56 // Control modifier is rarely used on Mac, and all valid uses must be
57 // whitelisted.
58 for (const auto& entry : accelerator_list) {
59 if (whitelisted_control_shortcuts.count(entry.command_id))
60 continue;
61 EXPECT_FALSE(entry.modifiers & ui::EF_CONTROL_DOWN)
62 << "Found non-whitelisted accelerator that contains Control "
63 "modifier: " << entry.command_id;
64 }
65
66 // Test that whitelist is not outdated.
67 for (const auto& whitelist_entry : whitelisted_control_shortcuts) {
68 const auto entry =
69 std::find_if(accelerator_list.begin(), accelerator_list.end(),
70 [whitelist_entry](const AcceleratorMapping& a) {
71 return a.command_id == whitelist_entry &&
72 (a.modifiers & ui::EF_CONTROL_DOWN) != 0;
73 });
74 EXPECT_TRUE(entry != accelerator_list.end())
Peter Kasting 2016/11/01 00:46:21 Nit: Can this use EXPECT_NE? If not, I suggest us
themblsha 2016/11/01 14:36:25 Looks much better, thanks!
75 << "Whitelisted accelerator not found in the actual list: "
76 << whitelist_entry;
77 }
78 }
79
80 // Verifies that Alt-only (or with just Shift) accelerators are not present in
81 // the list.
82 TEST(AcceleratorTableTest, CheckMacOSAltAccelerators) {
83 const int kNonShiftMask =
84 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN;
85 for (const auto& entry : GetAcceleratorList()) {
86 EXPECT_FALSE((entry.modifiers & kNonShiftMask) == ui::EF_ALT_DOWN)
87 << "Found accelerator that uses solely Alt modifier: "
88 << entry.command_id;
89 }
90 }
91
92 // Vefifies that accelerator filtering works correctly and we have an
93 // alternative shortcut for each filtered-out accelerator.
94 TEST(AcceleratorTableTest, CheckMacOSFilteredOutAcceleratorsHaveAlternatives) {
95 // It's okay not to have an alternative accelerator for these commands as
96 // there's no alternative for them in the Cocoa browser.
97 const std::set<int> whitelisted_unique_shortcuts = {
98 IDC_FOCUS_TOOLBAR,
99 IDC_FOCUS_BOOKMARKS,
100 IDC_FOCUS_INFOBARS,
101 IDC_SHOW_APP_MENU,
102 };
103
104 const AcceleratorMappingSet accelerator_list(
Peter Kasting 2016/11/01 00:46:22 Nit: It seems kinda misleading to use "list" in th
themblsha 2016/11/01 14:36:25 Done. I thought that the _list suffix would be fin
105 FromVector(GetAcceleratorList()));
106 const AcceleratorMappingSet full_accelerator_list(
107 FromVector(GetUnfilteredAcceleratorListForTesting()));
108
109 // Ensure that we still have alternative mappings for all filtered-out
110 // accelerators.
111 AcceleratorMappingSet filtered_list(full_accelerator_list);
112 // Remove all accelerators that are present in |accelerator_list|
tapted 2016/11/01 00:22:50 nit: fullstop at end
themblsha 2016/11/01 14:36:25 Done.
113 for (const auto& m : accelerator_list) {
114 filtered_list.erase(m);
tapted 2016/11/01 00:22:50 optional: there's an STL algorithm that will do th
Peter Kasting 2016/11/01 00:46:22 See base::STLSetDifference(), which wraps this in
themblsha 2016/11/01 14:36:25 That's great! There's one big gotcha though: std::
themblsha 2016/11/01 14:36:25 Yeah, I found it in the STL reference and thought
Peter Kasting 2016/11/01 18:20:59 It isn't? Looks allowed to me by the Google style
themblsha 2016/11/02 17:31:37 It says "if your type doesn't have a natural order
Peter Kasting 2016/11/02 17:51:28 Ah, I missed that! Thanks.
115 }
116 EXPECT_GT(filtered_list.size(), 1u);
117
118 for (const auto& removed_entry : filtered_list) {
119 if (whitelisted_unique_shortcuts.count(removed_entry.command_id))
120 continue;
121
122 const auto entry =
123 std::find_if(accelerator_list.begin(), accelerator_list.end(),
124 [&removed_entry](const AcceleratorMapping& m) {
125 return removed_entry.command_id == m.command_id;
126 });
127 EXPECT_TRUE(entry != accelerator_list.end())
128 << "Filtered command doesn't have an alternative mapping: "
129 << removed_entry.command_id;
130 }
131
132 for (const auto& whitelist_entry : whitelisted_unique_shortcuts) {
133 const auto entry =
134 std::find_if(filtered_list.begin(), filtered_list.end(),
135 [&whitelist_entry](const AcceleratorMapping& m) {
136 return whitelist_entry == m.command_id;
137 });
138 EXPECT_TRUE(entry != filtered_list.end())
139 << "Whitelisted accelerator not found in the filtered-out list: "
140 << whitelist_entry;
141 }
142 }
143
144 namespace {
Peter Kasting 2016/11/01 00:46:22 Nit: I don't think there's any style rule on this,
themblsha 2016/11/01 14:36:25 Done.
145
146 void VerifyTable(
147 const KeyboardShortcutData* (*get_keyboard_shortcut_table)(size_t*),
148 const std::string& table_name) {
149 const std::vector<AcceleratorMapping> accelerator_list(GetAcceleratorList());
150
151 size_t num_shortcuts = 0;
152 const KeyboardShortcutData *it = get_keyboard_shortcut_table(&num_shortcuts);
153 for (size_t i = 0; i < num_shortcuts; ++i, ++it) {
154 int modifiers = 0;
155 if (it->command_key)
156 modifiers |= ui::EF_COMMAND_DOWN;
157 if (it->shift_key)
158 modifiers |= ui::EF_SHIFT_DOWN;
159 if (it->cntrl_key)
160 modifiers |= ui::EF_CONTROL_DOWN;
161 if (it->opt_key)
162 modifiers |= ui::EF_ALT_DOWN;
163
164 for (const auto& entry : accelerator_list) {
165 unichar character;
166 unichar shifted_character;
167 const int vkey_code = ui::MacKeyCodeForWindowsKeyCode(
168 entry.keycode, entry.modifiers, &shifted_character, &character);
169
170 if (it->vkey_code) {
171 if (modifiers == entry.modifiers && it->vkey_code == vkey_code &&
172 it->chrome_command == entry.command_id) {
173 EXPECT_TRUE(false) << "Duplicate command: " << entry.command_id
174 << " in table " << table_name;
175 }
176 } else {
177 if (modifiers == entry.modifiers &&
178 (it->key_char == character || it->key_char == shifted_character) &&
179 it->chrome_command == entry.command_id) {
180 EXPECT_TRUE(false) << "Duplicate command: " << entry.command_id
181 << " in table " << table_name;
182 }
183 }
Peter Kasting 2016/11/01 00:46:22 Nit: Not exactly simple, but simpler than this con
themblsha 2016/11/01 14:36:24 Thanks!
184 }
185 }
186 }
187
188 } // namespace
189
190 // Verifies that we're not processing any duplicate accelerators in
191 // global_keyboard_shortcuts_mac.mm functions.
192 TEST(AcceleratorTableTest, CheckNoDuplicatesGlobalKeyboardShortcutsMac) {
193 VerifyTable(GetWindowKeyboardShortcutTable, "WindowKeyboardShortcutTable");
194 VerifyTable(GetDelayedWindowKeyboardShortcutTable,
195 "DelayedWindowKeyboardShortcutTable");
196 VerifyTable(GetBrowserKeyboardShortcutTable, "BrowserKeyboardShortcutTable");
197 }
198
199 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698