blob: c380a89b9dc5a7c5f227f8559ffb240d39e6010f [file] [log] [blame]
// Copyright 2017 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/system/message_center/message_center_controller.h"
#include <utility>
#include "ash/public/cpp/ash_pref_names.h"
#include "ash/public/cpp/ash_switches.h"
#include "ash/public/cpp/vector_icons/vector_icons.h"
#include "ash/session/session_controller.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/message_center/arc_notification_manager_delegate_impl.h"
#include "ash/system/message_center/ash_message_center_lock_screen_controller.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/unguessable_token.h"
#include "components/account_id/account_id.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/vector_icons/vector_icons.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/message_center/public/cpp/notification_delegate.h"
#include "ui/message_center/public/cpp/notifier_id.h"
using message_center::MessageCenter;
using message_center::NotifierId;
namespace ash {
// static
void MessageCenterController::RegisterProfilePrefs(
PrefRegistrySimple* registry) {
registry->RegisterStringPref(
prefs::kMessageCenterLockScreenMode,
prefs::kMessageCenterLockScreenModeHide,
user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC);
}
namespace {
// A notification blocker that unconditionally blocks toasts. Implements
// --suppress-message-center-notifications.
class PopupNotificationBlocker : public message_center::NotificationBlocker {
public:
explicit PopupNotificationBlocker(MessageCenter* message_center)
: NotificationBlocker(message_center) {}
~PopupNotificationBlocker() override = default;
bool ShouldShowNotificationAsPopup(
const message_center::Notification& notification) const override {
return false;
}
private:
DISALLOW_COPY_AND_ASSIGN(PopupNotificationBlocker);
};
// This notification delegate passes actions back to the client that asked for
// the notification (Chrome).
class AshClientNotificationDelegate
: public message_center::NotificationDelegate {
public:
AshClientNotificationDelegate(const std::string& notification_id,
const base::UnguessableToken& display_token,
mojom::AshMessageCenterClient* client)
: notification_id_(notification_id),
display_token_(display_token),
client_(client) {}
void Close(bool by_user) override {
client_->HandleNotificationClosed(display_token_, by_user);
}
void Click(const base::Optional<int>& button_index,
const base::Optional<base::string16>& reply) override {
if (button_index) {
client_->HandleNotificationButtonClicked(notification_id_, *button_index,
reply);
} else {
client_->HandleNotificationClicked(notification_id_);
}
}
void SettingsClick() override {
client_->HandleNotificationSettingsButtonClicked(notification_id_);
}
void DisableNotification() override {
client_->DisableNotification(notification_id_);
}
private:
~AshClientNotificationDelegate() override = default;
// The ID of the notification.
const std::string notification_id_;
// The token that was generated for the ShowClientNotification() call.
const base::UnguessableToken display_token_;
mojom::AshMessageCenterClient* client_;
DISALLOW_COPY_AND_ASSIGN(AshClientNotificationDelegate);
};
} // namespace
MessageCenterController::MessageCenterController() {
message_center::MessageCenter::Initialize(
std::make_unique<AshMessageCenterLockScreenController>());
fullscreen_notification_blocker_ =
std::make_unique<FullscreenNotificationBlocker>(MessageCenter::Get());
inactive_user_notification_blocker_ =
std::make_unique<InactiveUserNotificationBlocker>(MessageCenter::Get());
session_state_notification_blocker_ =
std::make_unique<SessionStateNotificationBlocker>(MessageCenter::Get());
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSuppressMessageCenterPopups)) {
all_popup_blocker_ =
std::make_unique<PopupNotificationBlocker>(MessageCenter::Get());
}
message_center::RegisterVectorIcons({&vector_icons::kBusinessIcon,
&kNotificationAssistantIcon,
&kNotificationCaptivePortalIcon,
&kNotificationCellularAlertIcon,
&kNotificationDownloadIcon,
&kNotificationEndOfSupportIcon,
&kNotificationFamilyLinkIcon,
&kNotificationGoogleIcon,
&kNotificationImageIcon,
&kNotificationInstalledIcon,
&kNotificationLinuxIcon,
&kNotificationMessagesIcon,
&kNotificationMultiDeviceSetupIcon,
&kNotificationMobileDataIcon,
&kNotificationMobileDataOffIcon,
&kNotificationPlayPrismIcon,
&kNotificationPrintingDoneIcon,
&kNotificationPrintingIcon,
&kNotificationPrintingWarningIcon,
&kNotificationSettingsIcon,
&kNotificationStorageFullIcon,
&kNotificationSupervisedUserIcon,
&kNotificationVpnIcon,
&kNotificationWarningIcon,
&kNotificationWifiOffIcon});
// Set the system notification source display name ("Chrome OS" or "Chromium
// OS").
message_center::MessageCenter::Get()->SetSystemNotificationAppName(
l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_SYSTEM_APP_NAME));
}
MessageCenterController::~MessageCenterController() {
// These members all depend on the MessageCenter instance, so must be
// destroyed first.
all_popup_blocker_.reset();
session_state_notification_blocker_.reset();
inactive_user_notification_blocker_.reset();
fullscreen_notification_blocker_.reset();
arc_notification_manager_.reset();
message_center::MessageCenter::Shutdown();
}
void MessageCenterController::BindRequest(
mojom::AshMessageCenterControllerRequest request) {
binding_set_.AddBinding(this, std::move(request));
}
void MessageCenterController::SetNotifierEnabled(const NotifierId& notifier_id,
bool enabled) {
client_->SetNotifierEnabled(notifier_id, enabled);
}
void MessageCenterController::SetClient(
mojom::AshMessageCenterClientAssociatedPtrInfo client) {
DCHECK(!client_.is_bound());
client_.Bind(std::move(client));
}
void MessageCenterController::SetArcNotificationsInstance(
arc::mojom::NotificationsInstancePtr arc_notification_instance) {
if (!arc_notification_manager_) {
arc_notification_manager_ = std::make_unique<ArcNotificationManager>(
std::make_unique<ArcNotificationManagerDelegateImpl>(),
Shell::Get()
->session_controller()
->GetPrimaryUserSession()
->user_info->account_id,
message_center::MessageCenter::Get());
}
arc_notification_manager_->SetInstance(std::move(arc_notification_instance));
}
void MessageCenterController::ShowClientNotification(
const message_center::Notification& notification,
const base::UnguessableToken& display_token) {
DCHECK(client_.is_bound());
auto message_center_notification =
std::make_unique<message_center::Notification>(notification);
message_center_notification->set_delegate(
base::WrapRefCounted(new AshClientNotificationDelegate(
notification.id(), display_token, client_.get())));
MessageCenter::Get()->AddNotification(std::move(message_center_notification));
}
void MessageCenterController::CloseClientNotification(const std::string& id) {
MessageCenter::Get()->RemoveNotification(id, false /* by_user */);
}
void MessageCenterController::UpdateNotifierIcon(const NotifierId& notifier_id,
const gfx::ImageSkia& icon) {
for (auto& listener : notifier_settings_listeners_)
listener.UpdateNotifierIcon(notifier_id, icon);
}
void MessageCenterController::NotifierEnabledChanged(
const NotifierId& notifier_id,
bool enabled) {
if (!enabled)
MessageCenter::Get()->RemoveNotificationsForNotifierId(notifier_id);
}
void MessageCenterController::GetActiveNotifications(
GetActiveNotificationsCallback callback) {
message_center::NotificationList::Notifications notification_set =
MessageCenter::Get()->GetVisibleNotifications();
std::vector<message_center::Notification> notification_vector;
notification_vector.reserve(notification_set.size());
for (auto* notification : notification_set) {
notification_vector.emplace_back(*notification);
// The client doesn't know how to de-serialize vector icons,
// nor does it need to.
notification_vector.back().set_vector_small_image(gfx::kNoneIcon);
}
std::move(callback).Run(notification_vector);
}
void MessageCenterController::SetQuietMode(bool enabled) {
MessageCenter::Get()->SetQuietMode(enabled);
}
void MessageCenterController::GetArcAppIdByPackageName(
const std::string& package_name,
GetAppIdByPackageNameCallback callback) {
DCHECK(client_.is_bound());
client_->GetArcAppIdByPackageName(package_name, std::move(callback));
}
void MessageCenterController::ShowLockScreenNotificationSettings() {
DCHECK(client_.is_bound());
client_->ShowLockScreenNotificationSettings();
}
void MessageCenterController::AddNotifierSettingsListener(
NotifierSettingsListener* listener) {
DCHECK(listener);
notifier_settings_listeners_.AddObserver(listener);
}
void MessageCenterController::RemoveNotifierSettingsListener(
NotifierSettingsListener* listener) {
DCHECK(listener);
notifier_settings_listeners_.RemoveObserver(listener);
}
void MessageCenterController::RequestNotifierSettingsUpdate() {
// |client_| may not be bound in unit tests.
if (!client_.is_bound())
return;
client_->GetNotifierList(base::BindOnce(
&MessageCenterController::OnGotNotifierList, base::Unretained(this)));
}
void MessageCenterController::OnGotNotifierList(
std::vector<mojom::NotifierUiDataPtr> ui_data) {
disabled_notifier_count_ = 0;
for (const auto& notifier : ui_data) {
if (!notifier->enabled)
++disabled_notifier_count_;
}
for (auto& listener : notifier_settings_listeners_)
listener.OnNotifierListUpdated(ui_data);
}
} // namespace ash