190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/accelerators/exit_warning_handler.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/metrics/user_metrics_recorder.h" 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/shell.h" 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/shell_delegate.h" 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/shell_window_ids.h" 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h" 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "grit/ash_strings.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h" 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/aura/window.h" 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/canvas.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/font_list.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/text_utils.h" 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/views/controls/label.h" 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/views/layout/fill_layout.h" 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/views/view.h" 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/views/widget/widget.h" 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/views/widget/widget_delegate.h" 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace ash { 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int64 kTimeOutMilliseconds = 2000; 323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Color of the text of the warning message. 333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const SkColor kTextColor = SK_ColorWHITE; 343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Color of the window background. 353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const SkColor kWindowBackgroundColor = SkColorSetARGB(0xC0, 0x0, 0x0, 0x0); 363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Radius of the rounded corners of the window. 373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const int kWindowCornerRadius = 2; 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kHorizontalMarginAroundText = 100; 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kVerticalMarginAroundText = 100; 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class ExitWarningWidgetDelegateView : public views::WidgetDelegateView { 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExitWarningWidgetDelegateView() : text_width_(0), width_(0), height_(0) { 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#ifdef OS_CHROMEOS 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) text_ = l10n_util::GetStringUTF16(IDS_ASH_SIGN_OUT_WARNING_POPUP_TEXT); 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) accessible_name_ = l10n_util::GetStringUTF16( 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IDS_ASH_SIGN_OUT_WARNING_POPUP_TEXT_ACCESSIBLE); 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#else 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) text_ = l10n_util::GetStringUTF16(IDS_ASH_EXIT_WARNING_POPUP_TEXT); 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) accessible_name_ = 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) l10n_util::GetStringUTF16(IDS_ASH_EXIT_WARNING_POPUP_TEXT_ACCESSIBLE); 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::FontList& font_list = 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rb.GetFontList(ui::ResourceBundle::LargeFont); 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) text_width_ = gfx::GetStringWidth(text_, font_list); 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) width_ = text_width_ + kHorizontalMarginAroundText; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) height_ = font_list.GetHeight() + kVerticalMarginAroundText; 596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) views::Label* label = new views::Label(); 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) label->SetText(text_); 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) label->SetHorizontalAlignment(gfx::ALIGN_CENTER); 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) label->SetFontList(font_list); 633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) label->SetEnabledColor(kTextColor); 643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) label->SetDisabledColor(kTextColor); 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) label->SetAutoColorReadabilityEnabled(false); 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) label->SetSubpixelRenderingEnabled(false); 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AddChildView(label); 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetLayoutManager(new views::FillLayout); 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual gfx::Size GetPreferredSize() const OVERRIDE { 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return gfx::Size(width_, height_); 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { 763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) SkPaint paint; 773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) paint.setStyle(SkPaint::kFill_Style); 783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) paint.setColor(kWindowBackgroundColor); 793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) canvas->DrawRoundRect(GetLocalBounds(), kWindowCornerRadius, paint); 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) views::WidgetDelegateView::OnPaint(canvas); 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE { 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) state->name = accessible_name_; 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->role = ui::AX_ROLE_ALERT; 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::string16 text_; 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::string16 accessible_name_; 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int text_width_; 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int width_; 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int height_; 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ExitWarningWidgetDelegateView); 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} // namespace 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)ExitWarningHandler::ExitWarningHandler() 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : state_(IDLE), 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stub_timer_for_test_(false) { 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)ExitWarningHandler::~ExitWarningHandler() { 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Note: If a timer is outstanding, it is stopped in its destructor. 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Hide(); 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExitWarningHandler::HandleAccelerator() { 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ShellDelegate* shell_delegate = Shell::GetInstance()->delegate(); 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (state_) { 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case IDLE: 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) state_ = WAIT_FOR_DOUBLE_PRESS; 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Show(); 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StartTimer(); 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Shell::GetInstance()-> 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) metrics()->RecordUserMetricsAction(UMA_ACCEL_EXIT_FIRST_Q); 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case WAIT_FOR_DOUBLE_PRESS: 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) state_ = EXITING; 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CancelTimer(); 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Hide(); 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Shell::GetInstance()-> 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) metrics()->RecordUserMetricsAction(UMA_ACCEL_EXIT_SECOND_Q); 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) shell_delegate->Exit(); 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case EXITING: 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) default: 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NOTREACHED(); 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExitWarningHandler::TimerAction() { 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Hide(); 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (state_ == WAIT_FOR_DOUBLE_PRESS) 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) state_ = IDLE; 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExitWarningHandler::StartTimer() { 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (stub_timer_for_test_) 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) timer_.Start(FROM_HERE, 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::TimeDelta::FromMilliseconds(kTimeOutMilliseconds), 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) this, 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &ExitWarningHandler::TimerAction); 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExitWarningHandler::CancelTimer() { 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) timer_.Stop(); 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExitWarningHandler::Show() { 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (widget_) 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) aura::Window* root_window = Shell::GetTargetRootWindow(); 15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExitWarningWidgetDelegateView* delegate = new ExitWarningWidgetDelegateView; 16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size rs = root_window->bounds().size(); 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size ps = delegate->GetPreferredSize(); 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Rect bounds((rs.width() - ps.width()) / 2, 16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (rs.height() - ps.height()) / 3, 16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ps.width(), ps.height()); 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) views::Widget::InitParams params; 16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params.type = views::Widget::InitParams::TYPE_POPUP; 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params.accept_events = false; 17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params.keep_on_top = true; 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params.remove_standard_frame = true; 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params.delegate = delegate; 17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params.bounds = bounds; 174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch params.parent = 175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch Shell::GetContainer(root_window, kShellWindowId_SettingBubbleContainer); 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) widget_.reset(new views::Widget); 17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) widget_->Init(params); 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) widget_->SetContentsView(delegate); 17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) widget_->GetNativeView()->SetName("ExitWarningWindow"); 18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) widget_->Show(); 18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true); 18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExitWarningHandler::Hide() { 1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) widget_.reset(); 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace ash 190