cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / chrome / browser / chromeos / ui / idle_app_name_notification_view.cc
blob73b8f6524447304bb0b2ea3e7542b4664b6c42b2
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/ui/idle_app_name_notification_view.h"
7 #include <string>
9 #include "ash/shell.h"
10 #include "ash/shell_delegate.h"
11 #include "ash/shell_window_ids.h"
12 #include "ash/wm/window_animations.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/time/time.h"
16 #include "base/timer/timer.h"
17 #include "chrome/grit/generated_resources.h"
18 #include "extensions/common/extension.h"
19 #include "ui/accessibility/ax_view_state.h"
20 #include "ui/aura/window.h"
21 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/base/resource/resource_bundle.h"
23 #include "ui/compositor/layer_animation_observer.h"
24 #include "ui/compositor/scoped_layer_animation_settings.h"
25 #include "ui/gfx/canvas.h"
26 #include "ui/gfx/font_list.h"
27 #include "ui/gfx/text_utils.h"
28 #include "ui/views/controls/label.h"
29 #include "ui/views/layout/box_layout.h"
30 #include "ui/views/layout/fill_layout.h"
31 #include "ui/views/view.h"
32 #include "ui/views/widget/widget.h"
33 #include "ui/views/widget/widget_delegate.h"
35 namespace ui {
36 class LayerAnimationSequence;
39 namespace chromeos {
40 namespace {
42 // Color of the text of the warning message.
43 const SkColor kTextColor = SK_ColorBLACK;
45 // Color of the text of the warning message.
46 const SkColor kErrorTextColor = SK_ColorRED;
48 // Color of the window background.
49 const SkColor kWindowBackgroundColor = SK_ColorWHITE;
51 // Radius of the rounded corners of the window.
52 const int kWindowCornerRadius = 4;
54 // Creates and shows the message widget for |view| with |animation_time_ms|.
55 void CreateAndShowWidgetWithContent(views::WidgetDelegate* delegate,
56 views::View* view,
57 int animation_time_ms) {
58 aura::Window* root_window = ash::Shell::GetTargetRootWindow();
59 gfx::Size rs = root_window->bounds().size();
60 gfx::Size ps = view->GetPreferredSize();
61 gfx::Rect bounds((rs.width() - ps.width()) / 2,
62 -ps.height(),
63 ps.width(),
64 ps.height());
65 views::Widget::InitParams params;
66 params.type = views::Widget::InitParams::TYPE_POPUP;
67 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
68 params.ownership = views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET;
69 params.accept_events = false;
70 params.keep_on_top = true;
71 params.remove_standard_frame = true;
72 params.delegate = delegate;
73 params.bounds = bounds;
74 params.parent = ash::Shell::GetContainer(
75 root_window, ash::kShellWindowId_SettingBubbleContainer);
76 views::Widget* widget = new views::Widget;
77 widget->Init(params);
78 widget->SetContentsView(view);
79 gfx::NativeView native_view = widget->GetNativeView();
80 native_view->SetName("KioskIdleAppNameNotification");
82 // Note: We cannot use the Window show/hide animations since they are disabled
83 // for kiosk by command line.
84 ui::LayerAnimator* animator = new ui::LayerAnimator(
85 base::TimeDelta::FromMilliseconds(animation_time_ms));
86 native_view->layer()->SetAnimator(animator);
87 widget->Show();
89 // We don't care about the show animation since it is off screen, so stop the
90 // started animation and move the message into view.
91 animator->StopAnimating();
92 bounds.set_y((rs.height() - ps.height()) / 20);
93 widget->SetBounds(bounds);
95 // Allow to use the message for spoken feedback.
96 view->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
99 } // namespace
101 // The class which implements the content view for the message.
102 class IdleAppNameNotificationDelegateView
103 : public views::WidgetDelegateView,
104 public ui::ImplicitAnimationObserver {
105 public:
106 // An idle message which will get shown from the caller and hides itself after
107 // a time, calling |owner->CloseMessage| to inform the owner that it got
108 // destroyed. The |app_name| is a string which gets used as message and
109 // |error| is true if something is not correct.
110 // |message_visibility_time_in_ms| ms's after creation the message will start
111 // to remove itself from the screen.
112 IdleAppNameNotificationDelegateView(IdleAppNameNotificationView *owner,
113 const base::string16& app_name,
114 bool error,
115 int message_visibility_time_in_ms)
116 : owner_(owner),
117 widget_closed_(false) {
118 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
119 // Add the application name label to the message.
120 AddLabel(app_name, rb->GetFontList(ui::ResourceBundle::BoldFont),
121 error ? kErrorTextColor : kTextColor);
122 spoken_text_ = app_name;
123 SetLayoutManager(new views::FillLayout);
125 // Set a timer which will trigger to remove the message after the given
126 // time.
127 hide_timer_.Start(
128 FROM_HERE,
129 base::TimeDelta::FromMilliseconds(message_visibility_time_in_ms),
130 this,
131 &IdleAppNameNotificationDelegateView::RemoveMessage);
134 ~IdleAppNameNotificationDelegateView() override {
135 // The widget is already closing, but the other cleanup items need to be
136 // performed.
137 widget_closed_ = true;
138 Close();
141 // Close the widget immediately. This can be called from the owner or from
142 // this class.
143 void Close() {
144 // Stop the timer (if it was running).
145 hide_timer_.Stop();
146 // Inform our owner that we are going away.
147 if (owner_) {
148 IdleAppNameNotificationView* owner = owner_;
149 owner_ = NULL;
150 owner->CloseMessage();
152 // Close the owning widget - if required.
153 if (!widget_closed_) {
154 widget_closed_ = true;
155 GetWidget()->Close();
159 // Animate the window away (and close once done).
160 void RemoveMessage() {
161 aura::Window* widget_view = GetWidget()->GetNativeView();
162 ui::Layer* layer = widget_view->layer();
163 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
164 settings.AddObserver(this);
165 gfx::Rect rect = widget_view->bounds();
166 rect.set_y(-GetPreferredSize().height());
167 layer->SetBounds(rect);
170 void OnPaint(gfx::Canvas* canvas) override {
171 SkPaint paint;
172 paint.setStyle(SkPaint::kFill_Style);
173 paint.setColor(kWindowBackgroundColor);
174 canvas->DrawRoundRect(GetLocalBounds(), kWindowCornerRadius, paint);
175 views::WidgetDelegateView::OnPaint(canvas);
178 void GetAccessibleState(ui::AXViewState* state) override {
179 state->name = spoken_text_;
180 state->role = ui::AX_ROLE_ALERT;
183 // ImplicitAnimationObserver overrides
184 void OnImplicitAnimationsCompleted() override { Close(); }
186 private:
187 // Adds the label to the view, using |text| with a |font| and a |text_color|.
188 void AddLabel(const base::string16& text,
189 const gfx::FontList& font,
190 SkColor text_color) {
191 views::Label* label = new views::Label;
192 label->SetText(text);
193 label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
194 label->SetFontList(font);
195 label->SetEnabledColor(text_color);
196 label->SetDisabledColor(text_color);
197 label->SetAutoColorReadabilityEnabled(false);
198 AddChildView(label);
201 // A timer which calls us to remove the message from the screen.
202 base::OneShotTimer<IdleAppNameNotificationDelegateView> hide_timer_;
204 // The owner of this message which needs to get notified when the message
205 // closes.
206 IdleAppNameNotificationView* owner_;
208 // The spoken text.
209 base::string16 spoken_text_;
211 // True if the widget got already closed.
212 bool widget_closed_;
214 DISALLOW_COPY_AND_ASSIGN(IdleAppNameNotificationDelegateView);
217 IdleAppNameNotificationView::IdleAppNameNotificationView(
218 int message_visibility_time_in_ms,
219 int animation_time_ms,
220 const extensions::Extension* extension)
221 : view_(NULL) {
222 ShowMessage(message_visibility_time_in_ms, animation_time_ms, extension);
225 IdleAppNameNotificationView::~IdleAppNameNotificationView() {
226 CloseMessage();
229 void IdleAppNameNotificationView::CloseMessage() {
230 if (view_) {
231 IdleAppNameNotificationDelegateView* view = view_;
232 view_ = NULL;
233 view->Close();
237 bool IdleAppNameNotificationView::IsVisible() {
238 return view_ != NULL;
241 base::string16 IdleAppNameNotificationView::GetShownTextForTest() {
242 ui::AXViewState state;
243 DCHECK(view_);
244 view_->GetAccessibleState(&state);
245 return state.name;
248 void IdleAppNameNotificationView::ShowMessage(
249 int message_visibility_time_in_ms,
250 int animation_time_ms,
251 const extensions::Extension* extension) {
252 DCHECK(!view_);
254 base::string16 app_name;
255 bool error = false;
256 if (extension &&
257 !base::ContainsOnlyChars(extension->name(), base::kWhitespaceASCII)) {
258 app_name = base::UTF8ToUTF16(extension->name());
259 } else {
260 error = true;
261 app_name = l10n_util::GetStringUTF16(
262 IDS_IDLE_APP_NAME_UNKNOWN_APPLICATION_NOTIFICATION);
265 view_ = new IdleAppNameNotificationDelegateView(
266 this,
267 app_name,
268 error,
269 message_visibility_time_in_ms + animation_time_ms);
270 CreateAndShowWidgetWithContent(view_, view_, animation_time_ms);
273 } // namespace chromeos