blob: ac3acdb091a10251f1cf78276c01a72308612590 [file] [log] [blame]
// Copyright 2015 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/power/dual_role_notification.h"
#include <set>
#include "ash/public/cpp/notification_utils.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/model/system_tray_model.h"
#include "ash/system/power/power_status.h"
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/time_format.h"
#include "ui/gfx/image/image.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"
using message_center::MessageCenter;
using message_center::Notification;
namespace ash {
namespace {
const char kDualRoleNotificationId[] = "dual-role";
const char kNotifierDualRole[] = "ash.dual-role";
} // namespace
DualRoleNotification::DualRoleNotification(MessageCenter* message_center)
: message_center_(message_center),
num_dual_role_sinks_(0),
line_power_connected_(false) {}
DualRoleNotification::~DualRoleNotification() {
if (message_center_->FindVisibleNotificationById(kDualRoleNotificationId))
message_center_->RemoveNotification(kDualRoleNotificationId, false);
}
void DualRoleNotification::Update() {
const PowerStatus& status = *PowerStatus::Get();
DCHECK(status.HasDualRoleDevices());
std::string current_power_source_id = status.GetCurrentPowerSourceID();
std::unique_ptr<PowerStatus::PowerSource> new_source;
std::unique_ptr<PowerStatus::PowerSource> new_sink;
size_t num_sinks_found = 0;
for (const auto& source : status.GetPowerSources()) {
// The power source can't be changed if there's a dedicated charger.
if (source.type == PowerStatus::DEDICATED_CHARGER) {
dual_role_source_.reset();
line_power_connected_ = true;
if (message_center_->FindVisibleNotificationById(kDualRoleNotificationId))
message_center_->RemoveNotification(kDualRoleNotificationId, false);
return;
}
if (source.id == current_power_source_id) {
new_source.reset(new PowerStatus::PowerSource(source));
continue;
}
num_sinks_found++;
// The notification only shows the sink port if it is the only sink.
if (num_sinks_found == 1)
new_sink.reset(new PowerStatus::PowerSource(source));
else
new_sink.reset();
}
// Check if the notification should change.
bool change = false;
if (PowerStatus::Get()->IsLinePowerConnected() != line_power_connected_) {
change = true;
line_power_connected_ = PowerStatus::Get()->IsLinePowerConnected();
} else if (new_source && dual_role_source_) {
if (new_source->description_id != dual_role_source_->description_id)
change = true;
} else if (new_source || dual_role_source_) {
change = true;
} else {
// Notification differs for 0, 1, and 2+ sinks.
if ((num_sinks_found < num_dual_role_sinks_ && num_sinks_found < 2) ||
(num_sinks_found > num_dual_role_sinks_ && num_dual_role_sinks_ < 2)) {
change = true;
} else if (num_sinks_found == 1) {
// The description matters if there's only one dual-role device.
change = new_sink->description_id != dual_role_sink_->description_id;
}
}
dual_role_source_ = std::move(new_source);
dual_role_sink_ = std::move(new_sink);
num_dual_role_sinks_ = num_sinks_found;
if (!change)
return;
if (!message_center_->FindVisibleNotificationById(kDualRoleNotificationId)) {
message_center_->AddNotification(CreateNotification());
} else {
message_center_->UpdateNotification(kDualRoleNotificationId,
CreateNotification());
}
}
std::unique_ptr<Notification> DualRoleNotification::CreateNotification() {
base::string16 title;
if (dual_role_source_) {
title = l10n_util::GetStringFUTF16(
IDS_ASH_STATUS_TRAY_CHARGING_FROM_DUAL_ROLE_TITLE,
l10n_util::GetStringUTF16(dual_role_source_->description_id));
} else if (num_dual_role_sinks_ == 1) {
title = l10n_util::GetStringFUTF16(
IDS_ASH_STATUS_TRAY_CHARGING_DUAL_ROLE_DEVICE_TITLE,
l10n_util::GetStringUTF16(dual_role_sink_->description_id));
} else {
title = l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_CHARGING_DUAL_ROLE_DEVICES_TITLE);
}
auto delegate =
base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
base::BindRepeating([]() {
Shell::Get()
->system_tray_model()
->client_ptr()
->ShowPowerSettings();
}));
std::unique_ptr<Notification> notification = ash::CreateSystemNotification(
message_center::NOTIFICATION_TYPE_SIMPLE, kDualRoleNotificationId, title,
l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DUAL_ROLE_MESSAGE),
base::string16(), GURL(),
message_center::NotifierId(message_center::NotifierType::SYSTEM_COMPONENT,
kNotifierDualRole),
message_center::RichNotificationData(), std::move(delegate),
kNotificationChargingUsbCIcon,
message_center::SystemNotificationWarningLevel::NORMAL);
notification->set_priority(message_center::MIN_PRIORITY);
return notification;
}
} // namespace ash