123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/multi_device_setup/multi_device_notification_presenter.h"
- #include <memory>
- #include <utility>
- #include "ash/components/multidevice/logging/logging.h"
- #include "ash/constants/notifier_catalogs.h"
- #include "ash/public/cpp/notification_utils.h"
- #include "ash/public/cpp/system_tray_client.h"
- #include "ash/resources/vector_icons/vector_icons.h"
- #include "ash/session/session_controller_impl.h"
- #include "ash/shell.h"
- #include "ash/shell_delegate.h"
- #include "ash/strings/grit/ash_strings.h"
- #include "ash/system/model/system_tray_model.h"
- #include "base/callback_helpers.h"
- #include "base/memory/ptr_util.h"
- #include "base/metrics/histogram_functions.h"
- #include "base/strings/utf_string_conversions.h"
- #include "ui/base/l10n/l10n_util.h"
- #include "ui/chromeos/devicetype_utils.h"
- #include "ui/message_center/message_center.h"
- #include "ui/message_center/public/cpp/notifier_id.h"
- namespace ash {
- namespace {
- bool g_disable_notifications_for_test_ = false;
- const char kNotifierMultiDevice[] = "ash.multi_device_setup";
- } // namespace
- // static
- const char MultiDeviceNotificationPresenter::kSetupNotificationId[] =
- "cros_multi_device_setup_notification_id";
- // static
- const char MultiDeviceNotificationPresenter::kWifiSyncNotificationId[] =
- "cros_wifi_sync_announcement_notification_id";
- // static
- std::string
- MultiDeviceNotificationPresenter::GetNotificationDescriptionForLogging(
- Status notification_status) {
- switch (notification_status) {
- case Status::kNewUserNotificationVisible:
- return "notification to prompt setup";
- case Status::kExistingUserHostSwitchedNotificationVisible:
- return "notification of switch to new host";
- case Status::kExistingUserNewChromebookNotificationVisible:
- return "notification of new Chromebook added";
- case Status::kNoNotificationVisible:
- return "no notification";
- }
- NOTREACHED();
- }
- // static
- MultiDeviceNotificationPresenter::NotificationType
- MultiDeviceNotificationPresenter::GetMetricValueForNotification(
- Status notification_status) {
- switch (notification_status) {
- case Status::kNewUserNotificationVisible:
- return NotificationType::kNewUserPotentialHostExists;
- case Status::kExistingUserHostSwitchedNotificationVisible:
- return NotificationType::kExistingUserHostSwitched;
- case Status::kExistingUserNewChromebookNotificationVisible:
- return NotificationType::kExistingUserNewChromebookAdded;
- case Status::kNoNotificationVisible:
- NOTREACHED();
- return NotificationType::kErrorUnknown;
- }
- }
- MultiDeviceNotificationPresenter::MultiDeviceNotificationPresenter(
- message_center::MessageCenter* message_center)
- : message_center_(message_center) {
- DCHECK(message_center_);
- Shell::Get()->session_controller()->AddObserver(this);
- // If the constructor is called after the session state has already been set
- // (e.g., if recovering from a crash), handle that now. If the user has not
- // yet logged in, this will be a no-op.
- ObserveMultiDeviceSetupIfPossible();
- }
- MultiDeviceNotificationPresenter::~MultiDeviceNotificationPresenter() {
- message_center_->RemoveObserver(this);
- Shell::Get()->session_controller()->RemoveObserver(this);
- }
- void MultiDeviceNotificationPresenter::OnPotentialHostExistsForNewUser() {
- std::u16string title = l10n_util::GetStringUTF16(
- IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_TITLE);
- std::u16string message = l10n_util::GetStringFUTF16(
- IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_MESSAGE,
- ui::GetChromeOSDeviceName());
- ShowSetupNotification(Status::kNewUserNotificationVisible, title, message);
- }
- void MultiDeviceNotificationPresenter::OnNoLongerNewUser() {
- if (notification_status_ != Status::kNewUserNotificationVisible)
- return;
- RemoveMultiDeviceSetupNotification();
- }
- void MultiDeviceNotificationPresenter::OnConnectedHostSwitchedForExistingUser(
- const std::string& new_host_device_name) {
- std::u16string title = l10n_util::GetStringFUTF16(
- IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_HOST_SWITCHED_TITLE,
- base::ASCIIToUTF16(new_host_device_name));
- std::u16string message = l10n_util::GetStringFUTF16(
- IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_HOST_SWITCHED_MESSAGE,
- ui::GetChromeOSDeviceName());
- ShowSetupNotification(Status::kExistingUserHostSwitchedNotificationVisible,
- title, message);
- }
- void MultiDeviceNotificationPresenter::OnNewChromebookAddedForExistingUser(
- const std::string& new_host_device_name) {
- std::u16string title = l10n_util::GetStringFUTF16(
- IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROME_DEVICE_ADDED_TITLE,
- base::ASCIIToUTF16(new_host_device_name));
- std::u16string message = l10n_util::GetStringFUTF16(
- IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROME_DEVICE_ADDED_MESSAGE,
- ui::GetChromeOSDeviceName());
- ShowSetupNotification(Status::kExistingUserNewChromebookNotificationVisible,
- title, message);
- }
- void MultiDeviceNotificationPresenter::OnBecameEligibleForWifiSync() {
- std::u16string title =
- l10n_util::GetStringUTF16(IDS_ASH_MULTI_DEVICE_WIFI_SYNC_AVAILABLE_TITLE);
- std::u16string message = l10n_util::GetStringFUTF16(
- IDS_ASH_MULTI_DEVICE_WIFI_SYNC_AVAILABLE_MESSAGE,
- ui::GetChromeOSDeviceName());
- message_center::RichNotificationData optional_fields;
- optional_fields.buttons.push_back(
- message_center::ButtonInfo(l10n_util::GetStringUTF16(
- IDS_ASH_MULTI_DEVICE_WIFI_SYNC_AVAILABLE_TURN_ON_BUTTON)));
- optional_fields.buttons.push_back(
- message_center::ButtonInfo(l10n_util::GetStringUTF16(
- IDS_ASH_MULTI_DEVICE_WIFI_SYNC_AVAILABLE_CANCEL_BUTTON)));
- ShowNotification(kWifiSyncNotificationId, title, message, optional_fields);
- base::UmaHistogramEnumeration("MultiDeviceSetup_NotificationShown",
- NotificationType::kWifiSyncAnnouncement);
- }
- // static
- std::unique_ptr<base::AutoReset<bool>>
- MultiDeviceNotificationPresenter::DisableNotificationsForTesting() {
- return std::make_unique<base::AutoReset<bool>>(
- &g_disable_notifications_for_test_, true);
- }
- void MultiDeviceNotificationPresenter::RemoveMultiDeviceSetupNotification() {
- notification_status_ = Status::kNoNotificationVisible;
- message_center_->RemoveNotification(kSetupNotificationId,
- /* by_user */ false);
- }
- void MultiDeviceNotificationPresenter::OnUserSessionAdded(
- const AccountId& account_id) {
- ObserveMultiDeviceSetupIfPossible();
- }
- void MultiDeviceNotificationPresenter::OnSessionStateChanged(
- session_manager::SessionState state) {
- ObserveMultiDeviceSetupIfPossible();
- }
- void MultiDeviceNotificationPresenter::OnNotificationRemoved(
- const std::string& notification_id,
- bool by_user) {
- if (!by_user) {
- return;
- }
- if (notification_id == kSetupNotificationId) {
- base::UmaHistogramEnumeration(
- "MultiDeviceSetup_NotificationDismissed",
- GetMetricValueForNotification(notification_status_));
- return;
- }
- if (notification_id == kWifiSyncNotificationId) {
- base::UmaHistogramEnumeration("MultiDeviceSetup_NotificationDismissed",
- NotificationType::kWifiSyncAnnouncement);
- return;
- }
- }
- void MultiDeviceNotificationPresenter::OnNotificationClicked(
- const std::string& notification_id,
- const absl::optional<int>& button_index,
- const absl::optional<std::u16string>& reply) {
- if (notification_id == kWifiSyncNotificationId) {
- message_center_->RemoveNotification(kWifiSyncNotificationId,
- /* by_user */ false);
- if (button_index) {
- switch (*button_index) {
- case 0: // "Turn on" button
- PA_LOG(INFO) << "Enabling Wi-Fi Sync.";
- multidevice_setup_remote_->SetFeatureEnabledState(
- multidevice_setup::mojom::Feature::kWifiSync,
- /*enabled=*/true, /*auth_token=*/absl::nullopt,
- /*callback=*/base::DoNothing());
- break;
- case 1: // "Cancel" button
- base::UmaHistogramEnumeration(
- "MultiDeviceSetup_NotificationDismissed",
- NotificationType::kWifiSyncAnnouncement);
- return;
- }
- }
- Shell::Get()->system_tray_model()->client()->ShowWifiSyncSettings();
- base::UmaHistogramEnumeration("MultiDeviceSetup_NotificationClicked",
- NotificationType::kWifiSyncAnnouncement);
- return;
- }
- if (notification_id != kSetupNotificationId)
- return;
- DCHECK(notification_status_ != Status::kNoNotificationVisible);
- PA_LOG(VERBOSE) << "User clicked "
- << GetNotificationDescriptionForLogging(notification_status_)
- << ".";
- base::UmaHistogramEnumeration(
- "MultiDeviceSetup_NotificationClicked",
- GetMetricValueForNotification(notification_status_));
- switch (notification_status_) {
- case Status::kNewUserNotificationVisible:
- Shell::Get()->system_tray_model()->client()->ShowMultiDeviceSetup();
- break;
- case Status::kExistingUserHostSwitchedNotificationVisible:
- // Clicks on the 'host switched' and 'Chromebook added' notifications have
- // the same effect, i.e. opening the Settings subpage.
- [[fallthrough]];
- case Status::kExistingUserNewChromebookNotificationVisible:
- Shell::Get()
- ->system_tray_model()
- ->client()
- ->ShowConnectedDevicesSettings();
- break;
- case Status::kNoNotificationVisible:
- NOTREACHED();
- }
- RemoveMultiDeviceSetupNotification();
- }
- void MultiDeviceNotificationPresenter::ObserveMultiDeviceSetupIfPossible() {
- // If already the delegate, there is nothing else to do.
- if (multidevice_setup_remote_)
- return;
- const SessionControllerImpl* session_controller =
- Shell::Get()->session_controller();
- if (session_controller->GetSessionState() !=
- session_manager::SessionState::ACTIVE) {
- return;
- }
- const UserSession* user_session = session_controller->GetPrimaryUserSession();
- // The primary user session may be unavailable (e.g., for test/guest users).
- if (!user_session)
- return;
- Shell::Get()->shell_delegate()->BindMultiDeviceSetup(
- multidevice_setup_remote_.BindNewPipeAndPassReceiver());
- // Add this object as the delegate of the MultiDeviceSetup Service.
- multidevice_setup_remote_->SetAccountStatusChangeDelegate(
- receiver_.BindNewPipeAndPassRemote());
- message_center_->AddObserver(this);
- }
- void MultiDeviceNotificationPresenter::ShowSetupNotification(
- const Status notification_status,
- const std::u16string& title,
- const std::u16string& message) {
- PA_LOG(VERBOSE) << "Showing "
- << GetNotificationDescriptionForLogging(notification_status)
- << ".";
- base::UmaHistogramEnumeration(
- "MultiDeviceSetup_NotificationShown",
- GetMetricValueForNotification(notification_status));
- ShowNotification(kSetupNotificationId, title, message,
- message_center::RichNotificationData());
- notification_status_ = notification_status;
- }
- void MultiDeviceNotificationPresenter::ShowNotification(
- const std::string& id,
- const std::u16string& title,
- const std::u16string& message,
- message_center::RichNotificationData optional_fields) {
- if (g_disable_notifications_for_test_)
- return;
- std::unique_ptr<message_center::Notification> notification =
- CreateSystemNotification(
- message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE, id, title,
- message, std::u16string() /* display_source */,
- GURL() /* origin_url */,
- message_center::NotifierId(
- message_center::NotifierType::SYSTEM_COMPONENT,
- kNotifierMultiDevice, NotificationCatalogName::kMultiDevice),
- optional_fields, nullptr /* delegate */,
- kNotificationMultiDeviceSetupIcon,
- message_center::SystemNotificationWarningLevel::NORMAL);
- if (message_center_->FindVisibleNotificationById(kSetupNotificationId)) {
- message_center_->UpdateNotification(id, std::move(notification));
- return;
- }
- message_center_->AddNotification(std::move(notification));
- }
- void MultiDeviceNotificationPresenter::FlushForTesting() {
- if (multidevice_setup_remote_)
- multidevice_setup_remote_.FlushForTesting();
- }
- } // namespace ash
|