1 // Copyright 2019 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/login/ui/pin_request_widget.h"
6 
7 #include <utility>
8 
9 #include "ash/keyboard/keyboard_controller_impl.h"
10 #include "ash/public/cpp/shell_window_ids.h"
11 #include "ash/session/session_controller_impl.h"
12 #include "ash/shell.h"
13 #include "ash/wm/window_dimmer.h"
14 #include "base/no_destructor.h"
15 #include "components/session_manager/session_manager_types.h"
16 #include "ui/views/widget/widget.h"
17 
18 namespace ash {
19 
20 namespace {
21 
22 PinRequestWidget* instance_ = nullptr;
23 
GetOnShownCallback()24 base::RepeatingClosure& GetOnShownCallback() {
25   static base::NoDestructor<base::RepeatingClosure> on_shown;
26   return *on_shown;
27 }
28 
29 }  // namespace
30 
TestApi(PinRequestWidget * widget)31 PinRequestWidget::TestApi::TestApi(PinRequestWidget* widget)
32     : pin_request_widget_(widget) {}
33 
34 PinRequestWidget::TestApi::~TestApi() = default;
35 
pin_request_view()36 PinRequestView* PinRequestWidget::TestApi::pin_request_view() {
37   return pin_request_widget_->GetView();
38 }
39 
40 // static
Show(PinRequest request,PinRequestView::Delegate * delegate)41 void PinRequestWidget::Show(PinRequest request,
42                             PinRequestView::Delegate* delegate) {
43   DCHECK(!instance_);
44   instance_ = new PinRequestWidget(std::move(request), delegate);
45   if (GetOnShownCallback())
46     GetOnShownCallback().Run();
47 }
48 
49 // static
Get()50 PinRequestWidget* PinRequestWidget::Get() {
51   return instance_;
52 }
53 
54 // static
SetShownCallbackForTesting(base::RepeatingClosure on_shown)55 void PinRequestWidget::SetShownCallbackForTesting(
56     base::RepeatingClosure on_shown) {
57   GetOnShownCallback() = std::move(on_shown);
58 }
59 
UpdateState(PinRequestViewState state,const base::string16 & title,const base::string16 & description)60 void PinRequestWidget::UpdateState(PinRequestViewState state,
61                                    const base::string16& title,
62                                    const base::string16& description) {
63   DCHECK_EQ(instance_, this);
64   GetView()->UpdateState(state, title, description);
65 }
66 
SetPinInputEnabled(bool enabled)67 void PinRequestWidget::SetPinInputEnabled(bool enabled) {
68   DCHECK_EQ(instance_, this);
69   GetView()->SetInputEnabled(enabled);
70 }
71 
ClearInput()72 void PinRequestWidget::ClearInput() {
73   DCHECK_EQ(instance_, this);
74   GetView()->ClearInput();
75 }
76 
Close(bool success)77 void PinRequestWidget::Close(bool success) {
78   DCHECK_EQ(instance_, this);
79   PinRequestWidget* instance = instance_;
80   instance_ = nullptr;
81   std::move(on_pin_request_done_).Run(success);
82   widget_->Close();
83   delete instance;
84 }
85 
PinRequestWidget(PinRequest request,PinRequestView::Delegate * delegate)86 PinRequestWidget::PinRequestWidget(PinRequest request,
87                                    PinRequestView::Delegate* delegate)
88     : on_pin_request_done_(std::move(request.on_pin_request_done)) {
89   views::Widget::InitParams widget_params;
90   // Using window frameless to be able to get focus on the view input fields,
91   // which does not work with popup type.
92   widget_params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
93   widget_params.ownership =
94       views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
95   widget_params.opacity =
96       views::Widget::InitParams::WindowOpacity::kTranslucent;
97   widget_params.accept_events = true;
98 
99   ShellWindowId parent_window_id =
100       Shell::Get()->session_controller()->GetSessionState() ==
101               session_manager::SessionState::ACTIVE
102           ? kShellWindowId_SystemModalContainer
103           : kShellWindowId_LockSystemModalContainer;
104   widget_params.parent =
105       Shell::GetPrimaryRootWindow()->GetChildById(parent_window_id);
106   if (request.extra_dimmer)
107     dimmer_ = std::make_unique<WindowDimmer>(widget_params.parent);
108   request.on_pin_request_done =
109       base::BindOnce(&PinRequestWidget::Close, weak_factory_.GetWeakPtr());
110   widget_params.delegate = new PinRequestView(std::move(request), delegate);
111 
112   widget_ = std::make_unique<views::Widget>();
113   widget_->Init(std::move(widget_params));
114 
115   Show();
116 }
117 
118 PinRequestWidget::~PinRequestWidget() = default;
119 
Show()120 void PinRequestWidget::Show() {
121   if (dimmer_)
122     dimmer_->window()->Show();
123 
124   DCHECK(widget_);
125   widget_->Show();
126 
127   auto* keyboard_controller = Shell::Get()->keyboard_controller();
128   if (keyboard_controller && keyboard_controller->IsKeyboardEnabled())
129     keyboard_controller->HideKeyboard(HideReason::kSystem);
130 }
131 
GetView()132 PinRequestView* PinRequestWidget::GetView() {
133   return static_cast<PinRequestView*>(widget_->widget_delegate());
134 }
135 
136 }  // namespace ash
137