1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/message_center/popup_timers_controller.h"
#include <algorithm>
#include <memory>
#include "base/containers/contains.h"
#include "ui/base/ui_base_features.h"
#include "ui/message_center/public/cpp/message_center_constants.h"
#include "ui/message_center/public/cpp/notification_types.h"
namespace message_center {
namespace {
bool UseHighPriorityDelay(Notification* notification) {
#if BUILDFLAG(IS_CHROMEOS)
// ChromeOS is going to ignore the `never_timeout` field so all notification
// popups are automatically dismissed in 6 seconds. System priority
// notifications with `never_timeout` set will be displayed for 30 minutes.
const bool use_high_priority_delay =
notification->never_timeout() &&
notification->priority() == SYSTEM_PRIORITY;
#else
// Web Notifications are given a longer on-screen time on non-Chrome OS
// platforms as there is no notification center to dismiss them to.
const bool use_high_priority_delay =
notification->priority() > DEFAULT_PRIORITY ||
notification->notifier_id().type == NotifierType::WEB_PAGE;
#endif
return use_high_priority_delay;
}
} // namespace
// Timeout values used to dismiss notifications automatically after they are
// shown.
int notification_timeout_default_seconds_ = kAutocloseDefaultDelaySeconds;
int notification_timeout_high_priority_seconds_ =
kAutocloseHighPriorityDelaySeconds;
PopupTimersController::PopupTimersController(MessageCenter* message_center)
: message_center_(message_center) {
message_center_->AddObserver(this);
}
PopupTimersController::~PopupTimersController() {
message_center_->RemoveObserver(this);
}
void PopupTimersController::StartTimer(const std::string& id,
const base::TimeDelta& timeout) {
PopupTimerCollection::const_iterator iter = popup_timers_.find(id);
if (iter != popup_timers_.end()) {
DCHECK(iter->second);
iter->second->Start();
return;
}
auto timer =
std::make_unique<PopupTimer>(id, timeout, weak_ptr_factory_.GetWeakPtr());
timer->Start();
popup_timers_.emplace(id, std::move(timer));
}
void PopupTimersController::StartAll() {
for (const auto& iter : popup_timers_)
iter.second->Start();
}
void PopupTimersController::PauseAll() {
for (const auto& iter : popup_timers_)
iter.second->Pause();
}
void PopupTimersController::CancelTimer(const std::string& id) {
popup_timers_.erase(id);
}
void PopupTimersController::SetNotificationTimeouts(int default_timeout,
int high_priority_timeout) {
notification_timeout_default_seconds_ = default_timeout;
notification_timeout_high_priority_seconds_ = high_priority_timeout;
}
void PopupTimersController::CancelAll() {
popup_timers_.clear();
}
void PopupTimersController::TimerFinished(const std::string& id) {
if (!base::Contains(popup_timers_, id))
return;
CancelTimer(id);
message_center_->MarkSinglePopupAsShown(id, false);
}
base::TimeDelta PopupTimersController::GetTimeoutForNotification(
Notification* notification) {
return base::Seconds(UseHighPriorityDelay(notification)
? notification_timeout_high_priority_seconds_
: notification_timeout_default_seconds_);
}
int PopupTimersController::GetNotificationTimeoutDefault() {
return notification_timeout_default_seconds_;
}
void PopupTimersController::OnNotificationDisplayed(
const std::string& id,
const DisplaySource source) {
OnNotificationUpdated(id);
}
void PopupTimersController::OnNotificationUpdated(const std::string& id) {
NotificationList::PopupNotifications popup_notifications =
message_center_->GetPopupNotifications();
if (popup_notifications.empty()) {
CancelAll();
return;
}
auto iter = popup_notifications.begin();
for (; iter != popup_notifications.end(); ++iter) {
if ((*iter)->id() == id)
break;
}
if (iter == popup_notifications.end()) {
CancelTimer(id);
return;
}
// ChromeOS is going to ignore the `never_timeout` field for notification
// popups. Only enabled behind the `kNotificationsIgnoreRequireInteraction`
// flag for now.
const bool must_cancel_timer =
(*iter)->never_timeout()
#if BUILDFLAG(IS_CHROMEOS)
&& !features::IsNotificationsIgnoreRequireInteractionEnabled()
#endif
;
if (must_cancel_timer) {
CancelTimer(id);
return;
}
auto timer = popup_timers_.find(id);
// The timer must already have been started and not be running. Relies on
// the invariant that |popup_timers_| only contains timers that have been
// started.
bool was_paused = timer != popup_timers_.end() && !timer->second->IsRunning();
CancelTimer(id);
StartTimer(id, GetTimeoutForNotification(*iter));
// If a timer was paused before, pause it afterwards as well.
// See crbug.com/710298
if (was_paused) {
popup_timers_.find(id)->second->Pause();
}
}
void PopupTimersController::OnNotificationRemoved(const std::string& id,
bool by_user) {
CancelTimer(id);
}
} // namespace message_center
|