15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/ui/idle_app_name_notification_view.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string>
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shell.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shell_delegate.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shell_window_ids.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/window_animations.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/time/time.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/timer/timer.h"
176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/grit/generated_resources.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension.h"
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/window.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/compositor/layer_animation_observer.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/canvas.h"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/font_list.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/text_utils.h"
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/controls/label.h"
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/layout/box_layout.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/layout/fill_layout.h"
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/view.h"
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/widget/widget.h"
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/widget/widget_delegate.h"
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace ui {
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class LayerAnimationSequence;
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace chromeos {
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Color of the text of the warning message.
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const SkColor kTextColor = SK_ColorBLACK;
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Color of the text of the warning message.
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const SkColor kErrorTextColor = SK_ColorRED;
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Color of the window background.
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const SkColor kWindowBackgroundColor = SK_ColorWHITE;
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Radius of the rounded corners of the window.
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kWindowCornerRadius = 4;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Creates and shows the message widget for |view| with |animation_time_ms|.
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CreateAndShowWidgetWithContent(views::WidgetDelegate* delegate,
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    views::View* view,
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    int animation_time_ms) {
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::Window* root_window = ash::Shell::GetTargetRootWindow();
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Size rs = root_window->bounds().size();
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Size ps = view->GetPreferredSize();
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Rect bounds((rs.width() - ps.width()) / 2,
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   -ps.height(),
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   ps.width(),
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   ps.height());
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  views::Widget::InitParams params;
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.type = views::Widget::InitParams::TYPE_POPUP;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.ownership = views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET;
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.accept_events = false;
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.keep_on_top = true;
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.remove_standard_frame = true;
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.delegate = delegate;
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.bounds = bounds;
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.parent = ash::Shell::GetContainer(
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root_window, ash::kShellWindowId_SettingBubbleContainer);
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  views::Widget* widget = new views::Widget;
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  widget->Init(params);
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  widget->SetContentsView(view);
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::NativeView native_view = widget->GetNativeView();
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  native_view->SetName("KioskIdleAppNameNotification");
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Note: We cannot use the Window show/hide animations since they are disabled
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // for kiosk by command line.
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::LayerAnimator* animator = new ui::LayerAnimator(
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::TimeDelta::FromMilliseconds(animation_time_ms));
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  native_view->layer()->SetAnimator(animator);
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  widget->Show();
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We don't care about the show animation since it is off screen, so stop the
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // started animation and move the message into view.
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  animator->StopAnimating();
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bounds.set_y((rs.height() - ps.height()) / 20);
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  widget->SetBounds(bounds);
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Allow to use the message for spoken feedback.
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  view->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The class which implements the content view for the message.
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class IdleAppNameNotificationDelegateView
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : public views::WidgetDelegateView,
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      public ui::ImplicitAnimationObserver {
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // An idle message which will get shown from the caller and hides itself after
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // a time, calling |owner->CloseMessage| to inform the owner that it got
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // destroyed. The |app_name| is a string which gets used as message and
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // |error| is true if something is not correct.
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |message_visibility_time_in_ms| ms's after creation the message will start
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // to remove itself from the screen.
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IdleAppNameNotificationDelegateView(IdleAppNameNotificationView *owner,
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      const base::string16& app_name,
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      bool error,
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      int message_visibility_time_in_ms)
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : owner_(owner),
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        widget_closed_(false) {
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Add the application name label to the message.
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddLabel(app_name,
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             rb.GetFontList(ui::ResourceBundle::BoldFont),
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             error ? kErrorTextColor : kTextColor);
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    spoken_text_ = app_name;
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SetLayoutManager(new views::FillLayout);
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Set a timer which will trigger to remove the message after the given
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // time.
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    hide_timer_.Start(
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FROM_HERE,
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(message_visibility_time_in_ms),
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        this,
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &IdleAppNameNotificationDelegateView::RemoveMessage);
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~IdleAppNameNotificationDelegateView() {
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // The widget is already closing, but the other cleanup items need to be
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // performed.
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    widget_closed_ = true;
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Close();
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Close the widget immediately. This can be called from the owner or from
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // this class.
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Close() {
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Stop the timer (if it was running).
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    hide_timer_.Stop();
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Inform our owner that we are going away.
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (owner_) {
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      IdleAppNameNotificationView* owner = owner_;
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      owner_ = NULL;
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      owner->CloseMessage();
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Close the owning widget - if required.
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!widget_closed_) {
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      widget_closed_ = true;
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetWidget()->Close();
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Animate the window away (and close once done).
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void RemoveMessage() {
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    aura::Window* widget_view = GetWidget()->GetNativeView();
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::Layer* layer = widget_view->layer();
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    settings.AddObserver(this);
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::Rect rect = widget_view->bounds();
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    rect.set_y(-GetPreferredSize().height());
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    layer->SetBounds(rect);
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SkPaint paint;
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    paint.setStyle(SkPaint::kFill_Style);
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    paint.setColor(kWindowBackgroundColor);
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    canvas->DrawRoundRect(GetLocalBounds(), kWindowCornerRadius, paint);
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    views::WidgetDelegateView::OnPaint(canvas);
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE {
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    state->name = spoken_text_;
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    state->role = ui::AX_ROLE_ALERT;
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // ImplicitAnimationObserver overrides
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnImplicitAnimationsCompleted() OVERRIDE {
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Close();
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Adds the label to the view, using |text| with a |font| and a |text_color|.
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void AddLabel(const base::string16& text,
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                const gfx::FontList& font,
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                SkColor text_color) {
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    views::Label* label = new views::Label;
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    label->SetText(text);
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    label->SetFontList(font);
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    label->SetEnabledColor(text_color);
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    label->SetDisabledColor(text_color);
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    label->SetAutoColorReadabilityEnabled(false);
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddChildView(label);
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // A timer which calls us to remove the message from the screen.
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::OneShotTimer<IdleAppNameNotificationDelegateView> hide_timer_;
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The owner of this message which needs to get notified when the message
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // closes.
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IdleAppNameNotificationView* owner_;
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The spoken text.
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 spoken_text_;
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // True if the widget got already closed.
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool widget_closed_;
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(IdleAppNameNotificationDelegateView);
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)IdleAppNameNotificationView::IdleAppNameNotificationView(
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int message_visibility_time_in_ms,
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int animation_time_ms,
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const extensions::Extension* extension)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : view_(NULL) {
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShowMessage(message_visibility_time_in_ms, animation_time_ms, extension);
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)IdleAppNameNotificationView::~IdleAppNameNotificationView() {
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CloseMessage();
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IdleAppNameNotificationView::CloseMessage() {
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (view_) {
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IdleAppNameNotificationDelegateView* view = view_;
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    view_ = NULL;
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    view->Close();
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool IdleAppNameNotificationView::IsVisible() {
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return view_ != NULL;
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 IdleAppNameNotificationView::GetShownTextForTest() {
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ui::AXViewState state;
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(view_);
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  view_->GetAccessibleState(&state);
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return state.name;
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void IdleAppNameNotificationView::ShowMessage(
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int message_visibility_time_in_ms,
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int animation_time_ms,
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const extensions::Extension* extension) {
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!view_);
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 app_name;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool error = false;
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (extension &&
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      !base::ContainsOnlyChars(extension->name(), base::kWhitespaceASCII)) {
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    app_name = base::UTF8ToUTF16(extension->name());
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error = true;
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    app_name = l10n_util::GetStringUTF16(
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        IDS_IDLE_APP_NAME_UNKNOWN_APPLICATION_NOTIFICATION);
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  view_ = new IdleAppNameNotificationDelegateView(
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      this,
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      app_name,
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error,
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      message_visibility_time_in_ms + animation_time_ms);
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CreateAndShowWidgetWithContent(view_, view_, animation_time_ms);
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace chromeos
277