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.
4
5#include "ash/system/chromeos/multi_user/user_switch_util.h"
6
7#include "ash/shell.h"
8#include "ash/system/chromeos/screen_security/screen_tray_item.h"
9#include "ash/system/tray/system_tray.h"
10#include "grit/ash_strings.h"
11#include "ui/base/l10n/l10n_util.h"
12#include "ui/base/resource/resource_bundle.h"
13#include "ui/views/controls/label.h"
14#include "ui/views/layout/grid_layout.h"
15#include "ui/views/widget/widget.h"
16#include "ui/views/window/dialog_delegate.h"
17
18namespace ash {
19
20namespace {
21
22// Default width/height of the dialog.
23const int kDefaultWidth = 500;
24const int kDefaultHeight = 150;
25
26const int kPaddingToMessage = 30;
27const int kInset = 40;
28const int kTopInset = 10;
29
30////////////////////////////////////////////////////////////////////////////////
31// Dialog for multi-profiles desktop casting warning.
32class DesktopCastingWarningView : public views::DialogDelegateView {
33 public:
34  DesktopCastingWarningView(base::Callback<void()> on_accept);
35  virtual ~DesktopCastingWarningView();
36
37  static void ShowDialog(const base::Callback<void()> on_accept);
38
39  // views::DialogDelegate overrides.
40  virtual bool Accept() OVERRIDE;
41  virtual base::string16 GetDialogButtonLabel(
42        ui::DialogButton button) const OVERRIDE;
43  virtual bool IsDialogButtonEnabled(ui::DialogButton button) const OVERRIDE;
44  virtual int GetDefaultDialogButton() const OVERRIDE;
45
46  // views::WidgetDelegate overrides.
47  virtual ui::ModalType GetModalType() const OVERRIDE;
48
49  // views::View overrides.
50  virtual gfx::Size GetPreferredSize() const OVERRIDE;
51
52 private:
53  void InitDialog();
54
55  const base::Callback<void()> on_switch_;
56
57  DISALLOW_COPY_AND_ASSIGN(DesktopCastingWarningView);
58};
59
60// The current instance of the running dialog - or NULL. This is used for
61// unittest related functions.
62static DesktopCastingWarningView* instance_for_test;
63
64////////////////////////////////////////////////////////////////////////////////
65// DesktopCastingWarningView implementation.
66
67DesktopCastingWarningView::DesktopCastingWarningView(
68    const base::Callback<void()> on_switch)
69    : on_switch_(on_switch) {
70  DCHECK(!instance_for_test);
71  instance_for_test = this;
72}
73
74DesktopCastingWarningView::~DesktopCastingWarningView() {
75  DCHECK(instance_for_test);
76  instance_for_test = NULL;
77}
78
79// static
80void DesktopCastingWarningView::ShowDialog(
81    const base::Callback<void()> on_accept) {
82  DesktopCastingWarningView* dialog_view =
83      new DesktopCastingWarningView(on_accept);
84  views::DialogDelegate::CreateDialogWidget(
85      dialog_view, ash::Shell::GetTargetRootWindow(), NULL);
86  dialog_view->InitDialog();
87  views::Widget* widget = dialog_view->GetWidget();
88  DCHECK(widget);
89  widget->Show();
90}
91
92bool DesktopCastingWarningView::Accept() {
93  // Stop screen sharing and capturing.
94  SystemTray* system_tray = ash::Shell::GetInstance()->GetPrimarySystemTray();
95  if (system_tray->GetScreenShareItem()->is_started())
96    system_tray->GetScreenShareItem()->Stop();
97  if (system_tray->GetScreenCaptureItem()->is_started())
98    system_tray->GetScreenCaptureItem()->Stop();
99
100  on_switch_.Run();
101  return true;
102}
103
104base::string16 DesktopCastingWarningView::GetDialogButtonLabel(
105      ui::DialogButton button) const {
106  return l10n_util::GetStringUTF16(
107      button == ui::DIALOG_BUTTON_OK ?
108          IDS_DESKTOP_CASTING_ACTIVE_BUTTON_SWITCH_USER :
109          IDS_DESKTOP_CASTING_ACTIVE_BUTTON_ABORT_USER_SWITCH);
110}
111
112bool DesktopCastingWarningView::IsDialogButtonEnabled(
113    ui::DialogButton button) const {
114  return button == ui::DIALOG_BUTTON_OK || button == ui::DIALOG_BUTTON_CANCEL;
115}
116
117int DesktopCastingWarningView::GetDefaultDialogButton() const {
118  // The default should turn off the casting.
119  return ui::DIALOG_BUTTON_CANCEL;
120}
121
122ui::ModalType DesktopCastingWarningView::GetModalType() const {
123  return ui::MODAL_TYPE_SYSTEM;
124}
125
126gfx::Size DesktopCastingWarningView::GetPreferredSize() const {
127  return gfx::Size(kDefaultWidth, kDefaultHeight);
128}
129
130void DesktopCastingWarningView::InitDialog() {
131  const gfx::Insets kDialogInsets(kTopInset, kInset, kInset, kInset);
132
133  // Create the views and layout manager and set them up.
134  views::GridLayout* grid_layout = views::GridLayout::CreatePanel(this);
135  grid_layout->SetInsets(kDialogInsets);
136
137  views::ColumnSet* column_set = grid_layout->AddColumnSet(0);
138  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
139                        views::GridLayout::USE_PREF, 0, 0);
140
141  // Title
142  views::Label* title_label_ = new views::Label(
143      l10n_util::GetStringUTF16(IDS_DESKTOP_CASTING_ACTIVE_TITLE));
144  title_label_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
145      ui::ResourceBundle::MediumBoldFont));
146  title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
147  grid_layout->StartRow(0, 0);
148  grid_layout->AddView(title_label_);
149  grid_layout->AddPaddingRow(0, kPaddingToMessage);
150
151  // Explanation string
152  views::Label* label = new views::Label(
153      l10n_util::GetStringUTF16(IDS_DESKTOP_CASTING_ACTIVE_MESSAGE));
154  label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
155      ui::ResourceBundle::MediumFont));
156  label->SetMultiLine(true);
157  label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
158  label->SetAllowCharacterBreak(true);
159  grid_layout->StartRow(0, 0);
160  grid_layout->AddView(label);
161
162  SetLayoutManager(grid_layout);
163  Layout();
164}
165
166}  // namespace
167
168////////////////////////////////////////////////////////////////////////////////
169// Factory function.
170
171void TrySwitchingActiveUser(
172   const base::Callback<void()> on_switch) {
173  // Some unit tests do not have a shell. In that case simply execute.
174  if (!ash::Shell::HasInstance()) {
175    on_switch.Run();
176    return;
177  }
178  // If neither screen sharing nor capturing is going on we can immediately
179  // switch users.
180  SystemTray* system_tray = ash::Shell::GetInstance()->GetPrimarySystemTray();
181  if (!system_tray->GetScreenShareItem()->is_started() &&
182      !system_tray->GetScreenCaptureItem()->is_started()) {
183    on_switch.Run();
184    return;
185  }
186  DesktopCastingWarningView::ShowDialog(on_switch);
187}
188
189bool TestAndTerminateDesktopCastingWarningForTest(bool accept) {
190  if (!instance_for_test)
191    return false;
192  if (accept)
193    instance_for_test->Accept();
194  delete instance_for_test->GetWidget()->GetNativeWindow();
195  CHECK(!instance_for_test);
196  return true;
197}
198
199}  // namespace chromeos
200