Upload upstream chromium 85.0.4183.84
[platform/framework/web/chromium-efl.git] / ash / multi_device_setup / multi_device_notification_presenter.cc
1 // Copyright 2018 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/multi_device_setup/multi_device_notification_presenter.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "ash/public/cpp/notification_utils.h"
11 #include "ash/public/cpp/system_tray_client.h"
12 #include "ash/resources/vector_icons/vector_icons.h"
13 #include "ash/session/session_controller_impl.h"
14 #include "ash/shell.h"
15 #include "ash/shell_delegate.h"
16 #include "ash/strings/grit/ash_strings.h"
17 #include "ash/system/model/system_tray_model.h"
18 #include "base/bind_helpers.h"
19 #include "base/memory/ptr_util.h"
20 #include "base/metrics/histogram_macros.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "chromeos/components/multidevice/logging/logging.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/chromeos/devicetype_utils.h"
25 #include "ui/message_center/message_center.h"
26 #include "ui/message_center/public/cpp/notification_types.h"
27 #include "ui/message_center/public/cpp/notifier_id.h"
28
29 namespace ash {
30
31 namespace {
32
33 const char kNotifierMultiDevice[] = "ash.multi_device_setup";
34
35 }  // namespace
36
37 // static
38 const char MultiDeviceNotificationPresenter::kNotificationId[] =
39     "cros_multi_device_setup_notification_id";
40
41 // static
42 std::string
43 MultiDeviceNotificationPresenter::GetNotificationDescriptionForLogging(
44     Status notification_status) {
45   switch (notification_status) {
46     case Status::kNewUserNotificationVisible:
47       return "notification to prompt setup";
48     case Status::kExistingUserHostSwitchedNotificationVisible:
49       return "notification of switch to new host";
50     case Status::kExistingUserNewChromebookNotificationVisible:
51       return "notification of new Chromebook added";
52     case Status::kNoNotificationVisible:
53       return "no notification";
54   }
55   NOTREACHED();
56 }
57
58 // static
59 MultiDeviceNotificationPresenter::NotificationType
60 MultiDeviceNotificationPresenter::GetMetricValueForNotification(
61     Status notification_status) {
62   switch (notification_status) {
63     case Status::kNewUserNotificationVisible:
64       return kNotificationTypeNewUserPotentialHostExists;
65     case Status::kExistingUserHostSwitchedNotificationVisible:
66       return kNotificationTypeExistingUserHostSwitched;
67     case Status::kExistingUserNewChromebookNotificationVisible:
68       return kNotificationTypeExistingUserNewChromebookAdded;
69     case Status::kNoNotificationVisible:
70       NOTREACHED();
71       return kNotificationTypeMax;
72   }
73 }
74
75 MultiDeviceNotificationPresenter::MultiDeviceNotificationPresenter(
76     message_center::MessageCenter* message_center)
77     : message_center_(message_center) {
78   DCHECK(message_center_);
79
80   Shell::Get()->session_controller()->AddObserver(this);
81
82   // If the constructor is called after the session state has already been set
83   // (e.g., if recovering from a crash), handle that now. If the user has not
84   // yet logged in, this will be a no-op.
85   ObserveMultiDeviceSetupIfPossible();
86 }
87
88 MultiDeviceNotificationPresenter::~MultiDeviceNotificationPresenter() {
89   message_center_->RemoveObserver(this);
90   Shell::Get()->session_controller()->RemoveObserver(this);
91 }
92
93 void MultiDeviceNotificationPresenter::OnPotentialHostExistsForNewUser() {
94   base::string16 title = l10n_util::GetStringUTF16(
95       IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_TITLE);
96   base::string16 message = l10n_util::GetStringFUTF16(
97       IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_MESSAGE,
98       ui::GetChromeOSDeviceName());
99   ShowNotification(Status::kNewUserNotificationVisible, title, message);
100 }
101
102 void MultiDeviceNotificationPresenter::OnNoLongerNewUser() {
103   if (notification_status_ != Status::kNewUserNotificationVisible)
104     return;
105   RemoveMultiDeviceSetupNotification();
106 }
107
108 void MultiDeviceNotificationPresenter::OnConnectedHostSwitchedForExistingUser(
109     const std::string& new_host_device_name) {
110   base::string16 title = l10n_util::GetStringFUTF16(
111       IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_HOST_SWITCHED_TITLE,
112       base::ASCIIToUTF16(new_host_device_name));
113   base::string16 message = l10n_util::GetStringFUTF16(
114       IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_HOST_SWITCHED_MESSAGE,
115       ui::GetChromeOSDeviceName());
116   ShowNotification(Status::kExistingUserHostSwitchedNotificationVisible, title,
117                    message);
118 }
119
120 void MultiDeviceNotificationPresenter::OnNewChromebookAddedForExistingUser(
121     const std::string& new_host_device_name) {
122   base::string16 title = l10n_util::GetStringFUTF16(
123       IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROME_DEVICE_ADDED_TITLE,
124       base::ASCIIToUTF16(new_host_device_name));
125   base::string16 message = l10n_util::GetStringFUTF16(
126       IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROME_DEVICE_ADDED_MESSAGE,
127       ui::GetChromeOSDeviceName());
128   ShowNotification(Status::kExistingUserNewChromebookNotificationVisible, title,
129                    message);
130 }
131
132 void MultiDeviceNotificationPresenter::RemoveMultiDeviceSetupNotification() {
133   notification_status_ = Status::kNoNotificationVisible;
134   message_center_->RemoveNotification(kNotificationId,
135                                       /* by_user */ false);
136 }
137
138 void MultiDeviceNotificationPresenter::OnUserSessionAdded(
139     const AccountId& account_id) {
140   ObserveMultiDeviceSetupIfPossible();
141 }
142
143 void MultiDeviceNotificationPresenter::OnSessionStateChanged(
144     session_manager::SessionState state) {
145   ObserveMultiDeviceSetupIfPossible();
146 }
147
148 void MultiDeviceNotificationPresenter::OnNotificationRemoved(
149     const std::string& notification_id,
150     bool by_user) {
151   if (by_user && notification_id == kNotificationId) {
152     UMA_HISTOGRAM_ENUMERATION(
153         "MultiDeviceSetup_NotificationDismissed",
154         GetMetricValueForNotification(notification_status_),
155         kNotificationTypeMax);
156   }
157 }
158
159 void MultiDeviceNotificationPresenter::OnNotificationClicked(
160     const std::string& notification_id,
161     const base::Optional<int>& button_index,
162     const base::Optional<base::string16>& reply) {
163   if (notification_id != kNotificationId)
164     return;
165
166   DCHECK(notification_status_ != Status::kNoNotificationVisible);
167   PA_LOG(VERBOSE) << "User clicked "
168                   << GetNotificationDescriptionForLogging(notification_status_)
169                   << ".";
170   UMA_HISTOGRAM_ENUMERATION("MultiDeviceSetup_NotificationClicked",
171                             GetMetricValueForNotification(notification_status_),
172                             kNotificationTypeMax);
173   switch (notification_status_) {
174     case Status::kNewUserNotificationVisible:
175       Shell::Get()->system_tray_model()->client()->ShowMultiDeviceSetup();
176       break;
177     case Status::kExistingUserHostSwitchedNotificationVisible:
178       // Clicks on the 'host switched' and 'Chromebook added' notifications have
179       // the same effect, i.e. opening the Settings subpage.
180       FALLTHROUGH;
181     case Status::kExistingUserNewChromebookNotificationVisible:
182       Shell::Get()
183           ->system_tray_model()
184           ->client()
185           ->ShowConnectedDevicesSettings();
186       break;
187     case Status::kNoNotificationVisible:
188       NOTREACHED();
189   }
190   RemoveMultiDeviceSetupNotification();
191 }
192
193 void MultiDeviceNotificationPresenter::ObserveMultiDeviceSetupIfPossible() {
194   // If already the delegate, there is nothing else to do.
195   if (multidevice_setup_remote_)
196     return;
197
198   const SessionControllerImpl* session_controller =
199       Shell::Get()->session_controller();
200
201   if (session_controller->GetSessionState() !=
202       session_manager::SessionState::ACTIVE) {
203     return;
204   }
205
206   const UserSession* user_session = session_controller->GetPrimaryUserSession();
207
208   // The primary user session may be unavailable (e.g., for test/guest users).
209   if (!user_session)
210     return;
211
212   Shell::Get()->shell_delegate()->BindMultiDeviceSetup(
213       multidevice_setup_remote_.BindNewPipeAndPassReceiver());
214
215   // Add this object as the delegate of the MultiDeviceSetup Service.
216   multidevice_setup_remote_->SetAccountStatusChangeDelegate(
217       receiver_.BindNewPipeAndPassRemote());
218
219   message_center_->AddObserver(this);
220 }
221
222 void MultiDeviceNotificationPresenter::ShowNotification(
223     const Status notification_status,
224     const base::string16& title,
225     const base::string16& message) {
226   PA_LOG(VERBOSE) << "Showing "
227                   << GetNotificationDescriptionForLogging(notification_status)
228                   << ".";
229   UMA_HISTOGRAM_ENUMERATION("MultiDeviceSetup_NotificationShown",
230                             GetMetricValueForNotification(notification_status),
231                             kNotificationTypeMax);
232   if (message_center_->FindVisibleNotificationById(kNotificationId)) {
233     message_center_->UpdateNotification(kNotificationId,
234                                         CreateNotification(title, message));
235   } else {
236     message_center_->AddNotification(CreateNotification(title, message));
237   }
238   notification_status_ = notification_status;
239 }
240
241 std::unique_ptr<message_center::Notification>
242 MultiDeviceNotificationPresenter::CreateNotification(
243     const base::string16& title,
244     const base::string16& message) {
245   return CreateSystemNotification(
246       message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE,
247       kNotificationId, title, message, base::string16() /* display_source */,
248       GURL() /* origin_url */,
249       message_center::NotifierId(message_center::NotifierType::SYSTEM_COMPONENT,
250                                  kNotifierMultiDevice),
251       message_center::RichNotificationData(), nullptr /* delegate */,
252       kNotificationMultiDeviceSetupIcon,
253       message_center::SystemNotificationWarningLevel::NORMAL);
254 }
255
256 void MultiDeviceNotificationPresenter::FlushForTesting() {
257   if (multidevice_setup_remote_)
258     multidevice_setup_remote_.FlushForTesting();
259 }
260
261 }  // namespace ash