| Index: chrome/browser/ui/views/accelerator_table_unittest_mac.mm
|
| diff --git a/chrome/browser/ui/views/accelerator_table_unittest_mac.mm b/chrome/browser/ui/views/accelerator_table_unittest_mac.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5adb4be0b995a4d60aa400fd5cf70dbf1827057a
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/views/accelerator_table_unittest_mac.mm
|
| @@ -0,0 +1,196 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <stddef.h>
|
| +
|
| +#include <set>
|
| +
|
| +#include "build/build_config.h"
|
| +#include "chrome/app/chrome_command_ids.h"
|
| +#include "chrome/browser/global_keyboard_shortcuts_mac.h"
|
| +#include "chrome/browser/ui/views/accelerator_table.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "ui/events/event_constants.h"
|
| +#include "ui/events/keycodes/keyboard_code_conversion_mac.h"
|
| +
|
| +namespace chrome {
|
| +
|
| +// Vefifies that only the whitelisted accelerators could have Control key
|
| +// modifier, while running on macOS.
|
| +TEST(AcceleratorTableTest, CheckMacOSControlAccelerators) {
|
| + // Only the accelerators that also work in Cocoa browser are allowed to appear
|
| + // on this whitelist.
|
| + const std::set<int> whitelisted_control_shortcuts = {
|
| + IDC_SELECT_NEXT_TAB,
|
| + IDC_SELECT_PREVIOUS_TAB,
|
| + IDC_FULLSCREEN,
|
| + };
|
| +
|
| + const std::vector<AcceleratorMapping> accelerator_list(GetAcceleratorList());
|
| +
|
| + // Control modifier is rarely used on Mac, and all valid uses must be
|
| + // whitelisted.
|
| + for (const auto& entry : accelerator_list) {
|
| + if (whitelisted_control_shortcuts.find(entry.command_id) !=
|
| + whitelisted_control_shortcuts.end())
|
| + continue;
|
| + EXPECT_FALSE(entry.modifiers & ui::EF_CONTROL_DOWN)
|
| + << "Found non-whitelisted accelerator that contains Control "
|
| + "modifier: " << entry.command_id;
|
| + }
|
| +
|
| + // Test that whitelist is not outdated.
|
| + for (const auto& whitelist_entry : whitelisted_control_shortcuts) {
|
| + const auto entry =
|
| + std::find_if(accelerator_list.begin(), accelerator_list.end(),
|
| + [whitelist_entry](const AcceleratorMapping& a) {
|
| + return a.command_id == whitelist_entry &&
|
| + a.modifiers & ui::EF_CONTROL_DOWN;
|
| + });
|
| + EXPECT_TRUE(entry != accelerator_list.end())
|
| + << "Whitelisted accelerator not found in the actual list: "
|
| + << whitelist_entry;
|
| + }
|
| +}
|
| +
|
| +// Verifies that Alt-only (or with just Shift) accelerators are not present in
|
| +// the list.
|
| +TEST(AcceleratorTableTest, CheckMacOSAltAccelerators) {
|
| + const int kNonShiftMask =
|
| + ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN;
|
| + for (const auto& entry : GetAcceleratorList()) {
|
| + EXPECT_FALSE((entry.modifiers & kNonShiftMask) == ui::EF_ALT_DOWN)
|
| + << "Found accelerator that uses solely Alt modifier: "
|
| + << entry.command_id;
|
| + }
|
| +}
|
| +
|
| +// Vefifies that accelerator filtering works correctly and we have an
|
| +// alternative shortcut for each filtered-out accelerator.
|
| +TEST(AcceleratorTableTest, CheckMacOSFilteredOutAcceleratorsHaveAlternatives) {
|
| + // It's okay not to have an alternative accelerator for these commands as
|
| + // there's no alternative for them in the Cocoa browser.
|
| + const std::set<int> whitelisted_unique_shortcuts = {
|
| + IDC_FOCUS_TOOLBAR,
|
| + IDC_FOCUS_BOOKMARKS,
|
| + IDC_FOCUS_INFOBARS,
|
| + IDC_SHOW_APP_MENU,
|
| + };
|
| +
|
| + const std::vector<AcceleratorMapping> accelerator_list(GetAcceleratorList());
|
| + const std::vector<AcceleratorMapping> full_accelerator_list(
|
| + GetUnfilteredAcceleratorListForTesting());
|
| +
|
| + // Ensure that we still have alternative mappings for all filtered-out
|
| + // accelerators.
|
| + std::vector<AcceleratorMapping> filtered_list(full_accelerator_list);
|
| + auto remove_start =
|
| + std::remove_if(filtered_list.begin(), filtered_list.end(),
|
| + [&accelerator_list](const AcceleratorMapping& m1) {
|
| + // Remove all accelerators that are present in |accelerator_list|
|
| + return std::find_if(accelerator_list.begin(), accelerator_list.end(),
|
| + [&m1](const AcceleratorMapping& m2) {
|
| + return m1.command_id == m2.command_id &&
|
| + m1.keycode == m2.keycode &&
|
| + m1.modifiers == m2.modifiers;
|
| + }) != accelerator_list.end();
|
| + });
|
| + filtered_list.erase(remove_start, filtered_list.end());
|
| + EXPECT_GT(filtered_list.size(), 1u);
|
| +
|
| + for (const auto& removed_entry : filtered_list) {
|
| + if (whitelisted_unique_shortcuts.find(removed_entry.command_id) !=
|
| + whitelisted_unique_shortcuts.end())
|
| + continue;
|
| +
|
| + const auto entry =
|
| + std::find_if(accelerator_list.begin(), accelerator_list.end(),
|
| + [&removed_entry](const AcceleratorMapping& m) {
|
| + return removed_entry.command_id == m.command_id;
|
| + });
|
| + EXPECT_TRUE(entry != accelerator_list.end())
|
| + << "Filtered command doesn't have an alternative mapping: "
|
| + << removed_entry.command_id;
|
| + }
|
| +
|
| + for (const auto& whitelist_entry : whitelisted_unique_shortcuts) {
|
| + const auto entry =
|
| + std::find_if(filtered_list.begin(), filtered_list.end(),
|
| + [&whitelist_entry](const AcceleratorMapping& m) {
|
| + return whitelist_entry == m.command_id;
|
| + });
|
| + EXPECT_TRUE(entry != filtered_list.end())
|
| + << "Whitelisted accelerator not found in the filtered-out list: "
|
| + << whitelist_entry;
|
| + }
|
| +}
|
| +
|
| +namespace {
|
| +
|
| +static void VerifyTable(
|
| + const KeyboardShortcutData* (*get_keyboard_shortcut_table)(size_t*),
|
| + const std::string& table_name) {
|
| + const std::vector<AcceleratorMapping> accelerator_list(GetAcceleratorList());
|
| +
|
| + size_t num_shortcuts = 0;
|
| + const KeyboardShortcutData *it = get_keyboard_shortcut_table(&num_shortcuts);
|
| + for (size_t i = 0; i < num_shortcuts; ++i, ++it) {
|
| + int modifiers = 0;
|
| + if (it->command_key)
|
| + modifiers |= ui::EF_COMMAND_DOWN;
|
| + if (it->shift_key)
|
| + modifiers |= ui::EF_SHIFT_DOWN;
|
| + if (it->cntrl_key)
|
| + modifiers |= ui::EF_CONTROL_DOWN;
|
| + if (it->opt_key)
|
| + modifiers |= ui::EF_ALT_DOWN;
|
| +
|
| + for (const auto& entry : accelerator_list) {
|
| + unichar character;
|
| + unichar shifted_character;
|
| + const int vkey_code = ui::MacKeyCodeForWindowsKeyCode(
|
| + entry.keycode, entry.modifiers, &shifted_character, &character);
|
| +
|
| + if (it->vkey_code) {
|
| + if (modifiers == entry.modifiers && it->vkey_code == vkey_code &&
|
| + it->chrome_command == entry.command_id) {
|
| + EXPECT_TRUE(false) << "Duplicate command: " << entry.command_id
|
| + << " in table " << table_name;
|
| + }
|
| + } else {
|
| + if (modifiers == entry.modifiers &&
|
| + (it->key_char == character || it->key_char == shifted_character) &&
|
| + it->chrome_command == entry.command_id) {
|
| + EXPECT_TRUE(false) << "Duplicate command: " << entry.command_id
|
| + << " in table " << table_name;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// Verifies that we're not processing any duplicate accelerators in
|
| +// global_keyboard_shortcuts_mac.mm functions.
|
| +TEST(AcceleratorTableTest, CheckNoDuplicatesGlobalKeyboardShortcutsMac) {
|
| + VerifyTable(GetWindowKeyboardShortcutTable, "WindowKeyboardShortcutTable");
|
| + VerifyTable(GetDelayedWindowKeyboardShortcutTable,
|
| + "DelayedWindowKeyboardShortcutTable");
|
| + VerifyTable(GetBrowserKeyboardShortcutTable, "BrowserKeyboardShortcutTable");
|
| +
|
| + // https://cs.chromium.org/chromium/src/ui/content_accelerators/accelerator_util.cc?sq=package:chromium&dr=CSs&rcl=1476256712&l=38
|
| + // ui::Accelerator GetAcceleratorFromNativeWebKeyboardEvent(
|
| + // const content::NativeWebKeyboardEvent& event) {
|
| + // ui::Accelerator accelerator(
|
| + // static_cast<ui::KeyboardCode>(event.windowsKeyCode),
|
| + // GetModifiersFromNativeWebKeyboardEvent(event));
|
| + // if (event.type == blink::WebInputEvent::KeyUp)
|
| + // accelerator.set_type(ui::ET_KEY_RELEASED);
|
| + // return accelerator;
|
| + // }
|
| + // https://cs.chromium.org/chromium/src/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm?sq=package:chromium&dr=CSs
|
| +}
|
| +
|
| +} // namespace chrome
|
|
|