summaryrefslogtreecommitdiffstats
path: root/ash/accelerators
diff options
context:
space:
mode:
authorsschmitz@chromium.org <sschmitz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-15 08:48:03 +0000
committersschmitz@chromium.org <sschmitz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-15 08:48:03 +0000
commit059c8d351d5083744525c595110f730081cf5280 (patch)
tree249e08b2fbbe8ff215b17ee21eb59d902598e527 /ash/accelerators
parente9304b9fefc5deeeaa99363945ab7dd1bd6260be (diff)
downloadchromium_src-059c8d351d5083744525c595110f730081cf5280.zip
chromium_src-059c8d351d5083744525c595110f730081cf5280.tar.gz
chromium_src-059c8d351d5083744525c595110f730081cf5280.tar.bz2
Unify and change logout/sleep/lock shortcuts
This CL implements an exit warning and requires the user to hold the exit shortcut for a while, before actually exiting. This is to prevent accidental exits due shortcut mistakes. Expert user can exit quickly with a double press. BUG=225903 R=sky@chromium.org TEST=manual out/Debug/ash_unittests --gtest_filter='AcceleratorControllerTest.ExitWarningHandlerTest*' Review URL: https://chromiumcodereview.appspot.com/14587007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200204 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/accelerators')
-rw-r--r--ash/accelerators/accelerator_controller.cc5
-rw-r--r--ash/accelerators/accelerator_controller.h8
-rw-r--r--ash/accelerators/accelerator_controller_unittest.cc97
-rw-r--r--ash/accelerators/accelerator_table.cc12
-rw-r--r--ash/accelerators/accelerator_table.h3
-rw-r--r--ash/accelerators/exit_warning_handler.cc196
-rw-r--r--ash/accelerators/exit_warning_handler.h126
7 files changed, 440 insertions, 7 deletions
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index 2c6ca35..daa013a 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -574,8 +574,9 @@ bool AcceleratorController::PerformAction(int action,
case OPEN_FEEDBACK_PAGE:
ash::Shell::GetInstance()->delegate()->OpenFeedbackPage();
return true;
- case EXIT:
- Shell::GetInstance()->delegate()->Exit();
+ case EXIT_PRESSED:
+ case EXIT_RELEASED:
+ exit_warning_handler_.HandleExitKey(action == EXIT_PRESSED);
return true;
case NEW_INCOGNITO_WINDOW:
Shell::GetInstance()->delegate()->NewWindow(true /* is_incognito */);
diff --git a/ash/accelerators/accelerator_controller.h b/ash/accelerators/accelerator_controller.h
index 53ed723..b1e4bfc 100644
--- a/ash/accelerators/accelerator_controller.h
+++ b/ash/accelerators/accelerator_controller.h
@@ -8,6 +8,7 @@
#include <map>
#include <set>
+#include "ash/accelerators/exit_warning_handler.h"
#include "ash/ash_export.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
@@ -23,6 +24,7 @@ namespace ash {
struct AcceleratorData;
class BrightnessControlDelegate;
+class ExitWarningHandler;
class ImeControlDelegate;
class KeyboardBrightnessControlDelegate;
class ScreenshotDelegate;
@@ -115,6 +117,11 @@ class ASH_EXPORT AcceleratorController : public ui::AcceleratorTarget {
return &context_;
}
+ // Provides access to the ExitWarningHandler for testing.
+ ExitWarningHandler* GetExitWarningHandlerForTest() {
+ return &exit_warning_handler_;
+ }
+
private:
FRIEND_TEST_ALL_PREFIXES(AcceleratorControllerTest, GlobalAccelerators);
@@ -134,6 +141,7 @@ class ASH_EXPORT AcceleratorController : public ui::AcceleratorTarget {
// TODO(derat): BrightnessControlDelegate is also used by the system tray;
// move it outside of this class.
scoped_ptr<BrightnessControlDelegate> brightness_control_delegate_;
+ ExitWarningHandler exit_warning_handler_;
scoped_ptr<ImeControlDelegate> ime_control_delegate_;
scoped_ptr<KeyboardBrightnessControlDelegate>
keyboard_brightness_control_delegate_;
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index 7ef53ff..292cc3e 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -321,6 +321,26 @@ class AcceleratorControllerTest : public test::AshTestBase {
static AcceleratorController* GetController();
static bool ProcessWithContext(const ui::Accelerator& accelerator);
+ // Several functions to access ExitWarningHandler (as friend).
+ static void StubForTest(ExitWarningHandler& ewh) {
+ ewh.stub_timers_for_test_ = true;
+ }
+ static void SimulateTimer1Expired(ExitWarningHandler& ewh) {
+ ewh.Timer1Action();
+ }
+ static void SimulateTimer2Expired(ExitWarningHandler& ewh) {
+ ewh.Timer2Action();
+ }
+ 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;
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(AcceleratorControllerTest);
};
@@ -336,6 +356,72 @@ bool AcceleratorControllerTest::ProcessWithContext(
return controller->Process(accelerator);
}
+// Quick double press of exit key => exiting
+TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestDoublePress) {
+ ExitWarningHandler ewh;
+ StubForTest(ewh);
+ EXPECT_TRUE(is_idle(ewh));
+ EXPECT_FALSE(is_ui_shown(ewh));
+
+ ewh.HandleExitKey(true);
+ EXPECT_TRUE(is_ui_shown(ewh));
+ ewh.HandleExitKey(false);
+ ewh.HandleExitKey(true); // double press
+ SimulateTimer1Expired(ewh); // simulate double press timer expired
+ SimulateTimer2Expired(ewh); // simulate long hold timer expired
+ ewh.HandleExitKey(false);
+ EXPECT_FALSE(is_ui_shown(ewh));
+ EXPECT_TRUE(is_exiting(ewh));
+}
+
+// Long hold of exit key => exiting
+TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestLongHold) {
+ ExitWarningHandler ewh;
+ StubForTest(ewh);
+ EXPECT_TRUE(is_idle(ewh));
+ EXPECT_FALSE(is_ui_shown(ewh));
+
+ ewh.HandleExitKey(true);
+ EXPECT_TRUE(is_ui_shown(ewh));
+ SimulateTimer1Expired(ewh); // simulate double press timer expired
+ SimulateTimer2Expired(ewh); // simulate long hold timer expired
+ ewh.HandleExitKey(false); // release after long hold
+ EXPECT_FALSE(is_ui_shown(ewh));
+ EXPECT_TRUE(is_exiting(ewh));
+}
+
+// Release of exit key before hold time limit => cancel
+TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestEarlyRelease) {
+ ExitWarningHandler ewh;
+ StubForTest(ewh);
+ EXPECT_TRUE(is_idle(ewh));
+ EXPECT_FALSE(is_ui_shown(ewh));
+
+ ewh.HandleExitKey(true);
+ EXPECT_TRUE(is_ui_shown(ewh));
+ SimulateTimer1Expired(ewh); // simulate double press timer expired
+ ewh.HandleExitKey(false); // release before long hold limit
+ SimulateTimer2Expired(ewh); // simulate long hold timer expired
+ EXPECT_FALSE(is_ui_shown(ewh));
+ EXPECT_TRUE(is_idle(ewh));
+}
+
+// Release of exit key before double press limit => cancel.
+TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestQuickRelease) {
+ ExitWarningHandler ewh;
+ StubForTest(ewh);
+ EXPECT_TRUE(is_idle(ewh));
+ EXPECT_FALSE(is_ui_shown(ewh));
+
+ ewh.HandleExitKey(true);
+ EXPECT_TRUE(is_ui_shown(ewh));
+ ewh.HandleExitKey(false); // release before double press limit
+ SimulateTimer1Expired(ewh); // simulate double press timer expired
+ SimulateTimer2Expired(ewh); // simulate long hold timer expired
+ EXPECT_FALSE(is_ui_shown(ewh));
+ EXPECT_TRUE(is_idle(ewh));
+}
+
TEST_F(AcceleratorControllerTest, Register) {
const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
TestTarget target;
@@ -860,8 +946,19 @@ TEST_F(AcceleratorControllerTest, GlobalAccelerators) {
#if !defined(OS_WIN)
// Exit
+ ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
+ ASSERT_TRUE(!!ewh);
+ StubForTest(*ewh);
+ EXPECT_TRUE(is_idle(*ewh));
+ EXPECT_FALSE(is_ui_shown(*ewh));
EXPECT_TRUE(ProcessWithContext(
ui::Accelerator(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
+ EXPECT_FALSE(is_idle(*ewh));
+ EXPECT_TRUE(is_ui_shown(*ewh));
+ SimulateTimer1Expired(*ewh);
+ SimulateTimer2Expired(*ewh);
+ EXPECT_FALSE(is_ui_shown(*ewh));
+ EXPECT_TRUE(is_exiting(*ewh));
#endif
// New tab
diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc
index 62e4d81..d9a6813 100644
--- a/ash/accelerators/accelerator_table.cc
+++ b/ash/accelerators/accelerator_table.cc
@@ -73,7 +73,8 @@ const AcceleratorData kAcceleratorData[] = {
#endif // defined(OS_CHROMEOS)
{ true, ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, OPEN_FEEDBACK_PAGE },
#if !defined(OS_WIN)
- { true, ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, EXIT },
+ { true, ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, EXIT_PRESSED },
+ { false, ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, EXIT_RELEASED },
#endif
{ true, ui::VKEY_I, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN,
TOUCH_HUD_MODE_CHANGE },
@@ -276,7 +277,8 @@ const size_t kActionsAllowedAtLoginOrLockScreenLength =
arraysize(kActionsAllowedAtLoginOrLockScreen);
const AcceleratorAction kActionsAllowedAtLockScreen[] = {
- EXIT,
+ EXIT_PRESSED,
+ EXIT_RELEASED
};
const size_t kActionsAllowedAtLockScreenLength =
@@ -286,7 +288,8 @@ const AcceleratorAction kActionsAllowedAtModalWindow[] = {
BRIGHTNESS_DOWN,
BRIGHTNESS_UP,
DISABLE_CAPS_LOCK,
- EXIT,
+ EXIT_PRESSED,
+ EXIT_RELEASED,
KEYBOARD_BRIGHTNESS_DOWN,
KEYBOARD_BRIGHTNESS_UP,
MAGNIFY_SCREEN_ZOOM_IN,
@@ -348,7 +351,8 @@ const AcceleratorAction kActionsAllowedInAppMode[] = {
CYCLE_FORWARD_LINEAR,
CYCLE_FORWARD_MRU,
DISABLE_CAPS_LOCK,
- EXIT,
+ EXIT_PRESSED,
+ EXIT_RELEASED,
KEYBOARD_BRIGHTNESS_DOWN,
KEYBOARD_BRIGHTNESS_UP,
MAGNIFY_SCREEN_ZOOM_IN, // Control+F7
diff --git a/ash/accelerators/accelerator_table.h b/ash/accelerators/accelerator_table.h
index ca2d2701..70e57d8d 100644
--- a/ash/accelerators/accelerator_table.h
+++ b/ash/accelerators/accelerator_table.h
@@ -28,7 +28,8 @@ enum AcceleratorAction {
DEBUG_TOGGLE_SHOW_FPS_COUNTER,
DEBUG_TOGGLE_SHOW_PAINT_RECTS,
DISABLE_CAPS_LOCK,
- EXIT,
+ EXIT_PRESSED,
+ EXIT_RELEASED,
FOCUS_LAUNCHER,
FOCUS_NEXT_PANE,
FOCUS_PREVIOUS_PANE,
diff --git a/ash/accelerators/exit_warning_handler.cc b/ash/accelerators/exit_warning_handler.cc
new file mode 100644
index 0000000..a285560
--- /dev/null
+++ b/ash/accelerators/exit_warning_handler.cc
@@ -0,0 +1,196 @@
+// Copyright 2013 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/exit_warning_handler.h"
+
+#include "ash/shell.h"
+#include "ash/shell_delegate.h"
+#include "ash/shell_window_ids.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time.h"
+#include "base/timer.h"
+#include "grit/ash_strings.h"
+#include "ui/aura/root_window.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+
+namespace ash {
+namespace {
+
+const int64 kDoublePressTimeOutMilliseconds = 300;
+const int64 kHoldTimeOutMilliseconds = 1700;
+const SkColor kForegroundColor = 0xFFFFFFFF;
+const SkColor kBackgroundColor = 0xE0808080;
+const int kHorizontalMarginAroundText = 100;
+const int kVerticalMarginAroundText = 100;
+
+class ExitWarningWidgetDelegateView : public views::WidgetDelegateView {
+ public:
+ ExitWarningWidgetDelegateView() : text_width_(0), width_(0), height_(0) {
+ text_ = l10n_util::GetStringUTF16(IDS_ASH_EXIT_WARNING_POPUP_TEXT);
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ font_ = rb.GetFont(ui::ResourceBundle::LargeFont);
+ text_width_ = font_.GetStringWidth(text_);
+ width_ = text_width_ + kHorizontalMarginAroundText;
+ height_ = font_.GetHeight() + kVerticalMarginAroundText;
+ views::Label* label = new views::Label;
+ label->SetText(text_);
+ label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+ label->SetFont(font_);
+ label->SetEnabledColor(kForegroundColor);
+ label->SetDisabledColor(kForegroundColor);
+ label->SetAutoColorReadabilityEnabled(false);
+ AddChildView(label);
+ SetLayoutManager(new views::FillLayout);
+ }
+
+ virtual gfx::Size GetPreferredSize() OVERRIDE {
+ return gfx::Size(width_, height_);
+ }
+
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
+ canvas->FillRect(GetLocalBounds(), kBackgroundColor);
+ views::WidgetDelegateView::OnPaint(canvas);
+ }
+
+ private:
+ base::string16 text_;
+ gfx::Font font_;
+ int text_width_;
+ int width_;
+ int height_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExitWarningWidgetDelegateView);
+};
+
+} // namespace
+
+ExitWarningHandler::ExitWarningHandler()
+ : state_(IDLE),
+ widget_(NULL),
+ stub_timers_for_test_(false) {
+}
+
+ExitWarningHandler::~ExitWarningHandler() {
+ // Note: If a timer is outstanding, it is stopped in its destructor.
+ Hide();
+}
+
+void ExitWarningHandler::HandleExitKey(bool press) {
+ switch (state_) {
+ case IDLE:
+ if (press) {
+ state_ = WAIT_FOR_QUICK_RELEASE;
+ Show();
+ StartTimers();
+ }
+ break;
+ case WAIT_FOR_QUICK_RELEASE:
+ if (!press)
+ state_ = WAIT_FOR_DOUBLE_PRESS;
+ break;
+ case WAIT_FOR_DOUBLE_PRESS:
+ if (press) {
+ state_ = EXITING;
+ CancelTimers();
+ Hide();
+ Shell::GetInstance()->delegate()->Exit();
+ }
+ break;
+ case WAIT_FOR_LONG_HOLD:
+ if (!press)
+ state_ = CANCELED;
+ break;
+ case CANCELED:
+ case EXITING:
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+void ExitWarningHandler::Timer1Action() {
+ if (state_ == WAIT_FOR_QUICK_RELEASE)
+ state_ = WAIT_FOR_LONG_HOLD;
+ else if (state_ == WAIT_FOR_DOUBLE_PRESS)
+ state_ = CANCELED;
+}
+
+void ExitWarningHandler::Timer2Action() {
+ if (state_ == CANCELED) {
+ state_ = IDLE;
+ Hide();
+ }
+ else if (state_ == WAIT_FOR_LONG_HOLD) {
+ state_ = EXITING;
+ Hide();
+ Shell::GetInstance()->delegate()->Exit();
+ }
+}
+
+void ExitWarningHandler::StartTimers() {
+ if (stub_timers_for_test_)
+ return;
+ timer1_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(
+ kDoublePressTimeOutMilliseconds),
+ this,
+ &ExitWarningHandler::Timer1Action);
+ timer2_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kHoldTimeOutMilliseconds),
+ this,
+ &ExitWarningHandler::Timer2Action);
+}
+
+void ExitWarningHandler::CancelTimers() {
+ timer1_.Stop();
+ timer2_.Stop();
+}
+
+void ExitWarningHandler::Show() {
+ if (widget_)
+ return;
+ aura::RootWindow* root_window = Shell::GetActiveRootWindow();
+ ExitWarningWidgetDelegateView* delegate = new ExitWarningWidgetDelegateView;
+ gfx::Size rs = root_window->bounds().size();
+ gfx::Size ps = delegate->GetPreferredSize();
+ gfx::Rect bounds((rs.width() - ps.width()) / 2,
+ (rs.height() - ps.height()) / 3,
+ ps.width(), ps.height());
+ views::Widget::InitParams params;
+ params.type = views::Widget::InitParams::TYPE_POPUP;
+ params.transient = true;
+ params.transparent = true;
+ params.accept_events = false;
+ params.can_activate = false;
+ params.keep_on_top = true;
+ params.remove_standard_frame = true;
+ params.delegate = delegate;
+ params.bounds = bounds;
+ params.parent = Shell::GetContainer(
+ root_window,
+ internal::kShellWindowId_SettingBubbleContainer);
+ widget_ = new views::Widget;
+ widget_->Init(params);
+ widget_->SetContentsView(delegate);
+ widget_->GetNativeView()->SetName("ExitWarningWindow");
+ widget_->Show();
+}
+
+void ExitWarningHandler::Hide() {
+ if (!widget_)
+ return;
+ widget_->Close();
+ widget_ = NULL;
+}
+
+} // namespace ash
diff --git a/ash/accelerators/exit_warning_handler.h b/ash/accelerators/exit_warning_handler.h
new file mode 100644
index 0000000..5b3d718e
--- /dev/null
+++ b/ash/accelerators/exit_warning_handler.h
@@ -0,0 +1,126 @@
+// Copyright 2013 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.
+
+#ifndef ASH_ACCELERATORS_EXIT_WARNING_HANDLER_H_
+#define ASH_ACCELERATORS_EXIT_WARNING_HANDLER_H_
+
+#include "ash/ash_export.h"
+#include "base/timer.h"
+
+namespace views {
+class Widget;
+}
+
+namespace ash {
+
+// In order to avoid accidental exits when the user presses the exit
+// shortcut by mistake, we require the user to hold the shortcut for
+// a period of time. During that time we show a popup informing the
+// user of this. We exit only if the user holds the shortcut longer
+// than this time limit.
+// An expert user may quickly release and then press again (double press)
+// for immediate exit. The press, release and press must happen within
+// the double press time limit.
+// If the user releases (without double press) before the required hold
+// time, we will cancel the exit, but show the ui until the hold time limit
+// has expired to avoid a short popup flash.
+//
+// State Transition Diagrams:
+//
+// T1 - double press time limit (short)
+// T2 - hold to exit time limit (long)
+//
+// IDLE
+// | Press
+// WAIT_FOR_QUICK_RELEASE action: show ui & start timers
+// | Release (DT < T1)
+// WAIT_FOR_DOUBLE_PRESS
+// | Press (DT < T1)
+// EXITING action: hide ui, stop timers, exit
+//
+// IDLE
+// | Press
+// WAIT_FOR_QUICK_RELEASE action: show ui & start timers
+// | T1 timer expires
+// WAIT_FOR_LONG_HOLD
+// | T2 Timer exipres
+// EXITING action: hide ui, exit
+//
+// IDLE
+// | Press
+// WAIT_FOR_QUICK_RELEASE action: show ui & start timers
+// | T1 timer expiers
+// WAIT_FOR_LONG_HOLD
+// | Release
+// CANCELED
+// | T2 timer expires
+// IDLE action: hide ui
+//
+// IDLE
+// | Press
+// WAIT_FOR_QUICK_RELEASE action: show ui & start timers
+// | Release (DT < T1)
+// WAIT_FOR_DOUBLE_PRESS
+// | T1 timer expires
+// CANCELED
+// | T2 timer expires
+// IDLE action: hide ui
+//
+
+class AcceleratorControllerTest;
+
+class ASH_EXPORT ExitWarningHandler {
+ public:
+ ExitWarningHandler();
+
+ ~ExitWarningHandler();
+
+ // Handles shortcut key press and release (Ctrl-Shift-Q).
+ void HandleExitKey(bool press);
+
+ private:
+ friend class AcceleratorControllerTest;
+
+ enum State {
+ IDLE,
+ WAIT_FOR_QUICK_RELEASE,
+ WAIT_FOR_DOUBLE_PRESS,
+ WAIT_FOR_LONG_HOLD,
+ CANCELED,
+ EXITING
+ };
+
+ // Performs actions (see state diagram above) when the "double key
+ // press" time limit is exceeded. This is the shorter of the two
+ // time limits.
+ void Timer1Action();
+
+ // Performs actions (see state diagram above) when the hold time
+ // limit is exceeded. See state diagram above. This is the longer
+ // of the two time limits.
+ void Timer2Action();
+
+ void StartTimers();
+ void CancelTimers();
+
+ void Show();
+ void Hide();
+
+ State state_;
+ views::Widget* widget_; // owned by |this|.
+ base::OneShotTimer<ExitWarningHandler> timer1_; // short; double press
+ base::OneShotTimer<ExitWarningHandler> timer2_; // long; hold to exit
+
+ // Flag to suppress starting the timers for testing. For test we
+ // call TimerAction1() and TimerAction2() directly to simulate the
+ // expiration of the timers.
+ bool stub_timers_for_test_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExitWarningHandler);
+};
+
+} // namespace ash
+
+#endif // ASH_ACCELERATORS_EXIT_WARNING_HANDLER_H_
+