summaryrefslogtreecommitdiffstats
path: root/chrome/browser/notifications
diff options
context:
space:
mode:
authorjohnnyg@chromium.org <johnnyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-12 17:13:49 +0000
committerjohnnyg@chromium.org <johnnyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-12 17:13:49 +0000
commit04b0c9332361ac2f7de9455d0df15290db94c693 (patch)
treefdc8b47e5f7c57b3e7382a7a236e5b92675b3f87 /chrome/browser/notifications
parent9e5c05aa2d4404c2a9946b49df19c2f781116b29 (diff)
downloadchromium_src-04b0c9332361ac2f7de9455d0df15290db94c693.zip
chromium_src-04b0c9332361ac2f7de9455d0df15290db94c693.tar.gz
chromium_src-04b0c9332361ac2f7de9455d0df15290db94c693.tar.bz2
Implement BiDi support and replace ID support for notifications.
BUG=none TEST=layout tests Review URL: http://codereview.chromium.org/1917004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52090 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/notifications')
-rw-r--r--chrome/browser/notifications/balloon.cc2
-rw-r--r--chrome/browser/notifications/desktop_notification_service.cc47
-rw-r--r--chrome/browser/notifications/desktop_notification_service.h35
-rw-r--r--chrome/browser/notifications/desktop_notifications_unittest.cc122
-rw-r--r--chrome/browser/notifications/desktop_notifications_unittest.h4
-rw-r--r--chrome/browser/notifications/notification.h20
-rw-r--r--chrome/browser/notifications/notification_ui_manager.cc42
-rw-r--r--chrome/browser/notifications/notification_ui_manager.h4
8 files changed, 186 insertions, 90 deletions
diff --git a/chrome/browser/notifications/balloon.cc b/chrome/browser/notifications/balloon.cc
index 4d9a94f..969bde1 100644
--- a/chrome/browser/notifications/balloon.cc
+++ b/chrome/browser/notifications/balloon.cc
@@ -38,10 +38,12 @@ void Balloon::Show() {
notification_->Display();
if (balloon_view_.get()) {
balloon_view_->Show(this);
+ balloon_view_->RepositionToBalloon();
}
}
void Balloon::Update(const Notification& notification) {
+ notification_->Close(false);
notification_.reset(new Notification(notification));
notification_->Display();
if (balloon_view_.get()) {
diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc
index 4a5f3ab..bc66077 100644
--- a/chrome/browser/notifications/desktop_notification_service.cc
+++ b/chrome/browser/notifications/desktop_notification_service.cc
@@ -36,12 +36,14 @@
#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPresenter.h"
using WebKit::WebNotificationPresenter;
+using WebKit::WebTextDirection;
const ContentSetting kDefaultSetting = CONTENT_SETTING_ASK;
// static
string16 DesktopNotificationService::CreateDataUrl(
- const GURL& icon_url, const string16& title, const string16& body) {
+ const GURL& icon_url, const string16& title, const string16& body,
+ WebTextDirection dir) {
int resource;
string16 line_name;
string16 line;
@@ -51,6 +53,9 @@ string16 DesktopNotificationService::CreateDataUrl(
subst.push_back(icon_url.spec());
subst.push_back(EscapeForHTML(UTF16ToUTF8(title)));
subst.push_back(EscapeForHTML(UTF16ToUTF8(body)));
+ // icon float position
+ subst.push_back(dir == WebKit::WebTextDirectionRightToLeft ?
+ "right" : "left");
} else if (title.empty() || body.empty()) {
resource = IDR_NOTIFICATION_1LINE_HTML;
line = title.empty() ? body : title;
@@ -64,6 +69,9 @@ string16 DesktopNotificationService::CreateDataUrl(
subst.push_back(EscapeForHTML(UTF16ToUTF8(title)));
subst.push_back(EscapeForHTML(UTF16ToUTF8(body)));
}
+ // body text direction
+ subst.push_back(dir == WebKit::WebTextDirectionRightToLeft ?
+ "rtl" : "ltr");
const base::StringPiece template_html(
ResourceBundle::GetSharedInstance().GetRawDataResource(
@@ -529,37 +537,32 @@ bool DesktopNotificationService::CancelDesktopNotification(
scoped_refptr<NotificationObjectProxy> proxy(
new NotificationObjectProxy(process_id, route_id, notification_id,
false));
- Notification notif(GURL(), GURL(), L"", proxy);
+ // TODO(johnnyg): clean up this "empty" notification.
+ Notification notif(GURL(), GURL(), L"", ASCIIToUTF16(""), proxy);
return ui_manager_->Cancel(notif);
}
bool DesktopNotificationService::ShowDesktopNotification(
- const GURL& origin, const GURL& url, int process_id, int route_id,
- DesktopNotificationSource source, int notification_id) {
+ const ViewHostMsg_ShowNotification_Params& params,
+ int process_id, int route_id, DesktopNotificationSource source) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ const GURL& origin = params.origin;
NotificationObjectProxy* proxy =
new NotificationObjectProxy(process_id, route_id,
- notification_id,
+ params.notification_id,
source == WorkerNotification);
- Notification notif(origin, url, DisplayNameForOrigin(origin), proxy);
- ShowNotification(notif);
- return true;
-}
-
-bool DesktopNotificationService::ShowDesktopNotificationText(
- const GURL& origin, const GURL& icon, const string16& title,
- const string16& text, int process_id, int route_id,
- DesktopNotificationSource source, int notification_id) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- NotificationObjectProxy* proxy =
- new NotificationObjectProxy(process_id, route_id,
- notification_id,
- source == WorkerNotification);
- // "upconvert" the string parameters to a data: URL.
- string16 data_url = CreateDataUrl(icon, title, text);
+ GURL contents;
+ if (params.is_html) {
+ contents = params.contents_url;
+ } else {
+ // "upconvert" the string parameters to a data: URL.
+ contents = GURL(
+ CreateDataUrl(params.icon_url, params.title, params.body,
+ params.direction));
+ }
Notification notif(
- origin, GURL(data_url), DisplayNameForOrigin(origin), proxy);
+ origin, contents, DisplayNameForOrigin(origin), params.replace_id, proxy);
ShowNotification(notif);
return true;
}
diff --git a/chrome/browser/notifications/desktop_notification_service.h b/chrome/browser/notifications/desktop_notification_service.h
index 3f97425..ae38b18 100644
--- a/chrome/browser/notifications/desktop_notification_service.h
+++ b/chrome/browser/notifications/desktop_notification_service.h
@@ -14,6 +14,7 @@
#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 NotificationUIManager;
class NotificationsPrefsCache;
@@ -21,6 +22,7 @@ class PrefService;
class Profile;
class Task;
class TabContents;
+struct ViewHostMsg_ShowNotification_Params;
// The DesktopNotificationService is an object, owned by the Profile,
// which provides the creation of desktop "toasts" to web pages and workers.
@@ -44,23 +46,13 @@ class DesktopNotificationService : public NotificationObserver {
int callback_context,
TabContents* tab);
- // Takes a notification object and shows it in the UI.
- void ShowNotification(const Notification& notification);
-
- // Two ShowNotification methods: getting content either from remote
- // URL or as local parameters. These are called on the UI thread
- // in response to IPCs from a child process running script. |origin|
- // is the origin of the script. |source| indicates whether the
- // script is in a worker or page. |notification_id| is an opaque
- // value to be passed back to the process when events occur on
- // this notification.
- bool ShowDesktopNotification(const GURL& origin, const GURL& url,
- int process_id, int route_id, DesktopNotificationSource source,
- int notification_id);
- bool ShowDesktopNotificationText(const GURL& origin, const GURL& icon,
- const string16& title, const string16& text, int process_id,
- int route_id, DesktopNotificationSource source, int notification_id);
-
+ // ShowNotification is called on the UI thread handling IPCs from a child
+ // process, identified by |process_id| and |route_id|. |source| indicates
+ // whether the script is in a worker or page. |params| contains all the
+ // other parameters supplied by the worker or page.
+ bool ShowDesktopNotification(
+ const ViewHostMsg_ShowNotification_Params& params,
+ int process_id, int route_id, DesktopNotificationSource source);
// Cancels a notification. If it has already been shown, it will be
// removed from the screen. If it hasn't been shown yet, it won't be
@@ -83,8 +75,10 @@ class DesktopNotificationService : public NotificationObserver {
// Creates a data:xxxx URL which contains the full HTML for a notification
// using supplied icon, title, and text, run through a template which contains
// the standard formatting for notifications.
- static string16 CreateDataUrl(const GURL& icon_url, const string16& title,
- const string16& body);
+ static string16 CreateDataUrl(const GURL& icon_url,
+ const string16& title,
+ const string16& body,
+ WebKit::WebTextDirection dir);
// The default content setting determines how to handle origins that haven't
// been allowed or denied yet.
@@ -112,6 +106,9 @@ class DesktopNotificationService : public NotificationObserver {
void StartObserving();
void StopObserving();
+ // Takes a notification object and shows it in the UI.
+ void ShowNotification(const Notification& notification);
+
// Save a permission change to the profile.
void PersistPermissionChange(const GURL& origin, bool is_allowed);
diff --git a/chrome/browser/notifications/desktop_notifications_unittest.cc b/chrome/browser/notifications/desktop_notifications_unittest.cc
index 5cd03c3..459d9a0 100644
--- a/chrome/browser/notifications/desktop_notifications_unittest.cc
+++ b/chrome/browser/notifications/desktop_notifications_unittest.cc
@@ -21,6 +21,7 @@ void MockBalloonCollection::Add(const Notification& notification,
Notification test_notification(notification.origin_url(),
notification.content_url(),
notification.display_source(),
+ string16(), /* replace_id */
log_proxy_.get());
BalloonCollectionImpl::Add(test_notification, profile);
}
@@ -29,6 +30,7 @@ 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);
}
@@ -87,18 +89,35 @@ void DesktopNotificationsTest::TearDown() {
ui_manager_.reset(NULL);
}
+ViewHostMsg_ShowNotification_Params
+DesktopNotificationsTest::StandardTestNotification() {
+ ViewHostMsg_ShowNotification_Params params;
+ params.notification_id = 0;
+ params.origin = GURL("http://www.google.com");
+ params.is_html = false;
+ params.icon_url = GURL("/icon.png");
+ params.title = ASCIIToUTF16("Title");
+ params.body = ASCIIToUTF16("Text");
+ return params;
+}
+
TEST_F(DesktopNotificationsTest, TestShow) {
- EXPECT_TRUE(service_->ShowDesktopNotificationText(
- GURL("http://www.google.com"),
- GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, 1));
+ ViewHostMsg_ShowNotification_Params params = StandardTestNotification();
+ params.notification_id = 1;
+
+ EXPECT_TRUE(service_->ShowDesktopNotification(
+ params, 0, 0, DesktopNotificationService::PageNotification));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
+ ViewHostMsg_ShowNotification_Params params2;
+ params2.origin = GURL("http://www.google.com");
+ params2.is_html = true;
+ params2.contents_url = GURL("http://www.google.com/notification.html");
+ params2.notification_id = 2;
+
EXPECT_TRUE(service_->ShowDesktopNotification(
- GURL("http://www.google.com"),
- GURL("http://www.google.com/notification.html"),
- 0, 0, DesktopNotificationService::PageNotification, 2));
+ params2, 0, 0, DesktopNotificationService::PageNotification));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(2, balloon_collection_->count());
@@ -108,11 +127,12 @@ TEST_F(DesktopNotificationsTest, TestShow) {
}
TEST_F(DesktopNotificationsTest, TestClose) {
+ ViewHostMsg_ShowNotification_Params params = StandardTestNotification();
+ params.notification_id = 1;
+
// Request a notification; should open a balloon.
- EXPECT_TRUE(service_->ShowDesktopNotificationText(
- GURL("http://www.google.com"),
- GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, 1));
+ EXPECT_TRUE(service_->ShowDesktopNotification(
+ params, 0, 0, DesktopNotificationService::PageNotification));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
@@ -130,12 +150,14 @@ TEST_F(DesktopNotificationsTest, TestCancel) {
int process_id = 0;
int route_id = 0;
int notification_id = 1;
+
+ ViewHostMsg_ShowNotification_Params params = StandardTestNotification();
+ params.notification_id = notification_id;
+
// Request a notification; should open a balloon.
- EXPECT_TRUE(service_->ShowDesktopNotificationText(
- GURL("http://www.google.com"),
- GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- process_id, route_id, DesktopNotificationService::PageNotification,
- notification_id));
+ EXPECT_TRUE(service_->ShowDesktopNotification(
+ params, process_id, route_id,
+ DesktopNotificationService::PageNotification));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
@@ -154,15 +176,15 @@ TEST_F(DesktopNotificationsTest, TestCancel) {
#if defined(OS_WIN) || defined(TOOLKIT_VIEWS)
TEST_F(DesktopNotificationsTest, TestPositioning) {
+ ViewHostMsg_ShowNotification_Params params = StandardTestNotification();
std::string expected_log;
// Create some toasts. After each but the first, make sure there
// is a minimum separation between the toasts.
int last_top = 0;
for (int id = 0; id <= 3; ++id) {
- EXPECT_TRUE(service_->ShowDesktopNotificationText(
- GURL("http://www.google.com"),
- GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, id));
+ params.notification_id = id;
+ EXPECT_TRUE(service_->ShowDesktopNotification(
+ params, 0, 0, DesktopNotificationService::PageNotification));
expected_log.append("notification displayed\n");
int top = balloon_collection_->UppermostVerticalPosition();
if (id > 0)
@@ -174,21 +196,29 @@ TEST_F(DesktopNotificationsTest, TestPositioning) {
}
TEST_F(DesktopNotificationsTest, TestVariableSize) {
+ ViewHostMsg_ShowNotification_Params params;
+ params.origin = GURL("http://long.google.com");
+ params.is_html = false;
+ params.icon_url = GURL("/icon.png");
+ params.title = ASCIIToUTF16("Really Really Really Really Really Really "
+ "Really Really Really Really Really Really "
+ "Really Really Really Really Really Really "
+ "Really Long Title"),
+ params.body = ASCIIToUTF16("Text");
+ params.notification_id = 0;
+
std::string expected_log;
// Create some toasts. After each but the first, make sure there
// is a minimum separation between the toasts.
- EXPECT_TRUE(service_->ShowDesktopNotificationText(
- GURL("http://long.google.com"), GURL("/icon.png"),
- ASCIIToUTF16("Really Really Really Really Really Really "
- "Really Really Really Really Really Really "
- "Really Really Really Really Really Really Really Long Title"),
- ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, 0));
+ EXPECT_TRUE(service_->ShowDesktopNotification(
+ params, 0, 0, DesktopNotificationService::PageNotification));
expected_log.append("notification displayed\n");
- EXPECT_TRUE(service_->ShowDesktopNotificationText(
- GURL("http://short.google.com"), GURL("/icon.png"),
- ASCIIToUTF16("Short title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, 1));
+
+ params.origin = GURL("http://short.google.com");
+ params.title = ASCIIToUTF16("Short title");
+ params.notification_id = 1;
+ EXPECT_TRUE(service_->ShowDesktopNotification(
+ params, 0, 0, DesktopNotificationService::PageNotification));
expected_log.append("notification displayed\n");
std::deque<Balloon*>& balloons = balloon_collection_->balloons();
@@ -213,13 +243,13 @@ TEST_F(DesktopNotificationsTest, TestQueueing) {
int route_id = 0;
// Request lots of identical notifications.
+ ViewHostMsg_ShowNotification_Params params = StandardTestNotification();
const int kLotsOfToasts = 20;
for (int id = 1; id <= kLotsOfToasts; ++id) {
- EXPECT_TRUE(service_->ShowDesktopNotificationText(
- GURL("http://www.google.com"),
- GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- process_id, route_id,
- DesktopNotificationService::PageNotification, id));
+ params.notification_id = id;
+ EXPECT_TRUE(service_->ShowDesktopNotification(
+ params, process_id, route_id,
+ DesktopNotificationService::PageNotification));
}
MessageLoopForUI::current()->RunAllPending();
@@ -265,11 +295,11 @@ TEST_F(DesktopNotificationsTest, TestQueueing) {
TEST_F(DesktopNotificationsTest, TestEarlyDestruction) {
// Create some toasts and then prematurely delete the notification service,
// just to make sure nothing crashes/leaks.
+ ViewHostMsg_ShowNotification_Params params = StandardTestNotification();
for (int id = 0; id <= 3; ++id) {
- EXPECT_TRUE(service_->ShowDesktopNotificationText(
- GURL("http://www.google.com"),
- GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, id));
+ params.notification_id = id;
+ EXPECT_TRUE(service_->ShowDesktopNotification(
+ params, 0, 0, DesktopNotificationService::PageNotification));
}
service_.reset(NULL);
}
@@ -277,12 +307,12 @@ TEST_F(DesktopNotificationsTest, TestEarlyDestruction) {
TEST_F(DesktopNotificationsTest, TestUserInputEscaping) {
// Create a test script with some HTML; assert that it doesn't get into the
// data:// URL that's produced for the balloon.
- EXPECT_TRUE(service_->ShowDesktopNotificationText(
- GURL("http://www.google.com"),
- GURL("/icon.png"),
- ASCIIToUTF16("<script>window.alert('uh oh');</script>"),
- ASCIIToUTF16("<i>this text is in italics</i>, as is %3ci%3ethis%3c/i%3e"),
- 0, 0, DesktopNotificationService::PageNotification, 1));
+ ViewHostMsg_ShowNotification_Params params = StandardTestNotification();
+ params.title = ASCIIToUTF16("<script>window.alert('uh oh');</script>");
+ params.body = ASCIIToUTF16("<i>this text is in italics</i>");
+ params.notification_id = 1;
+ EXPECT_TRUE(service_->ShowDesktopNotification(
+ params, 0, 0, DesktopNotificationService::PageNotification));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
diff --git a/chrome/browser/notifications/desktop_notifications_unittest.h b/chrome/browser/notifications/desktop_notifications_unittest.h
index 46bfeb4e..56a2a6b 100644
--- a/chrome/browser/notifications/desktop_notifications_unittest.h
+++ b/chrome/browser/notifications/desktop_notifications_unittest.h
@@ -15,6 +15,7 @@
#include "chrome/browser/notifications/notification_test_util.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/browser/notifications/notifications_prefs_cache.h"
+#include "chrome/common/render_messages.h"
#include "chrome/test/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -91,6 +92,9 @@ class DesktopNotificationsTest : public testing::Test {
return service_->prefs_cache()->HasPermission(origin);
}
+ // Constructs a notification parameter structure for use in tests.
+ ViewHostMsg_ShowNotification_Params StandardTestNotification();
+
// Create a message loop to allow notifications code to post tasks,
// and a thread so that notifications code runs on the expected thread.
MessageLoopForUI message_loop_;
diff --git a/chrome/browser/notifications/notification.h b/chrome/browser/notifications/notification.h
index a58c2ad..bdad291 100644
--- a/chrome/browser/notifications/notification.h
+++ b/chrome/browser/notifications/notification.h
@@ -16,12 +16,15 @@ class NotificationDelegate;
// data: URLs representing simple text+icon notifications.
class Notification {
public:
+ // TODO: http://crbug.com/43899 Convert this class to string16.
Notification(const GURL& origin_url, const GURL& content_url,
const std::wstring& display_source,
+ const string16& replace_id,
NotificationDelegate* delegate)
: origin_url_(origin_url),
content_url_(content_url),
display_source_(display_source),
+ replace_id_(replace_id),
delegate_(delegate) {
}
@@ -29,9 +32,18 @@ class Notification {
: origin_url_(notification.origin_url()),
content_url_(notification.content_url()),
display_source_(notification.display_source()),
+ replace_id_(notification.replace_id()),
delegate_(notification.delegate()) {
}
+ void operator=(const Notification& notification) {
+ origin_url_ = notification.origin_url();
+ content_url_ = notification.content_url();
+ display_source_ = notification.display_source();
+ replace_id_ = notification.replace_id();
+ delegate_ = notification.delegate();
+ }
+
// The URL (may be data:) containing the contents for the notification.
const GURL& content_url() const { return content_url_; }
@@ -41,6 +53,8 @@ class Notification {
// A display string for the source of the notification.
const std::wstring& display_source() const { return display_source_; }
+ const string16& replace_id() const { return replace_id_; }
+
void Display() const { delegate()->Display(); }
void Error() const { delegate()->Error(); }
void Close(bool by_user) const { delegate()->Close(by_user); }
@@ -63,12 +77,12 @@ class Notification {
// the same as origin_url_, or the name of an extension.
std::wstring display_source_;
+ // The replace ID for the notification.
+ string16 replace_id_;
+
// A proxy object that allows access back to the JavaScript object that
// represents the notification, for firing events.
scoped_refptr<NotificationDelegate> delegate_;
-
- // Disallow assign. Copy constructor written above.
- void operator=(const Notification&);
};
#endif // CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_H_
diff --git a/chrome/browser/notifications/notification_ui_manager.cc b/chrome/browser/notifications/notification_ui_manager.cc
index e5ae3bd..42b9c5e 100644
--- a/chrome/browser/notifications/notification_ui_manager.cc
+++ b/chrome/browser/notifications/notification_ui_manager.cc
@@ -22,6 +22,10 @@ class QueuedNotification {
const Notification& notification() const { return notification_; }
Profile* profile() const { return profile_; }
+ void Replace(const Notification& new_notification) {
+ notification_ = new_notification;
+ }
+
private:
// The notification to be shown.
Notification notification_;
@@ -51,6 +55,10 @@ NotificationUIManager* NotificationUIManager::Create() {
void NotificationUIManager::Add(const Notification& notification,
Profile* profile) {
+ if (TryReplacement(notification)) {
+ return;
+ }
+
LOG(INFO) << "Added notification. URL: "
<< notification.content_url().spec().c_str();
show_queue_.push_back(
@@ -88,3 +96,37 @@ void NotificationUIManager::ShowNotifications() {
void NotificationUIManager::OnBalloonSpaceChanged() {
CheckAndShowNotifications();
}
+
+bool NotificationUIManager::TryReplacement(const Notification& notification) {
+ const GURL& origin = notification.origin_url();
+ const string16& replace_id = notification.replace_id();
+
+ if (replace_id.empty())
+ return false;
+
+ // First check the queue of pending notifications for replacement.
+ // Then check the list of notifications already being shown.
+ NotificationDeque::iterator iter;
+ for (iter = show_queue_.begin(); iter != show_queue_.end(); ++iter) {
+ if (origin == (*iter)->notification().origin_url() &&
+ replace_id == (*iter)->notification().replace_id()) {
+ (*iter)->Replace(notification);
+ return true;
+ }
+ }
+
+ BalloonCollection::Balloons::iterator balloon_iter;
+ BalloonCollection::Balloons balloons =
+ balloon_collection_->GetActiveBalloons();
+ for (balloon_iter = balloons.begin();
+ balloon_iter != balloons.end();
+ ++balloon_iter) {
+ if (origin == (*balloon_iter)->notification().origin_url() &&
+ replace_id == (*balloon_iter)->notification().replace_id()) {
+ (*balloon_iter)->Update(notification);
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/chrome/browser/notifications/notification_ui_manager.h b/chrome/browser/notifications/notification_ui_manager.h
index 2eaedd3..e510e7f 100644
--- a/chrome/browser/notifications/notification_ui_manager.h
+++ b/chrome/browser/notifications/notification_ui_manager.h
@@ -61,6 +61,10 @@ class NotificationUIManager
// BalloonCollectionObserver implementation.
virtual void OnBalloonSpaceChanged();
+ // Replace an existing notification with this one if applicable;
+ // returns true if the replacement happened.
+ bool TryReplacement(const Notification& notification);
+
// An owned pointer to the collection of active balloons.
scoped_ptr<BalloonCollection> balloon_collection_;