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 "base/stl_util.h" |
| 10 #include "build/build_config.h" |
| 11 #include "chrome/app/chrome_command_ids.h" |
| 12 #import "chrome/browser/global_keyboard_shortcuts_mac.h" |
| 13 #include "chrome/browser/ui/views/accelerator_table.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 #include "ui/events/event_constants.h" |
| 16 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" |
| 17 |
| 18 using namespace chrome; |
| 19 |
| 20 namespace { |
| 21 |
| 22 struct KeyboardShortcutDataComparator { |
| 23 bool operator()(const KeyboardShortcutData& lhs, |
| 24 const KeyboardShortcutData& rhs) const { |
| 25 return std::tie(lhs.command_key, lhs.shift_key, lhs.cntrl_key, lhs.opt_key, |
| 26 lhs.vkey_code, lhs.key_char, lhs.chrome_command) < |
| 27 std::tie(rhs.command_key, rhs.shift_key, rhs.cntrl_key, rhs.opt_key, |
| 28 rhs.vkey_code, rhs.key_char, rhs.chrome_command); |
| 29 } |
| 30 }; |
| 31 |
| 32 std::set<KeyboardShortcutData, KeyboardShortcutDataComparator> |
| 33 AsKeyboardShortcutDataSet(const std::vector<AcceleratorMapping>& accelerators) { |
| 34 std::set<KeyboardShortcutData, KeyboardShortcutDataComparator> result; |
| 35 for (auto& entry : accelerators) { |
| 36 unichar character; |
| 37 unichar shifted_character; |
| 38 const int vkey_code = ui::MacKeyCodeForWindowsKeyCode( |
| 39 entry.keycode, entry.modifiers, &shifted_character, |
| 40 &character); |
| 41 |
| 42 result.insert({entry.modifiers & ui::EF_COMMAND_DOWN, |
| 43 entry.modifiers & ui::EF_SHIFT_DOWN, |
| 44 entry.modifiers & ui::EF_CONTROL_DOWN, |
| 45 entry.modifiers & ui::EF_ALT_DOWN, |
| 46 vkey_code, |
| 47 0, |
| 48 entry.command_id}); |
| 49 } |
| 50 return result; |
| 51 } |
| 52 |
| 53 void VerifyHasDuplicates(const std::vector<KeyboardShortcutData>& table, |
| 54 const std::string& table_name) { |
| 55 const auto accelerators(AsKeyboardShortcutDataSet(GetAcceleratorList())); |
| 56 |
| 57 // These accelerators are impossible to migrate to accelerator_table.cc |
| 58 // (crbug.com/25946). |
| 59 const std::set<KeyboardShortcutData, KeyboardShortcutDataComparator> |
| 60 unique_accelerators = { |
| 61 {true, false, false, false, 0, '}', IDC_SELECT_NEXT_TAB}, |
| 62 {true, false, false, false, 0, '{', IDC_SELECT_PREVIOUS_TAB}}; |
| 63 |
| 64 for (const auto& table_entry : table) { |
| 65 if (unique_accelerators.find(table_entry) != unique_accelerators.end()) |
| 66 continue; |
| 67 |
| 68 EXPECT_TRUE(accelerators.find(table_entry) != accelerators.end()) |
| 69 << "Unique command: " << table_entry.chrome_command << " in table " |
| 70 << table_name; |
| 71 } |
| 72 } |
| 73 |
| 74 void VerifyTableDoesntHaveDuplicates( |
| 75 const std::vector<KeyboardShortcutData>& table, |
| 76 const std::string& table_name) { |
| 77 const auto accelerators(AsKeyboardShortcutDataSet(GetAcceleratorList())); |
| 78 |
| 79 for (const auto& table_entry : table) { |
| 80 EXPECT_TRUE(accelerators.find(table_entry) == accelerators.end()) |
| 81 << "Duplicate command: " << table_entry.chrome_command |
| 82 << " in table " << table_name; |
| 83 } |
| 84 } |
| 85 |
| 86 } // namespace |
| 87 |
| 88 // Vefifies that only the whitelisted accelerators could have Control key |
| 89 // modifier, while running on macOS. |
| 90 TEST(AcceleratorTableTest, CheckMacOSControlAccelerators) { |
| 91 // Only the accelerators that also work in Cocoa browser are allowed to appear |
| 92 // on this whitelist. |
| 93 const std::set<int> whitelisted_control_shortcuts = { |
| 94 IDC_SELECT_NEXT_TAB, |
| 95 IDC_SELECT_PREVIOUS_TAB, |
| 96 IDC_FULLSCREEN, |
| 97 }; |
| 98 |
| 99 const std::vector<AcceleratorMapping> accelerators(GetAcceleratorList()); |
| 100 |
| 101 // Control modifier is rarely used on Mac, and all valid uses must be |
| 102 // whitelisted. |
| 103 for (const auto& entry : accelerators) { |
| 104 if (base::ContainsKey(whitelisted_control_shortcuts, entry.command_id)) |
| 105 continue; |
| 106 EXPECT_FALSE(entry.modifiers & ui::EF_CONTROL_DOWN) |
| 107 << "Found non-whitelisted accelerator that contains Control " |
| 108 "modifier: " << entry.command_id; |
| 109 } |
| 110 |
| 111 // Test that whitelist is not outdated. |
| 112 for (const auto& whitelist_entry : whitelisted_control_shortcuts) { |
| 113 const auto entry = |
| 114 std::find_if(accelerators.begin(), accelerators.end(), |
| 115 [whitelist_entry](const AcceleratorMapping& a) { |
| 116 return a.command_id == whitelist_entry && |
| 117 (a.modifiers & ui::EF_CONTROL_DOWN) != 0; |
| 118 }); |
| 119 EXPECT_NE(entry, accelerators.end()) |
| 120 << "Whitelisted accelerator not found in the actual list: " |
| 121 << whitelist_entry; |
| 122 } |
| 123 } |
| 124 |
| 125 // Verifies that Alt-only (or with just Shift) accelerators are not present in |
| 126 // the list. |
| 127 TEST(AcceleratorTableTest, CheckMacOSAltAccelerators) { |
| 128 const int kNonShiftMask = |
| 129 ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN; |
| 130 for (const auto& entry : GetAcceleratorList()) { |
| 131 EXPECT_FALSE((entry.modifiers & kNonShiftMask) == ui::EF_ALT_DOWN) |
| 132 << "Found accelerator that uses solely Alt modifier: " |
| 133 << entry.command_id; |
| 134 } |
| 135 } |
| 136 |
| 137 // Verifies that we're not processing any duplicate accelerators in |
| 138 // global_keyboard_shortcuts_mac.mm functions. |
| 139 TEST(AcceleratorTableTest, CheckNoDuplicatesGlobalKeyboardShortcutsMac) { |
| 140 VerifyHasDuplicates(GetWindowKeyboardShortcutTable(), |
| 141 "WindowKeyboardShortcutTable"); |
| 142 VerifyTableDoesntHaveDuplicates(GetDelayedWindowKeyboardShortcutTable(), |
| 143 "DelayedWindowKeyboardShortcutTable"); |
| 144 VerifyTableDoesntHaveDuplicates(GetBrowserKeyboardShortcutTable(), |
| 145 "BrowserKeyboardShortcutTable"); |
| 146 } |
OLD | NEW |