// Copyright (c) 2012 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 "ash/accelerators/accelerator_controller_impl.h"

#include <utility>

#include "ash/accelerators/accelerator_confirmation_dialog.h"
#include "ash/accelerators/accelerator_table.h"
#include "ash/accelerators/pre_target_accelerator_handler.h"
#include "ash/accessibility/accessibility_controller_impl.h"
#include "ash/accessibility/test_accessibility_controller_client.h"
#include "ash/app_list/app_list_metrics.h"
#include "ash/app_list/test/app_list_test_helper.h"
#include "ash/display/screen_orientation_controller.h"
#include "ash/display/screen_orientation_controller_test_api.h"
#include "ash/ime/ime_controller.h"
#include "ash/ime/mode_indicator_observer.h"
#include "ash/ime/test_ime_controller_client.h"
#include "ash/magnifier/docked_magnifier_controller_impl.h"
#include "ash/magnifier/magnification_controller.h"
#include "ash/media/media_controller_impl.h"
#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/ash_pref_names.h"
#include "ash/public/cpp/ash_switches.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/test/shell_test_api.h"
#include "ash/public/mojom/ime_info.mojom.h"
#include "ash/session/session_controller_impl.h"
#include "ash/session/test_session_controller_client.h"
#include "ash/shell.h"
#include "ash/system/brightness_control_delegate.h"
#include "ash/system/keyboard_brightness_control_delegate.h"
#include "ash/system/power/power_button_controller_test_api.h"
#include "ash/test/ash_test_base.h"
#include "ash/test_media_client.h"
#include "ash/test_screenshot_delegate.h"
#include "ash/wm/lock_state_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/test_session_state_animator.h"
#include "ash/wm/window_positioning_utils.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
#include "base/command_line.h"
#include "base/files/scoped_temp_dir.h"
#include "base/json/json_writer.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "media/base/media_switches.h"
#include "services/media_session/public/cpp/test/test_media_controller.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/base/accelerators/media_keys_util.h"
#include "ui/base/accelerators/test_accelerator_target.h"
#include "ui/base/ime/chromeos/fake_ime_keyboard.h"
#include "ui/base/ime/chromeos/ime_keyboard.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/screen.h"
#include "ui/display/test/display_manager_test_api.h"
#include "ui/events/devices/device_data_manager_test_api.h"
#include "ui/events/event.h"
#include "ui/events/event_sink.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/test/event_generator.h"
#include "ui/message_center/message_center.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_client_view.h"
#include "ui/wm/core/accelerator_filter.h"

namespace ash {

using media_session::mojom::MediaSessionAction;

namespace {

void AddTestImes() {
  mojom::ImeInfoPtr ime1 = mojom::ImeInfo::New();
  ime1->id = "id1";
  mojom::ImeInfoPtr ime2 = mojom::ImeInfo::New();
  ime2->id = "id2";
  std::vector<mojom::ImeInfoPtr> available_imes;
  available_imes.push_back(std::move(ime1));
  available_imes.push_back(std::move(ime2));
  Shell::Get()->ime_controller()->RefreshIme(
      "id1", std::move(available_imes), std::vector<mojom::ImeMenuItemPtr>());
}

ui::Accelerator CreateReleaseAccelerator(ui::KeyboardCode key_code,
                                         int modifiers) {
  ui::Accelerator accelerator(key_code, modifiers);
  accelerator.set_key_state(ui::Accelerator::KeyState::RELEASED);
  return accelerator;
}

class DummyBrightnessControlDelegate : public BrightnessControlDelegate {
 public:
  DummyBrightnessControlDelegate()
      : handle_brightness_down_count_(0), handle_brightness_up_count_(0) {}
  ~DummyBrightnessControlDelegate() override = default;

  void HandleBrightnessDown(const ui::Accelerator& accelerator) override {
    ++handle_brightness_down_count_;
    last_accelerator_ = accelerator;
  }
  void HandleBrightnessUp(const ui::Accelerator& accelerator) override {
    ++handle_brightness_up_count_;
    last_accelerator_ = accelerator;
  }
  void SetBrightnessPercent(double percent, bool gradual) override {}
  void GetBrightnessPercent(
      base::OnceCallback<void(base::Optional<double>)> callback) override {
    std::move(callback).Run(100.0);
  }

  int handle_brightness_down_count() const {
    return handle_brightness_down_count_;
  }
  int handle_brightness_up_count() const { return handle_brightness_up_count_; }
  const ui::Accelerator& last_accelerator() const { return last_accelerator_; }

 private:
  int handle_brightness_down_count_;
  int handle_brightness_up_count_;
  ui::Accelerator last_accelerator_;

  DISALLOW_COPY_AND_ASSIGN(DummyBrightnessControlDelegate);
};

class DummyKeyboardBrightnessControlDelegate
    : public KeyboardBrightnessControlDelegate {
 public:
  DummyKeyboardBrightnessControlDelegate()
      : handle_keyboard_brightness_down_count_(0),
        handle_keyboard_brightness_up_count_(0) {}
  ~DummyKeyboardBrightnessControlDelegate() override = default;

  void HandleKeyboardBrightnessDown(
      const ui::Accelerator& accelerator) override {
    ++handle_keyboard_brightness_down_count_;
    last_accelerator_ = accelerator;
  }

  void HandleKeyboardBrightnessUp(const ui::Accelerator& accelerator) override {
    ++handle_keyboard_brightness_up_count_;
    last_accelerator_ = accelerator;
  }

  int handle_keyboard_brightness_down_count() const {
    return handle_keyboard_brightness_down_count_;
  }

  int handle_keyboard_brightness_up_count() const {
    return handle_keyboard_brightness_up_count_;
  }

  const ui::Accelerator& last_accelerator() const { return last_accelerator_; }

 private:
  int handle_keyboard_brightness_down_count_;
  int handle_keyboard_brightness_up_count_;
  ui::Accelerator last_accelerator_;

  DISALLOW_COPY_AND_ASSIGN(DummyKeyboardBrightnessControlDelegate);
};

}  // namespace

class AcceleratorControllerTest : public AshTestBase {
 public:
  AcceleratorControllerTest() = default;
  ~AcceleratorControllerTest() override = default;

  void SetUp() override {
    AshTestBase::SetUp();
    controller_ = Shell::Get()->accelerator_controller();
    test_api_ =
        std::make_unique<AcceleratorControllerImpl::TestApi>(controller_);
  }

 protected:
  static bool ProcessInController(const ui::Accelerator& accelerator) {
    AcceleratorControllerImpl* controller =
        Shell::Get()->accelerator_controller();
    if (accelerator.key_state() == ui::Accelerator::KeyState::RELEASED) {
      // If the |accelerator| should trigger on release, then we store the
      // pressed version of it first in history then the released one to
      // simulate what happens in reality.
      ui::Accelerator pressed_accelerator = accelerator;
      pressed_accelerator.set_key_state(ui::Accelerator::KeyState::PRESSED);
      controller->accelerator_history()->StoreCurrentAccelerator(
          pressed_accelerator);
    }
    controller->accelerator_history()->StoreCurrentAccelerator(accelerator);
    return controller->Process(accelerator);
  }

  bool ContainsHighContrastNotification() const {
    return nullptr != message_center()->FindVisibleNotificationById(
                          kHighContrastToggleAccelNotificationId);
  }

  bool ContainsDockedMagnifierNotification() const {
    return nullptr != message_center()->FindVisibleNotificationById(
                          kDockedMagnifierToggleAccelNotificationId);
  }

  bool ContainsFullscreenMagnifierNotification() const {
    return nullptr != message_center()->FindVisibleNotificationById(
                          kFullscreenMagnifierToggleAccelNotificationId);
  }

  bool IsConfirmationDialogOpen() {
    return !!(test_api_->GetConfirmationDialog());
  }

  void AcceptConfirmationDialog() {
    DCHECK(test_api_->GetConfirmationDialog());
    test_api_->GetConfirmationDialog()->GetDialogClientView()->AcceptWindow();
  }

  void CancelConfirmationDialog() {
    DCHECK(test_api_->GetConfirmationDialog());
    test_api_->GetConfirmationDialog()->GetDialogClientView()->CancelWindow();
  }

  void RemoveAllNotifications() const {
    message_center()->RemoveAllNotifications(
        false /* by_user */, message_center::MessageCenter::RemoveType::ALL);
  }

  static const ui::Accelerator& GetPreviousAccelerator() {
    return Shell::Get()
        ->accelerator_controller()
        ->accelerator_history()
        ->previous_accelerator();
  }

  static const ui::Accelerator& GetCurrentAccelerator() {
    return Shell::Get()
        ->accelerator_controller()
        ->accelerator_history()
        ->current_accelerator();
  }

  // Several functions to access ExitWarningHandler (as friend).
  static void StubForTest(ExitWarningHandler* ewh) {
    ewh->stub_timer_for_test_ = true;
  }
  static void Reset(ExitWarningHandler* ewh) {
    ewh->state_ = ExitWarningHandler::IDLE;
  }
  static void SimulateTimerExpired(ExitWarningHandler* ewh) {
    ewh->TimerAction();
  }
  static bool is_ui_shown(ExitWarningHandler* ewh) { return !!ewh->widget_; }
  static bool is_idle(ExitWarningHandler* ewh) {
    return ewh->state_ == ExitWarningHandler::IDLE;
  }
  static bool is_exiting(ExitWarningHandler* ewh) {
    return ewh->state_ == ExitWarningHandler::EXITING;
  }

  message_center::MessageCenter* message_center() const {
    return message_center::MessageCenter::Get();
  }

  void SetBrightnessControlDelegate(
      std::unique_ptr<BrightnessControlDelegate> delegate) {
    Shell::Get()->brightness_control_delegate_ = std::move(delegate);
  }

  void SetKeyboardBrightnessControlDelegate(
      std::unique_ptr<KeyboardBrightnessControlDelegate> delegate) {
    Shell::Get()->keyboard_brightness_control_delegate_ = std::move(delegate);
  }

  bool WriteJsonFile(const base::FilePath& file_path,
                     const std::string& json_string) const {
    if (!base::DirectoryExists(file_path.DirName()))
      base::CreateDirectory(file_path.DirName());

    int data_size = static_cast<int>(json_string.size());
    int bytes_written =
        base::WriteFile(file_path, json_string.data(), data_size);
    if (bytes_written != data_size) {
      LOG(ERROR) << " Wrote " << bytes_written << " byte(s) instead of "
                 << data_size << " to " << file_path.value();
      return false;
    }
    return true;
  }

  AcceleratorControllerImpl* controller_ = nullptr;  // Not owned.
  std::unique_ptr<AcceleratorControllerImpl::TestApi> test_api_;

 private:
  DISALLOW_COPY_AND_ASSIGN(AcceleratorControllerTest);
};

// Double press of exit shortcut => exiting
TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestDoublePress) {
  ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
  ui::Accelerator release(press);
  release.set_key_state(ui::Accelerator::KeyState::RELEASED);
  ExitWarningHandler* ewh = controller_->GetExitWarningHandlerForTest();
  ASSERT_TRUE(ewh);
  StubForTest(ewh);
  EXPECT_TRUE(is_idle(ewh));
  EXPECT_FALSE(is_ui_shown(ewh));
  EXPECT_TRUE(ProcessInController(press));
  EXPECT_FALSE(ProcessInController(release));
  EXPECT_FALSE(is_idle(ewh));
  EXPECT_TRUE(is_ui_shown(ewh));
  EXPECT_TRUE(ProcessInController(press));  // second press before timer.
  EXPECT_FALSE(ProcessInController(release));
  SimulateTimerExpired(ewh);
  EXPECT_TRUE(is_exiting(ewh));
  EXPECT_FALSE(is_ui_shown(ewh));
  Reset(ewh);
}

// Single press of exit shortcut before timer => idle
TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestSinglePress) {
  ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
  ui::Accelerator release(press);
  release.set_key_state(ui::Accelerator::KeyState::RELEASED);
  ExitWarningHandler* ewh = controller_->GetExitWarningHandlerForTest();
  ASSERT_TRUE(ewh);
  StubForTest(ewh);
  EXPECT_TRUE(is_idle(ewh));
  EXPECT_FALSE(is_ui_shown(ewh));
  EXPECT_TRUE(ProcessInController(press));
  EXPECT_FALSE(ProcessInController(release));
  EXPECT_FALSE(is_idle(ewh));
  EXPECT_TRUE(is_ui_shown(ewh));
  SimulateTimerExpired(ewh);
  EXPECT_TRUE(is_idle(ewh));
  EXPECT_FALSE(is_ui_shown(ewh));
  Reset(ewh);
}

// Shutdown ash with exit warning bubble open should not crash.
TEST_F(AcceleratorControllerTest, LingeringExitWarningBubble) {
  ExitWarningHandler* ewh = controller_->GetExitWarningHandlerForTest();
  ASSERT_TRUE(ewh);
  StubForTest(ewh);

  // Trigger once to show the bubble.
  ewh->HandleAccelerator();
  EXPECT_FALSE(is_idle(ewh));
  EXPECT_TRUE(is_ui_shown(ewh));

  // Exit ash and there should be no crash
}

TEST_F(AcceleratorControllerTest, Register) {
  ui::TestAcceleratorTarget target;
  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
  const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
  const ui::Accelerator accelerator_c(ui::VKEY_C, ui::EF_NONE);
  const ui::Accelerator accelerator_d(ui::VKEY_D, ui::EF_NONE);

  controller_->Register(
      {accelerator_a, accelerator_b, accelerator_c, accelerator_d}, &target);

  // The registered accelerators are processed.
  EXPECT_TRUE(ProcessInController(accelerator_a));
  EXPECT_TRUE(ProcessInController(accelerator_b));
  EXPECT_TRUE(ProcessInController(accelerator_c));
  EXPECT_TRUE(ProcessInController(accelerator_d));
  EXPECT_EQ(4, target.accelerator_count());
}

TEST_F(AcceleratorControllerTest, RegisterMultipleTarget) {
  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
  ui::TestAcceleratorTarget target1;
  controller_->Register({accelerator_a}, &target1);
  ui::TestAcceleratorTarget target2;
  controller_->Register({accelerator_a}, &target2);

  // If multiple targets are registered with the same accelerator, the target
  // registered later processes the accelerator.
  EXPECT_TRUE(ProcessInController(accelerator_a));
  EXPECT_EQ(0, target1.accelerator_count());
  EXPECT_EQ(1, target2.accelerator_count());
}

TEST_F(AcceleratorControllerTest, Unregister) {
  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
  const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
  ui::TestAcceleratorTarget target;
  controller_->Register({accelerator_a, accelerator_b}, &target);

  // Unregistering a different accelerator does not affect the other
  // accelerator.
  controller_->Unregister(accelerator_b, &target);
  EXPECT_TRUE(ProcessInController(accelerator_a));
  EXPECT_EQ(1, target.accelerator_count());

  // The unregistered accelerator is no longer processed.
  target.ResetCounts();
  controller_->Unregister(accelerator_a, &target);
  EXPECT_FALSE(ProcessInController(accelerator_a));
  EXPECT_EQ(0, target.accelerator_count());
}

TEST_F(AcceleratorControllerTest, UnregisterAll) {
  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
  const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
  ui::TestAcceleratorTarget target1;
  controller_->Register({accelerator_a, accelerator_b}, &target1);
  const ui::Accelerator accelerator_c(ui::VKEY_C, ui::EF_NONE);
  ui::TestAcceleratorTarget target2;
  controller_->Register({accelerator_c}, &target2);
  controller_->UnregisterAll(&target1);

  // All the accelerators registered for |target1| are no longer processed.
  EXPECT_FALSE(ProcessInController(accelerator_a));
  EXPECT_FALSE(ProcessInController(accelerator_b));
  EXPECT_EQ(0, target1.accelerator_count());

  // UnregisterAll with a different target does not affect the other target.
  EXPECT_TRUE(ProcessInController(accelerator_c));
  EXPECT_EQ(1, target2.accelerator_count());
}

TEST_F(AcceleratorControllerTest, Process) {
  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
  ui::TestAcceleratorTarget target1;
  controller_->Register({accelerator_a}, &target1);

  // The registered accelerator is processed.
  EXPECT_TRUE(ProcessInController(accelerator_a));
  EXPECT_EQ(1, target1.accelerator_count());

  // The non-registered accelerator is not processed.
  const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
  EXPECT_FALSE(ProcessInController(accelerator_b));
}

TEST_F(AcceleratorControllerTest, IsRegistered) {
  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
  const ui::Accelerator accelerator_shift_a(ui::VKEY_A, ui::EF_SHIFT_DOWN);
  ui::TestAcceleratorTarget target;
  controller_->Register({accelerator_a}, &target);
  EXPECT_TRUE(controller_->IsRegistered(accelerator_a));
  EXPECT_FALSE(controller_->IsRegistered(accelerator_shift_a));
  controller_->UnregisterAll(&target);
  EXPECT_FALSE(controller_->IsRegistered(accelerator_a));
}

TEST_F(AcceleratorControllerTest, WindowSnap) {
  std::unique_ptr<aura::Window> window(
      CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
  WindowState* window_state = WindowState::Get(window.get());

  window_state->Activate();

  {
    controller_->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_LEFT, {});
    gfx::Rect expected_bounds =
        GetDefaultLeftSnappedWindowBoundsInParent(window.get());
    EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString());
  }
  {
    controller_->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_RIGHT, {});
    gfx::Rect expected_bounds =
        GetDefaultRightSnappedWindowBoundsInParent(window.get());
    EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString());
  }
  {
    gfx::Rect normal_bounds = window_state->GetRestoreBoundsInParent();

    controller_->PerformActionIfEnabled(TOGGLE_MAXIMIZED, {});
    EXPECT_TRUE(window_state->IsMaximized());
    EXPECT_NE(normal_bounds.ToString(), window->bounds().ToString());

    controller_->PerformActionIfEnabled(TOGGLE_MAXIMIZED, {});
    EXPECT_FALSE(window_state->IsMaximized());
    // Window gets restored to its restore bounds since side-maximized state
    // is treated as a "maximized" state.
    EXPECT_EQ(normal_bounds.ToString(), window->bounds().ToString());

    controller_->PerformActionIfEnabled(TOGGLE_MAXIMIZED, {});
    controller_->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_LEFT, {});
    EXPECT_FALSE(window_state->IsMaximized());

    controller_->PerformActionIfEnabled(TOGGLE_MAXIMIZED, {});
    controller_->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_RIGHT, {});
    EXPECT_FALSE(window_state->IsMaximized());

    controller_->PerformActionIfEnabled(TOGGLE_MAXIMIZED, {});
    EXPECT_TRUE(window_state->IsMaximized());
    controller_->PerformActionIfEnabled(WINDOW_MINIMIZE, {});
    EXPECT_FALSE(window_state->IsMaximized());
    EXPECT_TRUE(window_state->IsMinimized());
    window_state->Restore();
    window_state->Activate();
  }
  {
    controller_->PerformActionIfEnabled(WINDOW_MINIMIZE, {});
    EXPECT_TRUE(window_state->IsMinimized());
  }
}

// Tests that window snapping works.
TEST_F(AcceleratorControllerTest, TestRepeatedSnap) {
  std::unique_ptr<aura::Window> window(
      CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));

  WindowState* window_state = WindowState::Get(window.get());
  window_state->Activate();

  // Snap right.
  controller_->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_RIGHT, {});
  gfx::Rect normal_bounds = window_state->GetRestoreBoundsInParent();
  gfx::Rect expected_bounds =
      GetDefaultRightSnappedWindowBoundsInParent(window.get());
  EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString());
  EXPECT_TRUE(window_state->IsSnapped());
  // Snap right again ->> becomes normal.
  controller_->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_RIGHT, {});
  EXPECT_TRUE(window_state->IsNormalStateType());
  EXPECT_EQ(normal_bounds.ToString(), window->bounds().ToString());
  // Snap right.
  controller_->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_RIGHT, {});
  EXPECT_TRUE(window_state->IsSnapped());
  // Snap left.
  controller_->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_LEFT, {});
  EXPECT_TRUE(window_state->IsSnapped());
  expected_bounds = GetDefaultLeftSnappedWindowBoundsInParent(window.get());
  EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString());
  // Snap left again ->> becomes normal.
  controller_->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_LEFT, {});
  EXPECT_TRUE(window_state->IsNormalStateType());
  EXPECT_EQ(normal_bounds.ToString(), window->bounds().ToString());
}

TEST_F(AcceleratorControllerTest, RotateScreen) {
  display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
  display::Display::Rotation initial_rotation =
      GetActiveDisplayRotation(display.id());
  ui::test::EventGenerator* generator = GetEventGenerator();
  AccessibilityControllerImpl* accessibility_controller =
      Shell::Get()->accessibility_controller();

  EXPECT_FALSE(accessibility_controller
                   ->HasDisplayRotationAcceleratorDialogBeenAccepted());
  generator->PressKey(ui::VKEY_BROWSER_REFRESH,
                      ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN);
  generator->ReleaseKey(ui::VKEY_BROWSER_REFRESH,
                        ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN);
  // Dialog should be open.
  EXPECT_TRUE(IsConfirmationDialogOpen());
  // Cancel on the dialog should have no effect.
  CancelConfirmationDialog();
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(accessibility_controller
                   ->HasDisplayRotationAcceleratorDialogBeenAccepted());

  display::Display::Rotation rotation_after_cancel =
      GetActiveDisplayRotation(display.id());
  // Screen rotation should not have been triggered.
  EXPECT_EQ(initial_rotation, rotation_after_cancel);

  // Use short cut again.
  generator->PressKey(ui::VKEY_BROWSER_REFRESH,
                      ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN);
  generator->ReleaseKey(ui::VKEY_BROWSER_REFRESH,
                        ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN);
  EXPECT_TRUE(IsConfirmationDialogOpen());
  AcceptConfirmationDialog();
  base::RunLoop().RunUntilIdle();

  // Dialog should be closed.
  EXPECT_FALSE(IsConfirmationDialogOpen());
  EXPECT_TRUE(accessibility_controller
                  ->HasDisplayRotationAcceleratorDialogBeenAccepted());
  display::Display::Rotation rotation_after_accept =
      GetActiveDisplayRotation(display.id());
  // |new_rotation| is determined by the AcceleratorController.
  EXPECT_NE(initial_rotation, rotation_after_accept);
}

TEST_F(AcceleratorControllerTest, AutoRepeat) {
  ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_CONTROL_DOWN);
  ui::TestAcceleratorTarget target_a;
  controller_->Register({accelerator_a}, &target_a);
  ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_CONTROL_DOWN);
  ui::TestAcceleratorTarget target_b;
  controller_->Register({accelerator_b}, &target_b);

  ui::test::EventGenerator* generator = GetEventGenerator();
  generator->PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
  generator->ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);

  EXPECT_EQ(1, target_a.accelerator_count());
  EXPECT_EQ(0, target_a.accelerator_repeat_count());

  // Long press should generate one
  generator->PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
  generator->PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
  EXPECT_EQ(2, target_a.accelerator_non_repeat_count());
  EXPECT_EQ(1, target_a.accelerator_repeat_count());
  generator->PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
  EXPECT_EQ(2, target_a.accelerator_non_repeat_count());
  EXPECT_EQ(2, target_a.accelerator_repeat_count());
  generator->ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
  EXPECT_EQ(2, target_a.accelerator_non_repeat_count());
  EXPECT_EQ(2, target_a.accelerator_repeat_count());

  // Long press was intercepted by another key press.
  generator->PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
  generator->PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
  generator->PressKey(ui::VKEY_B, ui::EF_CONTROL_DOWN);
  generator->ReleaseKey(ui::VKEY_B, ui::EF_CONTROL_DOWN);
  generator->PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
  generator->PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
  generator->ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);

  EXPECT_EQ(1, target_b.accelerator_non_repeat_count());
  EXPECT_EQ(0, target_b.accelerator_repeat_count());
  EXPECT_EQ(4, target_a.accelerator_non_repeat_count());
  EXPECT_EQ(4, target_a.accelerator_repeat_count());
}

TEST_F(AcceleratorControllerTest, Previous) {
  ui::test::EventGenerator* generator = GetEventGenerator();
  generator->PressKey(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
  generator->ReleaseKey(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);

  EXPECT_EQ(ui::VKEY_VOLUME_MUTE, GetPreviousAccelerator().key_code());
  EXPECT_EQ(ui::EF_NONE, GetPreviousAccelerator().modifiers());

  generator->PressKey(ui::VKEY_TAB, ui::EF_CONTROL_DOWN);
  generator->ReleaseKey(ui::VKEY_TAB, ui::EF_CONTROL_DOWN);

  EXPECT_EQ(ui::VKEY_TAB, GetPreviousAccelerator().key_code());
  EXPECT_EQ(ui::EF_CONTROL_DOWN, GetPreviousAccelerator().modifiers());
}

TEST_F(AcceleratorControllerTest, DontRepeatToggleFullscreen) {
  const AcceleratorData accelerators[] = {
      {true, ui::VKEY_J, ui::EF_ALT_DOWN, TOGGLE_FULLSCREEN},
      {true, ui::VKEY_K, ui::EF_ALT_DOWN, TOGGLE_FULLSCREEN},
  };
  test_api_->RegisterAccelerators(accelerators, base::size(accelerators));

  views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
  params.bounds = gfx::Rect(5, 5, 20, 20);
  views::Widget* widget = new views::Widget;
  params.context = CurrentContext();
  widget->Init(std::move(params));
  widget->Show();
  widget->Activate();
  widget->GetNativeView()->SetProperty(
      aura::client::kResizeBehaviorKey,
      aura::client::kResizeBehaviorCanMaximize);

  ui::test::EventGenerator* generator = GetEventGenerator();
  WindowState* window_state = WindowState::Get(widget->GetNativeView());

  // Toggling not suppressed.
  generator->PressKey(ui::VKEY_J, ui::EF_ALT_DOWN);
  EXPECT_TRUE(window_state->IsFullscreen());

  // The same accelerator - toggling suppressed.
  generator->PressKey(ui::VKEY_J, ui::EF_ALT_DOWN | ui::EF_IS_REPEAT);
  EXPECT_TRUE(window_state->IsFullscreen());

  // Different accelerator.
  generator->PressKey(ui::VKEY_K, ui::EF_ALT_DOWN);
  EXPECT_FALSE(window_state->IsFullscreen());
}

// TODO(oshima): Fix this test to use EventGenerator.
TEST_F(AcceleratorControllerTest, ProcessOnce) {
  // The IME event filter interferes with the basic key event propagation we
  // attempt to do here, so we disable it.
  DisableIME();
  ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
  ui::TestAcceleratorTarget target;
  controller_->Register({accelerator_a}, &target);

  // The accelerator is processed only once.
  ui::EventSink* sink = Shell::GetPrimaryRootWindow()->GetHost()->event_sink();

  ui::KeyEvent key_event1(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
  ui::EventDispatchDetails details = sink->OnEventFromSource(&key_event1);
  EXPECT_TRUE(key_event1.handled() || details.dispatcher_destroyed);

  ui::KeyEvent key_event2('A', ui::VKEY_A, ui::DomCode::NONE, ui::EF_NONE);
  details = sink->OnEventFromSource(&key_event2);
  EXPECT_FALSE(key_event2.handled() || details.dispatcher_destroyed);

  ui::KeyEvent key_event3(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::EF_NONE);
  details = sink->OnEventFromSource(&key_event3);
  EXPECT_FALSE(key_event3.handled() || details.dispatcher_destroyed);
  EXPECT_EQ(1, target.accelerator_count());
}

TEST_F(AcceleratorControllerTest, GlobalAccelerators) {
  // CycleBackward
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
  // CycleForward
  EXPECT_TRUE(
      ProcessInController(ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN)));
  // CycleLinear
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_NONE)));

  // The "Take Screenshot", "Take Partial Screenshot", volume, brightness, and
  // keyboard brightness accelerators are only defined on ChromeOS.
  {
    TestScreenshotDelegate* delegate = GetScreenshotDelegate();
    delegate->set_can_take_screenshot(false);
    EXPECT_TRUE(ProcessInController(
        ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
    EXPECT_TRUE(
        ProcessInController(ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE)));
    EXPECT_TRUE(ProcessInController(ui::Accelerator(
        ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));

    delegate->set_can_take_screenshot(true);
    EXPECT_EQ(0, delegate->handle_take_screenshot_count());
    EXPECT_TRUE(ProcessInController(
        ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
    EXPECT_EQ(1, delegate->handle_take_screenshot_count());
    EXPECT_TRUE(
        ProcessInController(ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE)));
    EXPECT_EQ(2, delegate->handle_take_screenshot_count());
    EXPECT_TRUE(ProcessInController(ui::Accelerator(
        ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
    EXPECT_EQ(2, delegate->handle_take_screenshot_count());
  }
  const ui::Accelerator volume_mute(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
  const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
  const ui::Accelerator volume_up(ui::VKEY_VOLUME_UP, ui::EF_NONE);
  {
    base::UserActionTester user_action_tester;
    ui::AcceleratorHistory* history = controller_->accelerator_history();

    EXPECT_EQ(0, user_action_tester.GetActionCount("Accel_VolumeMute_F8"));
    EXPECT_TRUE(ProcessInController(volume_mute));
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeMute_F8"));
    EXPECT_EQ(volume_mute, history->current_accelerator());

    EXPECT_EQ(0, user_action_tester.GetActionCount("Accel_VolumeDown_F9"));
    EXPECT_TRUE(ProcessInController(volume_down));
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeDown_F9"));
    EXPECT_EQ(volume_down, history->current_accelerator());

    EXPECT_EQ(0, user_action_tester.GetActionCount("Accel_VolumeUp_F10"));
    EXPECT_TRUE(ProcessInController(volume_up));
    EXPECT_EQ(volume_up, history->current_accelerator());
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeUp_F10"));
  }
  // Brightness
  // ui::VKEY_BRIGHTNESS_DOWN/UP are not defined on Windows.
  const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE);
  const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE);
  {
    DummyBrightnessControlDelegate* delegate =
        new DummyBrightnessControlDelegate;
    SetBrightnessControlDelegate(
        std::unique_ptr<BrightnessControlDelegate>(delegate));
    EXPECT_EQ(0, delegate->handle_brightness_down_count());
    EXPECT_TRUE(ProcessInController(brightness_down));
    EXPECT_EQ(1, delegate->handle_brightness_down_count());
    EXPECT_EQ(brightness_down, delegate->last_accelerator());
    EXPECT_EQ(0, delegate->handle_brightness_up_count());
    EXPECT_TRUE(ProcessInController(brightness_up));
    EXPECT_EQ(1, delegate->handle_brightness_up_count());
    EXPECT_EQ(brightness_up, delegate->last_accelerator());
  }

  // Keyboard brightness
  const ui::Accelerator alt_brightness_down(ui::VKEY_BRIGHTNESS_DOWN,
                                            ui::EF_ALT_DOWN);
  const ui::Accelerator alt_brightness_up(ui::VKEY_BRIGHTNESS_UP,
                                          ui::EF_ALT_DOWN);
  {
    EXPECT_TRUE(ProcessInController(alt_brightness_down));
    EXPECT_TRUE(ProcessInController(alt_brightness_up));
    DummyKeyboardBrightnessControlDelegate* delegate =
        new DummyKeyboardBrightnessControlDelegate;
    SetKeyboardBrightnessControlDelegate(
        std::unique_ptr<KeyboardBrightnessControlDelegate>(delegate));
    EXPECT_EQ(0, delegate->handle_keyboard_brightness_down_count());
    EXPECT_TRUE(ProcessInController(alt_brightness_down));
    EXPECT_EQ(1, delegate->handle_keyboard_brightness_down_count());
    EXPECT_EQ(alt_brightness_down, delegate->last_accelerator());
    EXPECT_EQ(0, delegate->handle_keyboard_brightness_up_count());
    EXPECT_TRUE(ProcessInController(alt_brightness_up));
    EXPECT_EQ(1, delegate->handle_keyboard_brightness_up_count());
    EXPECT_EQ(alt_brightness_up, delegate->last_accelerator());
  }

  // Exit
  ExitWarningHandler* ewh = controller_->GetExitWarningHandlerForTest();
  ASSERT_TRUE(ewh);
  StubForTest(ewh);
  EXPECT_TRUE(is_idle(ewh));
  EXPECT_FALSE(is_ui_shown(ewh));
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
  EXPECT_FALSE(is_idle(ewh));
  EXPECT_TRUE(is_ui_shown(ewh));
  SimulateTimerExpired(ewh);
  EXPECT_TRUE(is_idle(ewh));
  EXPECT_FALSE(is_ui_shown(ewh));
  Reset(ewh);

  // New tab
  EXPECT_TRUE(
      ProcessInController(ui::Accelerator(ui::VKEY_T, ui::EF_CONTROL_DOWN)));

  // New incognito window
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));

  // New window
  EXPECT_TRUE(
      ProcessInController(ui::Accelerator(ui::VKEY_N, ui::EF_CONTROL_DOWN)));

  // Restore tab
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));

  // Show task manager
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_COMMAND_DOWN)));

  // Open file manager
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_M, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));

  // Lock screen
  // NOTE: Accelerators that do not work on the lock screen need to be
  // tested before the sequence below is invoked because it causes a side
  // effect of locking the screen.
  EXPECT_TRUE(
      ProcessInController(ui::Accelerator(ui::VKEY_L, ui::EF_COMMAND_DOWN)));

  message_center::MessageCenter::Get()->RemoveAllNotifications(
      false /* by_user */, message_center::MessageCenter::RemoveType::ALL);
}

TEST_F(AcceleratorControllerTest, GlobalAcceleratorsToggleAppList) {
  AccessibilityControllerImpl* accessibility_controller =
      Shell::Get()->accessibility_controller();

  // The press event should not toggle the AppList, the release should instead.
  EXPECT_FALSE(
      ProcessInController(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(ui::VKEY_LWIN, GetCurrentAccelerator().key_code());
  GetAppListTestHelper()->CheckVisibility(false);

  EXPECT_TRUE(ProcessInController(
      CreateReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(true);
  EXPECT_EQ(ui::VKEY_LWIN, GetPreviousAccelerator().key_code());

  // When spoken feedback is on, the AppList should not toggle.
  accessibility_controller->SetSpokenFeedbackEnabled(true,
                                                     A11Y_NOTIFICATION_NONE);
  EXPECT_TRUE(accessibility_controller->spoken_feedback_enabled());
  EXPECT_FALSE(
      ProcessInController(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
  EXPECT_FALSE(ProcessInController(
      CreateReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
  accessibility_controller->SetSpokenFeedbackEnabled(false,
                                                     A11Y_NOTIFICATION_NONE);
  EXPECT_FALSE(accessibility_controller->spoken_feedback_enabled());
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(true);

  // Turning off spoken feedback should allow the AppList to toggle again.
  EXPECT_FALSE(
      ProcessInController(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
  EXPECT_TRUE(ProcessInController(
      CreateReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(false);

  // The press of VKEY_BROWSER_SEARCH should toggle the AppList
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_NONE)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(true);
  EXPECT_FALSE(ProcessInController(
      CreateReleaseAccelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_NONE)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(true);

  // When pressed key is interrupted by mouse, the AppList should not toggle.
  EXPECT_FALSE(
      ProcessInController(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
  controller_->accelerator_history()->InterruptCurrentAccelerator();
  EXPECT_FALSE(ProcessInController(
      CreateReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(true);
}

TEST_F(AcceleratorControllerTest, GlobalAcceleratorsToggleAppListFullscreen) {
  base::HistogramTester histogram_tester;

  int toggle_count_total = 0;
  int toggle_count_regular = 0;
  int toggle_count_fullscreen = 0;

  // Shift+VKEY_BROWSER_SEARCH should toggle the AppList in fullscreen mode.
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_SHIFT_DOWN)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(true);
  GetAppListTestHelper()->CheckState(ash::AppListViewState::kFullscreenAllApps);
  histogram_tester.ExpectTotalCount(kAppListToggleMethodHistogram,
                                    ++toggle_count_total);
  histogram_tester.ExpectBucketCount(kAppListToggleMethodHistogram,
                                     kSearchKeyFullscreen,
                                     ++toggle_count_fullscreen);

  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_SHIFT_DOWN)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(false);

  // Shift+VKEY_BROWSER_SEARCH should transition from peeking to fullscreen
  // mode.
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_NONE)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(true);
  GetAppListTestHelper()->CheckState(ash::AppListViewState::kPeeking);
  histogram_tester.ExpectTotalCount(kAppListToggleMethodHistogram,
                                    ++toggle_count_total);
  histogram_tester.ExpectBucketCount(kAppListToggleMethodHistogram, kSearchKey,
                                     ++toggle_count_regular);

  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_SHIFT_DOWN)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(true);
  GetAppListTestHelper()->CheckState(ash::AppListViewState::kFullscreenAllApps);
  histogram_tester.ExpectTotalCount(kAppListToggleMethodHistogram,
                                    ++toggle_count_total);
  histogram_tester.ExpectBucketCount(kAppListToggleMethodHistogram,
                                     kSearchKeyFullscreen,
                                     ++toggle_count_fullscreen);
  // VKEY_BROWSER_SEARCH (no shift) should not return to peeking, but close the
  // AppList.
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_NONE)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(false);

  // Open AppList in peeking mode and type in the search box.
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_NONE)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(true);
  GetAppListTestHelper()->CheckState(ash::AppListViewState::kPeeking);
  histogram_tester.ExpectTotalCount(kAppListToggleMethodHistogram,
                                    ++toggle_count_total);
  histogram_tester.ExpectBucketCount(kAppListToggleMethodHistogram, kSearchKey,
                                     ++toggle_count_regular);
  ui::test::EventGenerator* generator = GetEventGenerator();
  generator->PressKey(ui::VKEY_0, ui::EF_NONE);
  generator->ReleaseKey(ui::VKEY_0, ui::EF_NONE);
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(true);
  GetAppListTestHelper()->CheckState(ash::AppListViewState::kHalf);
  // Shift+VKEY_BROWSER_SEARCH transitions to FULLSCREEN_SEARCH.
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_SHIFT_DOWN)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(true);
  GetAppListTestHelper()->CheckState(ash::AppListViewState::kFullscreenSearch);
  histogram_tester.ExpectTotalCount(kAppListToggleMethodHistogram,
                                    ++toggle_count_total);
  histogram_tester.ExpectBucketCount(kAppListToggleMethodHistogram,
                                     kSearchKeyFullscreen,
                                     ++toggle_count_fullscreen);

  // Shift+VKEY_BROWSER_SEARCH closes the AppList.
  EXPECT_TRUE(ProcessInController(
      ui::Accelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_SHIFT_DOWN)));
  base::RunLoop().RunUntilIdle();
  GetAppListTestHelper()->CheckVisibility(false);
}

TEST_F(AcceleratorControllerTest, ImeGlobalAccelerators) {
  ASSERT_EQ(0u, Shell::Get()->ime_controller()->available_imes().size());

  // Cycling IME is blocked because there is nothing to switch to.
  ui::Accelerator control_space_down(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
  ui::Accelerator control_space_up(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
  control_space_up.set_key_state(ui::Accelerator::KeyState::RELEASED);
  ui::Accelerator control_shift_space(ui::VKEY_SPACE,
                                      ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN);
  EXPECT_FALSE(ProcessInController(control_space_down));
  EXPECT_FALSE(ProcessInController(control_space_up));
  EXPECT_FALSE(ProcessInController(control_shift_space));

  // Cycling IME works when there are IMEs available.
  AddTestImes();
  EXPECT_TRUE(ProcessInController(control_space_down));
  EXPECT_TRUE(ProcessInController(control_space_up));
  EXPECT_TRUE(ProcessInController(control_shift_space));
}

// TODO(nona|mazda): Remove this when crbug.com/139556 in a better way.
TEST_F(AcceleratorControllerTest, ImeGlobalAcceleratorsWorkaround139556) {
  // The workaround for crbug.com/139556 depends on the fact that we don't
  // use Shift+Alt+Enter/Space with ET_KEY_PRESSED as an accelerator. Test it.
  const ui::Accelerator shift_alt_return_press(
      ui::VKEY_RETURN, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
  EXPECT_FALSE(ProcessInController(shift_alt_return_press));
  const ui::Accelerator shift_alt_space_press(
      ui::VKEY_SPACE, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
  EXPECT_FALSE(ProcessInController(shift_alt_space_press));
}

TEST_F(AcceleratorControllerTest, PreferredReservedAccelerators) {
  // Power key is reserved on chromeos.
  EXPECT_TRUE(
      controller_->IsReserved(ui::Accelerator(ui::VKEY_POWER, ui::EF_NONE)));
  EXPECT_FALSE(
      controller_->IsPreferred(ui::Accelerator(ui::VKEY_POWER, ui::EF_NONE)));

  // ALT+Tab are not reserved but preferred.
  EXPECT_FALSE(
      controller_->IsReserved(ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN)));
  EXPECT_FALSE(controller_->IsReserved(
      ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
  EXPECT_TRUE(
      controller_->IsPreferred(ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN)));
  EXPECT_TRUE(controller_->IsPreferred(
      ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));

  // Others are not reserved nor preferred
  EXPECT_FALSE(
      controller_->IsReserved(ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE)));
  EXPECT_FALSE(controller_->IsPreferred(
      ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE)));
  EXPECT_FALSE(
      controller_->IsReserved(ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE)));
  EXPECT_FALSE(
      controller_->IsPreferred(ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE)));
  EXPECT_FALSE(
      controller_->IsReserved(ui::Accelerator(ui::VKEY_A, ui::EF_NONE)));
  EXPECT_FALSE(
      controller_->IsPreferred(ui::Accelerator(ui::VKEY_A, ui::EF_NONE)));
}

TEST_F(AcceleratorControllerTest, SideVolumeButtonLocation) {
  // |side_volume_button_location_| should be empty when location info file
  // doesn't exist.
  EXPECT_TRUE(test_api_->side_volume_button_location().region.empty());
  EXPECT_TRUE(test_api_->side_volume_button_location().side.empty());

  // Tests that |side_volume_button_location_| is read correctly if the location
  // file exists.
  base::DictionaryValue location;
  location.SetString(AcceleratorControllerImpl::kVolumeButtonRegion,
                     AcceleratorControllerImpl::kVolumeButtonRegionScreen);
  location.SetString(AcceleratorControllerImpl::kVolumeButtonSide,
                     AcceleratorControllerImpl::kVolumeButtonSideLeft);
  std::string json_location;
  base::JSONWriter::Write(location, &json_location);
  base::ScopedTempDir file_tmp_dir;
  ASSERT_TRUE(file_tmp_dir.CreateUniqueTempDir());
  base::FilePath file_path = file_tmp_dir.GetPath().Append("location.json");
  ASSERT_TRUE(WriteJsonFile(file_path, json_location));
  EXPECT_TRUE(base::PathExists(file_path));
  test_api_->SetSideVolumeButtonFilePath(file_path);
  controller_->ParseSideVolumeButtonLocationInfo();
  EXPECT_EQ(AcceleratorControllerImpl::kVolumeButtonRegionScreen,
            test_api_->side_volume_button_location().region);
  EXPECT_EQ(AcceleratorControllerImpl::kVolumeButtonSideLeft,
            test_api_->side_volume_button_location().side);
  base::DeleteFile(file_path, false);
}

// Tests the histogram of volume adjustment in tablet mode.
TEST_F(AcceleratorControllerTest, TabletModeVolumeAdjustHistogram) {
  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  base::HistogramTester histogram_tester;
  const ui::Accelerator kVolumeDown(ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
  const ui::Accelerator kVolumeUp(ui::VKEY_VOLUME_UP, ui::EF_NONE);

  // Disable features::kSwapSideVolumeButtonsForOrientation.
  {
    base::test::ScopedFeatureList scoped_feature_list;
    scoped_feature_list.InitAndDisableFeature(
        features::kSwapSideVolumeButtonsForOrientation);
    EXPECT_FALSE(features::IsSwapSideVolumeButtonsForOrientationEnabled());
    EXPECT_TRUE(
        histogram_tester.GetAllSamples(kTabletCountOfVolumeAdjustType).empty());
    // Starts with volume down but ends with an overall-increased volume.
    ProcessInController(kVolumeDown);
    ProcessInController(kVolumeUp);
    ProcessInController(kVolumeUp);
    EXPECT_TRUE(test_api_->TriggerTabletModeVolumeAdjustTimer());
    EXPECT_FALSE(
        histogram_tester.GetAllSamples(kTabletCountOfVolumeAdjustType).empty());
    histogram_tester.ExpectBucketCount(
        kTabletCountOfVolumeAdjustType,
        TabletModeVolumeAdjustType::kAccidentalAdjustWithSwapDisabled, 1);

    // Starts with volume up and ends with an overall-increased volume.
    ProcessInController(kVolumeUp);
    ProcessInController(kVolumeUp);
    ProcessInController(kVolumeUp);
    EXPECT_TRUE(test_api_->TriggerTabletModeVolumeAdjustTimer());
    histogram_tester.ExpectBucketCount(
        kTabletCountOfVolumeAdjustType,
        TabletModeVolumeAdjustType::kNormalAdjustWithSwapDisabled, 1);
  }

  // Enable features::kSwapSideVolumeButtonsForOrientation.
  {
    base::test::ScopedFeatureList scoped_feature_list;
    scoped_feature_list.InitAndEnableFeature(
        features::kSwapSideVolumeButtonsForOrientation);
    EXPECT_TRUE(features::IsSwapSideVolumeButtonsForOrientationEnabled());
    // Starts with volume up but ends with an overall-decreased volume.
    ProcessInController(kVolumeUp);
    ProcessInController(kVolumeDown);
    ProcessInController(kVolumeDown);
    EXPECT_TRUE(test_api_->TriggerTabletModeVolumeAdjustTimer());
    histogram_tester.ExpectBucketCount(
        kTabletCountOfVolumeAdjustType,
        TabletModeVolumeAdjustType::kAccidentalAdjustWithSwapEnabled, 1);

    // Starts with volume up and ends with an overall-increased volume.
    ProcessInController(kVolumeUp);
    ProcessInController(kVolumeUp);
    ProcessInController(kVolumeUp);
    EXPECT_TRUE(test_api_->TriggerTabletModeVolumeAdjustTimer());
    histogram_tester.ExpectBucketCount(
        kTabletCountOfVolumeAdjustType,
        TabletModeVolumeAdjustType::kNormalAdjustWithSwapEnabled, 1);
  }
}

class SideVolumeButtonAcceleratorTest
    : public AcceleratorControllerTest,
      public testing::WithParamInterface<std::pair<std::string, std::string>> {
 public:
  // Input device id of the side volume button.
  static constexpr int kSideVolumeButtonId = 7;

  SideVolumeButtonAcceleratorTest()
      : region_(GetParam().first), side_(GetParam().second) {}
  ~SideVolumeButtonAcceleratorTest() override = default;

  void SetUp() override {
    AcceleratorControllerTest::SetUp();
    Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
    test_api_->SetSideVolumeButtonLocation(region_, side_);
    ui::DeviceDataManagerTestApi().SetUncategorizedDevices({ui::InputDevice(
        kSideVolumeButtonId, ui::InputDeviceType::INPUT_DEVICE_INTERNAL,
        "cros_ec_buttons")});
    scoped_feature_list_.InitAndEnableFeature(
        features::kSwapSideVolumeButtonsForOrientation);
  }

  bool IsLeftOrRightSide() const {
    return side_ == AcceleratorControllerImpl::kVolumeButtonSideLeft ||
           side_ == AcceleratorControllerImpl::kVolumeButtonSideRight;
  }

  bool IsOnKeyboard() const {
    return region_ == AcceleratorControllerImpl::kVolumeButtonRegionKeyboard;
  }

 private:
  std::string region_, side_;
  base::test::ScopedFeatureList scoped_feature_list_;

  DISALLOW_COPY_AND_ASSIGN(SideVolumeButtonAcceleratorTest);
};

// Tests the the action of side volume button will get flipped in corresponding
// screen orientation.
TEST_P(SideVolumeButtonAcceleratorTest, FlipSideVolumeButtonAction) {
  display::test::ScopedSetInternalDisplayId set_internal(
      display_manager(), GetPrimaryDisplay().id());

  ScreenOrientationControllerTestApi test_api(
      Shell::Get()->screen_orientation_controller());
  // Set the screen orientation to LANDSCAPE_PRIMARY.
  test_api.SetDisplayRotation(display::Display::ROTATE_0,
                              display::Display::RotationSource::ACTIVE);
  EXPECT_EQ(test_api.GetCurrentOrientation(),
            OrientationLockType::kLandscapePrimary);

  base::UserActionTester user_action_tester;
  const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
  ASSERT_EQ(ui::ED_UNKNOWN_DEVICE, volume_down.source_device_id());
  ProcessInController(volume_down);
  // Tests that the VOLUME_DOWN accelerator always goes to decrease the volume
  // if it is not from the side volume button.
  EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeDown_F9"));
  user_action_tester.ResetCounts();

  ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_VOLUME_DOWN,
                     ui::DomCode::VOLUME_DOWN, /*flags=*/0, /*dom_key=*/2099727,
                     base::TimeTicks::Now());
  event.set_source_device_id(kSideVolumeButtonId);
  const ui::Accelerator volume_down_from_side_volume_button(event);
  ProcessInController(volume_down_from_side_volume_button);
  // Tests that the action of side volume button will get flipped in landscape
  // primary if the the button is at the left or right of keyboard.
  if (IsOnKeyboard() && IsLeftOrRightSide())
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeUp_F10"));
  else
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeDown_F9"));
  user_action_tester.ResetCounts();

  // Rotate the screen by 270 degree.
  test_api.SetDisplayRotation(display::Display::ROTATE_270,
                              display::Display::RotationSource::ACTIVE);
  EXPECT_EQ(test_api.GetCurrentOrientation(),
            OrientationLockType::kPortraitPrimary);
  ProcessInController(volume_down_from_side_volume_button);
  // Tests that the action of side volume button will not be flipped in portrait
  // primary if the button is at the left or right of screen. Otherwise, the
  // action will be flipped.
  if (!IsOnKeyboard() && IsLeftOrRightSide())
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeDown_F9"));
  else
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeUp_F10"));
  user_action_tester.ResetCounts();

  // Rotate the screen by 180 degree.
  test_api.SetDisplayRotation(display::Display::ROTATE_180,
                              display::Display::RotationSource::ACTIVE);
  EXPECT_EQ(test_api.GetCurrentOrientation(),
            OrientationLockType::kLandscapeSecondary);
  ProcessInController(volume_down_from_side_volume_button);
  // Tests that the action of side volume button will not be flipped in
  // landscape secondary if the button is at the left or right of keyboard.
  // Otherwise, the action will be flipped.
  if (IsOnKeyboard() && IsLeftOrRightSide())
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeDown_F9"));
  else
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeUp_F10"));
  user_action_tester.ResetCounts();

  // Rotate the screen by 90 degree.
  test_api.SetDisplayRotation(display::Display::ROTATE_90,
                              display::Display::RotationSource::ACTIVE);
  EXPECT_EQ(test_api.GetCurrentOrientation(),
            OrientationLockType::kPortraitSecondary);
  ProcessInController(volume_down_from_side_volume_button);
  // Tests that the action of side volume button will be flipped in portrait
  // secondary if the buttonis at the left or right of screen.
  if (!IsOnKeyboard() && IsLeftOrRightSide())
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeUp_F10"));
  else
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeDown_F9"));
}

INSTANTIATE_TEST_SUITE_P(
    AshSideVolumeButton,
    SideVolumeButtonAcceleratorTest,
    testing::ValuesIn(
        {std::make_pair<std::string, std::string>(
             AcceleratorControllerImpl::kVolumeButtonRegionKeyboard,
             AcceleratorControllerImpl::kVolumeButtonSideLeft),
         std::make_pair<std::string, std::string>(
             AcceleratorControllerImpl::kVolumeButtonRegionKeyboard,
             AcceleratorControllerImpl::kVolumeButtonSideRight),
         std::make_pair<std::string, std::string>(
             AcceleratorControllerImpl::kVolumeButtonRegionKeyboard,
             AcceleratorControllerImpl::kVolumeButtonSideBottom),
         std::make_pair<std::string, std::string>(
             AcceleratorControllerImpl::kVolumeButtonRegionScreen,
             AcceleratorControllerImpl::kVolumeButtonSideLeft),
         std::make_pair<std::string, std::string>(
             AcceleratorControllerImpl::kVolumeButtonRegionScreen,
             AcceleratorControllerImpl::kVolumeButtonSideRight),
         std::make_pair<std::string, std::string>(
             AcceleratorControllerImpl::kVolumeButtonRegionScreen,
             AcceleratorControllerImpl::kVolumeButtonSideTop),
         std::make_pair<std::string, std::string>(
             AcceleratorControllerImpl::kVolumeButtonRegionScreen,
             AcceleratorControllerImpl::kVolumeButtonSideBottom)}));

namespace {

// Tests the TOGGLE_CAPS_LOCK accelerator.
TEST_F(AcceleratorControllerTest, ToggleCapsLockAccelerators) {
  ImeController* controller = Shell::Get()->ime_controller();

  TestImeControllerClient client;
  controller->SetClient(client.CreateInterfacePtr());
  EXPECT_EQ(0, client.set_caps_lock_count_);

  // 1. Press Alt, Press Search, Release Search, Release Alt.
  // Note when you press Alt then press search, the key_code at this point is
  // VKEY_LWIN (for search) and Alt is the modifier.
  const ui::Accelerator press_alt_then_search(ui::VKEY_LWIN, ui::EF_ALT_DOWN);
  EXPECT_FALSE(ProcessInController(press_alt_then_search));
  // When you release Search before Alt, the key_code is still VKEY_LWIN and
  // Alt is still the modifier.
  const ui::Accelerator release_search_before_alt(
      CreateReleaseAccelerator(ui::VKEY_LWIN, ui::EF_ALT_DOWN));
  EXPECT_TRUE(ProcessInController(release_search_before_alt));
  controller->FlushMojoForTesting();
  EXPECT_EQ(1, client.set_caps_lock_count_);
  EXPECT_TRUE(controller->IsCapsLockEnabled());
  controller->UpdateCapsLockState(false);

  // 2. Press Search, Press Alt, Release Search, Release Alt.
  const ui::Accelerator press_search_then_alt(ui::VKEY_MENU,
                                              ui::EF_COMMAND_DOWN);
  EXPECT_FALSE(ProcessInController(press_search_then_alt));
  EXPECT_TRUE(ProcessInController(release_search_before_alt));
  controller->FlushMojoForTesting();
  EXPECT_EQ(2, client.set_caps_lock_count_);
  EXPECT_TRUE(controller->IsCapsLockEnabled());
  controller->UpdateCapsLockState(false);

  // 3. Press Alt, Press Search, Release Alt, Release Search.
  EXPECT_FALSE(ProcessInController(press_alt_then_search));
  const ui::Accelerator release_alt_before_search(
      CreateReleaseAccelerator(ui::VKEY_MENU, ui::EF_COMMAND_DOWN));
  EXPECT_TRUE(ProcessInController(release_alt_before_search));
  controller->FlushMojoForTesting();
  EXPECT_EQ(3, client.set_caps_lock_count_);
  EXPECT_TRUE(controller->IsCapsLockEnabled());
  controller->UpdateCapsLockState(false);

  // 4. Press Search, Press Alt, Release Alt, Release Search.
  EXPECT_FALSE(ProcessInController(press_search_then_alt));
  EXPECT_TRUE(ProcessInController(release_alt_before_search));
  controller->FlushMojoForTesting();
  EXPECT_EQ(4, client.set_caps_lock_count_);
  EXPECT_TRUE(controller->IsCapsLockEnabled());
  controller->UpdateCapsLockState(false);

  // 5. Press M, Press Alt, Press Search, Release Alt. After that CapsLock
  // should not be triggered. https://crbug.com/789283
  ui::test::EventGenerator* generator = GetEventGenerator();
  generator->PressKey(ui::VKEY_M, ui::EF_NONE);
  generator->PressKey(ui::VKEY_MENU, ui::EF_NONE);
  generator->PressKey(ui::VKEY_LWIN, ui::EF_ALT_DOWN);
  generator->ReleaseKey(ui::VKEY_MENU, ui::EF_COMMAND_DOWN);
  controller->FlushMojoForTesting();
  EXPECT_FALSE(controller->IsCapsLockEnabled());
  controller->UpdateCapsLockState(false);
  generator->ReleaseKey(ui::VKEY_M, ui::EF_NONE);
  generator->ReleaseKey(ui::VKEY_LWIN, ui::EF_ALT_DOWN);

  // 6. Toggle CapsLock shortcut should still work after the partial screenshot
  // shortcut is used. (https://crbug.com/920030)
  {
    TestScreenshotDelegate* delegate = GetScreenshotDelegate();
    delegate->set_can_take_screenshot(true);

    EXPECT_EQ(0, delegate->handle_take_partial_screenshot_count());

    // Press Ctrl+Shift+F5 then release to enter the partial screenshot session.
    const ui::Accelerator press_partial_screenshot_shortcut(
        ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
    EXPECT_TRUE(ProcessInController(press_partial_screenshot_shortcut));
    const ui::Accelerator release_partial_screenshot_shortcut =
        CreateReleaseAccelerator(ui::VKEY_MEDIA_LAUNCH_APP1,
                                 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
    EXPECT_FALSE(ProcessInController(release_partial_screenshot_shortcut));

    // Press mouse left button, move mouse and release mouse button. Then
    // the partial screenshot is taken.
    generator->MoveMouseTo(0, 0);
    generator->PressLeftButton();
    generator->MoveMouseTo(10, 10);
    generator->ReleaseLeftButton();
    EXPECT_EQ(1, delegate->handle_take_partial_screenshot_count());

    // Press Search, Press Alt, Release Search, Release Alt. CapsLock should be
    // triggered.
    EXPECT_FALSE(ProcessInController(press_search_then_alt));
    EXPECT_TRUE(ProcessInController(release_search_before_alt));
    controller->FlushMojoForTesting();
    EXPECT_EQ(5, client.set_caps_lock_count_);
    EXPECT_TRUE(controller->IsCapsLockEnabled());
    controller->UpdateCapsLockState(false);
  }

  // 7. Toggle CapsLock shortcut should still work after fake events generated.
  // (https://crbug.com/918317).
  generator->PressKey(ui::VKEY_PROCESSKEY, ui::EF_IME_FABRICATED_KEY);
  generator->ReleaseKey(ui::VKEY_UNKNOWN, ui::EF_IME_FABRICATED_KEY);

  // Press Search, Press Alt, Release Search, Release Alt. CapsLock should be
  // triggered.
  EXPECT_FALSE(ProcessInController(press_search_then_alt));
  EXPECT_TRUE(ProcessInController(release_search_before_alt));
  controller->FlushMojoForTesting();
  EXPECT_EQ(6, client.set_caps_lock_count_);
  EXPECT_TRUE(controller->IsCapsLockEnabled());
  controller->UpdateCapsLockState(false);
}

class PreferredReservedAcceleratorsTest : public AshTestBase {
 public:
  PreferredReservedAcceleratorsTest() = default;
  ~PreferredReservedAcceleratorsTest() override = default;

  // AshTestBase:
  void SetUp() override {
    AshTestBase::SetUp();
    Shell::Get()->lock_state_controller()->set_animator_for_test(
        new TestSessionStateAnimator);
    Shell::Get()->power_button_controller()->OnGetSwitchStates(
        chromeos::PowerManagerClient::SwitchStates{
            chromeos::PowerManagerClient::LidState::OPEN,
            chromeos::PowerManagerClient::TabletMode::ON});
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(PreferredReservedAcceleratorsTest);
};

}  // namespace

TEST_F(PreferredReservedAcceleratorsTest, AcceleratorsWithFullscreen) {
  aura::Window* w1 = CreateTestWindowInShellWithId(0);
  aura::Window* w2 = CreateTestWindowInShellWithId(1);
  wm::ActivateWindow(w1);

  WMEvent fullscreen(WM_EVENT_FULLSCREEN);
  WindowState* w1_state = WindowState::Get(w1);
  w1_state->OnWMEvent(&fullscreen);
  ASSERT_TRUE(w1_state->IsFullscreen());

  ui::test::EventGenerator* generator = GetEventGenerator();

  // Power key (reserved) should always be handled.
  Shell::Get()->power_button_controller()->OnTabletModeStarted();
  PowerButtonControllerTestApi test_api(
      Shell::Get()->power_button_controller());
  EXPECT_FALSE(test_api.PowerButtonMenuTimerIsRunning());
  generator->PressKey(ui::VKEY_POWER, ui::EF_NONE);
  EXPECT_TRUE(test_api.PowerButtonMenuTimerIsRunning());

  auto press_and_release_alt_tab = [&generator]() {
    generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
    // Release the alt key to trigger the window activation.
    generator->ReleaseKey(ui::VKEY_MENU, ui::EF_NONE);
  };

  // A fullscreen window can consume ALT-TAB (preferred).
  ASSERT_EQ(w1, window_util::GetActiveWindow());
  press_and_release_alt_tab();
  ASSERT_EQ(w1, window_util::GetActiveWindow());
  ASSERT_NE(w2, window_util::GetActiveWindow());

  // ALT-TAB is non repeatable. Press A to cancel the
  // repeat record.
  generator->PressKey(ui::VKEY_A, ui::EF_NONE);
  generator->ReleaseKey(ui::VKEY_A, ui::EF_NONE);

  // A normal window shouldn't consume preferred accelerator.
  WMEvent normal(WM_EVENT_NORMAL);
  w1_state->OnWMEvent(&normal);
  ASSERT_FALSE(w1_state->IsFullscreen());

  EXPECT_EQ(w1, window_util::GetActiveWindow());
  press_and_release_alt_tab();
  ASSERT_NE(w1, window_util::GetActiveWindow());
  ASSERT_EQ(w2, window_util::GetActiveWindow());
}

TEST_F(PreferredReservedAcceleratorsTest, AcceleratorsWithPinned) {
  aura::Window* w1 = CreateTestWindowInShellWithId(0);
  aura::Window* w2 = CreateTestWindowInShellWithId(1);
  wm::ActivateWindow(w1);

  {
    WMEvent pin_event(WM_EVENT_PIN);
    WindowState* w1_state = WindowState::Get(w1);
    w1_state->OnWMEvent(&pin_event);
    ASSERT_TRUE(w1_state->IsPinned());
  }

  ui::test::EventGenerator* generator = GetEventGenerator();

  // Power key (reserved) should always be handled.
  Shell::Get()->power_button_controller()->OnTabletModeStarted();
  PowerButtonControllerTestApi test_api(
      Shell::Get()->power_button_controller());
  EXPECT_FALSE(test_api.PowerButtonMenuTimerIsRunning());
  generator->PressKey(ui::VKEY_POWER, ui::EF_NONE);
  EXPECT_TRUE(test_api.PowerButtonMenuTimerIsRunning());

  // A pinned window can consume ALT-TAB (preferred), but no side effect.
  ASSERT_EQ(w1, window_util::GetActiveWindow());
  generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  generator->ReleaseKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  ASSERT_EQ(w1, window_util::GetActiveWindow());
  ASSERT_NE(w2, window_util::GetActiveWindow());
}

TEST_F(AcceleratorControllerTest, DisallowedAtModalWindow) {
  std::set<AcceleratorAction> all_actions;
  for (size_t i = 0; i < kAcceleratorDataLength; ++i)
    all_actions.insert(kAcceleratorData[i].action);
  std::set<AcceleratorAction> all_debug_actions;
  for (size_t i = 0; i < kDebugAcceleratorDataLength; ++i)
    all_debug_actions.insert(kDebugAcceleratorData[i].action);
  std::set<AcceleratorAction> all_dev_actions;
  for (size_t i = 0; i < kDeveloperAcceleratorDataLength; ++i)
    all_dev_actions.insert(kDeveloperAcceleratorData[i].action);

  std::set<AcceleratorAction> actionsAllowedAtModalWindow;
  for (size_t k = 0; k < kActionsAllowedAtModalWindowLength; ++k)
    actionsAllowedAtModalWindow.insert(kActionsAllowedAtModalWindow[k]);
  for (const auto& action : actionsAllowedAtModalWindow) {
    EXPECT_TRUE(all_actions.find(action) != all_actions.end() ||
                all_debug_actions.find(action) != all_debug_actions.end() ||
                all_dev_actions.find(action) != all_dev_actions.end())
        << " action from kActionsAllowedAtModalWindow"
        << " not found in kAcceleratorData, kDebugAcceleratorData or"
        << " kDeveloperAcceleratorData action: " << action;
  }
  std::unique_ptr<aura::Window> window(
      CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
  wm::ActivateWindow(window.get());
  ShellTestApi().SimulateModalWindowOpenForTest(true);
  for (const auto& action : all_actions) {
    if (actionsAllowedAtModalWindow.find(action) ==
        actionsAllowedAtModalWindow.end()) {
      EXPECT_TRUE(controller_->PerformActionIfEnabled(action, {}))
          << " for action (disallowed at modal window): " << action;
    }
  }
  //  Testing of top row (F5-F10) accelerators that should still work
  //  when a modal window is open
  //
  // Screenshot
  {
    TestScreenshotDelegate* delegate = GetScreenshotDelegate();
    delegate->set_can_take_screenshot(false);
    EXPECT_TRUE(ProcessInController(
        ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
    EXPECT_TRUE(
        ProcessInController(ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE)));
    EXPECT_TRUE(ProcessInController(ui::Accelerator(
        ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
    delegate->set_can_take_screenshot(true);
    EXPECT_EQ(0, delegate->handle_take_screenshot_count());
    EXPECT_TRUE(ProcessInController(
        ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
    EXPECT_EQ(1, delegate->handle_take_screenshot_count());
    EXPECT_TRUE(
        ProcessInController(ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE)));
    EXPECT_EQ(2, delegate->handle_take_screenshot_count());
    EXPECT_TRUE(ProcessInController(ui::Accelerator(
        ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
    EXPECT_EQ(2, delegate->handle_take_screenshot_count());
  }
  // Brightness
  const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE);
  const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE);
  {
    DummyBrightnessControlDelegate* delegate =
        new DummyBrightnessControlDelegate;
    SetBrightnessControlDelegate(
        std::unique_ptr<BrightnessControlDelegate>(delegate));
    EXPECT_EQ(0, delegate->handle_brightness_down_count());
    EXPECT_TRUE(ProcessInController(brightness_down));
    EXPECT_EQ(1, delegate->handle_brightness_down_count());
    EXPECT_EQ(brightness_down, delegate->last_accelerator());
    EXPECT_EQ(0, delegate->handle_brightness_up_count());
    EXPECT_TRUE(ProcessInController(brightness_up));
    EXPECT_EQ(1, delegate->handle_brightness_up_count());
    EXPECT_EQ(brightness_up, delegate->last_accelerator());
  }
  // Volume
  const ui::Accelerator volume_mute(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
  const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
  const ui::Accelerator volume_up(ui::VKEY_VOLUME_UP, ui::EF_NONE);
  {
    base::UserActionTester user_action_tester;
    ui::AcceleratorHistory* history = controller_->accelerator_history();

    EXPECT_EQ(0, user_action_tester.GetActionCount("Accel_VolumeMute_F8"));
    EXPECT_TRUE(ProcessInController(volume_mute));
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeMute_F8"));
    EXPECT_EQ(volume_mute, history->current_accelerator());

    EXPECT_EQ(0, user_action_tester.GetActionCount("Accel_VolumeDown_F9"));
    EXPECT_TRUE(ProcessInController(volume_down));
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeDown_F9"));
    EXPECT_EQ(volume_down, history->current_accelerator());

    EXPECT_EQ(0, user_action_tester.GetActionCount("Accel_VolumeUp_F10"));
    EXPECT_TRUE(ProcessInController(volume_up));
    EXPECT_EQ(volume_up, history->current_accelerator());
    EXPECT_EQ(1, user_action_tester.GetActionCount("Accel_VolumeUp_F10"));
  }
}

TEST_F(AcceleratorControllerTest, DisallowedWithNoWindow) {
  AccessibilityControllerImpl* accessibility_controller =
      Shell::Get()->accessibility_controller();
  TestAccessibilityControllerClient client;

  // Extract the accelerators of actions that need windows to be able to provide
  // them to PerformActionIfEnabled(), otherwise we could hit some NOTREACHED()
  // if we don't provide the correct keybindings.
  std::set<AcceleratorAction> actions_needing_window;
  for (size_t i = 0; i < kActionsNeedingWindowLength; ++i)
    actions_needing_window.insert(kActionsNeedingWindow[i]);
  std::map<AcceleratorAction, ui::Accelerator> accelerators_needing_window;
  for (size_t i = 0; i < kAcceleratorDataLength; ++i) {
    const auto& accelerator_data = kAcceleratorData[i];
    auto iter = actions_needing_window.find(accelerator_data.action);
    if (iter == actions_needing_window.end())
      continue;

    ui::Accelerator accelerator{accelerator_data.keycode,
                                accelerator_data.modifiers};
    if (!accelerator_data.trigger_on_press)
      accelerator.set_key_state(ui::Accelerator::KeyState::RELEASED);
    accelerators_needing_window[*iter] = accelerator;
  }

  for (const auto& iter : accelerators_needing_window) {
    accessibility_controller->TriggerAccessibilityAlert(
        AccessibilityAlert::NONE);
    EXPECT_TRUE(controller_->PerformActionIfEnabled(iter.first, iter.second));
    EXPECT_EQ(AccessibilityAlert::WINDOW_NEEDED, client.last_a11y_alert());
  }

  // Make sure we don't alert if we do have a window.
  std::unique_ptr<aura::Window> window;
  for (const auto& iter : accelerators_needing_window) {
    window.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
    wm::ActivateWindow(window.get());
    accessibility_controller->TriggerAccessibilityAlert(
        AccessibilityAlert::NONE);
    controller_->PerformActionIfEnabled(iter.first, iter.second);
    EXPECT_NE(AccessibilityAlert::WINDOW_NEEDED, client.last_a11y_alert());
  }

  // Don't alert if we have a minimized window either.
  for (const auto& iter : accelerators_needing_window) {
    window.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
    wm::ActivateWindow(window.get());
    controller_->PerformActionIfEnabled(WINDOW_MINIMIZE, {});
    accessibility_controller->TriggerAccessibilityAlert(
        AccessibilityAlert::NONE);
    controller_->PerformActionIfEnabled(iter.first, iter.second);
    EXPECT_NE(AccessibilityAlert::WINDOW_NEEDED, client.last_a11y_alert());
  }
}

TEST_F(AcceleratorControllerTest, TestDialogCancel) {
  ui::Accelerator accelerator(ui::VKEY_H,
                              ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN);
  AccessibilityControllerImpl* accessibility_controller =
      Shell::Get()->accessibility_controller();
  // Pressing cancel on the dialog should have no effect.
  EXPECT_FALSE(
      accessibility_controller->HasHighContrastAcceleratorDialogBeenAccepted());
  EXPECT_FALSE(IsConfirmationDialogOpen());
  EXPECT_TRUE(ProcessInController(accelerator));
  EXPECT_TRUE(IsConfirmationDialogOpen());
  CancelConfirmationDialog();
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(
      accessibility_controller->HasHighContrastAcceleratorDialogBeenAccepted());
  EXPECT_FALSE(IsConfirmationDialogOpen());
}

TEST_F(AcceleratorControllerTest, TestToggleHighContrast) {
  ui::Accelerator accelerator(ui::VKEY_H,
                              ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN);
  // High Contrast Mode Enabled dialog and notification should be shown.
  EXPECT_FALSE(IsConfirmationDialogOpen());
  AccessibilityControllerImpl* accessibility_controller =
      Shell::Get()->accessibility_controller();
  EXPECT_FALSE(
      accessibility_controller->HasHighContrastAcceleratorDialogBeenAccepted());
  EXPECT_TRUE(ProcessInController(accelerator));
  EXPECT_TRUE(IsConfirmationDialogOpen());
  AcceptConfirmationDialog();
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(ContainsHighContrastNotification());
  EXPECT_TRUE(
      accessibility_controller->HasHighContrastAcceleratorDialogBeenAccepted());
  EXPECT_FALSE(IsConfirmationDialogOpen());

  // High Contrast Mode Enabled dialog and notification should be hidden as the
  // feature is disabled.
  EXPECT_TRUE(ProcessInController(accelerator));
  EXPECT_FALSE(ContainsHighContrastNotification());
  EXPECT_TRUE(
      accessibility_controller->HasHighContrastAcceleratorDialogBeenAccepted());

  // Notification should be shown again when toggled, but dialog will not be
  // shown.
  EXPECT_TRUE(ProcessInController(accelerator));
  EXPECT_FALSE(IsConfirmationDialogOpen());
  EXPECT_TRUE(ContainsHighContrastNotification());
  RemoveAllNotifications();
}

namespace {

// defines a class to test the behavior of deprecated accelerators.
class DeprecatedAcceleratorTester : public AcceleratorControllerTest {
 public:
  DeprecatedAcceleratorTester() = default;
  ~DeprecatedAcceleratorTester() override = default;

  ui::Accelerator CreateAccelerator(const AcceleratorData& data) const {
    ui::Accelerator result(data.keycode, data.modifiers);
    result.set_key_state(data.trigger_on_press
                             ? ui::Accelerator::KeyState::PRESSED
                             : ui::Accelerator::KeyState::RELEASED);
    return result;
  }

  void ResetStateIfNeeded() {
    if (Shell::Get()->session_controller()->IsScreenLocked() ||
        Shell::Get()->session_controller()->IsUserSessionBlocked()) {
      UnblockUserSession();
    }
  }

  bool ContainsDeprecatedAcceleratorNotification(const char* const id) const {
    return nullptr != message_center()->FindVisibleNotificationById(id);
  }

  bool IsMessageCenterEmpty() const {
    return message_center()->GetVisibleNotifications().empty();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(DeprecatedAcceleratorTester);
};

}  // namespace

TEST_F(DeprecatedAcceleratorTester, TestDeprecatedAcceleratorsBehavior) {
  for (size_t i = 0; i < kDeprecatedAcceleratorsLength; ++i) {
    const AcceleratorData& entry = kDeprecatedAccelerators[i];

    const DeprecatedAcceleratorData* data =
        test_api_->GetDeprecatedAcceleratorData(entry.action);
    DCHECK(data);

    EXPECT_TRUE(IsMessageCenterEmpty());
    ui::Accelerator deprecated_accelerator = CreateAccelerator(entry);
    if (data->deprecated_enabled)
      EXPECT_TRUE(ProcessInController(deprecated_accelerator));
    else
      EXPECT_FALSE(ProcessInController(deprecated_accelerator));

    // We expect to see a notification in the message center.
    EXPECT_TRUE(
        ContainsDeprecatedAcceleratorNotification(data->uma_histogram_name));
    RemoveAllNotifications();

    // If the action is LOCK_SCREEN, we must reset the state by unlocking the
    // screen before we proceed testing the rest of accelerators.
    ResetStateIfNeeded();
  }
}

TEST_F(DeprecatedAcceleratorTester, TestNewAccelerators) {
  // Add below the new accelerators that replaced the deprecated ones (if any).
  const AcceleratorData kNewAccelerators[] = {
      {true, ui::VKEY_L, ui::EF_COMMAND_DOWN, LOCK_SCREEN},
      {true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN,
       SWITCH_TO_NEXT_IME},
      {true, ui::VKEY_ESCAPE, ui::EF_COMMAND_DOWN, SHOW_TASK_MANAGER},
      {true, ui::VKEY_K, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN,
       SHOW_IME_MENU_BUBBLE},
      {true, ui::VKEY_H, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN,
       TOGGLE_HIGH_CONTRAST},
  };

  // The SWITCH_TO_NEXT_IME accelerator requires multiple IMEs to be available.
  AddTestImes();

  EXPECT_TRUE(IsMessageCenterEmpty());

  for (auto data : kNewAccelerators) {
    EXPECT_TRUE(ProcessInController(CreateAccelerator(data)));

    // Expect no notifications from the new accelerators.
    if (data.action != TOGGLE_HIGH_CONTRAST) {
      // The toggle high contrast accelerator displays a notification specific
      // to the high contrast mode.
      EXPECT_TRUE(IsMessageCenterEmpty());
    }

    // If the action is LOCK_SCREEN, we must reset the state by unlocking the
    // screen before we proceed testing the rest of accelerators.
    ResetStateIfNeeded();
  }

  RemoveAllNotifications();
}

using AcceleratorControllerGuestModeTest = NoSessionAshTestBase;

TEST_F(AcceleratorControllerGuestModeTest, IncognitoWindowDisabled) {
  SimulateGuestLogin();

  // New incognito window is disabled.
  EXPECT_FALSE(Shell::Get()->accelerator_controller()->PerformActionIfEnabled(
      NEW_INCOGNITO_WINDOW, {}));
}

namespace {

constexpr char kUserEmail[] = "user@magnifier";

class MagnifiersAcceleratorsTester : public AcceleratorControllerTest {
 public:
  MagnifiersAcceleratorsTester() = default;
  ~MagnifiersAcceleratorsTester() override = default;

  DockedMagnifierControllerImpl* docked_magnifier_controller() const {
    return Shell::Get()->docked_magnifier_controller();
  }

  MagnificationController* fullscreen_magnifier_controller() const {
    return Shell::Get()->magnification_controller();
  }

  PrefService* user_pref_service() {
    return Shell::Get()->session_controller()->GetUserPrefServiceForUser(
        AccountId::FromUserEmail(kUserEmail));
  }

  void SetUp() override {
    AcceleratorControllerTest::SetUp();

    // Create user session and simulate its login.
    SimulateUserLogin(kUserEmail);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(MagnifiersAcceleratorsTester);
};

}  // namespace

// TODO (afakhry): Remove this class after refactoring MagnificationManager.
// Mocked chrome/browser/chromeos/accessibility/magnification_manager.cc
class FakeMagnificationManager {
 public:
  FakeMagnificationManager() = default;

  void SetPrefs(PrefService* prefs) {
    pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
    pref_change_registrar_->Init(prefs);
    pref_change_registrar_->Add(
        prefs::kAccessibilityScreenMagnifierEnabled,
        base::BindRepeating(&FakeMagnificationManager::UpdateMagnifierFromPrefs,
                            base::Unretained(this)));
    prefs_ = prefs;
  }

  void UpdateMagnifierFromPrefs() {
    Shell::Get()->magnification_controller()->SetEnabled(
        prefs_->GetBoolean(prefs::kAccessibilityScreenMagnifierEnabled));
  }

 private:
  std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
  PrefService* prefs_;

  DISALLOW_COPY_AND_ASSIGN(FakeMagnificationManager);
};

TEST_F(MagnifiersAcceleratorsTester, TestToggleFullscreenMagnifier) {
  FakeMagnificationManager manager;
  manager.SetPrefs(user_pref_service());
  EXPECT_FALSE(docked_magnifier_controller()->GetEnabled());
  EXPECT_FALSE(fullscreen_magnifier_controller()->IsEnabled());
  EXPECT_FALSE(IsConfirmationDialogOpen());

  AccessibilityControllerImpl* accessibility_controller =
      Shell::Get()->accessibility_controller();
  // Toggle the fullscreen magnifier on/off, dialog should be shown on first use
  // of accelerator.
  const ui::Accelerator fullscreen_magnifier_accelerator(
      ui::VKEY_M, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN);
  EXPECT_FALSE(accessibility_controller
                   ->HasScreenMagnifierAcceleratorDialogBeenAccepted());
  EXPECT_TRUE(ProcessInController(fullscreen_magnifier_accelerator));
  EXPECT_TRUE(IsConfirmationDialogOpen());
  AcceptConfirmationDialog();
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(IsConfirmationDialogOpen());
  EXPECT_FALSE(docked_magnifier_controller()->GetEnabled());
  EXPECT_TRUE(fullscreen_magnifier_controller()->IsEnabled());
  EXPECT_TRUE(ContainsFullscreenMagnifierNotification());

  EXPECT_TRUE(ProcessInController(fullscreen_magnifier_accelerator));
  EXPECT_FALSE(docked_magnifier_controller()->GetEnabled());
  EXPECT_FALSE(fullscreen_magnifier_controller()->IsEnabled());
  EXPECT_TRUE(accessibility_controller
                  ->HasScreenMagnifierAcceleratorDialogBeenAccepted());
  EXPECT_FALSE(IsConfirmationDialogOpen());
  EXPECT_FALSE(ContainsFullscreenMagnifierNotification());

  // Dialog will not be shown the second time the accelerator is used.
  EXPECT_TRUE(ProcessInController(fullscreen_magnifier_accelerator));
  EXPECT_FALSE(IsConfirmationDialogOpen());
  EXPECT_TRUE(accessibility_controller
                  ->HasScreenMagnifierAcceleratorDialogBeenAccepted());
  EXPECT_FALSE(docked_magnifier_controller()->GetEnabled());
  EXPECT_TRUE(fullscreen_magnifier_controller()->IsEnabled());
  EXPECT_TRUE(ContainsFullscreenMagnifierNotification());

  RemoveAllNotifications();
}

TEST_F(MagnifiersAcceleratorsTester, TestToggleDockedMagnifier) {
  EXPECT_FALSE(docked_magnifier_controller()->GetEnabled());
  EXPECT_FALSE(fullscreen_magnifier_controller()->IsEnabled());
  EXPECT_FALSE(IsConfirmationDialogOpen());

  AccessibilityControllerImpl* accessibility_controller =
      Shell::Get()->accessibility_controller();
  // Toggle the docked magnifier on/off, dialog should be shown on first use of
  // accelerator.
  const ui::Accelerator docked_magnifier_accelerator(
      ui::VKEY_D, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN);
  EXPECT_TRUE(ProcessInController(docked_magnifier_accelerator));
  EXPECT_TRUE(IsConfirmationDialogOpen());
  AcceptConfirmationDialog();
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(IsConfirmationDialogOpen());
  EXPECT_TRUE(docked_magnifier_controller()->GetEnabled());
  EXPECT_FALSE(fullscreen_magnifier_controller()->IsEnabled());
  EXPECT_TRUE(ContainsDockedMagnifierNotification());

  EXPECT_TRUE(ProcessInController(docked_magnifier_accelerator));
  EXPECT_FALSE(docked_magnifier_controller()->GetEnabled());
  EXPECT_FALSE(fullscreen_magnifier_controller()->IsEnabled());
  EXPECT_TRUE(accessibility_controller
                  ->HasDockedMagnifierAcceleratorDialogBeenAccepted());
  EXPECT_FALSE(IsConfirmationDialogOpen());
  EXPECT_FALSE(ContainsDockedMagnifierNotification());

  // Dialog will not be shown the second time accelerator is used.
  EXPECT_TRUE(ProcessInController(docked_magnifier_accelerator));
  EXPECT_FALSE(IsConfirmationDialogOpen());
  EXPECT_TRUE(docked_magnifier_controller()->GetEnabled());
  EXPECT_FALSE(fullscreen_magnifier_controller()->IsEnabled());
  EXPECT_TRUE(ContainsDockedMagnifierNotification());

  RemoveAllNotifications();
}

namespace {

struct MediaSessionAcceleratorTestConfig {
  // Runs the test with the media session service enabled.
  bool service_enabled;

  // Runs the test with the supplied action enabled and will also send the media
  // session info to the controller.
  base::Optional<MediaSessionAction> with_action_enabled;

  // If true then we should expect the action will handle the media keys.
  bool eligible_action = false;

  // If true then we should force forwarding the action to the client.
  bool force_key_handling = false;
};

}  // namespace

// MediaSessionAcceleratorTest tests media key handling with media session
// service integration. The parameter is a struct that configures different
// settings to run the test under.
class MediaSessionAcceleratorTest
    : public AcceleratorControllerTest,
      public testing::WithParamInterface<MediaSessionAcceleratorTestConfig> {
 public:
  MediaSessionAcceleratorTest() = default;
  ~MediaSessionAcceleratorTest() override = default;

  // AcceleratorControllerTest:
  void SetUp() override {
    if (service_enabled()) {
      scoped_feature_list_.InitAndEnableFeature(
          media::kHardwareMediaKeyHandling);
    } else {
      scoped_feature_list_.InitAndDisableFeature(
          media::kHardwareMediaKeyHandling);
    }

    AcceleratorControllerTest::SetUp();

    client_ = std::make_unique<TestMediaClient>();
    controller_ = std::make_unique<media_session::test::TestMediaController>();

    MediaControllerImpl* media_controller = Shell::Get()->media_controller();
    media_controller->SetClient(client_.get());
    media_controller->SetMediaSessionControllerForTest(
        controller_->CreateMediaControllerRemote());
    media_controller->SetForceMediaClientKeyHandling(
        GetParam().force_key_handling);
    media_controller->FlushForTesting();
  }

  void MaybeEnableMediaSession(
      media_session::mojom::MediaPlaybackState playback_state) {
    if (!GetParam().with_action_enabled)
      return;

    SimulateActionsChanged(GetParam().with_action_enabled);
    SimulatePlaybackState(playback_state);
  }

  void SimulateActionsChanged(base::Optional<MediaSessionAction> action) {
    std::vector<MediaSessionAction> actions;

    if (action)
      actions.push_back(*action);

    controller()->SimulateMediaSessionActionsChanged(actions);
    controller()->Flush();
  }

  TestMediaClient* client() const { return client_.get(); }

  media_session::test::TestMediaController* controller() const {
    return controller_.get();
  }

  bool service_enabled() const { return GetParam().service_enabled; }

  bool eligible_action() const { return GetParam().eligible_action; }

  bool force_key_handling() const { return GetParam().force_key_handling; }

  void ExpectActionRecorded(ui::MediaHardwareKeyAction action) {
    histogram_tester_.ExpectBucketCount(
        ui::kMediaHardwareKeyActionHistogramName,
        static_cast<base::HistogramBase::Sample>(action), 1);
  }

 private:
  void SimulatePlaybackState(
      media_session::mojom::MediaPlaybackState playback_state) {
    media_session::mojom::MediaSessionInfoPtr session_info(
        media_session::mojom::MediaSessionInfo::New());

    session_info->state =
        media_session::mojom::MediaSessionInfo::SessionState::kActive;
    session_info->playback_state = playback_state;

    controller()->SimulateMediaSessionInfoChanged(std::move(session_info));
    controller()->Flush();
  }

  std::unique_ptr<TestMediaClient> client_;
  std::unique_ptr<media_session::test::TestMediaController> controller_;

  base::HistogramTester histogram_tester_;
  base::test::ScopedFeatureList scoped_feature_list_;

  DISALLOW_COPY_AND_ASSIGN(MediaSessionAcceleratorTest);
};

INSTANTIATE_TEST_SUITE_P(
    ,
    MediaSessionAcceleratorTest,
    testing::Values(
        MediaSessionAcceleratorTestConfig{true, MediaSessionAction::kPlay,
                                          true},
        MediaSessionAcceleratorTestConfig{true, MediaSessionAction::kPause,
                                          true},
        MediaSessionAcceleratorTestConfig{
            true, MediaSessionAction::kPreviousTrack, true},
        MediaSessionAcceleratorTestConfig{true, MediaSessionAction::kNextTrack,
                                          true},
        MediaSessionAcceleratorTestConfig{true,
                                          MediaSessionAction::kSeekBackward},
        MediaSessionAcceleratorTestConfig{true,
                                          MediaSessionAction::kSeekForward},
        MediaSessionAcceleratorTestConfig{true, MediaSessionAction::kStop},
        MediaSessionAcceleratorTestConfig{false, MediaSessionAction::kPlay},
        MediaSessionAcceleratorTestConfig{false, MediaSessionAction::kPause},
        MediaSessionAcceleratorTestConfig{false,
                                          MediaSessionAction::kPreviousTrack},
        MediaSessionAcceleratorTestConfig{false,
                                          MediaSessionAction::kNextTrack},
        MediaSessionAcceleratorTestConfig{false,
                                          MediaSessionAction::kSeekBackward},
        MediaSessionAcceleratorTestConfig{false,
                                          MediaSessionAction::kSeekForward},
        MediaSessionAcceleratorTestConfig{false, MediaSessionAction::kStop},
        MediaSessionAcceleratorTestConfig{true, MediaSessionAction::kPlay,
                                          false, true},
        MediaSessionAcceleratorTestConfig{true, MediaSessionAction::kPause,
                                          false, true},
        MediaSessionAcceleratorTestConfig{true, MediaSessionAction::kNextTrack,
                                          false, true},
        MediaSessionAcceleratorTestConfig{
            true, MediaSessionAction::kPreviousTrack, false, true}));

TEST_P(MediaSessionAcceleratorTest, MediaPlaybackAcceleratorsBehavior) {
  const ui::KeyboardCode media_keys[] = {ui::VKEY_MEDIA_NEXT_TRACK,
                                         ui::VKEY_MEDIA_PLAY_PAUSE,
                                         ui::VKEY_MEDIA_PREV_TRACK};

  std::unique_ptr<ui::AcceleratorHistory> accelerator_history(
      std::make_unique<ui::AcceleratorHistory>());
  ::wm::AcceleratorFilter filter(
      std::make_unique<PreTargetAcceleratorHandler>(),
      accelerator_history.get());

  for (ui::KeyboardCode key : media_keys) {
    // If the media session service integration is enabled then media keys will
    // be handled in ash.
    std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(1));
    {
      ui::KeyEvent press_key(ui::ET_KEY_PRESSED, key, ui::EF_NONE);
      ui::Event::DispatcherApi dispatch_helper(&press_key);
      dispatch_helper.set_target(window.get());
      filter.OnKeyEvent(&press_key);
      EXPECT_EQ(service_enabled(), press_key.stopped_propagation());
    }

    // Setting a window property on the target allows media keys to pass
    // through.
    WindowState::Get(window.get())->SetCanConsumeSystemKeys(true);
    {
      ui::KeyEvent press_key(ui::ET_KEY_PRESSED, key, ui::EF_NONE);
      ui::Event::DispatcherApi dispatch_helper(&press_key);
      dispatch_helper.set_target(window.get());
      filter.OnKeyEvent(&press_key);
      EXPECT_FALSE(press_key.stopped_propagation());
    }
  }
}

TEST_P(MediaSessionAcceleratorTest, MediaGlobalAccelerators_NextTrack) {
  MaybeEnableMediaSession(media_session::mojom::MediaPlaybackState::kPaused);

  EXPECT_EQ(0, client()->handle_media_next_track_count());
  EXPECT_EQ(0, controller()->next_track_count());

  ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE));
  Shell::Get()->media_controller()->FlushForTesting();

  if (service_enabled() && eligible_action() && !force_key_handling()) {
    EXPECT_EQ(0, client()->handle_media_next_track_count());
    EXPECT_EQ(1, controller()->next_track_count());
  } else {
    EXPECT_EQ(1, client()->handle_media_next_track_count());
    EXPECT_EQ(0, controller()->next_track_count());
  }

  ExpectActionRecorded(ui::MediaHardwareKeyAction::kNextTrack);
}

TEST_P(MediaSessionAcceleratorTest, MediaGlobalAccelerators_Play) {
  MaybeEnableMediaSession(media_session::mojom::MediaPlaybackState::kPaused);

  EXPECT_EQ(0, client()->handle_media_play_pause_count());
  EXPECT_EQ(0, controller()->resume_count());

  ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_PLAY_PAUSE, ui::EF_NONE));
  Shell::Get()->media_controller()->FlushForTesting();

  if (service_enabled() && eligible_action()) {
    EXPECT_EQ(0, client()->handle_media_play_pause_count());
    EXPECT_EQ(1, controller()->resume_count());

    // If media session handles the key then we should always know the playback
    // state so we can record a more granular action.
    ExpectActionRecorded(ui::MediaHardwareKeyAction::kPlay);
  } else {
    EXPECT_EQ(1, client()->handle_media_play_pause_count());
    EXPECT_EQ(0, controller()->resume_count());

    // If we pass through to the client we don't know whether the action will
    // play or pause so we should record a generic "play/pause" action.
    ExpectActionRecorded(ui::MediaHardwareKeyAction::kPlayPause);
  }
}

TEST_P(MediaSessionAcceleratorTest, MediaGlobalAccelerators_Pause) {
  MaybeEnableMediaSession(media_session::mojom::MediaPlaybackState::kPlaying);

  EXPECT_EQ(0, client()->handle_media_play_pause_count());
  EXPECT_EQ(0, controller()->suspend_count());

  ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_PLAY_PAUSE, ui::EF_NONE));
  Shell::Get()->media_controller()->FlushForTesting();

  if (service_enabled() && eligible_action() && !force_key_handling()) {
    EXPECT_EQ(0, client()->handle_media_play_pause_count());
    EXPECT_EQ(1, controller()->suspend_count());

    // If media session handles the key then we should always know the playback
    // state so we can record a more granular action.
    ExpectActionRecorded(ui::MediaHardwareKeyAction::kPause);
  } else {
    EXPECT_EQ(1, client()->handle_media_play_pause_count());
    EXPECT_EQ(0, controller()->suspend_count());

    // If we pass through to the client we don't know whether the action will
    // play or pause so we should record a generic "play/pause" action.
    ExpectActionRecorded(ui::MediaHardwareKeyAction::kPlayPause);
  }
}

TEST_P(MediaSessionAcceleratorTest, MediaGlobalAccelerators_PrevTrack) {
  MaybeEnableMediaSession(media_session::mojom::MediaPlaybackState::kPaused);

  EXPECT_EQ(0, client()->handle_media_prev_track_count());
  EXPECT_EQ(0, controller()->previous_track_count());

  ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_PREV_TRACK, ui::EF_NONE));
  Shell::Get()->media_controller()->FlushForTesting();

  if (service_enabled() && eligible_action() && !force_key_handling()) {
    EXPECT_EQ(0, client()->handle_media_prev_track_count());
    EXPECT_EQ(1, controller()->previous_track_count());
  } else {
    EXPECT_EQ(1, client()->handle_media_prev_track_count());
    EXPECT_EQ(0, controller()->previous_track_count());
  }

  ExpectActionRecorded(ui::MediaHardwareKeyAction::kPreviousTrack);
}

TEST_P(MediaSessionAcceleratorTest,
       MediaGlobalAccelerators_UpdateAction_Disable) {
  MaybeEnableMediaSession(media_session::mojom::MediaPlaybackState::kPaused);

  EXPECT_EQ(0, client()->handle_media_next_track_count());
  EXPECT_EQ(0, controller()->next_track_count());

  ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE));
  Shell::Get()->media_controller()->FlushForTesting();

  if (service_enabled() && eligible_action() && !force_key_handling()) {
    EXPECT_EQ(0, client()->handle_media_next_track_count());
    EXPECT_EQ(1, controller()->next_track_count());
  } else {
    EXPECT_EQ(1, client()->handle_media_next_track_count());
    EXPECT_EQ(0, controller()->next_track_count());
  }

  SimulateActionsChanged(base::nullopt);

  ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE));
  Shell::Get()->media_controller()->FlushForTesting();

  if (service_enabled() && eligible_action() && !force_key_handling()) {
    EXPECT_EQ(1, client()->handle_media_next_track_count());
    EXPECT_EQ(1, controller()->next_track_count());
  } else {
    EXPECT_EQ(2, client()->handle_media_next_track_count());
    EXPECT_EQ(0, controller()->next_track_count());
  }
}

TEST_P(MediaSessionAcceleratorTest,
       MediaGlobalAccelerators_UpdateAction_Enable) {
  EXPECT_EQ(0, client()->handle_media_next_track_count());
  EXPECT_EQ(0, controller()->next_track_count());

  ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE));
  Shell::Get()->media_controller()->FlushForTesting();

  EXPECT_EQ(1, client()->handle_media_next_track_count());
  EXPECT_EQ(0, controller()->next_track_count());

  MaybeEnableMediaSession(media_session::mojom::MediaPlaybackState::kPaused);

  ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE));
  Shell::Get()->media_controller()->FlushForTesting();

  if (service_enabled() && eligible_action() && !force_key_handling()) {
    EXPECT_EQ(1, client()->handle_media_next_track_count());
    EXPECT_EQ(1, controller()->next_track_count());
  } else {
    EXPECT_EQ(2, client()->handle_media_next_track_count());
    EXPECT_EQ(0, controller()->next_track_count());
  }
}

TEST_P(MediaSessionAcceleratorTest,
       MediaGlobalAccelerators_UpdateForceKeyHandling) {
  MaybeEnableMediaSession(media_session::mojom::MediaPlaybackState::kPaused);

  EXPECT_EQ(0, client()->handle_media_next_track_count());
  EXPECT_EQ(0, controller()->next_track_count());

  ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE));
  Shell::Get()->media_controller()->FlushForTesting();

  if (service_enabled() && eligible_action() && !force_key_handling()) {
    EXPECT_EQ(0, client()->handle_media_next_track_count());
    EXPECT_EQ(1, controller()->next_track_count());
  } else {
    EXPECT_EQ(1, client()->handle_media_next_track_count());
    EXPECT_EQ(0, controller()->next_track_count());
  }

  // Update the force media client key handling setting. It may have been
  // previously set if |force_key_handling| is true.
  Shell::Get()->media_controller()->SetForceMediaClientKeyHandling(false);

  ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE));
  Shell::Get()->media_controller()->FlushForTesting();

  if (service_enabled() && force_key_handling()) {
    // If we had |force_key_handling| true the first time we pressed the play
    // pause key then we should see the previous action that was forward to the
    // client. Since the service is enabled, the second action will be handled
    // by the controller.
    EXPECT_EQ(1, client()->handle_media_next_track_count());
    EXPECT_EQ(1, controller()->next_track_count());
  } else if (service_enabled() && eligible_action()) {
    // If we had |force_key_handling| disabled the whole time and the service
    // enabled then both actions should be handled in the controller.
    EXPECT_EQ(0, client()->handle_media_next_track_count());
    EXPECT_EQ(2, controller()->next_track_count());
  } else {
    // If we had |force_key_handling| disabled the whole time and the service
    // disabled then both actions should fallback to the client because there is
    // nothing in Ash to handle them.
    EXPECT_EQ(2, client()->handle_media_next_track_count());
    EXPECT_EQ(0, controller()->next_track_count());
  }
}

// Tests the IME mode change key.
TEST_F(AcceleratorControllerTest, ChangeIMEMode_SwitchesInputMethod) {
  AddTestImes();

  ImeController* controller = Shell::Get()->ime_controller();

  TestImeControllerClient client;
  controller->SetClient(client.CreateInterfacePtr());

  EXPECT_EQ(0, client.next_ime_count_);

  ProcessInController(ui::Accelerator(ui::VKEY_MODECHANGE, ui::EF_NONE));
  controller->FlushMojoForTesting();

  EXPECT_EQ(1, client.next_ime_count_);
}

}  // namespace ash
