blob: d379e0294f2b21745351805cf7b608b4b5b90d79 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/privacy_hub/privacy_hub_notification_controller.h"
#include "ash/public/cpp/new_window_delegate.h"
#include "ash/public/cpp/sensor_disabled_notification_delegate.h"
#include "ash/public/cpp/system_tray_client.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/model/system_tray_model.h"
#include "ash/system/privacy_hub/camera_privacy_switch_controller.h"
#include "ash/system/privacy_hub/microphone_privacy_switch_controller.h"
#include "ash/system/privacy_hub/privacy_hub_metrics.h"
#include "chromeos/ash/components/audio/cras_audio_handler.h"
#include "ui/message_center/message_center.h"
namespace ash {
namespace {
void SetAndLogMicrophoneMute(const bool muted) {
CrasAudioHandler::Get()->SetInputMute(
muted, CrasAudioHandler::InputMuteChangeMethod::kOther);
privacy_hub_metrics::LogMicrophoneEnabledFromNotification(!muted);
}
constexpr char kLearnMoreUrl[] =
"https://support.google.com/chromebook/?p=privacy_hub";
} // namespace
PrivacyHubNotificationController::PrivacyHubNotificationController() {
sw_notifications_.emplace(
Sensor::kCamera,
std::make_unique<PrivacyHubNotification>(
kPrivacyHubCameraOffNotificationId,
IDS_PRIVACY_HUB_CAMERA_OFF_NOTIFICATION_TITLE,
PrivacyHubNotification::MessageIds{
IDS_PRIVACY_HUB_CAMERA_OFF_NOTIFICATION_MESSAGE,
IDS_PRIVACY_HUB_CAMERA_OFF_NOTIFICATION_MESSAGE_WITH_ONE_APP_NAME,
IDS_PRIVACY_HUB_CAMERA_OFF_NOTIFICATION_MESSAGE_WITH_TWO_APP_NAMES},
PrivacyHubNotification::SensorSet{
SensorDisabledNotificationDelegate::Sensor::kCamera},
base::MakeRefCounted<PrivacyHubNotificationClickDelegate>(
base::BindRepeating([]() {
CameraPrivacySwitchController::
SetAndLogCameraPreferenceFromNotification(true);
})),
ash::NotificationCatalogName::kPrivacyHubCamera,
IDS_PRIVACY_HUB_TURN_ON_CAMERA_ACTION_BUTTON));
sw_notifications_.emplace(
Sensor::kMicrophone,
std::make_unique<PrivacyHubNotification>(
MicrophonePrivacySwitchController::kNotificationId,
IDS_MICROPHONE_MUTED_BY_SW_SWITCH_NOTIFICATION_TITLE,
PrivacyHubNotification::MessageIds{
IDS_MICROPHONE_MUTED_NOTIFICATION_MESSAGE,
IDS_MICROPHONE_MUTED_NOTIFICATION_MESSAGE_WITH_ONE_APP_NAME,
IDS_MICROPHONE_MUTED_NOTIFICATION_MESSAGE_WITH_TWO_APP_NAMES},
PrivacyHubNotification::SensorSet{
SensorDisabledNotificationDelegate::Sensor::kMicrophone},
base::MakeRefCounted<PrivacyHubNotificationClickDelegate>(
base::BindRepeating([]() { SetAndLogMicrophoneMute(false); })),
ash::NotificationCatalogName::kMicrophoneMute,
IDS_MICROPHONE_MUTED_NOTIFICATION_ACTION_BUTTON));
auto combined_delegate = base::MakeRefCounted<
PrivacyHubNotificationClickDelegate>(base::BindRepeating([]() {
SetAndLogMicrophoneMute(false);
CameraPrivacySwitchController::SetAndLogCameraPreferenceFromNotification(
true);
}));
combined_delegate->SetMessageClickCallback(base::BindRepeating(
&PrivacyHubNotificationController::HandleNotificationMessageClicked,
weak_ptr_factory_.GetWeakPtr()));
combined_notification_ = std::make_unique<PrivacyHubNotification>(
kCombinedNotificationId,
IDS_PRIVACY_HUB_MICROPHONE_AND_CAMERA_OFF_NOTIFICATION_TITLE,
PrivacyHubNotification::MessageIds{
IDS_PRIVACY_HUB_MICROPHONE_AND_CAMERA_OFF_NOTIFICATION_MESSAGE,
IDS_PRIVACY_HUB_MICROPHONE_AND_CAMERA_OFF_NOTIFICATION_MESSAGE_WITH_ONE_APP_NAME,
IDS_PRIVACY_HUB_MICROPHONE_AND_CAMERA_OFF_NOTIFICATION_MESSAGE_WITH_TWO_APP_NAMES},
PrivacyHubNotification::SensorSet{
SensorDisabledNotificationDelegate::Sensor::kCamera,
SensorDisabledNotificationDelegate::Sensor::kMicrophone},
combined_delegate, NotificationCatalogName::kPrivacyHubMicAndCamera,
IDS_PRIVACY_HUB_MICROPHONE_AND_CAMERA_OFF_NOTIFICATION_BUTTON);
}
PrivacyHubNotificationController::~PrivacyHubNotificationController() = default;
void PrivacyHubNotificationController::ShowSensorDisabledNotification(
const Sensor sensor) {
sensors_.Put(sensor);
ShowAllActiveNotifications(sensor);
}
void PrivacyHubNotificationController::RemoveSensorDisabledNotification(
const Sensor sensor) {
sensors_.Remove(sensor);
if (!sensors_.HasAny(combinable_sensors_)) {
ignore_new_combinable_notifications_ = false;
}
ShowAllActiveNotifications(sensor);
}
void PrivacyHubNotificationController::OpenPrivacyHubSettingsPage() {
privacy_hub_metrics::LogPrivacyHubOpenedFromNotification();
Shell::Get()->system_tray_model()->client()->ShowPrivacyHubSettings();
}
void PrivacyHubNotificationController::OpenSupportUrl() {
NewWindowDelegate::GetPrimary()->OpenUrl(
GURL(kLearnMoreUrl), NewWindowDelegate::OpenUrlFrom::kUserInteraction,
NewWindowDelegate::Disposition::kNewForegroundTab);
}
void PrivacyHubNotificationController::ShowAllActiveNotifications(
const Sensor changed_sensor) {
message_center::MessageCenter* message_center =
message_center::MessageCenter::Get();
DCHECK(message_center);
if (combinable_sensors_.Has(changed_sensor)) {
combined_notification_->Hide();
if (ignore_new_combinable_notifications_)
return;
if (sensors_.HasAll(combinable_sensors_)) {
for (Sensor sensor : combinable_sensors_) {
sw_notifications_.at(sensor)->Hide();
}
combined_notification_->Show();
return;
}
}
// Remove the notification for the current sensor in case the sensor is
// no longer active it won't be shown again in the for loop later.
// The other case where the sensor is added (again) to the set this
// (re)surfaces the notification, e.g. because a different app now wants to
// access the sensor.
sw_notifications_.at(changed_sensor)->Hide();
for (const Sensor active_sensor : sensors_) {
sw_notifications_.at(active_sensor)->Show();
}
}
void PrivacyHubNotificationController::HandleNotificationMessageClicked() {
ignore_new_combinable_notifications_ = true;
}
} // namespace ash