summaryrefslogtreecommitdiffstats
path: root/chrome/browser/notifications
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-01-07 14:18:56 +0000
committerBen Murdoch <benm@google.com>2011-01-11 10:23:13 +0000
commit201ade2fbba22bfb27ae029f4d23fca6ded109a0 (patch)
treeb793f4ed916f73cf18357ea467ff3deb5ffb5b52 /chrome/browser/notifications
parentd8c4c37a7d0961944bfdfaa117d5c68c8e129c97 (diff)
downloadexternal_chromium-201ade2fbba22bfb27ae029f4d23fca6ded109a0.zip
external_chromium-201ade2fbba22bfb27ae029f4d23fca6ded109a0.tar.gz
external_chromium-201ade2fbba22bfb27ae029f4d23fca6ded109a0.tar.bz2
Merge chromium at 9.0.597.55: Initial merge by git.
Change-Id: Id686a88437441ec7e17abb3328a404c7b6c3c6ad
Diffstat (limited to 'chrome/browser/notifications')
-rw-r--r--chrome/browser/notifications/balloon.cc1
-rw-r--r--chrome/browser/notifications/balloon_collection.cc63
-rw-r--r--chrome/browser/notifications/balloon_collection.h13
-rw-r--r--chrome/browser/notifications/balloon_collection_base.cc85
-rw-r--r--chrome/browser/notifications/balloon_collection_base.h65
-rw-r--r--chrome/browser/notifications/balloon_collection_impl.h27
-rw-r--r--chrome/browser/notifications/balloon_collection_linux.cc5
-rw-r--r--chrome/browser/notifications/balloon_collection_win.cc5
-rw-r--r--chrome/browser/notifications/balloon_host.cc48
-rw-r--r--chrome/browser/notifications/balloon_host.h3
-rw-r--r--chrome/browser/notifications/desktop_notification_service.cc66
-rw-r--r--chrome/browser/notifications/desktop_notification_service.h14
-rw-r--r--chrome/browser/notifications/desktop_notifications_unittest.cc22
-rw-r--r--chrome/browser/notifications/desktop_notifications_unittest.h7
-rw-r--r--chrome/browser/notifications/notification.cc4
-rw-r--r--chrome/browser/notifications/notification.h4
-rw-r--r--chrome/browser/notifications/notification_exceptions_table_model.cc45
-rw-r--r--chrome/browser/notifications/notification_exceptions_table_model.h19
-rw-r--r--chrome/browser/notifications/notification_options_menu_model.cc18
-rw-r--r--chrome/browser/notifications/notification_test_util.h23
-rw-r--r--chrome/browser/notifications/notification_ui_manager.cc45
-rw-r--r--chrome/browser/notifications/notification_ui_manager.h28
22 files changed, 476 insertions, 134 deletions
diff --git a/chrome/browser/notifications/balloon.cc b/chrome/browser/notifications/balloon.cc
index 96f3fca..d9f9111 100644
--- a/chrome/browser/notifications/balloon.cc
+++ b/chrome/browser/notifications/balloon.cc
@@ -9,6 +9,7 @@
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/renderer_host/site_instance.h"
#include "gfx/rect.h"
+#include "gfx/size.h"
Balloon::Balloon(const Notification& notification, Profile* profile,
BalloonCollection* collection)
diff --git a/chrome/browser/notifications/balloon_collection.cc b/chrome/browser/notifications/balloon_collection.cc
index a125837..9d60626 100644
--- a/chrome/browser/notifications/balloon_collection.cc
+++ b/chrome/browser/notifications/balloon_collection.cc
@@ -45,7 +45,6 @@ BalloonCollectionImpl::BalloonCollectionImpl()
}
BalloonCollectionImpl::~BalloonCollectionImpl() {
- STLDeleteElements(&balloons_);
}
void BalloonCollectionImpl::Add(const Notification& notification,
@@ -59,10 +58,11 @@ void BalloonCollectionImpl::Add(const Notification& notification,
new_balloon->SetPosition(layout_.OffScreenLocation(), false);
new_balloon->Show();
#if USE_OFFSETS
- if (balloons_.size() > 0)
- new_balloon->set_offset(balloons_[balloons_.size() - 1]->offset());
+ int count = base_.count();
+ if (count > 0)
+ new_balloon->set_offset(base_.balloons()[count - 1]->offset());
#endif
- balloons_.push_back(new_balloon);
+ base_.Add(new_balloon);
PositionBalloons(false);
// There may be no listener in a unit test.
@@ -74,28 +74,28 @@ void BalloonCollectionImpl::Add(const Notification& notification,
on_collection_changed_callback_->Run();
}
-bool BalloonCollectionImpl::Remove(const Notification& notification) {
- Balloons::iterator iter;
- for (iter = balloons_.begin(); iter != balloons_.end(); ++iter) {
- if (notification.IsSame((*iter)->notification())) {
- // Balloon.CloseByScript() will cause OnBalloonClosed() to be called on
- // this object, which will remove it from the collection and free it.
- (*iter)->CloseByScript();
- return true;
- }
- }
- return false;
+bool BalloonCollectionImpl::RemoveById(const std::string& id) {
+ return base_.CloseById(id);
+}
+
+bool BalloonCollectionImpl::RemoveBySourceOrigin(const GURL& origin) {
+ return base_.CloseAllBySourceOrigin(origin);
+}
+
+void BalloonCollectionImpl::RemoveAll() {
+ base_.CloseAll();
}
bool BalloonCollectionImpl::HasSpace() const {
- if (count() < kMinAllowedBalloonCount)
+ int count = base_.count();
+ if (count < kMinAllowedBalloonCount)
return true;
int max_balloon_size = 0;
int total_size = 0;
layout_.GetMaxLinearSize(&max_balloon_size, &total_size);
- int current_max_size = max_balloon_size * count();
+ int current_max_size = max_balloon_size * count;
int max_allowed_size = static_cast<int>(total_size *
kPercentBalloonFillFactor);
return current_max_size < max_allowed_size - max_balloon_size;
@@ -114,16 +114,16 @@ void BalloonCollectionImpl::DisplayChanged() {
void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) {
// We want to free the balloon when finished.
- scoped_ptr<Balloon> closed(source);
- Balloons::iterator it = balloons_.begin();
+ const Balloons& balloons = base_.balloons();
+ Balloons::const_iterator it = balloons.begin();
#if USE_OFFSETS
gfx::Point offset;
bool apply_offset = false;
- while (it != balloons_.end()) {
+ while (it != balloons.end()) {
if (*it == source) {
- it = balloons_.erase(it);
- if (it != balloons_.end()) {
+ ++it;
+ if (it != balloons.end()) {
apply_offset = true;
offset.set_y((source)->offset().y() - (*it)->offset().y() +
(*it)->content_size().height() - source->content_size().height());
@@ -138,15 +138,9 @@ void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) {
// leaves the balloon area.
if (apply_offset)
AddMessageLoopObserver();
-#else
- for (; it != balloons_.end(); ++it) {
- if (*it == source) {
- balloons_.erase(it);
- break;
- }
- }
#endif
+ base_.Remove(source);
PositionBalloons(true);
// There may be no listener in a unit test.
@@ -159,9 +153,13 @@ void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) {
}
void BalloonCollectionImpl::PositionBalloonsInternal(bool reposition) {
+ const Balloons& balloons = base_.balloons();
+
layout_.RefreshSystemMetrics();
gfx::Point origin = layout_.GetLayoutOrigin();
- for (Balloons::iterator it = balloons_.begin(); it != balloons_.end(); ++it) {
+ for (Balloons::const_iterator it = balloons.begin();
+ it != balloons.end();
+ ++it) {
gfx::Point upper_left = layout_.NextPosition((*it)->GetViewSize(), &origin);
(*it)->SetPosition(upper_left, reposition);
}
@@ -188,7 +186,10 @@ void BalloonCollectionImpl::CancelOffsets() {
// Unhook from listening to all UI events.
RemoveMessageLoopObserver();
- for (Balloons::iterator it = balloons_.begin(); it != balloons_.end(); ++it)
+ const Balloons& balloons = base_.balloons();
+ for (Balloons::const_iterator it = balloons.begin();
+ it != balloons.end();
+ ++it)
(*it)->set_offset(gfx::Point(0, 0));
PositionBalloons(true);
diff --git a/chrome/browser/notifications/balloon_collection.h b/chrome/browser/notifications/balloon_collection.h
index 499b937..13875dc 100644
--- a/chrome/browser/notifications/balloon_collection.h
+++ b/chrome/browser/notifications/balloon_collection.h
@@ -9,11 +9,13 @@
#pragma once
#include <deque>
+#include <string>
#include "base/callback.h"
#include "base/scoped_ptr.h"
class Balloon;
+class GURL;
class Notification;
class Profile;
@@ -44,9 +46,16 @@ class BalloonCollection {
virtual void Add(const Notification& notification,
Profile* profile) = 0;
- // Removes a balloon from the collection if present. Returns
+ // Removes any balloons that have this notification id. Returns
// true if anything was removed.
- virtual bool Remove(const Notification& notification) = 0;
+ virtual bool RemoveById(const std::string& id) = 0;
+
+ // Removes any balloons that have this source origin. Returns
+ // true if anything was removed.
+ virtual bool RemoveBySourceOrigin(const GURL& source_origin) = 0;
+
+ // Removes all balloons.
+ virtual void RemoveAll() = 0;
// Is there room to add another notification?
virtual bool HasSpace() const = 0;
diff --git a/chrome/browser/notifications/balloon_collection_base.cc b/chrome/browser/notifications/balloon_collection_base.cc
new file mode 100644
index 0000000..b0551dd
--- /dev/null
+++ b/chrome/browser/notifications/balloon_collection_base.cc
@@ -0,0 +1,85 @@
+// Copyright (c) 2010 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 "chrome/browser/notifications/balloon_collection_base.h"
+
+#include "base/stl_util-inl.h"
+#include "chrome/browser/notifications/balloon.h"
+#include "chrome/browser/notifications/notification.h"
+#include "googleurl/src/gurl.h"
+
+BalloonCollectionBase::BalloonCollectionBase() {
+}
+
+BalloonCollectionBase::~BalloonCollectionBase() {
+ STLDeleteElements(&balloons_);
+}
+
+void BalloonCollectionBase::Add(Balloon* balloon) {
+ balloons_.push_back(balloon);
+}
+
+void BalloonCollectionBase::Remove(Balloon* balloon) {
+ // Free after removing.
+ scoped_ptr<Balloon> to_delete(balloon);
+ Balloons::iterator iter;
+ for (iter = balloons_.begin(); iter != balloons_.end(); ++iter) {
+ if ((*iter) == balloon) {
+ balloons_.erase(iter);
+ return;
+ }
+ }
+}
+
+bool BalloonCollectionBase::CloseById(const std::string& id) {
+ // Use a local list of balloons to close to avoid breaking
+ // iterator changes on each close.
+ Balloons to_close;
+ Balloons::iterator iter;
+ for (iter = balloons_.begin(); iter != balloons_.end(); ++iter) {
+ if ((*iter)->notification().notification_id() == id)
+ to_close.push_back(*iter);
+ }
+ for (iter = to_close.begin(); iter != to_close.end(); ++iter)
+ (*iter)->CloseByScript();
+
+ return !to_close.empty();
+}
+
+bool BalloonCollectionBase::CloseAllBySourceOrigin(
+ const GURL& source_origin) {
+ // Use a local list of balloons to close to avoid breaking
+ // iterator changes on each close.
+ Balloons to_close;
+ Balloons::iterator iter;
+ for (iter = balloons_.begin(); iter != balloons_.end(); ++iter) {
+ if ((*iter)->notification().origin_url() == source_origin)
+ to_close.push_back(*iter);
+ }
+ for (iter = to_close.begin(); iter != to_close.end(); ++iter)
+ (*iter)->CloseByScript();
+
+ return !to_close.empty();
+}
+
+void BalloonCollectionBase::CloseAll() {
+ // Use a local list of balloons to close to avoid breaking
+ // iterator changes on each close.
+ Balloons to_close = balloons_;
+ for (Balloons::iterator iter = to_close.begin();
+ iter != to_close.end(); ++iter)
+ (*iter)->CloseByScript();
+}
+
+Balloon* BalloonCollectionBase::FindBalloon(
+ const Notification& notification) {
+ Balloons::iterator iter;
+ for (iter = balloons_.begin(); iter != balloons_.end(); ++iter) {
+ if ((*iter)->notification().notification_id() ==
+ notification.notification_id()) {
+ return *iter;
+ }
+ }
+ return NULL;
+}
diff --git a/chrome/browser/notifications/balloon_collection_base.h b/chrome/browser/notifications/balloon_collection_base.h
new file mode 100644
index 0000000..c388ac9
--- /dev/null
+++ b/chrome/browser/notifications/balloon_collection_base.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2010 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.
+
+// Handles the visible notification (or balloons).
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_BALLOON_COLLECTION_BASE_H_
+#define CHROME_BROWSER_NOTIFICATIONS_BALLOON_COLLECTION_BASE_H_
+#pragma once
+
+#include <deque>
+#include <string>
+
+#include "base/basictypes.h"
+
+class Balloon;
+class GURL;
+class Notification;
+
+// This class provides support for implementing a BalloonCollection
+// including the parts common between Chrome UI and ChromeOS UI.
+class BalloonCollectionBase {
+ public:
+ BalloonCollectionBase();
+ virtual ~BalloonCollectionBase();
+
+ typedef std::deque<Balloon*> Balloons;
+
+ // Adds a balloon to the collection. Takes ownership of pointer.
+ virtual void Add(Balloon* balloon);
+
+ // Removes a balloon from the collection (if present). Frees
+ // the pointer after removal.
+ virtual void Remove(Balloon* balloon);
+
+ // Finds any balloon matching the given notification id, and
+ // calls CloseByScript on it. Returns true if anything was
+ // found.
+ virtual bool CloseById(const std::string& id);
+
+ // Finds all balloons matching the given notification source,
+ // and calls CloseByScript on them. Returns true if anything
+ // was found.
+ virtual bool CloseAllBySourceOrigin(const GURL& source_origin);
+
+ // Calls CloseByScript on all balloons.
+ virtual void CloseAll();
+
+ const Balloons& balloons() const { return balloons_; }
+
+ // Returns the balloon matching the given notification, or
+ // NULL if there is no matching balloon.
+ Balloon* FindBalloon(const Notification& notification);
+
+ // The number of balloons being displayed.
+ int count() const { return static_cast<int>(balloons_.size()); }
+
+ private:
+ // Queue of active balloons. Pointers are owned by this class.
+ Balloons balloons_;
+
+ DISALLOW_COPY_AND_ASSIGN(BalloonCollectionBase);
+};
+
+#endif // CHROME_BROWSER_NOTIFICATIONS_BALLOON_COLLECTION_BASE_H_
diff --git a/chrome/browser/notifications/balloon_collection_impl.h b/chrome/browser/notifications/balloon_collection_impl.h
index a9c7afc..7fb1ea9 100644
--- a/chrome/browser/notifications/balloon_collection_impl.h
+++ b/chrome/browser/notifications/balloon_collection_impl.h
@@ -13,6 +13,7 @@
#include "base/basictypes.h"
#include "base/message_loop.h"
#include "chrome/browser/notifications/balloon_collection.h"
+#include "chrome/browser/notifications/balloon_collection_base.h"
#include "gfx/point.h"
#include "gfx/rect.h"
@@ -41,14 +42,14 @@ class BalloonCollectionImpl : public BalloonCollection
// BalloonCollection interface.
virtual void Add(const Notification& notification,
Profile* profile);
- virtual bool Remove(const Notification& notification);
+ virtual bool RemoveById(const std::string& id);
+ virtual bool RemoveBySourceOrigin(const GURL& source_origin);
+ virtual void RemoveAll();
virtual bool HasSpace() const;
virtual void ResizeBalloon(Balloon* balloon, const gfx::Size& size);
virtual void DisplayChanged();
virtual void OnBalloonClosed(Balloon* source);
- virtual const Balloons& GetActiveBalloons() {
- return balloons_;
- }
+ virtual const Balloons& GetActiveBalloons() { return base_.balloons(); }
// MessageLoopForUI::Observer interface.
#if defined(OS_WIN)
@@ -135,9 +136,6 @@ class BalloonCollectionImpl : public BalloonCollection
Profile* profile);
private:
- // The number of balloons being displayed.
- int count() const { return balloons_.size(); }
-
// Adjusts the positions of the balloons (e.g., when one is closed).
// Implemented by each platform for specific UI requirements.
void PositionBalloons(bool is_reposition);
@@ -150,6 +148,12 @@ class BalloonCollectionImpl : public BalloonCollection
static gfx::Rect GetMacWorkArea();
#endif
+ // Base implementation for the collection of active balloons.
+ BalloonCollectionBase base_;
+
+ // The layout parameters for balloons in this collection.
+ Layout layout_;
+
#if USE_OFFSETS
// Start and stop observing all UI events.
void AddMessageLoopObserver();
@@ -163,16 +167,7 @@ class BalloonCollectionImpl : public BalloonCollection
// Is the current cursor in the balloon area?
bool IsCursorInBalloonCollection() const;
-#endif
- // Queue of active balloons.
- typedef std::deque<Balloon*> Balloons;
- Balloons balloons_;
-
- // The layout parameters for balloons in this collection.
- Layout layout_;
-
-#if USE_OFFSETS
// Factory for generating delayed reposition tasks on mouse motion.
ScopedRunnableMethodFactory<BalloonCollectionImpl> reposition_factory_;
diff --git a/chrome/browser/notifications/balloon_collection_linux.cc b/chrome/browser/notifications/balloon_collection_linux.cc
index f15c713..08354a0 100644
--- a/chrome/browser/notifications/balloon_collection_linux.cc
+++ b/chrome/browser/notifications/balloon_collection_linux.cc
@@ -46,10 +46,11 @@ void BalloonCollectionImpl::DidProcessEvent(GdkEvent* event) {
}
bool BalloonCollectionImpl::IsCursorInBalloonCollection() const {
- if (balloons_.empty())
+ const Balloons& balloons = base_.balloons();
+ if (balloons.empty())
return false;
- gfx::Point upper_left = balloons_[balloons_.size() - 1]->GetPosition();
+ gfx::Point upper_left = balloons[balloons.size() - 1]->GetPosition();
gfx::Point lower_right = layout_.GetLayoutOrigin();
gfx::Rect bounds = gfx::Rect(upper_left.x(),
diff --git a/chrome/browser/notifications/balloon_collection_win.cc b/chrome/browser/notifications/balloon_collection_win.cc
index 8915662..07bcd18 100644
--- a/chrome/browser/notifications/balloon_collection_win.cc
+++ b/chrome/browser/notifications/balloon_collection_win.cc
@@ -44,10 +44,11 @@ void BalloonCollectionImpl::DidProcessMessage(const MSG& msg) {
}
bool BalloonCollectionImpl::IsCursorInBalloonCollection() const {
- if (balloons_.empty())
+ const Balloons& balloons = base_.balloons();
+ if (balloons.empty())
return false;
- gfx::Point upper_left = balloons_[balloons_.size() - 1]->GetPosition();
+ gfx::Point upper_left = balloons[balloons.size() - 1]->GetPosition();
gfx::Point lower_right = layout_.GetLayoutOrigin();
gfx::Rect bounds = gfx::Rect(upper_left.x(),
diff --git a/chrome/browser/notifications/balloon_host.cc b/chrome/browser/notifications/balloon_host.cc
index 04f0b89..6fbc1e0 100644
--- a/chrome/browser/notifications/balloon_host.cc
+++ b/chrome/browser/notifications/balloon_host.cc
@@ -20,6 +20,30 @@
#include "chrome/common/url_constants.h"
#include "webkit/glue/webpreferences.h"
+namespace {
+class BalloonPaintObserver : public RenderWidgetHost::PaintObserver {
+ public:
+ explicit BalloonPaintObserver(BalloonHost* balloon_host)
+ : balloon_host_(balloon_host) {
+ }
+
+ virtual void RenderWidgetHostWillPaint(RenderWidgetHost* rhw) {}
+ virtual void RenderWidgetHostDidPaint(RenderWidgetHost* rwh);
+
+ private:
+ BalloonHost* balloon_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(BalloonPaintObserver);
+};
+
+void BalloonPaintObserver::RenderWidgetHostDidPaint(RenderWidgetHost* rwh) {
+ balloon_host_->RenderWidgetHostDidPaint();
+ // WARNING: we may have been deleted (if the balloon host cleared the paint
+ // observer).
+}
+
+} // namespace
+
BalloonHost::BalloonHost(Balloon* balloon)
: render_view_host_(NULL),
balloon_(balloon),
@@ -66,9 +90,10 @@ const string16& BalloonHost::GetSource() const {
}
WebPreferences BalloonHost::GetWebkitPrefs() {
- WebPreferences prefs;
- prefs.allow_scripts_to_close_windows = true;
- return prefs;
+ WebPreferences web_prefs =
+ RenderViewHostDelegateHelper::GetWebkitPrefs(GetProfile(), enable_dom_ui_);
+ web_prefs.allow_scripts_to_close_windows = true;
+ return web_prefs;
}
SiteInstance* BalloonHost::GetSiteInstance() const {
@@ -92,8 +117,12 @@ void BalloonHost::RenderViewCreated(RenderViewHost* render_view_host) {
render_view_host->Send(new ViewMsg_DisableScrollbarsForSmallWindows(
render_view_host->routing_id(), balloon_->min_scrollbar_size()));
render_view_host->WasResized();
+#if !defined(OS_MACOSX)
+ // TODO(levin): Make all of the code that went in originally with this change
+ // to be cross-platform. See http://crbug.com/64720
render_view_host->EnablePreferredSizeChangedMode(
kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow);
+#endif
}
void BalloonHost::RenderViewReady(RenderViewHost* render_view_host) {
@@ -198,6 +227,9 @@ void BalloonHost::Init() {
rvh->set_view(render_widget_host_view());
rvh->CreateRenderView(string16());
+#if defined(OS_MACOSX)
+ rvh->set_paint_observer(new BalloonPaintObserver(this));
+#endif
rvh->NavigateToURL(balloon_->notification().content_url());
initialized_ = true;
@@ -219,7 +251,15 @@ void BalloonHost::ClearInspectorSettings() {
RenderViewHostDelegateHelper::ClearInspectorSettings(GetProfile());
}
-BalloonHost::~BalloonHost() {}
+void BalloonHost::RenderWidgetHostDidPaint() {
+ render_view_host_->set_paint_observer(NULL);
+ render_view_host_->EnablePreferredSizeChangedMode(
+ kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow);
+}
+
+BalloonHost::~BalloonHost() {
+ DCHECK(!render_view_host_);
+}
void BalloonHost::NotifyDisconnect() {
if (!should_notify_on_disconnect_)
diff --git a/chrome/browser/notifications/balloon_host.h b/chrome/browser/notifications/balloon_host.h
index 4e51eba..c5a88e7 100644
--- a/chrome/browser/notifications/balloon_host.h
+++ b/chrome/browser/notifications/balloon_host.h
@@ -112,6 +112,9 @@ class BalloonHost : public RenderViewHostDelegate,
const std::string& value);
virtual void ClearInspectorSettings();
+ // Called when the render view has painted.
+ void RenderWidgetHostDidPaint();
+
protected:
virtual ~BalloonHost();
// Must override in platform specific implementations.
diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc
index e7530e4..8aa82d1 100644
--- a/chrome/browser/notifications/desktop_notification_service.cc
+++ b/chrome/browser/notifications/desktop_notification_service.cc
@@ -215,7 +215,7 @@ DesktopNotificationService::DesktopNotificationService(Profile* profile,
NotificationUIManager* ui_manager)
: profile_(profile),
ui_manager_(ui_manager) {
- registrar_.Init(profile_->GetPrefs());
+ prefs_registrar_.Init(profile_->GetPrefs());
InitPrefs();
StartObserving();
}
@@ -260,16 +260,24 @@ void DesktopNotificationService::InitPrefs() {
void DesktopNotificationService::StartObserving() {
if (!profile_->IsOffTheRecord()) {
- registrar_.Add(prefs::kDesktopNotificationDefaultContentSetting, this);
- registrar_.Add(prefs::kDesktopNotificationAllowedOrigins, this);
- registrar_.Add(prefs::kDesktopNotificationDeniedOrigins, this);
+ prefs_registrar_.Add(prefs::kDesktopNotificationDefaultContentSetting,
+ this);
+ prefs_registrar_.Add(prefs::kDesktopNotificationAllowedOrigins, this);
+ prefs_registrar_.Add(prefs::kDesktopNotificationDeniedOrigins, this);
+
+ notification_registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
+ NotificationService::AllSources());
}
+
+ notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
+ Source<Profile>(profile_));
}
void DesktopNotificationService::StopObserving() {
if (!profile_->IsOffTheRecord()) {
- registrar_.RemoveAll();
+ prefs_registrar_.RemoveAll();
}
+ notification_registrar_.RemoveAll();
}
void DesktopNotificationService::GrantPermission(const GURL& origin) {
@@ -282,6 +290,8 @@ void DesktopNotificationService::GrantPermission(const GURL& origin) {
NewRunnableMethod(
prefs_cache_.get(), &NotificationsPrefsCache::CacheAllowedOrigin,
origin));
+
+ NotifySettingsChange();
}
void DesktopNotificationService::DenyPermission(const GURL& origin) {
@@ -294,20 +304,32 @@ void DesktopNotificationService::DenyPermission(const GURL& origin) {
NewRunnableMethod(
prefs_cache_.get(), &NotificationsPrefsCache::CacheDeniedOrigin,
origin));
+
+ NotifySettingsChange();
}
void DesktopNotificationService::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
- DCHECK(NotificationType::PREF_CHANGED == type);
+ if (NotificationType::PREF_CHANGED == type) {
+ const std::string& name = *Details<std::string>(details).ptr();
+ OnPrefsChanged(name);
+ } else if (NotificationType::EXTENSION_UNLOADED == type) {
+ // Remove all notifications currently shown or queued by the extension
+ // which was unloaded.
+ Extension* extension = Details<Extension>(details).ptr();
+ if (extension)
+ ui_manager_->CancelAllBySourceOrigin(extension->url());
+ } else if (NotificationType::PROFILE_DESTROYED == type) {
+ StopObserving();
+ }
+}
+
+void DesktopNotificationService::OnPrefsChanged(const std::string& pref_name) {
PrefService* prefs = profile_->GetPrefs();
- const std::string& name = *Details<std::string>(details).ptr();
- if (name == prefs::kDesktopNotificationAllowedOrigins) {
- NotificationService::current()->Notify(
- NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
- Source<DesktopNotificationService>(this),
- NotificationService::NoDetails());
+ if (pref_name == prefs::kDesktopNotificationAllowedOrigins) {
+ NotifySettingsChange();
std::vector<GURL> allowed_origins(GetAllowedOrigins());
// Schedule a cache update on the IO thread.
@@ -317,11 +339,8 @@ void DesktopNotificationService::Observe(NotificationType type,
prefs_cache_.get(),
&NotificationsPrefsCache::SetCacheAllowedOrigins,
allowed_origins));
- } else if (name == prefs::kDesktopNotificationDeniedOrigins) {
- NotificationService::current()->Notify(
- NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
- Source<DesktopNotificationService>(this),
- NotificationService::NoDetails());
+ } else if (pref_name == prefs::kDesktopNotificationDeniedOrigins) {
+ NotifySettingsChange();
std::vector<GURL> denied_origins(GetBlockedOrigins());
// Schedule a cache update on the IO thread.
@@ -331,7 +350,7 @@ void DesktopNotificationService::Observe(NotificationType type,
prefs_cache_.get(),
&NotificationsPrefsCache::SetCacheDeniedOrigins,
denied_origins));
- } else if (name == prefs::kDesktopNotificationDefaultContentSetting) {
+ } else if (pref_name == prefs::kDesktopNotificationDefaultContentSetting) {
NotificationService::current()->Notify(
NotificationType::DESKTOP_NOTIFICATION_DEFAULT_CHANGED,
Source<DesktopNotificationService>(this),
@@ -563,9 +582,7 @@ bool DesktopNotificationService::CancelDesktopNotification(
scoped_refptr<NotificationObjectProxy> proxy(
new NotificationObjectProxy(process_id, route_id, notification_id,
false));
- // TODO(johnnyg): clean up this "empty" notification.
- Notification notif(GURL(), GURL(), string16(), string16(), proxy);
- return ui_manager_->Cancel(notif);
+ return ui_manager_->CancelById(proxy->id());
}
@@ -607,3 +624,10 @@ string16 DesktopNotificationService::DisplayNameForOrigin(
}
return UTF8ToUTF16(origin.host());
}
+
+void DesktopNotificationService::NotifySettingsChange() {
+ NotificationService::current()->Notify(
+ NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
+ Source<DesktopNotificationService>(this),
+ NotificationService::NoDetails());
+}
diff --git a/chrome/browser/notifications/desktop_notification_service.h b/chrome/browser/notifications/desktop_notification_service.h
index d92d7e6..a7a4ce2 100644
--- a/chrome/browser/notifications/desktop_notification_service.h
+++ b/chrome/browser/notifications/desktop_notification_service.h
@@ -6,24 +6,24 @@
#define CHROME_BROWSER_NOTIFICATIONS_DESKTOP_NOTIFICATION_SERVICE_H_
#pragma once
+#include <string>
#include <vector>
#include "base/basictypes.h"
+#include "base/ref_counted.h"
#include "base/string16.h"
-#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/prefs/pref_change_registrar.h"
#include "chrome/common/content_settings.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
-#include "chrome/common/notification_service.h"
#include "googleurl/src/gurl.h"
#include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h"
+class Notification;
class NotificationUIManager;
class NotificationsPrefsCache;
class PrefService;
class Profile;
-class Task;
class TabContents;
struct ViewHostMsg_ShowNotification_Params;
@@ -121,6 +121,8 @@ class DesktopNotificationService : public NotificationObserver {
void StartObserving();
void StopObserving();
+ void OnPrefsChanged(const std::string& pref_name);
+
// Takes a notification object and shows it in the UI.
void ShowNotification(const Notification& notification);
@@ -132,6 +134,9 @@ class DesktopNotificationService : public NotificationObserver {
// itself when dealing with extensions.
string16 DisplayNameForOrigin(const GURL& origin);
+ // Notifies the observers when permissions settings change.
+ void NotifySettingsChange();
+
// The profile which owns this object.
Profile* profile_;
@@ -143,7 +148,8 @@ class DesktopNotificationService : public NotificationObserver {
// UI for desktop toasts.
NotificationUIManager* ui_manager_;
- PrefChangeRegistrar registrar_;
+ PrefChangeRegistrar prefs_registrar_;
+ NotificationRegistrar notification_registrar_;
DISALLOW_COPY_AND_ASSIGN(DesktopNotificationService);
};
diff --git a/chrome/browser/notifications/desktop_notifications_unittest.cc b/chrome/browser/notifications/desktop_notifications_unittest.cc
index 9946690..ebb6ab8 100644
--- a/chrome/browser/notifications/desktop_notifications_unittest.cc
+++ b/chrome/browser/notifications/desktop_notifications_unittest.cc
@@ -16,26 +16,18 @@ std::string DesktopNotificationsTest::log_output_;
void MockBalloonCollection::Add(const Notification& notification,
Profile* profile) {
- // Swap in the logging proxy for the purpose of logging calls that
+ // Swap in a logging proxy for the purpose of logging calls that
// would be made into javascript, then pass this down to the
// balloon collection.
- Notification test_notification(notification.origin_url(),
- notification.content_url(),
- notification.display_source(),
- string16(), /* replace_id */
- log_proxy_.get());
+ Notification test_notification(
+ notification.origin_url(),
+ notification.content_url(),
+ notification.display_source(),
+ notification.replace_id(),
+ new LoggingNotificationProxy(notification.notification_id()));
BalloonCollectionImpl::Add(test_notification, profile);
}
-bool MockBalloonCollection::Remove(const Notification& notification) {
- Notification test_notification(notification.origin_url(),
- notification.content_url(),
- notification.display_source(),
- string16(), /* replace_id */
- log_proxy_.get());
- return BalloonCollectionImpl::Remove(test_notification);
-}
-
Balloon* MockBalloonCollection::MakeBalloon(const Notification& notification,
Profile* profile) {
// Start with a normal balloon but mock out the view.
diff --git a/chrome/browser/notifications/desktop_notifications_unittest.h b/chrome/browser/notifications/desktop_notifications_unittest.h
index 3b02b7b..9f556e4 100644
--- a/chrome/browser/notifications/desktop_notifications_unittest.h
+++ b/chrome/browser/notifications/desktop_notifications_unittest.h
@@ -22,15 +22,14 @@
#include "testing/gtest/include/gtest/gtest.h"
class DesktopNotificationsTest;
-typedef LoggingNotificationProxyBase<DesktopNotificationsTest>
+typedef LoggingNotificationDelegate<DesktopNotificationsTest>
LoggingNotificationProxy;
// Test version of the balloon collection which counts the number
// of notifications that are added to it.
class MockBalloonCollection : public BalloonCollectionImpl {
public:
- MockBalloonCollection() :
- log_proxy_(new LoggingNotificationProxy()) {}
+ MockBalloonCollection() {}
// Our mock collection has an area large enough for a fixed number
// of balloons.
@@ -40,7 +39,6 @@ class MockBalloonCollection : public BalloonCollectionImpl {
// BalloonCollectionImpl overrides
virtual void Add(const Notification& notification,
Profile* profile);
- virtual bool Remove(const Notification& notification);
virtual bool HasSpace() const { return count() < kMockBalloonSpace; }
virtual Balloon* MakeBalloon(const Notification& notification,
Profile* profile);
@@ -63,7 +61,6 @@ class MockBalloonCollection : public BalloonCollectionImpl {
private:
std::deque<Balloon*> balloons_;
- scoped_refptr<LoggingNotificationProxy> log_proxy_;
};
class DesktopNotificationsTest : public testing::Test {
diff --git a/chrome/browser/notifications/notification.cc b/chrome/browser/notifications/notification.cc
index c429efa..e6d69a6 100644
--- a/chrome/browser/notifications/notification.cc
+++ b/chrome/browser/notifications/notification.cc
@@ -34,7 +34,3 @@ Notification& Notification::operator=(const Notification& notification) {
delegate_ = notification.delegate();
return *this;
}
-
-bool Notification::IsSame(const Notification& other) const {
- return delegate()->id() == other.delegate()->id();
-}
diff --git a/chrome/browser/notifications/notification.h b/chrome/browser/notifications/notification.h
index 7b0ab8c..2040cf3 100644
--- a/chrome/browser/notifications/notification.h
+++ b/chrome/browser/notifications/notification.h
@@ -6,6 +6,8 @@
#define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_H_
#pragma once
+#include <string>
+
#include "base/basictypes.h"
#include "chrome/browser/notifications/notification_object_proxy.h"
#include "googleurl/src/gurl.h"
@@ -42,7 +44,7 @@ class Notification {
void Click() const { delegate()->Click(); }
void Close(bool by_user) const { delegate()->Close(by_user); }
- bool IsSame(const Notification& other) const;
+ std::string notification_id() const { return delegate()->id(); }
private:
NotificationDelegate* delegate() const { return delegate_.get(); }
diff --git a/chrome/browser/notifications/notification_exceptions_table_model.cc b/chrome/browser/notifications/notification_exceptions_table_model.cc
index 31a44d5..a3326f9 100644
--- a/chrome/browser/notifications/notification_exceptions_table_model.cc
+++ b/chrome/browser/notifications/notification_exceptions_table_model.cc
@@ -6,10 +6,13 @@
#include "app/l10n_util.h"
#include "app/table_model_observer.h"
+#include "base/auto_reset.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/content_settings.h"
#include "chrome/common/content_settings_helper.h"
#include "chrome/common/content_settings_types.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
@@ -24,15 +27,11 @@ struct NotificationExceptionsTableModel::Entry {
NotificationExceptionsTableModel::NotificationExceptionsTableModel(
DesktopNotificationService* service)
: service_(service),
+ updates_disabled_(false),
observer_(NULL) {
- std::vector<GURL> allowed(service_->GetAllowedOrigins());
- std::vector<GURL> blocked(service_->GetBlockedOrigins());
- entries_.reserve(allowed.size() + blocked.size());
- for (size_t i = 0; i < allowed.size(); ++i)
- entries_.push_back(Entry(allowed[i], CONTENT_SETTING_ALLOW));
- for (size_t i = 0; i < blocked.size(); ++i)
- entries_.push_back(Entry(blocked[i], CONTENT_SETTING_BLOCK));
- sort(entries_.begin(), entries_.end());
+ registrar_.Add(this, NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
+ NotificationService::AllSources());
+ LoadEntries();
}
NotificationExceptionsTableModel::~NotificationExceptionsTableModel() {}
@@ -43,6 +42,7 @@ bool NotificationExceptionsTableModel::CanRemoveRows(
}
void NotificationExceptionsTableModel::RemoveRows(const Rows& rows) {
+ AutoReset<bool> tmp(&updates_disabled_, true);
// This is O(n^2) in rows.size(). Since n is small, that's ok.
for (Rows::const_reverse_iterator i(rows.rbegin()); i != rows.rend(); ++i) {
size_t row = *i;
@@ -60,11 +60,11 @@ void NotificationExceptionsTableModel::RemoveRows(const Rows& rows) {
}
void NotificationExceptionsTableModel::RemoveAll() {
- int old_row_count = RowCount();
+ AutoReset<bool> tmp(&updates_disabled_, true);
entries_.clear();
service_->ResetAllOrigins();
if (observer_)
- observer_->OnItemsRemoved(0, old_row_count);
+ observer_->OnModelChanged();
}
int NotificationExceptionsTableModel::RowCount() {
@@ -98,6 +98,31 @@ void NotificationExceptionsTableModel::SetObserver(
observer_ = observer;
}
+void NotificationExceptionsTableModel::Observe(
+ NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (!updates_disabled_) {
+ DCHECK(type == NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED);
+ entries_.clear();
+ LoadEntries();
+
+ if (observer_)
+ observer_->OnModelChanged();
+ }
+}
+
+void NotificationExceptionsTableModel::LoadEntries() {
+ std::vector<GURL> allowed(service_->GetAllowedOrigins());
+ std::vector<GURL> blocked(service_->GetBlockedOrigins());
+ entries_.reserve(allowed.size() + blocked.size());
+ for (size_t i = 0; i < allowed.size(); ++i)
+ entries_.push_back(Entry(allowed[i], CONTENT_SETTING_ALLOW));
+ for (size_t i = 0; i < blocked.size(); ++i)
+ entries_.push_back(Entry(blocked[i], CONTENT_SETTING_BLOCK));
+ std::sort(entries_.begin(), entries_.end());
+}
+
NotificationExceptionsTableModel::Entry::Entry(
const GURL& in_origin,
ContentSetting in_setting)
diff --git a/chrome/browser/notifications/notification_exceptions_table_model.h b/chrome/browser/notifications/notification_exceptions_table_model.h
index 0fcf335..107b2ec 100644
--- a/chrome/browser/notifications/notification_exceptions_table_model.h
+++ b/chrome/browser/notifications/notification_exceptions_table_model.h
@@ -11,35 +11,46 @@
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/remove_rows_table_model.h"
+#include "chrome/common/notification_observer.h"
-class NotificationExceptionsTableModel : public RemoveRowsTableModel {
+class NotificationExceptionsTableModel : public RemoveRowsTableModel,
+ public NotificationObserver {
public:
explicit NotificationExceptionsTableModel(
DesktopNotificationService* service);
virtual ~NotificationExceptionsTableModel();
- // RemoveRowsTableModel overrides:
+ // Overridden from RemoveRowsTableModel:
virtual bool CanRemoveRows(const Rows& rows) const;
virtual void RemoveRows(const Rows& rows);
virtual void RemoveAll();
- // TableModel overrides:
+ // Overridden from TableModel:
virtual int RowCount();
virtual std::wstring GetText(int row, int column_id);
virtual void SetObserver(TableModelObserver* observer);
+ // Overridden from NotificationObserver:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
private:
struct Entry;
+ void LoadEntries();
+
DesktopNotificationService* service_;
typedef std::vector<Entry> EntriesVector;
EntriesVector entries_;
+ // We use this variable to prevent ourselves from handling further changes
+ // that we ourselves caused.
+ bool updates_disabled_;
+ NotificationRegistrar registrar_;
TableModelObserver* observer_;
DISALLOW_COPY_AND_ASSIGN(NotificationExceptionsTableModel);
};
#endif // CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_EXCEPTIONS_TABLE_MODEL_H_
-
diff --git a/chrome/browser/notifications/notification_options_menu_model.cc b/chrome/browser/notifications/notification_options_menu_model.cc
index 97d269c..7172cf7 100644
--- a/chrome/browser/notifications/notification_options_menu_model.cc
+++ b/chrome/browser/notifications/notification_options_menu_model.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/browser_list.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
+#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notifications_prefs_cache.h"
#include "chrome/browser/profile.h"
#include "chrome/common/content_settings_types.h"
@@ -17,6 +18,11 @@
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
+#if defined(OS_WIN)
+#include "chrome/browser/ui/views/browser_dialogs.h"
+#include "chrome/installer/util/install_util.h"
+#endif // OS_WIN
+
// Menu commands
const int kTogglePermissionCommand = 0;
const int kToggleExtensionCommand = 1;
@@ -139,9 +145,19 @@ void NotificationOptionsMenuModel::ExecuteCommand(int command_id) {
}
case kOpenContentSettingsCommand: {
Browser* browser = BrowserList::GetLastActive();
- if (browser)
+ if (browser) {
static_cast<TabContentsDelegate*>(browser)->ShowContentSettingsWindow(
CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
+ } else {
+#if defined(OS_WIN)
+ if (InstallUtil::IsChromeFrameProcess()) {
+ // We may not have a browser if this is a chrome frame process.
+ browser::ShowContentSettingsWindow(NULL,
+ CONTENT_SETTINGS_TYPE_DEFAULT,
+ balloon_->profile());
+ }
+#endif // OS_WIN
+ }
break;
}
default:
diff --git a/chrome/browser/notifications/notification_test_util.h b/chrome/browser/notifications/notification_test_util.h
index 4cbf600..fbaec4e 100644
--- a/chrome/browser/notifications/notification_test_util.h
+++ b/chrome/browser/notifications/notification_test_util.h
@@ -6,6 +6,8 @@
#define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_TEST_UTIL_H_
#pragma once
+#include <string>
+
#include "chrome/browser/notifications/notification_object_proxy.h"
#include "chrome/browser/notifications/balloon.h"
#include "gfx/size.h"
@@ -14,7 +16,7 @@
// the notification events are not important.
class MockNotificationDelegate : public NotificationDelegate {
public:
- explicit MockNotificationDelegate(std::string id) : id_(id) {}
+ explicit MockNotificationDelegate(const std::string& id) : id_(id) {}
virtual ~MockNotificationDelegate() {}
// NotificationDelegate interface.
@@ -26,6 +28,8 @@ class MockNotificationDelegate : public NotificationDelegate {
private:
std::string id_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockNotificationDelegate);
};
// Mock implementation of Javascript object proxy which logs events that
@@ -35,10 +39,11 @@ class MockNotificationDelegate : public NotificationDelegate {
// |Logger| class provided in template must implement method
// static void log(string);
template<class Logger>
-class LoggingNotificationProxyBase : public NotificationObjectProxy {
+class LoggingNotificationDelegate : public NotificationDelegate {
public:
- LoggingNotificationProxyBase() :
- NotificationObjectProxy(0, 0, 0, false) {}
+ explicit LoggingNotificationDelegate(std::string id)
+ : notification_id_(id) {
+ }
// NotificationObjectProxy override
virtual void Display() {
@@ -47,12 +52,22 @@ class LoggingNotificationProxyBase : public NotificationObjectProxy {
virtual void Error() {
Logger::log("notification error\n");
}
+ virtual void Click() {
+ Logger::log("notification clicked\n");
+ }
virtual void Close(bool by_user) {
if (by_user)
Logger::log("notification closed by user\n");
else
Logger::log("notification closed by script\n");
}
+ virtual std::string id() const {
+ return notification_id_;
+ }
+ private:
+ std::string notification_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(LoggingNotificationDelegate);
};
// Test version of a balloon view which doesn't do anything
diff --git a/chrome/browser/notifications/notification_ui_manager.cc b/chrome/browser/notifications/notification_ui_manager.cc
index adc44cf..6e2ff02 100644
--- a/chrome/browser/notifications/notification_ui_manager.cc
+++ b/chrome/browser/notifications/notification_ui_manager.cc
@@ -10,6 +10,8 @@
#include "chrome/browser/notifications/balloon_collection.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
// A class which represents a notification waiting to be shown.
class QueuedNotification {
@@ -38,6 +40,8 @@ class QueuedNotification {
NotificationUIManager::NotificationUIManager()
: balloon_collection_(NULL) {
+ registrar_.Add(this, NotificationType::APP_TERMINATING,
+ NotificationService::AllSources());
}
NotificationUIManager::~NotificationUIManager() {
@@ -66,17 +70,39 @@ void NotificationUIManager::Add(const Notification& notification,
CheckAndShowNotifications();
}
-bool NotificationUIManager::Cancel(const Notification& notification) {
- // First look through the notifications that haven't been shown. If not
- // found there, call to the active balloon collection to tear it down.
+bool NotificationUIManager::CancelById(const std::string& id) {
+ // See if this ID hasn't been shown yet.
NotificationDeque::iterator iter;
for (iter = show_queue_.begin(); iter != show_queue_.end(); ++iter) {
- if (notification.IsSame((*iter)->notification())) {
+ if ((*iter)->notification().notification_id() == id) {
show_queue_.erase(iter);
return true;
}
}
- return balloon_collection_->Remove(notification);
+ // If it has been shown, remove it from the balloon collections.
+ return balloon_collection_->RemoveById(id);
+}
+
+bool NotificationUIManager::CancelAllBySourceOrigin(const GURL& source) {
+ // Same pattern as CancelById, but more complicated than the above
+ // because there may be multiple notifications from the same source.
+ bool removed = false;
+ NotificationDeque::iterator iter;
+ for (iter = show_queue_.begin(); iter != show_queue_.end();) {
+ if ((*iter)->notification().origin_url() == source) {
+ iter = show_queue_.erase(iter);
+ removed = true;
+ } else {
+ ++iter;
+ }
+ }
+
+ return balloon_collection_->RemoveBySourceOrigin(source) || removed;
+}
+
+void NotificationUIManager::CancelAll() {
+ STLDeleteElements(&show_queue_);
+ balloon_collection_->RemoveAll();
}
void NotificationUIManager::CheckAndShowNotifications() {
@@ -130,3 +156,12 @@ bool NotificationUIManager::TryReplacement(const Notification& notification) {
return false;
}
+
+void NotificationUIManager::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type == NotificationType::APP_TERMINATING)
+ CancelAll();
+ else
+ NOTREACHED();
+}
diff --git a/chrome/browser/notifications/notification_ui_manager.h b/chrome/browser/notifications/notification_ui_manager.h
index 10687a9..de429db 100644
--- a/chrome/browser/notifications/notification_ui_manager.h
+++ b/chrome/browser/notifications/notification_ui_manager.h
@@ -7,11 +7,14 @@
#pragma once
#include <deque>
+#include <string>
#include "base/id_map.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/notifications/balloon.h"
#include "chrome/browser/notifications/balloon_collection.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
class Notification;
class Profile;
@@ -21,7 +24,8 @@ class SiteInstance;
// The notification manager manages use of the desktop for notifications.
// It maintains a queue of pending notifications when space becomes constrained.
class NotificationUIManager
- : public BalloonCollection::BalloonSpaceChangeListener {
+ : public BalloonCollection::BalloonSpaceChangeListener,
+ public NotificationObserver {
public:
NotificationUIManager();
virtual ~NotificationUIManager();
@@ -43,14 +47,29 @@ class NotificationUIManager
virtual void Add(const Notification& notification,
Profile* profile);
- // Removes a notification.
- virtual bool Cancel(const Notification& notification);
+ // Removes any notifications matching the supplied ID, either currently
+ // displayed or in the queue. Returns true if anything was removed.
+ virtual bool CancelById(const std::string& notification_id);
+
+ // Removes any notifications matching the supplied source origin
+ // (which could be an extension ID), either currently displayed or in the
+ // queue. Returns true if anything was removed.
+ virtual bool CancelAllBySourceOrigin(const GURL& source_origin);
+
+ // Cancels all pending notifications and closes anything currently showing.
+ // Used when the app is terminating.
+ void CancelAll();
// Returns balloon collection.
BalloonCollection* balloon_collection() {
return balloon_collection_.get();
}
+ // NotificationObserver interface (the event signaling kind of notifications)
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
private:
// Attempts to display notifications from the show_queue if the user
// is active.
@@ -73,6 +92,9 @@ class NotificationUIManager
typedef std::deque<QueuedNotification*> NotificationDeque;
NotificationDeque show_queue_;
+ // Registrar for the other kind of notifications (event signaling).
+ NotificationRegistrar registrar_;
+
DISALLOW_COPY_AND_ASSIGN(NotificationUIManager);
};