// 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.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.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/ime/ime_controller.h"
#include "ash/ime/test_ime_controller_client.h"
#include "ash/magnifier/docked_magnifier_controller.h"
#include "ash/magnifier/magnification_controller.h"
#include "ash/media/media_controller.h"
#include "ash/public/cpp/ash_switches.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/interfaces/ime_info.mojom.h"
#include "ash/session/session_controller.h"
#include "ash/session/test_session_controller_client.h"
#include "ash/shell.h"
#include "ash/shell_test_api.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/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/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.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 "services/ws/public/mojom/window_tree_constants.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/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;

 protected:
  static AcceleratorController* GetController();

  static bool ProcessInController(const ui::Accelerator& accelerator) {
    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);
      GetController()->accelerator_history()->StoreCurrentAccelerator(
          pressed_accelerator);
    }
    GetController()->accelerator_history()->StoreCurrentAccelerator(
        accelerator);
    return GetController()->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 !!(GetController()->confirmation_dialog_for_testing());
  }

  void AcceptConfirmationDialog() {
    DCHECK(GetController()->confirmation_dialog_for_testing());
    GetController()
        ->confirmation_dialog_for_testing()
        ->GetDialogClientView()
        ->AcceptWindow();
  }

  void CancelConfirmationDialog() {
    DCHECK(GetController()->confirmation_dialog_for_testing());
    GetController()
        ->confirmation_dialog_for_testing()
        ->GetDialogClientView()
        ->CancelWindow();
  }

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

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

  static const ui::Accelerator& GetCurrentAccelerator() {
    return GetController()->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;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(AcceleratorControllerTest);
};

AcceleratorController* AcceleratorControllerTest::GetController() {
  return Shell::Get()->accelerator_controller();
}

// 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 = GetController()->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 = GetController()->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 = GetController()->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);

  GetController()->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;
  GetController()->Register({accelerator_a}, &target1);
  ui::TestAcceleratorTarget target2;
  GetController()->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;
  GetController()->Register({accelerator_a, accelerator_b}, &target);

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

  // The unregistered accelerator is no longer processed.
  target.ResetCounts();
  GetController()->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;
  GetController()->Register({accelerator_a, accelerator_b}, &target1);
  const ui::Accelerator accelerator_c(ui::VKEY_C, ui::EF_NONE);
  ui::TestAcceleratorTarget target2;
  GetController()->Register({accelerator_c}, &target2);
  GetController()->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;
  GetController()->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;
  GetController()->Register({accelerator_a}, &target);
  EXPECT_TRUE(GetController()->IsRegistered(accelerator_a));
  EXPECT_FALSE(GetController()->IsRegistered(accelerator_shift_a));
  GetController()->UnregisterAll(&target);
  EXPECT_FALSE(GetController()->IsRegistered(accelerator_a));
}

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

  window_state->Activate();

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

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

    GetController()->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());

    GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED);
    GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_LEFT);
    EXPECT_FALSE(window_state->IsMaximized());

    GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED);
    GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_RIGHT);
    EXPECT_FALSE(window_state->IsMaximized());

    GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED);
    EXPECT_TRUE(window_state->IsMaximized());
    GetController()->PerformActionIfEnabled(WINDOW_MINIMIZE);
    EXPECT_FALSE(window_state->IsMaximized());
    EXPECT_TRUE(window_state->IsMinimized());
    window_state->Restore();
    window_state->Activate();
  }
  {
    GetController()->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)));

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

  // Snap right.
  GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_RIGHT);
  gfx::Rect normal_bounds = window_state->GetRestoreBoundsInParent();
  gfx::Rect expected_bounds =
      wm::GetDefaultRightSnappedWindowBoundsInParent(window.get());
  EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString());
  EXPECT_TRUE(window_state->IsSnapped());
  // Snap right again ->> becomes normal.
  GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_RIGHT);
  EXPECT_TRUE(window_state->IsNormalStateType());
  EXPECT_EQ(normal_bounds.ToString(), window->bounds().ToString());
  // Snap right.
  GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_RIGHT);
  EXPECT_TRUE(window_state->IsSnapped());
  // Snap left.
  GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_LEFT);
  EXPECT_TRUE(window_state->IsSnapped());
  expected_bounds = wm::GetDefaultLeftSnappedWindowBoundsInParent(window.get());
  EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString());
  // Snap left again ->> becomes normal.
  GetController()->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();
  AccessibilityController* 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;
  GetController()->Register({accelerator_a}, &target_a);
  ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_CONTROL_DOWN);
  ui::TestAcceleratorTarget target_b;
  GetController()->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},
  };
  GetController()->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(params);
  widget->Show();
  widget->Activate();
  widget->GetNativeView()->SetProperty(aura::client::kResizeBehaviorKey,
                                       ws::mojom::kResizeBehaviorCanMaximize);

  ui::test::EventGenerator* generator = GetEventGenerator();
  wm::WindowState* window_state = wm::GetWindowState(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;
  GetController()->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 = GetController()->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 = GetController()->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) {
  AccessibilityController* 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.
  controller->SetSpokenFeedbackEnabled(true, A11Y_NOTIFICATION_NONE);
  EXPECT_TRUE(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)));
  controller->SetSpokenFeedbackEnabled(false, A11Y_NOTIFICATION_NONE);
  EXPECT_FALSE(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)));
  GetController()->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::mojom::AppListViewState::kFullscreenAllApps);
  histogram_tester.ExpectTotalCount(app_list::kAppListToggleMethodHistogram,
                                    ++toggle_count_total);
  histogram_tester.ExpectBucketCount(app_list::kAppListToggleMethodHistogram,
                                     app_list::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::mojom::AppListViewState::kPeeking);
  histogram_tester.ExpectTotalCount(app_list::kAppListToggleMethodHistogram,
                                    ++toggle_count_total);
  histogram_tester.ExpectBucketCount(app_list::kAppListToggleMethodHistogram,
                                     app_list::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::mojom::AppListViewState::kFullscreenAllApps);
  histogram_tester.ExpectTotalCount(app_list::kAppListToggleMethodHistogram,
                                    ++toggle_count_total);
  histogram_tester.ExpectBucketCount(app_list::kAppListToggleMethodHistogram,
                                     app_list::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::mojom::AppListViewState::kPeeking);
  histogram_tester.ExpectTotalCount(app_list::kAppListToggleMethodHistogram,
                                    ++toggle_count_total);
  histogram_tester.ExpectBucketCount(app_list::kAppListToggleMethodHistogram,
                                     app_list::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::mojom::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::mojom::AppListViewState::kFullscreenSearch);
  histogram_tester.ExpectTotalCount(app_list::kAppListToggleMethodHistogram,
                                    ++toggle_count_total);
  histogram_tester.ExpectBucketCount(app_list::kAppListToggleMethodHistogram,
                                     app_list::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(GetController()->IsReserved(
      ui::Accelerator(ui::VKEY_POWER, ui::EF_NONE)));
  EXPECT_FALSE(GetController()->IsPreferred(
      ui::Accelerator(ui::VKEY_POWER, ui::EF_NONE)));

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

  // Others are not reserved nor preferred
  EXPECT_FALSE(GetController()->IsReserved(
      ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE)));
  EXPECT_FALSE(GetController()->IsPreferred(
      ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE)));
  EXPECT_FALSE(
      GetController()->IsReserved(ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE)));
  EXPECT_FALSE(
      GetController()->IsPreferred(ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE)));
  EXPECT_FALSE(
      GetController()->IsReserved(ui::Accelerator(ui::VKEY_A, ui::EF_NONE)));
  EXPECT_FALSE(
      GetController()->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(GetController()
                  ->side_volume_button_location_for_testing()
                  .region.empty());
  EXPECT_TRUE(
      GetController()->side_volume_button_location_for_testing().side.empty());

  // Tests that |side_volume_button_location_| is read correctly if the location
  // file exists.
  base::DictionaryValue location;
  location.SetString(AcceleratorController::kVolumeButtonRegion,
                     AcceleratorController::kVolumeButtonRegionScreen);
  location.SetString(AcceleratorController::kVolumeButtonSide,
                     AcceleratorController::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));
  GetController()->set_side_volume_button_file_path_for_testing(file_path);
  GetController()->ParseSideVolumeButtonLocationInfo();
  EXPECT_EQ(AcceleratorController::kVolumeButtonRegionScreen,
            GetController()->side_volume_button_location_for_testing().region);
  EXPECT_EQ(AcceleratorController::kVolumeButtonSideLeft,
            GetController()->side_volume_button_location_for_testing().side);
  base::DeleteFile(file_path, false);
}

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);

  wm::WMEvent fullscreen(wm::WM_EVENT_FULLSCREEN);
  wm::WindowState* w1_state = wm::GetWindowState(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, wm::GetActiveWindow());
  press_and_release_alt_tab();
  ASSERT_EQ(w1, wm::GetActiveWindow());
  ASSERT_NE(w2, wm::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.
  wm::WMEvent normal(wm::WM_EVENT_NORMAL);
  w1_state->OnWMEvent(&normal);
  ASSERT_FALSE(w1_state->IsFullscreen());

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

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

  {
    wm::WMEvent pin_event(wm::WM_EVENT_PIN);
    wm::WindowState* w1_state = wm::GetWindowState(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, wm::GetActiveWindow());
  generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  generator->ReleaseKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  ASSERT_EQ(w1, wm::GetActiveWindow());
  ASSERT_NE(w2, wm::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(GetController()->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 = GetController()->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) {
  TestAccessibilityControllerClient client;
  AccessibilityController* controller =
      Shell::Get()->accessibility_controller();
  controller->SetClient(client.CreateInterfacePtrAndBind());

  for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
    controller->TriggerAccessibilityAlert(mojom::AccessibilityAlert::NONE);
    controller->FlushMojoForTest();
    EXPECT_TRUE(
        GetController()->PerformActionIfEnabled(kActionsNeedingWindow[i]));
    controller->FlushMojoForTest();
    EXPECT_EQ(mojom::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 (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
    window.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
    wm::ActivateWindow(window.get());
    controller->TriggerAccessibilityAlert(mojom::AccessibilityAlert::NONE);
    controller->FlushMojoForTest();
    GetController()->PerformActionIfEnabled(kActionsNeedingWindow[i]);
    controller->FlushMojoForTest();
    EXPECT_NE(mojom::AccessibilityAlert::WINDOW_NEEDED,
              client.last_a11y_alert());
  }

  // Don't alert if we have a minimized window either.
  for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
    window.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
    wm::ActivateWindow(window.get());
    GetController()->PerformActionIfEnabled(WINDOW_MINIMIZE);
    controller->TriggerAccessibilityAlert(mojom::AccessibilityAlert::NONE);
    controller->FlushMojoForTest();
    GetController()->PerformActionIfEnabled(kActionsNeedingWindow[i]);
    controller->FlushMojoForTest();
    EXPECT_NE(mojom::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);
  AccessibilityController* 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());
  AccessibilityController* 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];

    auto itr = GetController()->actions_with_deprecations_.find(entry.action);
    ASSERT_TRUE(itr != GetController()->actions_with_deprecations_.end());
    const DeprecatedAcceleratorData* data = itr->second;

    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 {

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

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

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

 private:
  DISALLOW_COPY_AND_ASSIGN(MagnifiersAcceleratorsTester);
};

}  // namespace

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

  AccessibilityController* 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());

  AccessibilityController* 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>();

    MediaController* media_controller = Shell::Get()->media_controller();
    media_controller->SetClient(client_->CreateAssociatedPtrInfo());
    media_controller->SetMediaSessionControllerForTest(
        controller_->CreateMediaControllerPtr());
    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.
    wm::GetWindowState(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());
  }
}

}  // namespace ash
