Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / notifications / balloon_notification_ui_manager.cc
bloba420ce5876bc9a53600f4911e107844db1432066
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/notifications/balloon_notification_ui_manager.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/stl_util.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/fullscreen.h"
14 #include "chrome/browser/idle.h"
15 #include "chrome/browser/notifications/balloon_collection.h"
16 #include "chrome/browser/notifications/notification.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/common/pref_names.h"
19 #include "content/public/browser/notification_service.h"
21 // A class which represents a notification waiting to be shown.
22 class QueuedNotification {
23 public:
24 QueuedNotification(const Notification& notification, Profile* profile)
25 : notification_(notification),
26 profile_(profile) {
29 const Notification& notification() const { return notification_; }
30 Profile* profile() const { return profile_; }
32 void Replace(const Notification& new_notification) {
33 notification_ = new_notification;
36 private:
37 // The notification to be shown.
38 Notification notification_;
40 // Non owned pointer to the user's profile.
41 Profile* profile_;
43 DISALLOW_COPY_AND_ASSIGN(QueuedNotification);
46 BalloonNotificationUIManager::BalloonNotificationUIManager(
47 PrefService* local_state)
48 : NotificationPrefsManager(local_state),
49 // Passes NULL to blockers since |message_center| is not used from balloon
50 // notifications.
51 screen_lock_blocker_(NULL),
52 fullscreen_blocker_(NULL),
53 system_observer_(this) {
54 position_pref_.Init(
55 prefs::kDesktopNotificationPosition,
56 local_state,
57 base::Bind(
58 &BalloonNotificationUIManager::OnDesktopNotificationPositionChanged,
59 base::Unretained(this)));
62 BalloonNotificationUIManager::~BalloonNotificationUIManager() {
65 void BalloonNotificationUIManager::SetBalloonCollection(
66 BalloonCollection* balloon_collection) {
67 DCHECK(!balloon_collection_.get() ||
68 balloon_collection_->GetActiveBalloons().size() == 0);
69 DCHECK(balloon_collection);
70 balloon_collection_.reset(balloon_collection);
71 balloon_collection_->SetPositionPreference(
72 static_cast<BalloonCollection::PositionPreference>(
73 position_pref_.GetValue()));
74 balloon_collection_->set_space_change_listener(this);
77 void BalloonNotificationUIManager::Add(const Notification& notification,
78 Profile* profile) {
79 if (Update(notification, profile)) {
80 return;
83 VLOG(1) << "Added notification. URL: "
84 << notification.content_url().spec();
85 show_queue_.push_back(linked_ptr<QueuedNotification>(
86 new QueuedNotification(notification, profile)));
87 CheckAndShowNotifications();
90 bool BalloonNotificationUIManager::Update(const Notification& notification,
91 Profile* profile) {
92 const GURL& origin = notification.origin_url();
93 const base::string16& replace_id = notification.replace_id();
95 if (replace_id.empty())
96 return false;
98 // First check the queue of pending notifications for replacement.
99 // Then check the list of notifications already being shown.
100 for (NotificationDeque::const_iterator iter = show_queue_.begin();
101 iter != show_queue_.end(); ++iter) {
102 if (profile == (*iter)->profile() &&
103 origin == (*iter)->notification().origin_url() &&
104 replace_id == (*iter)->notification().replace_id()) {
105 (*iter)->Replace(notification);
106 return true;
110 return UpdateNotification(notification, profile);
113 const Notification* BalloonNotificationUIManager::FindById(
114 const std::string& id) const {
115 for (NotificationDeque::const_iterator iter = show_queue_.begin();
116 iter != show_queue_.end(); ++iter) {
117 if ((*iter)->notification().notification_id() == id) {
118 return &((*iter)->notification());
121 return balloon_collection_->FindById(id);
124 bool BalloonNotificationUIManager::CancelById(const std::string& id) {
125 // See if this ID hasn't been shown yet.
126 for (NotificationDeque::iterator iter = show_queue_.begin();
127 iter != show_queue_.end(); ++iter) {
128 if ((*iter)->notification().notification_id() == id) {
129 show_queue_.erase(iter);
130 return true;
133 // If it has been shown, remove it from the balloon collections.
134 return balloon_collection_->RemoveById(id);
137 std::set<std::string>
138 BalloonNotificationUIManager::GetAllIdsByProfileAndSourceOrigin(
139 Profile* profile,
140 const GURL& source) {
141 std::set<std::string> notification_ids;
142 for (NotificationDeque::iterator iter = show_queue_.begin();
143 iter != show_queue_.end(); iter++) {
144 if ((*iter)->notification().origin_url() == source &&
145 profile->IsSameProfile((*iter)->profile())) {
146 notification_ids.insert((*iter)->notification().notification_id());
150 const BalloonCollection::Balloons& balloons =
151 balloon_collection_->GetActiveBalloons();
152 for (BalloonCollection::Balloons::const_iterator iter = balloons.begin();
153 iter != balloons.end(); ++iter) {
154 if (profile->IsSameProfile((*iter)->profile()) &&
155 source == (*iter)->notification().origin_url()) {
156 notification_ids.insert((*iter)->notification().notification_id());
159 return notification_ids;
162 bool BalloonNotificationUIManager::CancelAllBySourceOrigin(const GURL& source) {
163 // Same pattern as CancelById, but more complicated than the above
164 // because there may be multiple notifications from the same source.
165 bool removed = false;
166 for (NotificationDeque::iterator loopiter = show_queue_.begin();
167 loopiter != show_queue_.end(); ) {
168 if ((*loopiter)->notification().origin_url() != source) {
169 ++loopiter;
170 continue;
173 loopiter = show_queue_.erase(loopiter);
174 removed = true;
176 return balloon_collection_->RemoveBySourceOrigin(source) || removed;
179 bool BalloonNotificationUIManager::CancelAllByProfile(Profile* profile) {
180 // Same pattern as CancelAllBySourceOrigin.
181 bool removed = false;
182 for (NotificationDeque::iterator loopiter = show_queue_.begin();
183 loopiter != show_queue_.end(); ) {
184 if ((*loopiter)->profile() != profile) {
185 ++loopiter;
186 continue;
189 loopiter = show_queue_.erase(loopiter);
190 removed = true;
192 return balloon_collection_->RemoveByProfile(profile) || removed;
195 void BalloonNotificationUIManager::CancelAll() {
196 balloon_collection_->RemoveAll();
199 BalloonCollection* BalloonNotificationUIManager::balloon_collection() {
200 return balloon_collection_.get();
203 NotificationPrefsManager* BalloonNotificationUIManager::prefs_manager() {
204 return this;
207 bool BalloonNotificationUIManager::ShowNotification(
208 const Notification& notification,
209 Profile* profile) {
210 if (!balloon_collection_->HasSpace())
211 return false;
212 balloon_collection_->Add(notification, profile);
213 return true;
216 void BalloonNotificationUIManager::OnBalloonSpaceChanged() {
217 CheckAndShowNotifications();
220 void BalloonNotificationUIManager::OnBlockingStateChanged(
221 message_center::NotificationBlocker* blocker) {
222 CheckAndShowNotifications();
225 bool BalloonNotificationUIManager::UpdateNotification(
226 const Notification& notification,
227 Profile* profile) {
228 const GURL& origin = notification.origin_url();
229 const base::string16& replace_id = notification.replace_id();
231 DCHECK(!replace_id.empty());
233 const BalloonCollection::Balloons& balloons =
234 balloon_collection_->GetActiveBalloons();
235 for (BalloonCollection::Balloons::const_iterator iter = balloons.begin();
236 iter != balloons.end(); ++iter) {
237 if (profile == (*iter)->profile() &&
238 origin == (*iter)->notification().origin_url() &&
239 replace_id == (*iter)->notification().replace_id()) {
240 (*iter)->Update(notification);
241 return true;
245 return false;
248 BalloonCollection::PositionPreference
249 BalloonNotificationUIManager::GetPositionPreference() const {
250 return static_cast<BalloonCollection::PositionPreference>(
251 position_pref_.GetValue());
254 void BalloonNotificationUIManager::SetPositionPreference(
255 BalloonCollection::PositionPreference preference) {
256 position_pref_.SetValue(static_cast<int>(preference));
257 balloon_collection_->SetPositionPreference(preference);
260 void BalloonNotificationUIManager::CheckAndShowNotifications() {
261 screen_lock_blocker_.CheckState();
262 fullscreen_blocker_.CheckState();
263 if (screen_lock_blocker_.is_locked() ||
264 fullscreen_blocker_.is_fullscreen_mode()) {
265 return;
267 ShowNotifications();
270 void BalloonNotificationUIManager::OnDesktopNotificationPositionChanged() {
271 balloon_collection_->SetPositionPreference(
272 static_cast<BalloonCollection::PositionPreference>(
273 position_pref_.GetValue()));
276 void BalloonNotificationUIManager::ShowNotifications() {
277 while (!show_queue_.empty()) {
278 linked_ptr<QueuedNotification> queued_notification(show_queue_.front());
279 show_queue_.pop_front();
280 if (!ShowNotification(queued_notification->notification(),
281 queued_notification->profile())) {
282 show_queue_.push_front(queued_notification);
283 return;
288 // static
289 BalloonNotificationUIManager*
290 BalloonNotificationUIManager::GetInstanceForTesting() {
291 if (NotificationUIManager::DelegatesToMessageCenter()) {
292 LOG(ERROR) << "Attempt to run a test that requires "
293 << "BalloonNotificationUIManager while delegating to a "
294 << "native MessageCenter. Test will fail. Ask dimich@";
295 return NULL;
297 return static_cast<BalloonNotificationUIManager*>(
298 g_browser_process->notification_ui_manager());
301 void BalloonNotificationUIManager::GetQueuedNotificationsForTesting(
302 std::vector<const Notification*>* notifications) {
303 for (NotificationDeque::const_iterator iter = show_queue_.begin();
304 iter != show_queue_.end(); ++iter) {
305 notifications->push_back(&(*iter)->notification());