Upload upstream chromium 94.0.4606.31
[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/callback_helpers.h"
19 #include "base/memory/ptr_util.h"
20 #include "base/metrics/histogram_functions.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/notifier_id.h"
27
28 namespace ash {
29
30 namespace {
31
32 const char kNotifierMultiDevice[] = "ash.multi_device_setup";
33
34 }  // namespace
35
36 // static
37 const char MultiDeviceNotificationPresenter::kSetupNotificationId[] =
38     "cros_multi_device_setup_notification_id";
39
40 // static
41 const char MultiDeviceNotificationPresenter::kWifiSyncNotificationId[] =
42     "cros_wifi_sync_announcement_notification_id";
43
44 // static
45 std::string
46 MultiDeviceNotificationPresenter::GetNotificationDescriptionForLogging(
47     Status notification_status) {
48   switch (notification_status) {
49     case Status::kNewUserNotificationVisible:
50       return "notification to prompt setup";
51     case Status::kExistingUserHostSwitchedNotificationVisible:
52       return "notification of switch to new host";
53     case Status::kExistingUserNewChromebookNotificationVisible:
54       return "notification of new Chromebook added";
55     case Status::kNoNotificationVisible:
56       return "no notification";
57   }
58   NOTREACHED();
59 }
60
61 // static
62 MultiDeviceNotificationPresenter::NotificationType
63 MultiDeviceNotificationPresenter::GetMetricValueForNotification(
64     Status notification_status) {
65   switch (notification_status) {
66     case Status::kNewUserNotificationVisible:
67       return NotificationType::kNewUserPotentialHostExists;
68     case Status::kExistingUserHostSwitchedNotificationVisible:
69       return NotificationType::kExistingUserHostSwitched;
70     case Status::kExistingUserNewChromebookNotificationVisible:
71       return NotificationType::kExistingUserNewChromebookAdded;
72     case Status::kNoNotificationVisible:
73       NOTREACHED();
74       return NotificationType::kErrorUnknown;
75   }
76 }
77
78 MultiDeviceNotificationPresenter::MultiDeviceNotificationPresenter(
79     message_center::MessageCenter* message_center)
80     : message_center_(message_center) {
81   DCHECK(message_center_);
82
83   Shell::Get()->session_controller()->AddObserver(this);
84
85   // If the constructor is called after the session state has already been set
86   // (e.g., if recovering from a crash), handle that now. If the user has not
87   // yet logged in, this will be a no-op.
88   ObserveMultiDeviceSetupIfPossible();
89 }
90
91 MultiDeviceNotificationPresenter::~MultiDeviceNotificationPresenter() {
92   message_center_->RemoveObserver(this);
93   Shell::Get()->session_controller()->RemoveObserver(this);
94 }
95
96 void MultiDeviceNotificationPresenter::OnPotentialHostExistsForNewUser() {
97   std::u16string title = l10n_util::GetStringUTF16(
98       IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_TITLE);
99   std::u16string message = l10n_util::GetStringFUTF16(
100       IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_MESSAGE,
101       ui::GetChromeOSDeviceName());
102   ShowSetupNotification(Status::kNewUserNotificationVisible, title, message);
103 }
104
105 void MultiDeviceNotificationPresenter::OnNoLongerNewUser() {
106   if (notification_status_ != Status::kNewUserNotificationVisible)
107     return;
108   RemoveMultiDeviceSetupNotification();
109 }
110
111 void MultiDeviceNotificationPresenter::OnConnectedHostSwitchedForExistingUser(
112     const std::string& new_host_device_name) {
113   std::u16string title = l10n_util::GetStringFUTF16(
114       IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_HOST_SWITCHED_TITLE,
115       base::ASCIIToUTF16(new_host_device_name));
116   std::u16string message = l10n_util::GetStringFUTF16(
117       IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_HOST_SWITCHED_MESSAGE,
118       ui::GetChromeOSDeviceName());
119   ShowSetupNotification(Status::kExistingUserHostSwitchedNotificationVisible,
120                         title, message);
121 }
122
123 void MultiDeviceNotificationPresenter::OnNewChromebookAddedForExistingUser(
124     const std::string& new_host_device_name) {
125   std::u16string title = l10n_util::GetStringFUTF16(
126       IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROME_DEVICE_ADDED_TITLE,
127       base::ASCIIToUTF16(new_host_device_name));
128   std::u16string message = l10n_util::GetStringFUTF16(
129       IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROME_DEVICE_ADDED_MESSAGE,
130       ui::GetChromeOSDeviceName());
131   ShowSetupNotification(Status::kExistingUserNewChromebookNotificationVisible,
132                         title, message);
133 }
134
135 void MultiDeviceNotificationPresenter::OnBecameEligibleForWifiSync() {
136   std::u16string title =
137       l10n_util::GetStringUTF16(IDS_ASH_MULTI_DEVICE_WIFI_SYNC_AVAILABLE_TITLE);
138   std::u16string message = l10n_util::GetStringFUTF16(
139       IDS_ASH_MULTI_DEVICE_WIFI_SYNC_AVAILABLE_MESSAGE,
140       ui::GetChromeOSDeviceName());
141   message_center::RichNotificationData optional_fields;
142   optional_fields.buttons.push_back(
143       message_center::ButtonInfo(l10n_util::GetStringUTF16(
144           IDS_ASH_MULTI_DEVICE_WIFI_SYNC_AVAILABLE_TURN_ON_BUTTON)));
145   optional_fields.buttons.push_back(
146       message_center::ButtonInfo(l10n_util::GetStringUTF16(
147           IDS_ASH_MULTI_DEVICE_WIFI_SYNC_AVAILABLE_CANCEL_BUTTON)));
148
149   ShowNotification(kWifiSyncNotificationId, title, message, optional_fields);
150   base::UmaHistogramEnumeration("MultiDeviceSetup_NotificationShown",
151                                 NotificationType::kWifiSyncAnnouncement);
152 }
153
154 void MultiDeviceNotificationPresenter::RemoveMultiDeviceSetupNotification() {
155   notification_status_ = Status::kNoNotificationVisible;
156   message_center_->RemoveNotification(kSetupNotificationId,
157                                       /* by_user */ false);
158 }
159
160 void MultiDeviceNotificationPresenter::OnUserSessionAdded(
161     const AccountId& account_id) {
162   ObserveMultiDeviceSetupIfPossible();
163 }
164
165 void MultiDeviceNotificationPresenter::OnSessionStateChanged(
166     session_manager::SessionState state) {
167   ObserveMultiDeviceSetupIfPossible();
168 }
169
170 void MultiDeviceNotificationPresenter::OnNotificationRemoved(
171     const std::string& notification_id,
172     bool by_user) {
173   if (!by_user) {
174     return;
175   }
176   if (notification_id == kSetupNotificationId) {
177     base::UmaHistogramEnumeration(
178         "MultiDeviceSetup_NotificationDismissed",
179         GetMetricValueForNotification(notification_status_));
180     return;
181   }
182   if (notification_id == kWifiSyncNotificationId) {
183     base::UmaHistogramEnumeration("MultiDeviceSetup_NotificationDismissed",
184                                   NotificationType::kWifiSyncAnnouncement);
185     return;
186   }
187 }
188
189 void MultiDeviceNotificationPresenter::OnNotificationClicked(
190     const std::string& notification_id,
191     const absl::optional<int>& button_index,
192     const absl::optional<std::u16string>& reply) {
193   if (notification_id == kWifiSyncNotificationId) {
194     message_center_->RemoveNotification(kWifiSyncNotificationId,
195                                         /* by_user */ false);
196
197     if (button_index) {
198       switch (*button_index) {
199         case 0:  // "Turn on" button
200           PA_LOG(INFO) << "Enabling Wi-Fi Sync.";
201           multidevice_setup_remote_->SetFeatureEnabledState(
202               chromeos::multidevice_setup::mojom::Feature::kWifiSync,
203               /*enabled=*/true, /*auth_token=*/absl::nullopt,
204               /*callback=*/base::DoNothing());
205           break;
206         case 1:  // "Cancel" button
207           base::UmaHistogramEnumeration(
208               "MultiDeviceSetup_NotificationDismissed",
209               NotificationType::kWifiSyncAnnouncement);
210           return;
211       }
212     }
213
214     Shell::Get()->system_tray_model()->client()->ShowWifiSyncSettings();
215     base::UmaHistogramEnumeration("MultiDeviceSetup_NotificationClicked",
216                                   NotificationType::kWifiSyncAnnouncement);
217     return;
218   }
219
220   if (notification_id != kSetupNotificationId)
221     return;
222
223   DCHECK(notification_status_ != Status::kNoNotificationVisible);
224   PA_LOG(VERBOSE) << "User clicked "
225                   << GetNotificationDescriptionForLogging(notification_status_)
226                   << ".";
227   base::UmaHistogramEnumeration(
228       "MultiDeviceSetup_NotificationClicked",
229       GetMetricValueForNotification(notification_status_));
230   switch (notification_status_) {
231     case Status::kNewUserNotificationVisible:
232       Shell::Get()->system_tray_model()->client()->ShowMultiDeviceSetup();
233       break;
234     case Status::kExistingUserHostSwitchedNotificationVisible:
235       // Clicks on the 'host switched' and 'Chromebook added' notifications have
236       // the same effect, i.e. opening the Settings subpage.
237       FALLTHROUGH;
238     case Status::kExistingUserNewChromebookNotificationVisible:
239       Shell::Get()
240           ->system_tray_model()
241           ->client()
242           ->ShowConnectedDevicesSettings();
243       break;
244     case Status::kNoNotificationVisible:
245       NOTREACHED();
246   }
247   RemoveMultiDeviceSetupNotification();
248 }
249
250 void MultiDeviceNotificationPresenter::ObserveMultiDeviceSetupIfPossible() {
251   // If already the delegate, there is nothing else to do.
252   if (multidevice_setup_remote_)
253     return;
254
255   const SessionControllerImpl* session_controller =
256       Shell::Get()->session_controller();
257
258   if (session_controller->GetSessionState() !=
259       session_manager::SessionState::ACTIVE) {
260     return;
261   }
262
263   const UserSession* user_session = session_controller->GetPrimaryUserSession();
264
265   // The primary user session may be unavailable (e.g., for test/guest users).
266   if (!user_session)
267     return;
268
269   Shell::Get()->shell_delegate()->BindMultiDeviceSetup(
270       multidevice_setup_remote_.BindNewPipeAndPassReceiver());
271
272   // Add this object as the delegate of the MultiDeviceSetup Service.
273   multidevice_setup_remote_->SetAccountStatusChangeDelegate(
274       receiver_.BindNewPipeAndPassRemote());
275
276   message_center_->AddObserver(this);
277 }
278
279 void MultiDeviceNotificationPresenter::ShowSetupNotification(
280     const Status notification_status,
281     const std::u16string& title,
282     const std::u16string& message) {
283   PA_LOG(VERBOSE) << "Showing "
284                   << GetNotificationDescriptionForLogging(notification_status)
285                   << ".";
286   base::UmaHistogramEnumeration(
287       "MultiDeviceSetup_NotificationShown",
288       GetMetricValueForNotification(notification_status));
289
290   ShowNotification(kSetupNotificationId, title, message,
291                    message_center::RichNotificationData());
292   notification_status_ = notification_status;
293 }
294
295 void MultiDeviceNotificationPresenter::ShowNotification(
296     const std::string& id,
297     const std::u16string& title,
298     const std::u16string& message,
299     message_center::RichNotificationData optional_fields) {
300   std::unique_ptr<message_center::Notification> notification =
301       CreateSystemNotification(
302           message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE, id, title,
303           message, std::u16string() /* display_source */,
304           GURL() /* origin_url */,
305           message_center::NotifierId(
306               message_center::NotifierType::SYSTEM_COMPONENT,
307               kNotifierMultiDevice),
308           optional_fields, nullptr /* delegate */,
309           kNotificationMultiDeviceSetupIcon,
310           message_center::SystemNotificationWarningLevel::NORMAL);
311
312   if (message_center_->FindVisibleNotificationById(kSetupNotificationId)) {
313     message_center_->UpdateNotification(id, std::move(notification));
314     return;
315   }
316
317   message_center_->AddNotification(std::move(notification));
318 }
319
320 void MultiDeviceNotificationPresenter::FlushForTesting() {
321   if (multidevice_setup_remote_)
322     multidevice_setup_remote_.FlushForTesting();
323 }
324
325 }  // namespace ash