// 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 <algorithm>
#include <cmath>
#include <iostream>
#include <string>

#include "ash/accelerators/accelerator_commands.h"
#include "ash/accelerators/accelerator_table.h"
#include "ash/accelerators/debug_commands.h"
#include "ash/ash_switches.h"
#include "ash/caps_lock_delegate.h"
#include "ash/debug.h"
#include "ash/display/display_controller.h"
#include "ash/display/display_manager.h"
#include "ash/focus_cycler.h"
#include "ash/ime_control_delegate.h"
#include "ash/launcher/launcher.h"
#include "ash/magnifier/magnification_controller.h"
#include "ash/magnifier/partial_magnification_controller.h"
#include "ash/media_delegate.h"
#include "ash/multi_profile_uma.h"
#include "ash/new_window_delegate.h"
#include "ash/root_window_controller.h"
#include "ash/rotator/screen_rotation.h"
#include "ash/screenshot_delegate.h"
#include "ash/session_state_delegate.h"
#include "ash/shelf/shelf_delegate.h"
#include "ash/shelf/shelf_model.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/shell_window_ids.h"
#include "ash/system/brightness_control_delegate.h"
#include "ash/system/keyboard_brightness/keyboard_brightness_control_delegate.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/tray/system_tray.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "ash/system/web_notification/web_notification_tray.h"
#include "ash/touch/touch_hud_debug.h"
#include "ash/volume_control_delegate.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/partial_screenshot_view.h"
#include "ash/wm/power_button_controller.h"
#include "ash/wm/window_cycle_controller.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/snap_sizer.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/user_metrics.h"
#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/accelerators/accelerator_manager.h"
#include "ui/compositor/debug_utils.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/screen.h"
#include "ui/oak/oak.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/debug_utils.h"
#include "ui/views/widget/widget.h"

#if defined(OS_CHROMEOS)
#include "ash/session_state_delegate.h"
#include "ash/system/chromeos/keyboard_brightness_controller.h"
#include "base/sys_info.h"
#endif  // defined(OS_CHROMEOS)

namespace ash {
namespace {

using internal::DisplayInfo;
using content::UserMetricsAction;

bool DebugShortcutsEnabled() {
#if defined(NDEBUG)
  return CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kAshDebugShortcuts);
#else
  return true;
#endif
}

bool HandleAccessibleFocusCycle(bool reverse) {
  if (reverse) {
    content::RecordAction(UserMetricsAction("Accel_Accessible_Focus_Previous"));
  } else {
    content::RecordAction(UserMetricsAction("Accel_Accessible_Focus_Next"));
  }

  if (!Shell::GetInstance()->accessibility_delegate()->
      IsSpokenFeedbackEnabled()) {
    return false;
  }
  aura::Window* active_window = ash::wm::GetActiveWindow();
  if (!active_window)
    return false;
  views::Widget* widget =
      views::Widget::GetWidgetForNativeWindow(active_window);
  if (!widget)
    return false;
  views::FocusManager* focus_manager = widget->GetFocusManager();
  if (!focus_manager)
    return false;
  views::View* view = focus_manager->GetFocusedView();
  if (!view)
    return false;
  if (!strcmp(view->GetClassName(), views::WebView::kViewClassName))
    return false;

  focus_manager->AdvanceFocus(reverse);
  return true;
}

bool HandleCycleBackwardMRU(const ui::Accelerator& accelerator) {
  Shell* shell = Shell::GetInstance();

  if (accelerator.key_code() == ui::VKEY_TAB)
    content::RecordAction(content::UserMetricsAction("Accel_PrevWindow_Tab"));

  if (switches::UseOverviewMode()) {
    shell->window_selector_controller()->HandleCycleWindow(
        WindowSelector::BACKWARD);
    return true;
  }
  shell->window_cycle_controller()->HandleCycleWindow(
      WindowCycleController::BACKWARD, accelerator.IsAltDown());
  return true;
}

bool HandleCycleForwardMRU(const ui::Accelerator& accelerator) {
  Shell* shell = Shell::GetInstance();

  if (accelerator.key_code() == ui::VKEY_TAB)
    content::RecordAction(content::UserMetricsAction("Accel_NextWindow_Tab"));

  if (switches::UseOverviewMode()) {
    shell->window_selector_controller()->HandleCycleWindow(
        WindowSelector::FORWARD);
    return true;
  }
  shell->window_cycle_controller()->HandleCycleWindow(
      WindowCycleController::FORWARD, accelerator.IsAltDown());
  return true;
}

bool HandleCycleLinear(const ui::Accelerator& accelerator) {
  Shell* shell = Shell::GetInstance();

  // TODO(jamescook): When overview becomes the default the AcceleratorAction
  // should be renamed from CYCLE_LINEAR to TOGGLE_OVERVIEW.
  if (switches::UseOverviewMode()) {
    content::RecordAction(content::UserMetricsAction("Accel_Overview_F5"));
    shell->window_selector_controller()->ToggleOverview();
    return true;
  }
  if (accelerator.key_code() == ui::VKEY_MEDIA_LAUNCH_APP1)
    content::RecordAction(content::UserMetricsAction("Accel_NextWindow_F5"));
  shell->window_cycle_controller()->HandleLinearCycleWindow();
  return true;
}

bool HandleDisableCapsLock(ui::KeyboardCode key_code,
                           ui::EventType previous_event_type,
                           ui::KeyboardCode previous_key_code) {
  Shell* shell = Shell::GetInstance();

  if (previous_event_type == ui::ET_KEY_RELEASED ||
      (previous_key_code != ui::VKEY_LSHIFT &&
       previous_key_code != ui::VKEY_SHIFT &&
       previous_key_code != ui::VKEY_RSHIFT)) {
    // If something else was pressed between the Shift key being pressed
    // and released, then ignore the release of the Shift key.
    return false;
  }
  content::RecordAction(UserMetricsAction("Accel_Disable_Caps_Lock"));
  if (shell->caps_lock_delegate()->IsCapsLockEnabled()) {
    shell->caps_lock_delegate()->SetCapsLockEnabled(false);
    return true;
  }
  return false;
}

bool HandleFocusLauncher() {
  Shell* shell = Shell::GetInstance();
  content::RecordAction(content::UserMetricsAction("Accel_Focus_Launcher"));
  return shell->focus_cycler()->FocusWidget(
      Launcher::ForPrimaryDisplay()->shelf_widget());
}

bool HandleLaunchAppN(int n) {
  content::RecordAction(UserMetricsAction("Accel_Launch_App"));
  Launcher::ForPrimaryDisplay()->LaunchAppIndexAt(n);
  return true;
}

bool HandleLaunchLastApp() {
  content::RecordAction(UserMetricsAction("Accel_Launch_Last_App"));
  Launcher::ForPrimaryDisplay()->LaunchAppIndexAt(-1);
  return true;
}

// Magnify the screen
bool HandleMagnifyScreen(int delta_index) {
  if (ash::Shell::GetInstance()->magnification_controller()->IsEnabled()) {
    // TODO(yoshiki): Move the following logic to MagnificationController.
    float scale =
        ash::Shell::GetInstance()->magnification_controller()->GetScale();
    // Calculate rounded logarithm (base kMagnificationScaleFactor) of scale.
    int scale_index =
        std::floor(std::log(scale) / std::log(kMagnificationScaleFactor) + 0.5);

    int new_scale_index = std::max(0, std::min(8, scale_index + delta_index));

    ash::Shell::GetInstance()->magnification_controller()->
        SetScale(std::pow(kMagnificationScaleFactor, new_scale_index), true);
  } else if (ash::Shell::GetInstance()->
             partial_magnification_controller()->is_enabled()) {
    float scale = delta_index > 0 ? kDefaultPartialMagnifiedScale : 1;
    ash::Shell::GetInstance()->partial_magnification_controller()->
        SetScale(scale);
  }

  return true;
}

bool HandleMediaNextTrack() {
  Shell::GetInstance()->media_delegate()->HandleMediaNextTrack();
  return true;
}

bool HandleMediaPlayPause() {
  Shell::GetInstance()->media_delegate()->HandleMediaPlayPause();
  return true;
}

bool HandleMediaPrevTrack() {
  Shell::GetInstance()->media_delegate()->HandleMediaPrevTrack();
  return true;
}

bool HandleNewIncognitoWindow() {
  content::RecordAction(UserMetricsAction("Accel_New_Incognito_Window"));
  bool incognito_allowed =
    Shell::GetInstance()->delegate()->IsIncognitoAllowed();
  if (incognito_allowed)
    Shell::GetInstance()->new_window_delegate()->NewWindow(
        true /* is_incognito */);
  return incognito_allowed;
}

bool HandleNewTab(ui::KeyboardCode key_code) {
  if (key_code == ui::VKEY_T)
    content::RecordAction(content::UserMetricsAction("Accel_NewTab_T"));
  Shell::GetInstance()->new_window_delegate()->NewTab();
  return true;
}

bool HandleNewWindow() {
  content::RecordAction(content::UserMetricsAction("Accel_New_Window"));
  Shell::GetInstance()->new_window_delegate()->NewWindow(
      false /* is_incognito */);
  return true;
}

bool HandleNextIme(ImeControlDelegate* ime_control_delegate,
                   ui::EventType previous_event_type,
                   ui::KeyboardCode previous_key_code) {
  // This check is necessary e.g. not to process the Shift+Alt+
  // ET_KEY_RELEASED accelerator for Chrome OS (see ash/accelerators/
  // accelerator_controller.cc) when Shift+Alt+Tab is pressed and then Tab
  // is released.
  if (previous_event_type == ui::ET_KEY_RELEASED &&
      // Workaround for crbug.com/139556. CJK IME users tend to press
      // Enter (or Space) and Shift+Alt almost at the same time to commit
      // an IME string and then switch from the IME to the English layout.
      // This workaround allows the user to trigger NEXT_IME even if the
      // user presses Shift+Alt before releasing Enter.
      // TODO(nona|mazda): Fix crbug.com/139556 in a cleaner way.
      previous_key_code != ui::VKEY_RETURN &&
      previous_key_code != ui::VKEY_SPACE) {
    // We totally ignore this accelerator.
    // TODO(mazda): Fix crbug.com/158217
    return false;
  }
  content::RecordAction(UserMetricsAction("Accel_Next_Ime"));
  if (ime_control_delegate)
    return ime_control_delegate->HandleNextIme();
  return false;
}

bool HandleOpenFeedbackPage() {
  content::RecordAction(UserMetricsAction("Accel_Open_Feedback_Page"));
  ash::Shell::GetInstance()->new_window_delegate()->OpenFeedbackPage();
  return true;
}

bool HandlePositionCenter() {
  content::RecordAction(UserMetricsAction("Accel_Window_Position_Center"));
  aura::Window* window = wm::GetActiveWindow();
  // Docked windows do not support centering and ignore accelerator.
  if (window && !wm::GetWindowState(window)->IsDocked()) {
    wm::CenterWindow(window);
    return true;
  }
  return false;
}

bool HandlePreviousIme(ImeControlDelegate* ime_control_delegate,
                       const ui::Accelerator& accelerator) {
  content::RecordAction(UserMetricsAction("Accel_Previous_Ime"));
  if (ime_control_delegate)
    return ime_control_delegate->HandlePreviousIme(accelerator);
  return false;
}

bool HandleRestoreTab() {
  content::RecordAction(content::UserMetricsAction("Accel_Restore_Tab"));
  Shell::GetInstance()->new_window_delegate()->RestoreTab();
  return true;
}

bool HandleRotatePaneFocus(Shell::Direction direction) {
  Shell* shell = Shell::GetInstance();
  switch (direction) {
    // TODO(stevet): Not sure if this is the same as IDC_FOCUS_NEXT_PANE.
    case Shell::FORWARD: {
      content::RecordAction(UserMetricsAction("Accel_Focus_Next_Pane"));
      shell->focus_cycler()->RotateFocus(internal::FocusCycler::FORWARD);
      break;
    }
    case Shell::BACKWARD: {
      content::RecordAction(UserMetricsAction("Accel_Focus_Previous_Pane"));
      shell->focus_cycler()->RotateFocus(internal::FocusCycler::BACKWARD);
      break;
    }
  }
  return true;
}

// Rotate the active window.
bool HandleRotateActiveWindow() {
  content::RecordAction(UserMetricsAction("Accel_Rotate_Window"));
  aura::Window* active_window = wm::GetActiveWindow();
  if (active_window) {
    // The rotation animation bases its target transform on the current
    // rotation and position. Since there could be an animation in progress
    // right now, queue this animation so when it starts it picks up a neutral
    // rotation and position. Use replace so we only enqueue one at a time.
    active_window->layer()->GetAnimator()->
        set_preemption_strategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
    active_window->layer()->GetAnimator()->StartAnimation(
        new ui::LayerAnimationSequence(
            new ash::ScreenRotation(360, active_window->layer())));
  }
  return true;
}

gfx::Display::Rotation GetNextRotation(gfx::Display::Rotation current) {
  switch (current) {
    case gfx::Display::ROTATE_0:
      return gfx::Display::ROTATE_90;
    case gfx::Display::ROTATE_90:
      return gfx::Display::ROTATE_180;
    case gfx::Display::ROTATE_180:
      return gfx::Display::ROTATE_270;
    case gfx::Display::ROTATE_270:
      return gfx::Display::ROTATE_0;
  }
  NOTREACHED() << "Unknown rotation:" << current;
  return gfx::Display::ROTATE_0;
}

// Rotates the screen.
bool HandleRotateScreen() {
  content::RecordAction(UserMetricsAction("Accel_Rotate_Window"));
  gfx::Point point = Shell::GetScreen()->GetCursorScreenPoint();
  gfx::Display display = Shell::GetScreen()->GetDisplayNearestPoint(point);
  const DisplayInfo& display_info =
      Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id());
  Shell::GetInstance()->display_manager()->SetDisplayRotation(
      display.id(), GetNextRotation(display_info.rotation()));
  return true;
}

bool HandleScaleReset() {
  internal::DisplayManager* display_manager =
      Shell::GetInstance()->display_manager();
  int64 display_id = display_manager->GetDisplayIdForUIScaling();
  if (display_id == gfx::Display::kInvalidDisplayID)
    return false;

  content::RecordAction(UserMetricsAction("Accel_Scale_Ui_Reset"));

  display_manager->SetDisplayUIScale(display_id, 1.0f);
  return true;
}

bool HandleScaleUI(bool up) {
  internal::DisplayManager* display_manager =
      Shell::GetInstance()->display_manager();
  int64 display_id = display_manager->GetDisplayIdForUIScaling();
  if (display_id == gfx::Display::kInvalidDisplayID)
    return false;

  if (up) {
    content::RecordAction(UserMetricsAction("Accel_Scale_Ui_Up"));
  } else {
    content::RecordAction(UserMetricsAction("Accel_Scale_Ui_Down"));
  }

  const DisplayInfo& display_info = display_manager->GetDisplayInfo(display_id);
  float next_scale =
      internal::DisplayManager::GetNextUIScale(display_info, up);
  display_manager->SetDisplayUIScale(display_id, next_scale);
  return true;
}

bool HandleSwapPrimaryDisplay() {
  content::RecordAction(UserMetricsAction("Accel_Swap_Primary_Display"));
  Shell::GetInstance()->display_controller()->SwapPrimaryDisplay();
  return true;
}

bool HandleShowKeyboardOverlay() {
  content::RecordAction(UserMetricsAction("Accel_Show_Keyboard_Overlay"));
  ash::Shell::GetInstance()->new_window_delegate()->ShowKeyboardOverlay();

  return true;
}

void HandleShowMessageCenterBubble() {
  content::RecordAction(UserMetricsAction("Accel_Show_Message_Center_Bubble"));
  internal::RootWindowController* controller =
    internal::RootWindowController::ForTargetRootWindow();
  internal::StatusAreaWidget* status_area_widget =
    controller->shelf()->status_area_widget();
  if (status_area_widget) {
    WebNotificationTray* notification_tray =
      status_area_widget->web_notification_tray();
    if (notification_tray->visible())
      notification_tray->ShowMessageCenterBubble();
  }
}

bool HandleShowOak() {
  if (CommandLine::ForCurrentProcess()->HasSwitch(
        switches::kAshEnableOak)) {
    oak::ShowOakWindowWithContext(Shell::GetPrimaryRootWindow());
    return true;
  }
  return false;
}

bool HandleShowSystemTrayBubble() {
  content::RecordAction(UserMetricsAction("Accel_Show_System_Tray_Bubble"));
  internal::RootWindowController* controller =
    internal::RootWindowController::ForTargetRootWindow();
  if (!controller->GetSystemTray()->HasSystemBubble()) {
    controller->GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW);
    return true;
  }
  return false;
}

bool HandleShowTaskManager() {
  content::RecordAction(UserMetricsAction("Accel_Show_Task_Manager"));
  Shell::GetInstance()->new_window_delegate()->ShowTaskManager();
  return true;
}

void HandleSilenceSpokenFeedback() {
  content::RecordAction(UserMetricsAction("Accel_Silence_Spoken_Feedback"));

  AccessibilityDelegate* delegate =
      Shell::GetInstance()->accessibility_delegate();
  if (!delegate->IsSpokenFeedbackEnabled())
    return;
  delegate->SilenceSpokenFeedback();
}

bool HandleSwitchIme(ImeControlDelegate* ime_control_delegate,
                     const ui::Accelerator& accelerator) {
  content::RecordAction(UserMetricsAction("Accel_Switch_Ime"));
  if (ime_control_delegate)
    return ime_control_delegate->HandleSwitchIme(accelerator);
  return false;
}

bool HandleTakePartialScreenshot(ScreenshotDelegate* screenshot_delegate) {
  content::RecordAction(UserMetricsAction("Accel_Take_Partial_Screenshot"));
  if (screenshot_delegate) {
    ash::PartialScreenshotView::StartPartialScreenshot(
        screenshot_delegate);
  }
  // Return true to prevent propagation of the key event because
  // this key combination is reserved for partial screenshot.
  return true;
}

bool HandleTakeScreenshot(ScreenshotDelegate* screenshot_delegate) {
  content::RecordAction(UserMetricsAction("Accel_Take_Screenshot"));
  if (screenshot_delegate &&
      screenshot_delegate->CanTakeScreenshot()) {
    screenshot_delegate->HandleTakeScreenshotForAllRootWindows();
  }
  // Return true to prevent propagation of the key event.
  return true;
}

bool HandleToggleAppList(ui::KeyboardCode key_code,
                         ui::EventType previous_event_type,
                         ui::KeyboardCode previous_key_code,
                         const ui::Accelerator& accelerator) {
  // If something else was pressed between the Search key (LWIN)
  // being pressed and released, then ignore the release of the
  // Search key.
  if (key_code == ui::VKEY_LWIN &&
      (previous_event_type == ui::ET_KEY_RELEASED ||
       previous_key_code != ui::VKEY_LWIN))
    return false;
  if (key_code == ui::VKEY_LWIN)
    content::RecordAction(content::UserMetricsAction("Accel_Search_LWin"));
  // When spoken feedback is enabled, we should neither toggle the list nor
  // consume the key since Search+Shift is one of the shortcuts the a11y
  // feature uses. crbug.com/132296
  DCHECK_EQ(ui::VKEY_LWIN, accelerator.key_code());
  if (Shell::GetInstance()->accessibility_delegate()->
      IsSpokenFeedbackEnabled())
    return false;
  ash::Shell::GetInstance()->ToggleAppList(NULL);
  return true;
}

bool HandleToggleCapsLock(ui::KeyboardCode key_code,
                          ui::EventType previous_event_type,
                          ui::KeyboardCode previous_key_code) {
  Shell* shell = Shell::GetInstance();
  if (key_code == ui::VKEY_LWIN) {
    // If something else was pressed between the Search key (LWIN)
    // being pressed and released, then ignore the release of the
    // Search key.
    // TODO(danakj): Releasing Alt first breaks this: crbug.com/166495
    if (previous_event_type == ui::ET_KEY_RELEASED ||
        previous_key_code != ui::VKEY_LWIN)
      return false;
  }
  content::RecordAction(UserMetricsAction("Accel_Toggle_Caps_Lock"));
  shell->caps_lock_delegate()->ToggleCapsLock();
  return true;
}

bool HandleToggleFullscreen(ui::KeyboardCode key_code) {
  if (key_code == ui::VKEY_MEDIA_LAUNCH_APP2) {
    content::RecordAction(UserMetricsAction("Accel_Fullscreen_F4"));
  }
  accelerators::ToggleFullscreen();
  return true;
}

bool HandleToggleRootWindowFullScreen() {
  Shell::GetPrimaryRootWindow()->GetDispatcher()->host()->ToggleFullScreen();
  return true;
}

bool HandleWindowSnap(int action) {
  wm::WindowState* window_state = wm::GetActiveWindowState();
  // Disable window snapping shortcut key for full screen window due to
  // http://crbug.com/135487.
  if (!window_state ||
      window_state->window()->type() != aura::client::WINDOW_TYPE_NORMAL ||
      window_state->IsFullscreen()) {
    return false;
  }

  if (action == WINDOW_SNAP_LEFT) {
    content::RecordAction(UserMetricsAction("Accel_Window_Snap_Left"));
  } else {
    content::RecordAction(UserMetricsAction("Accel_Window_Snap_Right"));
  }

  internal::SnapSizer::SnapWindow(window_state,
      action == WINDOW_SNAP_LEFT ? internal::SnapSizer::LEFT_EDGE :
      internal::SnapSizer::RIGHT_EDGE);
  return true;
}

bool HandleWindowMinimize() {
  content::RecordAction(
      content::UserMetricsAction("Accel_Toggle_Minimized_Minus"));
  return accelerators::ToggleMinimized();
}

#if defined(OS_CHROMEOS)
bool HandleAddRemoveDisplay() {
  content::RecordAction(UserMetricsAction("Accel_Add_Remove_Display"));
  Shell::GetInstance()->display_manager()->AddRemoveDisplay();
  return true;
}

bool HandleCrosh() {
  content::RecordAction(UserMetricsAction("Accel_Open_Crosh"));

  Shell::GetInstance()->new_window_delegate()->OpenCrosh();
  return true;
}

bool HandleFileManager() {
  content::RecordAction(UserMetricsAction("Accel_Open_File_Manager"));

  Shell::GetInstance()->new_window_delegate()->OpenFileManager();
  return true;
}

bool HandleLock(ui::KeyboardCode key_code) {
  content::RecordAction(UserMetricsAction("Accel_LockScreen_L"));
  Shell::GetInstance()->session_state_delegate()->LockScreen();
  return true;
}

bool HandleCycleUser(SessionStateDelegate::CycleUser cycle_user) {
  if (!Shell::GetInstance()->delegate()->IsMultiProfilesEnabled())
    return false;
  ash::SessionStateDelegate* delegate =
      ash::Shell::GetInstance()->session_state_delegate();
  if (delegate->NumberOfLoggedInUsers() <= 1)
    return false;
  MultiProfileUMA::RecordSwitchActiveUser(
      MultiProfileUMA::SWITCH_ACTIVE_USER_BY_ACCELERATOR);
  switch (cycle_user) {
    case SessionStateDelegate::CYCLE_TO_NEXT_USER:
      content::RecordAction(UserMetricsAction("Accel_Switch_To_Next_User"));
      break;
    case SessionStateDelegate::CYCLE_TO_PREVIOUS_USER:
      content::RecordAction(UserMetricsAction("Accel_Switch_To_Previous_User"));
      break;
  }
  delegate->CycleActiveUser(cycle_user);
  return true;
}

bool HandleToggleMirrorMode() {
  content::RecordAction(UserMetricsAction("Accel_Toggle_Mirror_Mode"));
  Shell::GetInstance()->display_controller()->ToggleMirrorMode();
  return true;
}

bool HandleToggleSpokenFeedback() {
  content::RecordAction(UserMetricsAction("Accel_Toggle_Spoken_Feedback"));

  Shell::GetInstance()->accessibility_delegate()->
      ToggleSpokenFeedback(A11Y_NOTIFICATION_SHOW);
  return true;
}

bool HandleTouchHudClear() {
  internal::RootWindowController* controller =
      internal::RootWindowController::ForTargetRootWindow();
  if (controller->touch_hud_debug()) {
    controller->touch_hud_debug()->Clear();
    return true;
  }
  return false;
}

bool HandleTouchHudModeChange() {
  internal::RootWindowController* controller =
      internal::RootWindowController::ForTargetRootWindow();
  if (controller->touch_hud_debug()) {
    controller->touch_hud_debug()->ChangeToNextMode();
    return true;
  }
  return false;
}

bool HandleTouchHudProjectToggle() {
  content::RecordAction(UserMetricsAction("Accel_Touch_Hud_Clear"));
  bool enabled = Shell::GetInstance()->is_touch_hud_projection_enabled();
  Shell::GetInstance()->SetTouchHudProjectionEnabled(!enabled);
  return true;
}

#endif  // defined(OS_CHROMEOS)

// Debug print methods.

bool HandlePrintLayerHierarchy() {
  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
  for (size_t i = 0; i < root_windows.size(); ++i) {
    ui::PrintLayerHierarchy(
        root_windows[i]->layer(),
        root_windows[i]->GetDispatcher()->GetLastMouseLocationInRoot());
  }
  return true;
}

bool HandlePrintViewHierarchy() {
  aura::Window* active_window = ash::wm::GetActiveWindow();
  if (!active_window)
    return true;
  views::Widget* browser_widget =
      views::Widget::GetWidgetForNativeWindow(active_window);
  if (!browser_widget)
    return true;
  views::PrintViewHierarchy(browser_widget->GetRootView());
  return true;
}

void PrintWindowHierarchy(aura::Window* window,
                          int indent,
                          std::ostringstream* out) {
  std::string indent_str(indent, ' ');
  std::string name(window->name());
  if (name.empty())
    name = "\"\"";
  *out << indent_str << name << " (" << window << ")"
       << " type=" << window->type()
       << (wm::IsActiveWindow(window) ? " [active] " : " ")
       << (window->IsVisible() ? " visible " : " ")
       << window->bounds().ToString()
       << '\n';

  for (size_t i = 0; i < window->children().size(); ++i)
    PrintWindowHierarchy(window->children()[i], indent + 3, out);
}

bool HandlePrintWindowHierarchy() {
  Shell::RootWindowControllerList controllers =
      Shell::GetAllRootWindowControllers();
  for (size_t i = 0; i < controllers.size(); ++i) {
    std::ostringstream out;
    out << "RootWindow " << i << ":\n";
    PrintWindowHierarchy(controllers[i]->root_window(), 0, &out);
    // Error so logs can be collected from end-users.
    LOG(ERROR) << out.str();
  }
  return true;
}

bool HandlePrintUIHierarchies() {
  // This is a separate command so the user only has to hit one key to generate
  // all the logs. Developers use the individual dumps repeatedly, so keep
  // those as separate commands to avoid spamming their logs.
  HandlePrintLayerHierarchy();
  HandlePrintWindowHierarchy();
  HandlePrintViewHierarchy();
  return true;
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// AcceleratorControllerContext, public:

AcceleratorControllerContext::AcceleratorControllerContext() {
  current_accelerator_.set_type(ui::ET_UNKNOWN);
  previous_accelerator_.set_type(ui::ET_UNKNOWN);
}

void AcceleratorControllerContext::UpdateContext(
    const ui::Accelerator& accelerator) {
  previous_accelerator_ = current_accelerator_;
  current_accelerator_ = accelerator;
}

////////////////////////////////////////////////////////////////////////////////
// AcceleratorController, public:

AcceleratorController::AcceleratorController()
    : accelerator_manager_(new ui::AcceleratorManager) {
  Init();
}

AcceleratorController::~AcceleratorController() {
}

void AcceleratorController::Init() {
  for (size_t i = 0; i < kActionsAllowedAtLoginOrLockScreenLength; ++i) {
    actions_allowed_at_login_screen_.insert(
        kActionsAllowedAtLoginOrLockScreen[i]);
    actions_allowed_at_lock_screen_.insert(
        kActionsAllowedAtLoginOrLockScreen[i]);
  }
  for (size_t i = 0; i < kActionsAllowedAtLockScreenLength; ++i)
    actions_allowed_at_lock_screen_.insert(kActionsAllowedAtLockScreen[i]);
  for (size_t i = 0; i < kActionsAllowedAtModalWindowLength; ++i)
    actions_allowed_at_modal_window_.insert(kActionsAllowedAtModalWindow[i]);
  for (size_t i = 0; i < kReservedActionsLength; ++i)
    reserved_actions_.insert(kReservedActions[i]);
  for (size_t i = 0; i < kNonrepeatableActionsLength; ++i)
    nonrepeatable_actions_.insert(kNonrepeatableActions[i]);
  for (size_t i = 0; i < kActionsAllowedInAppModeLength; ++i)
    actions_allowed_in_app_mode_.insert(kActionsAllowedInAppMode[i]);
  for (size_t i = 0; i < kActionsNeedingWindowLength; ++i)
    actions_needing_window_.insert(kActionsNeedingWindow[i]);

  RegisterAccelerators(kAcceleratorData, kAcceleratorDataLength);

#if !defined(NDEBUG)
  RegisterAccelerators(kDesktopAcceleratorData, kDesktopAcceleratorDataLength);
#endif

  if (DebugShortcutsEnabled()) {
    RegisterAccelerators(kDebugAcceleratorData, kDebugAcceleratorDataLength);
    for (size_t i = 0; i < kReservedDebugActionsLength; ++i)
      reserved_actions_.insert(kReservedDebugActions[i]);
  }

#if defined(OS_CHROMEOS)
  keyboard_brightness_control_delegate_.reset(
      new KeyboardBrightnessController());
#endif
}

void AcceleratorController::Register(const ui::Accelerator& accelerator,
                                     ui::AcceleratorTarget* target) {
  accelerator_manager_->Register(accelerator,
                                 ui::AcceleratorManager::kNormalPriority,
                                 target);
}

void AcceleratorController::Unregister(const ui::Accelerator& accelerator,
                                       ui::AcceleratorTarget* target) {
  accelerator_manager_->Unregister(accelerator, target);
}

void AcceleratorController::UnregisterAll(ui::AcceleratorTarget* target) {
  accelerator_manager_->UnregisterAll(target);
}

bool AcceleratorController::Process(const ui::Accelerator& accelerator) {
  if (ime_control_delegate_) {
    return accelerator_manager_->Process(
        ime_control_delegate_->RemapAccelerator(accelerator));
  }
  return accelerator_manager_->Process(accelerator);
}

bool AcceleratorController::IsRegistered(
    const ui::Accelerator& accelerator) const {
  return accelerator_manager_->GetCurrentTarget(accelerator) != NULL;
}

bool AcceleratorController::IsReservedAccelerator(
    const ui::Accelerator& accelerator) const {
  const ui::Accelerator remapped_accelerator = ime_control_delegate_.get() ?
      ime_control_delegate_->RemapAccelerator(accelerator) : accelerator;

  std::map<ui::Accelerator, int>::const_iterator iter =
      accelerators_.find(remapped_accelerator);
  if (iter == accelerators_.end())
    return false;  // not an accelerator.

  return reserved_actions_.find(iter->second) != reserved_actions_.end();
}

bool AcceleratorController::PerformAction(int action,
                                          const ui::Accelerator& accelerator) {
  ash::Shell* shell = ash::Shell::GetInstance();
  if (!shell->session_state_delegate()->IsActiveUserSessionStarted() &&
      actions_allowed_at_login_screen_.find(action) ==
      actions_allowed_at_login_screen_.end()) {
    return false;
  }
  if (shell->session_state_delegate()->IsScreenLocked() &&
      actions_allowed_at_lock_screen_.find(action) ==
      actions_allowed_at_lock_screen_.end()) {
    return false;
  }
  if (shell->IsSystemModalWindowOpen() &&
      actions_allowed_at_modal_window_.find(action) ==
      actions_allowed_at_modal_window_.end()) {
    // Note: we return true. This indicates the shortcut is handled
    // and will not be passed to the modal window. This is important
    // for things like Alt+Tab that would cause an undesired effect
    // in the modal window by cycling through its window elements.
    return true;
  }
  if (shell->delegate()->IsRunningInForcedAppMode() &&
      actions_allowed_in_app_mode_.find(action) ==
      actions_allowed_in_app_mode_.end()) {
    return false;
  }
  if (MruWindowTracker::BuildWindowList(false).empty() &&
      actions_needing_window_.find(action) != actions_needing_window_.end()) {
    Shell::GetInstance()->accessibility_delegate()->TriggerAccessibilityAlert(
        A11Y_ALERT_WINDOW_NEEDED);
    return true;
  }

  const ui::KeyboardCode key_code = accelerator.key_code();
  // PerformAction() is performed from gesture controllers and passes
  // empty Accelerator() instance as the second argument. Such events
  // should never be suspended.
  const bool gesture_event = key_code == ui::VKEY_UNKNOWN;

  // Ignore accelerators invoked as repeated (while holding a key for a long
  // time, if their handling is nonrepeatable.
  if (nonrepeatable_actions_.find(action) != nonrepeatable_actions_.end() &&
      context_.repeated() && !gesture_event) {
    return true;
  }
  // Type of the previous accelerator. Used by NEXT_IME and DISABLE_CAPS_LOCK.
  const ui::EventType previous_event_type =
    context_.previous_accelerator().type();
  const ui::KeyboardCode previous_key_code =
    context_.previous_accelerator().key_code();

  // You *MUST* return true when some action is performed. Otherwise, this
  // function might be called *twice*, via BrowserView::PreHandleKeyboardEvent
  // and BrowserView::HandleKeyboardEvent, for a single accelerator press.
  //
  // If your accelerator invokes more than one line of code, please either
  // implement it in your module's controller code (like TOGGLE_MIRROR_MODE
  // below) or pull it into a HandleFoo() function above.
  switch (action) {
    case ACCESSIBLE_FOCUS_NEXT:
      return HandleAccessibleFocusCycle(false);
    case ACCESSIBLE_FOCUS_PREVIOUS:
      return HandleAccessibleFocusCycle(true);
    case CYCLE_BACKWARD_MRU:
      return HandleCycleBackwardMRU(accelerator);
    case CYCLE_FORWARD_MRU:
      return HandleCycleForwardMRU(accelerator);
    case CYCLE_LINEAR:
      return HandleCycleLinear(accelerator);
#if defined(OS_CHROMEOS)
    case ADD_REMOVE_DISPLAY:
      return HandleAddRemoveDisplay();
    case TOGGLE_MIRROR_MODE:
      return HandleToggleMirrorMode();
    case LOCK_SCREEN:
      return HandleLock(key_code);
    case OPEN_FILE_MANAGER:
      return HandleFileManager();
    case OPEN_CROSH:
      return HandleCrosh();
    case SILENCE_SPOKEN_FEEDBACK:
      HandleSilenceSpokenFeedback();
      break;
    case SWAP_PRIMARY_DISPLAY:
      return HandleSwapPrimaryDisplay();
    case SWITCH_TO_NEXT_USER:
      return HandleCycleUser(SessionStateDelegate::CYCLE_TO_NEXT_USER);
    case SWITCH_TO_PREVIOUS_USER:
      return HandleCycleUser(SessionStateDelegate::CYCLE_TO_PREVIOUS_USER);
    case TOGGLE_SPOKEN_FEEDBACK:
      return HandleToggleSpokenFeedback();
    case TOGGLE_WIFI:
      Shell::GetInstance()->system_tray_notifier()->NotifyRequestToggleWifi();
      return true;
    case TOUCH_HUD_CLEAR:
      return HandleTouchHudClear();
    case TOUCH_HUD_MODE_CHANGE:
      return HandleTouchHudModeChange();
    case TOUCH_HUD_PROJECTION_TOGGLE:
      return HandleTouchHudProjectToggle();
    case DISABLE_GPU_WATCHDOG:
      content::GpuDataManager::GetInstance()->DisableGpuWatchdog();
      return true;
#endif  // OS_CHROMEOS
    case OPEN_FEEDBACK_PAGE:
      return HandleOpenFeedbackPage();
    case EXIT:
      // UMA metrics are recorded in the handler.
      exit_warning_handler_.HandleAccelerator();
      return true;
    case NEW_INCOGNITO_WINDOW:
      return HandleNewIncognitoWindow();
    case NEW_TAB:
      return HandleNewTab(key_code);
    case NEW_WINDOW:
      return HandleNewWindow();
    case RESTORE_TAB:
      return HandleRestoreTab();
    case TAKE_SCREENSHOT:
      return HandleTakeScreenshot(screenshot_delegate_.get());
    case TAKE_PARTIAL_SCREENSHOT:
      return HandleTakePartialScreenshot(screenshot_delegate_.get());
    case TOGGLE_APP_LIST:
      return HandleToggleAppList(
          key_code, previous_event_type, previous_key_code, accelerator);
    case DISABLE_CAPS_LOCK:
      return HandleDisableCapsLock(
          key_code, previous_event_type, previous_key_code);
    case TOGGLE_CAPS_LOCK:
      return HandleToggleCapsLock(
          key_code, previous_event_type, previous_key_code);
    case BRIGHTNESS_DOWN:
      if (brightness_control_delegate_)
        return brightness_control_delegate_->HandleBrightnessDown(accelerator);
      break;
    case BRIGHTNESS_UP:
      if (brightness_control_delegate_)
        return brightness_control_delegate_->HandleBrightnessUp(accelerator);
      break;
    case KEYBOARD_BRIGHTNESS_DOWN:
      if (keyboard_brightness_control_delegate_)
        return keyboard_brightness_control_delegate_->
            HandleKeyboardBrightnessDown(accelerator);
      break;
    case KEYBOARD_BRIGHTNESS_UP:
      if (keyboard_brightness_control_delegate_)
        return keyboard_brightness_control_delegate_->
            HandleKeyboardBrightnessUp(accelerator);
      break;
    case VOLUME_MUTE: {
      ash::VolumeControlDelegate* volume_delegate =
          shell->system_tray_delegate()->GetVolumeControlDelegate();
      return volume_delegate && volume_delegate->HandleVolumeMute(accelerator);
    }
    case VOLUME_DOWN: {
      ash::VolumeControlDelegate* volume_delegate =
          shell->system_tray_delegate()->GetVolumeControlDelegate();
      return volume_delegate && volume_delegate->HandleVolumeDown(accelerator);
    }
    case VOLUME_UP: {
      ash::VolumeControlDelegate* volume_delegate =
          shell->system_tray_delegate()->GetVolumeControlDelegate();
      return volume_delegate && volume_delegate->HandleVolumeUp(accelerator);
    }
    case FOCUS_LAUNCHER:
      return HandleFocusLauncher();
    case FOCUS_NEXT_PANE:
      return HandleRotatePaneFocus(Shell::FORWARD);
    case FOCUS_PREVIOUS_PANE:
      return HandleRotatePaneFocus(Shell::BACKWARD);
    case SHOW_KEYBOARD_OVERLAY:
      return HandleShowKeyboardOverlay();
    case SHOW_OAK:
      return HandleShowOak();
    case SHOW_SYSTEM_TRAY_BUBBLE:
      return HandleShowSystemTrayBubble();
    case SHOW_MESSAGE_CENTER_BUBBLE:
      HandleShowMessageCenterBubble();
      break;
    case SHOW_TASK_MANAGER:
      return HandleShowTaskManager();
    case NEXT_IME:
      return HandleNextIme(
          ime_control_delegate_.get(), previous_event_type, previous_key_code);
    case PREVIOUS_IME:
      return HandlePreviousIme(ime_control_delegate_.get(), accelerator);
    case PRINT_UI_HIERARCHIES:
      return HandlePrintUIHierarchies();
    case SWITCH_IME:
      return HandleSwitchIme(ime_control_delegate_.get(), accelerator);
    case LAUNCH_APP_0:
      return HandleLaunchAppN(0);
    case LAUNCH_APP_1:
      return HandleLaunchAppN(1);
    case LAUNCH_APP_2:
      return HandleLaunchAppN(2);
    case LAUNCH_APP_3:
      return HandleLaunchAppN(3);
    case LAUNCH_APP_4:
      return HandleLaunchAppN(4);
    case LAUNCH_APP_5:
      return HandleLaunchAppN(5);
    case LAUNCH_APP_6:
      return HandleLaunchAppN(6);
    case LAUNCH_APP_7:
      return HandleLaunchAppN(7);
    case LAUNCH_LAST_APP:
      return HandleLaunchLastApp();
    case WINDOW_SNAP_LEFT:
    case WINDOW_SNAP_RIGHT:
      return HandleWindowSnap(action);
    case WINDOW_MINIMIZE:
      return HandleWindowMinimize();
    case TOGGLE_FULLSCREEN:
      return HandleToggleFullscreen(key_code);
    case TOGGLE_MAXIMIZED:
      accelerators::ToggleMaximized();
      return true;
    case WINDOW_POSITION_CENTER:
     return HandlePositionCenter();
    case SCALE_UI_UP:
      return HandleScaleUI(true /* up */);
    case SCALE_UI_DOWN:
      return HandleScaleUI(false /* down */);
    case SCALE_UI_RESET:
      return HandleScaleReset();
    case ROTATE_WINDOW:
      return HandleRotateActiveWindow();
    case ROTATE_SCREEN:
      return HandleRotateScreen();
    case TOGGLE_DESKTOP_BACKGROUND_MODE:
      return debug::CycleDesktopBackgroundMode();
    case TOGGLE_ROOT_WINDOW_FULL_SCREEN:
      return HandleToggleRootWindowFullScreen();
    case DEBUG_TOGGLE_DEVICE_SCALE_FACTOR:
      Shell::GetInstance()->display_manager()->ToggleDisplayScaleFactor();
      return true;
    case DEBUG_TOGGLE_SHOW_DEBUG_BORDERS:
      ash::debug::ToggleShowDebugBorders();
      return true;
    case DEBUG_TOGGLE_SHOW_FPS_COUNTER:
      ash::debug::ToggleShowFpsCounter();
      return true;
    case DEBUG_TOGGLE_SHOW_PAINT_RECTS:
      ash::debug::ToggleShowPaintRects();
      return true;
    case MAGNIFY_SCREEN_ZOOM_IN:
      return HandleMagnifyScreen(1);
    case MAGNIFY_SCREEN_ZOOM_OUT:
      return HandleMagnifyScreen(-1);
    case MEDIA_NEXT_TRACK:
      return HandleMediaNextTrack();
    case MEDIA_PLAY_PAUSE:
       return HandleMediaPlayPause();
    case MEDIA_PREV_TRACK:
       return HandleMediaPrevTrack();
    case POWER_PRESSED:  // fallthrough
    case POWER_RELEASED:
#if defined(OS_CHROMEOS)
      if (!base::SysInfo::IsRunningOnChromeOS()) {
        // There is no powerd in linux desktop, so call the
        // PowerButtonController here.
        Shell::GetInstance()->power_button_controller()->
            OnPowerButtonEvent(action == POWER_PRESSED, base::TimeTicks());
      }
#endif
      // We don't do anything with these at present on the device,
      // (power button events are reported to us from powerm via
      // D-BUS), but we consume them to prevent them from getting
      // passed to apps -- see http://crbug.com/146609.
      return true;
    case LOCK_PRESSED:
    case LOCK_RELEASED:
      Shell::GetInstance()->power_button_controller()->
          OnLockButtonEvent(action == LOCK_PRESSED, base::TimeTicks());
      return true;
    case PRINT_LAYER_HIERARCHY:
      return HandlePrintLayerHierarchy();
    case PRINT_VIEW_HIERARCHY:
      return HandlePrintViewHierarchy();
    case PRINT_WINDOW_HIERARCHY:
      return HandlePrintWindowHierarchy();
    default:
      NOTREACHED() << "Unhandled action " << action;
  }
  return false;
}

void AcceleratorController::SetBrightnessControlDelegate(
    scoped_ptr<BrightnessControlDelegate> brightness_control_delegate) {
  // Install brightness control delegate only when internal
  // display exists.
  if (Shell::GetInstance()->display_manager()->HasInternalDisplay() ||
      CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kAshEnableBrightnessControl)) {
    brightness_control_delegate_ = brightness_control_delegate.Pass();
  }
}

void AcceleratorController::SetImeControlDelegate(
    scoped_ptr<ImeControlDelegate> ime_control_delegate) {
  ime_control_delegate_ = ime_control_delegate.Pass();
}

void AcceleratorController::SetScreenshotDelegate(
    scoped_ptr<ScreenshotDelegate> screenshot_delegate) {
  screenshot_delegate_ = screenshot_delegate.Pass();
}

////////////////////////////////////////////////////////////////////////////////
// AcceleratorController, ui::AcceleratorTarget implementation:

bool AcceleratorController::AcceleratorPressed(
    const ui::Accelerator& accelerator) {
  std::map<ui::Accelerator, int>::const_iterator it =
      accelerators_.find(accelerator);
  DCHECK(it != accelerators_.end());
  return PerformAction(static_cast<AcceleratorAction>(it->second), accelerator);
}

void AcceleratorController::RegisterAccelerators(
    const AcceleratorData accelerators[],
    size_t accelerators_length) {
  for (size_t i = 0; i < accelerators_length; ++i) {
    ui::Accelerator accelerator(accelerators[i].keycode,
                                accelerators[i].modifiers);
    accelerator.set_type(accelerators[i].trigger_on_press ?
                         ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED);
    Register(accelerator, this);
    accelerators_.insert(
        std::make_pair(accelerator, accelerators[i].action));
  }
}

void AcceleratorController::SetKeyboardBrightnessControlDelegate(
    scoped_ptr<KeyboardBrightnessControlDelegate>
    keyboard_brightness_control_delegate) {
  keyboard_brightness_control_delegate_ =
      keyboard_brightness_control_delegate.Pass();
}

bool AcceleratorController::CanHandleAccelerators() const {
  return true;
}

}  // namespace ash
