-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <utility>
+#include "ash/constants/ash_features.h"
+#include "ash/constants/notifier_catalogs.h"
#include "ash/public/cpp/notification_utils.h"
#include "ash/public/cpp/system_tray_client.h"
-#include "ash/public/cpp/vector_icons/vector_icons.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/bind_helpers.h"
+#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_functions.h"
#include "base/strings/utf_string_conversions.h"
-#include "chromeos/components/multidevice/logging/logging.h"
-#include "chromeos/services/multidevice_setup/public/mojom/constants.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
+#include "chromeos/ash/components/multidevice/logging/logging.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/notification_types.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::kNotificationId[] =
+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) {
NOTREACHED();
}
-MultiDeviceNotificationPresenter::OpenUiDelegate::~OpenUiDelegate() = default;
-
-void MultiDeviceNotificationPresenter::OpenUiDelegate::
- OpenMultiDeviceSetupUi() {
- Shell::Get()->system_tray_model()->client()->ShowMultiDeviceSetup();
-}
-
-void MultiDeviceNotificationPresenter::OpenUiDelegate::
- OpenConnectedDevicesSettings() {
- Shell::Get()->system_tray_model()->client()->ShowConnectedDevicesSettings();
-}
-
// static
MultiDeviceNotificationPresenter::NotificationType
MultiDeviceNotificationPresenter::GetMetricValueForNotification(
Status notification_status) {
switch (notification_status) {
case Status::kNewUserNotificationVisible:
- return kNotificationTypeNewUserPotentialHostExists;
+ return NotificationType::kNewUserPotentialHostExists;
case Status::kExistingUserHostSwitchedNotificationVisible:
- return kNotificationTypeExistingUserHostSwitched;
+ return NotificationType::kExistingUserHostSwitched;
case Status::kExistingUserNewChromebookNotificationVisible:
- return kNotificationTypeExistingUserNewChromebookAdded;
+ return NotificationType::kExistingUserNewChromebookAdded;
case Status::kNoNotificationVisible:
NOTREACHED();
- return kNotificationTypeMax;
+ return NotificationType::kErrorUnknown;
}
}
MultiDeviceNotificationPresenter::MultiDeviceNotificationPresenter(
- message_center::MessageCenter* message_center,
- service_manager::Connector* connector)
- : message_center_(message_center),
- connector_(connector),
- binding_(this),
- open_ui_delegate_(std::make_unique<OpenUiDelegate>()),
- weak_ptr_factory_(this) {
+ message_center::MessageCenter* message_center)
+ : message_center_(message_center) {
DCHECK(message_center_);
- DCHECK(connector_);
Shell::Get()->session_controller()->AddObserver(this);
}
void MultiDeviceNotificationPresenter::OnPotentialHostExistsForNewUser() {
- base::string16 title = l10n_util::GetStringUTF16(
- IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_TITLE);
- base::string16 message = l10n_util::GetStringFUTF16(
+ int title_message_id =
+ IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_TITLE;
+ if (features::IsPhoneHubOnboardingNotifierRevampEnabled() &&
+ !features::kPhoneHubOnboardingNotifierUseNudge.Get()) {
+ title_message_id =
+ features::kPhoneHubNotifierTextGroup.Get() ==
+ features::PhoneHubNotifierTextGroup::kNotifierTextGroupA
+ ? IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITH_PHONE_HUB
+ : IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITHOUT_PHONE_HUB;
+ }
+ std::u16string title = l10n_util::GetStringUTF16(title_message_id);
+ std::u16string message = l10n_util::GetStringFUTF16(
IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_MESSAGE,
ui::GetChromeOSDeviceName());
- ShowNotification(Status::kNewUserNotificationVisible, title, message);
+ ShowSetupNotification(Status::kNewUserNotificationVisible, title, message);
}
void MultiDeviceNotificationPresenter::OnNoLongerNewUser() {
void MultiDeviceNotificationPresenter::OnConnectedHostSwitchedForExistingUser(
const std::string& new_host_device_name) {
- base::string16 title = l10n_util::GetStringFUTF16(
+ std::u16string title = l10n_util::GetStringFUTF16(
IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_HOST_SWITCHED_TITLE,
base::ASCIIToUTF16(new_host_device_name));
- base::string16 message = l10n_util::GetStringFUTF16(
+ std::u16string message = l10n_util::GetStringFUTF16(
IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_HOST_SWITCHED_MESSAGE,
ui::GetChromeOSDeviceName());
- ShowNotification(Status::kExistingUserHostSwitchedNotificationVisible, title,
- message);
+ ShowSetupNotification(Status::kExistingUserHostSwitchedNotificationVisible,
+ title, message);
}
void MultiDeviceNotificationPresenter::OnNewChromebookAddedForExistingUser(
const std::string& new_host_device_name) {
- base::string16 title = l10n_util::GetStringFUTF16(
+ std::u16string title = l10n_util::GetStringFUTF16(
IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROME_DEVICE_ADDED_TITLE,
base::ASCIIToUTF16(new_host_device_name));
- base::string16 message = l10n_util::GetStringFUTF16(
+ std::u16string message = l10n_util::GetStringFUTF16(
IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROME_DEVICE_ADDED_MESSAGE,
ui::GetChromeOSDeviceName());
- ShowNotification(Status::kExistingUserNewChromebookNotificationVisible, title,
- message);
+ 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(kNotificationId,
+ message_center_->RemoveNotification(kSetupNotificationId,
/* by_user */ false);
}
+void MultiDeviceNotificationPresenter::UpdateIsSetupNotificationInteracted(
+ bool is_setup_notification_interacted) {
+ is_setup_notification_interacted_ = is_setup_notification_interacted;
+}
+
void MultiDeviceNotificationPresenter::OnUserSessionAdded(
const AccountId& account_id) {
ObserveMultiDeviceSetupIfPossible();
void MultiDeviceNotificationPresenter::OnNotificationRemoved(
const std::string& notification_id,
bool by_user) {
- if (by_user && notification_id == kNotificationId) {
- UMA_HISTOGRAM_ENUMERATION(
+ if (!by_user) {
+ return;
+ }
+ if (notification_id == kSetupNotificationId) {
+ base::UmaHistogramEnumeration(
"MultiDeviceSetup_NotificationDismissed",
- GetMetricValueForNotification(notification_status_),
- kNotificationTypeMax);
+ GetMetricValueForNotification(notification_status_));
+ return;
+ }
+ if (notification_id == kWifiSyncNotificationId) {
+ base::UmaHistogramEnumeration("MultiDeviceSetup_NotificationDismissed",
+ NotificationType::kWifiSyncAnnouncement);
+ return;
}
}
void MultiDeviceNotificationPresenter::OnNotificationClicked(
const std::string& notification_id,
- const base::Optional<int>& button_index,
- const base::Optional<base::string16>& reply) {
- if (notification_id != kNotificationId)
+ 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_)
<< ".";
- UMA_HISTOGRAM_ENUMERATION("MultiDeviceSetup_NotificationClicked",
- GetMetricValueForNotification(notification_status_),
- kNotificationTypeMax);
+ base::UmaHistogramEnumeration(
+ "MultiDeviceSetup_NotificationClicked",
+ GetMetricValueForNotification(notification_status_));
switch (notification_status_) {
case Status::kNewUserNotificationVisible:
- open_ui_delegate_->OpenMultiDeviceSetupUi();
+ Shell::Get()->system_tray_model()->client()->ShowMultiDeviceSetup();
+ // If user has not interacted with Phone Hub icon when the notification is
+ // visible, log MultiDeviceSetup.NotificationInteracted event when
+ // notification is clicked.
+ if (!is_setup_notification_interacted_) {
+ base::UmaHistogramCounts100("MultiDeviceSetup.NotificationInteracted",
+ 1);
+ } else {
+ // Restore the value when the notification is clicked.
+ UpdateIsSetupNotificationInteracted(false);
+ }
break;
case Status::kExistingUserHostSwitchedNotificationVisible:
// Clicks on the 'host switched' and 'Chromebook added' notifications have
// the same effect, i.e. opening the Settings subpage.
- FALLTHROUGH;
+ [[fallthrough]];
case Status::kExistingUserNewChromebookNotificationVisible:
- open_ui_delegate_->OpenConnectedDevicesSettings();
+ Shell::Get()
+ ->system_tray_model()
+ ->client()
+ ->ShowConnectedDevicesSettings();
break;
case Status::kNoNotificationVisible:
NOTREACHED();
void MultiDeviceNotificationPresenter::ObserveMultiDeviceSetupIfPossible() {
// If already the delegate, there is nothing else to do.
- if (multidevice_setup_ptr_)
+ if (multidevice_setup_remote_)
return;
const SessionControllerImpl* session_controller =
Shell::Get()->session_controller();
- // If no active user is logged in, there is nothing to do.
if (session_controller->GetSessionState() !=
session_manager::SessionState::ACTIVE) {
return;
if (!user_session)
return;
- base::Optional<base::Token> service_instance_group =
- user_session->user_info.service_instance_group;
-
- // Cannot proceed if there is no known service instance group.
- if (!service_instance_group)
- return;
-
- connector_->BindInterface(
- service_manager::ServiceFilter::ByNameInGroup(
- chromeos::multidevice_setup::mojom::kServiceName,
- *service_instance_group),
- &multidevice_setup_ptr_);
+ Shell::Get()->shell_delegate()->BindMultiDeviceSetup(
+ multidevice_setup_remote_.BindNewPipeAndPassReceiver());
// Add this object as the delegate of the MultiDeviceSetup Service.
- chromeos::multidevice_setup::mojom::AccountStatusChangeDelegatePtr
- delegate_ptr;
- binding_.Bind(mojo::MakeRequest(&delegate_ptr));
- multidevice_setup_ptr_->SetAccountStatusChangeDelegate(
- std::move(delegate_ptr));
+ multidevice_setup_remote_->SetAccountStatusChangeDelegate(
+ receiver_.BindNewPipeAndPassRemote());
message_center_->AddObserver(this);
}
-void MultiDeviceNotificationPresenter::ShowNotification(
+void MultiDeviceNotificationPresenter::ShowSetupNotification(
const Status notification_status,
- const base::string16& title,
- const base::string16& message) {
+ const std::u16string& title,
+ const std::u16string& message) {
PA_LOG(VERBOSE) << "Showing "
<< GetNotificationDescriptionForLogging(notification_status)
<< ".";
- UMA_HISTOGRAM_ENUMERATION("MultiDeviceSetup_NotificationShown",
- GetMetricValueForNotification(notification_status),
- kNotificationTypeMax);
- if (message_center_->FindVisibleNotificationById(kNotificationId)) {
- message_center_->UpdateNotification(kNotificationId,
- CreateNotification(title, message));
- } else {
- message_center_->AddNotification(CreateNotification(title, message));
- }
+ base::UmaHistogramEnumeration(
+ "MultiDeviceSetup_NotificationShown",
+ GetMetricValueForNotification(notification_status));
+
+ ShowNotification(kSetupNotificationId, title, message,
+ message_center::RichNotificationData());
notification_status_ = notification_status;
}
-std::unique_ptr<message_center::Notification>
-MultiDeviceNotificationPresenter::CreateNotification(
- const base::string16& title,
- const base::string16& message) {
- return ash::CreateSystemNotification(
- message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE,
- kNotificationId, title, message, base::string16() /* display_source */,
- GURL() /* origin_url */,
- message_center::NotifierId(message_center::NotifierType::SYSTEM_COMPONENT,
- kNotifierMultiDevice),
- message_center::RichNotificationData(), nullptr /* delegate */,
- ash::kNotificationMultiDeviceSetupIcon,
- message_center::SystemNotificationWarningLevel::NORMAL);
+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 =
+ CreateSystemNotificationPtr(
+ 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_ptr_)
- multidevice_setup_ptr_.FlushForTesting();
+ if (multidevice_setup_remote_)
+ multidevice_setup_remote_.FlushForTesting();
}
} // namespace ash