summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-17 01:19:06 +0000
committeroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-17 01:19:06 +0000
commit3b845753b707daca3fe3e733263065f162b7162b (patch)
treeb674a4d72a118323da1fad83f8caa43f57a86b32
parentfee8f0222a5f2a377ba5d7f2d3383481c02eafac (diff)
downloadchromium_src-3b845753b707daca3fe3e733263065f162b7162b.zip
chromium_src-3b845753b707daca3fe3e733263065f162b7162b.tar.gz
chromium_src-3b845753b707daca3fe3e733263065f162b7162b.tar.bz2
* Moved sticky/controls frag to chromeos::BalloonViewImpl
* Added AddSystemNotification to add system notification and UpdateNotification to update a notification. * refactored NotificationObjectProxy and added NotificationDelegate class. * Added notification_browser.cc. BUG=33306 TEST=added notification_browser.cc with minimal test. I'll add more in next step. Review URL: http://codereview.chromium.org/1013002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41801 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/notifications/balloon_collection_impl.cc89
-rw-r--r--chrome/browser/chromeos/notifications/balloon_collection_impl.h26
-rw-r--r--chrome/browser/chromeos/notifications/balloon_view.cc91
-rw-r--r--chrome/browser/chromeos/notifications/balloon_view.h26
-rw-r--r--chrome/browser/chromeos/notifications/desktop_notifications_unittest.cc46
-rw-r--r--chrome/browser/chromeos/notifications/notification_browsertest.cc83
-rw-r--r--chrome/browser/chromeos/notifications/notification_panel.cc62
-rw-r--r--chrome/browser/chromeos/notifications/notification_panel.h7
-rw-r--r--chrome/browser/chromeos/notifications/system_notification_factory.cc20
-rw-r--r--chrome/browser/chromeos/notifications/system_notification_factory.h29
-rw-r--r--chrome/browser/cocoa/notifications/balloon_controller_unittest.mm7
-rw-r--r--chrome/browser/cocoa/notifications/balloon_view_bridge.h1
-rw-r--r--chrome/browser/cocoa/notifications/balloon_view_host_mac.h1
-rw-r--r--chrome/browser/gtk/notifications/balloon_view_gtk.h1
-rw-r--r--chrome/browser/gtk/notifications/balloon_view_host_gtk.h1
-rw-r--r--chrome/browser/notifications/balloon.cc15
-rw-r--r--chrome/browser/notifications/balloon.h12
-rw-r--r--chrome/browser/notifications/desktop_notification_service.cc25
-rw-r--r--chrome/browser/notifications/desktop_notification_service.h15
-rw-r--r--chrome/browser/notifications/desktop_notifications_unittest.cc49
-rw-r--r--chrome/browser/notifications/notification.h35
-rw-r--r--chrome/browser/notifications/notification_delegate.h34
-rw-r--r--chrome/browser/notifications/notification_object_proxy.cc6
-rw-r--r--chrome/browser/notifications/notification_object_proxy.h23
-rw-r--r--chrome/browser/notifications/notification_test_util.h1
-rw-r--r--chrome/browser/notifications/notification_ui_manager.h5
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc4
-rw-r--r--chrome/browser/views/notifications/balloon_view.h9
-rw-r--r--chrome/browser/views/notifications/balloon_view_host.h1
-rwxr-xr-xchrome/chrome_browser.gypi3
-rw-r--r--chrome/chrome_tests.gypi6
31 files changed, 500 insertions, 233 deletions
diff --git a/chrome/browser/chromeos/notifications/balloon_collection_impl.cc b/chrome/browser/chromeos/notifications/balloon_collection_impl.cc
index 82a2594..b06edf1 100644
--- a/chrome/browser/chromeos/notifications/balloon_collection_impl.cc
+++ b/chrome/browser/chromeos/notifications/balloon_collection_impl.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/chromeos/notifications/balloon_collection_impl.h"
+#include <algorithm>
+
#include "base/logging.h"
#include "base/stl_util-inl.h"
#include "chrome/browser/chromeos/notifications/balloon_view.h"
@@ -27,19 +29,30 @@ const int kMinAllowedBalloonCount = 2;
const int kVerticalEdgeMargin = 5;
const int kHorizontalEdgeMargin = 5;
+class NotificationMatcher {
+ public:
+ explicit NotificationMatcher(const Notification& notification)
+ : notification_(notification) {}
+ bool operator()(const Balloon* b) {
+ return notification_.IsSame(b->notification());
+ }
+ private:
+ Notification notification_;
+};
+
} // namespace
namespace chromeos {
BalloonCollectionImpl::BalloonCollectionImpl()
- : panel_(new NotificationPanel()) {
+ : notification_ui_(new NotificationPanel()) {
}
BalloonCollectionImpl::~BalloonCollectionImpl() {
// We need to remove the panel first because deleting
// views that are not owned by parent will not remove
// themselves from the parent.
- panel_.reset();
+ notification_ui_.reset();
STLDeleteElements(&balloons_);
}
@@ -48,22 +61,51 @@ void BalloonCollectionImpl::Add(const Notification& notification,
Balloon* new_balloon = MakeBalloon(notification, profile);
balloons_.push_back(new_balloon);
new_balloon->Show();
- panel_->Add(new_balloon);
+ notification_ui_->Add(new_balloon);
// There may be no listener in a unit test.
if (space_change_listener_)
space_change_listener_->OnBalloonSpaceChanged();
}
+void BalloonCollectionImpl::AddSystemNotification(
+ const Notification& notification,
+ Profile* profile,
+ bool sticky,
+ bool control) {
+ // TODO(oshima): We need to modify BallonCollection/MakeBalloon pattern
+ // in order to add unit tests for system notification.
+ Balloon* new_balloon = new Balloon(notification, profile, this);
+ new_balloon->set_view(
+ new chromeos::BalloonViewImpl(sticky, control));
+ balloons_.push_back(new_balloon);
+ new_balloon->Show();
+ notification_ui_->Add(new_balloon);
+
+ // There may be no listener in a unit test.
+ if (space_change_listener_)
+ space_change_listener_->OnBalloonSpaceChanged();
+}
+
+bool BalloonCollectionImpl::UpdateNotification(
+ const Notification& notification) {
+ Balloons::iterator iter = FindBalloon(notification);
+ if (iter != balloons_.end()) {
+ Balloon* balloon = *iter;
+ balloon->Update(notification);
+ notification_ui_->Update(balloon);
+ return true;
+ }
+ return false;
+}
+
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;
- }
+ Balloons::iterator iter = FindBalloon(notification);
+ if (iter != balloons_.end()) {
+ // 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;
}
@@ -74,20 +116,18 @@ bool BalloonCollectionImpl::HasSpace() const {
void BalloonCollectionImpl::ResizeBalloon(Balloon* balloon,
const gfx::Size& size) {
- panel_->ResizeNotification(balloon, size);
+ notification_ui_->ResizeNotification(balloon, size);
}
void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) {
// We want to free the balloon when finished.
scoped_ptr<Balloon> closed(source);
- panel_->Remove(source);
+ notification_ui_->Remove(source);
- for (Balloons::iterator it = balloons_.begin(); it != balloons_.end(); ++it) {
- if (*it == source) {
- balloons_.erase(it);
- break;
- }
+ Balloons::iterator iter = FindBalloon(source->notification());
+ if (iter != balloons_.end()) {
+ balloons_.erase(iter);
}
// There may be no listener in a unit test.
if (space_change_listener_)
@@ -96,9 +136,16 @@ void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) {
Balloon* BalloonCollectionImpl::MakeBalloon(const Notification& notification,
Profile* profile) {
- Balloon* balloon = new Balloon(notification, profile, this);
- balloon->set_view(new chromeos::BalloonViewImpl());
- return balloon;
+ Balloon* new_balloon = new Balloon(notification, profile, this);
+ new_balloon->set_view(new chromeos::BalloonViewImpl(false, true));
+ return new_balloon;
+}
+
+std::deque<Balloon*>::iterator BalloonCollectionImpl::FindBalloon(
+ const Notification& notification) {
+ return std::find_if(balloons_.begin(),
+ balloons_.end(),
+ NotificationMatcher(notification));
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/notifications/balloon_collection_impl.h b/chrome/browser/chromeos/notifications/balloon_collection_impl.h
index 4172b0d..870030d 100644
--- a/chrome/browser/chromeos/notifications/balloon_collection_impl.h
+++ b/chrome/browser/chromeos/notifications/balloon_collection_impl.h
@@ -34,6 +34,7 @@ class BalloonCollectionImpl : public BalloonCollection {
// Add, remove and resize the balloon.
virtual void Add(Balloon* balloon) = 0;
+ virtual bool Update(Balloon* balloon) = 0;
virtual void Remove(Balloon* balloon) = 0;
virtual void ResizeNotification(Balloon* balloon,
const gfx::Size& size) = 0;
@@ -53,9 +54,26 @@ class BalloonCollectionImpl : public BalloonCollection {
virtual void DisplayChanged() {}
virtual void OnBalloonClosed(Balloon* source);
+ // Adds new system notification.
+ // |sticky| is used to indicate that the notification
+ // is sticky and cannot be dismissed by a user. |controls| turns on/off
+ // info label and option/dismiss buttons.
+ void AddSystemNotification(const Notification& notification,
+ Profile* profile, bool sticky, bool controls);
+
+ // Update the notification's content. It uses
+ // NotificationDelegate::id() to check the equality of notifications.
+ // Returns true if the notification has been updated. False if
+ // no corresponding notification is found.
+ bool UpdateNotification(const Notification& notification);
+
// Injects notification ui. Used to inject a mock implementation in tests.
void set_notification_ui(NotificationUI* ui) {
- panel_.reset(ui);
+ notification_ui_.reset(ui);
+ }
+
+ NotificationUI* notification_ui() {
+ return notification_ui_.get();
}
protected:
@@ -68,11 +86,13 @@ class BalloonCollectionImpl : public BalloonCollection {
// The number of balloons being displayed.
int count() const { return balloons_.size(); }
- // Queue of active balloons.
typedef std::deque<Balloon*> Balloons;
+ Balloons::iterator FindBalloon(const Notification& notification);
+
+ // Queue of active balloons.
Balloons balloons_;
- scoped_ptr<NotificationUI> panel_;
+ scoped_ptr<NotificationUI> notification_ui_;
DISALLOW_COPY_AND_ASSIGN(BalloonCollectionImpl);
};
diff --git a/chrome/browser/chromeos/notifications/balloon_view.cc b/chrome/browser/chromeos/notifications/balloon_view.cc
index 94feeae..6b9c4f0 100644
--- a/chrome/browser/chromeos/notifications/balloon_view.cc
+++ b/chrome/browser/chromeos/notifications/balloon_view.cc
@@ -35,7 +35,7 @@ const int kRevokePermissionCommand = 0;
namespace chromeos {
-BalloonViewImpl::BalloonViewImpl()
+BalloonViewImpl::BalloonViewImpl(bool sticky, bool controls)
: balloon_(NULL),
html_contents_(NULL),
method_factory_(this),
@@ -43,7 +43,9 @@ BalloonViewImpl::BalloonViewImpl()
options_menu_contents_(NULL),
options_menu_menu_(NULL),
options_menu_button_(NULL),
- stale_(false) {
+ stale_(false),
+ sticky_(sticky),
+ controls_(controls) {
// This object is not to be deleted by the views hierarchy,
// as it is owned by the balloon.
set_parent_owned(false);
@@ -71,41 +73,46 @@ void BalloonViewImpl::Show(Balloon* balloon) {
html_contents_ = new BalloonViewHost(balloon);
AddChildView(html_contents_);
- close_button_ = new views::TextButton(this, dismiss_text);
- close_button_->SetIcon(*rb.GetBitmapNamed(IDR_BALLOON_CLOSE));
- close_button_->SetHoverIcon(*rb.GetBitmapNamed(IDR_BALLOON_CLOSE_HOVER));
- close_button_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
- close_button_->SetEnabledColor(SK_ColorWHITE);
- close_button_->SetHoverColor(SK_ColorDKGRAY);
- close_button_->set_alignment(views::TextButton::ALIGN_CENTER);
- close_button_->set_icon_placement(views::TextButton::ICON_ON_RIGHT);
- AddChildView(close_button_);
-
- options_menu_button_ = new views::MenuButton(NULL, options_text, this, false);
- options_menu_button_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
- options_menu_button_->SetIcon(*rb.GetBitmapNamed(IDR_BALLOON_OPTIONS_ARROW));
- options_menu_button_->SetHoverIcon(
- *rb.GetBitmapNamed(IDR_BALLOON_OPTIONS_ARROW_HOVER));
- options_menu_button_->set_alignment(views::TextButton::ALIGN_CENTER);
- options_menu_button_->set_icon_placement(views::TextButton::ICON_ON_RIGHT);
- options_menu_button_->SetEnabledColor(SK_ColorWHITE);
- options_menu_button_->SetHoverColor(SK_ColorDKGRAY);
- AddChildView(options_menu_button_);
-
- source_label_ = new views::Label(source_label_text);
- source_label_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
- source_label_->SetColor(SK_ColorWHITE);
- source_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
- AddChildView(source_label_);
-
- SetBounds(0, 0,
- balloon_->content_size().width(),
- balloon_->content_size().height() +
- close_button_->GetPreferredSize().height());
+ if (controls_) {
+ close_button_ = new views::TextButton(this, dismiss_text);
+ close_button_->SetIcon(*rb.GetBitmapNamed(IDR_BALLOON_CLOSE));
+ close_button_->SetHoverIcon(*rb.GetBitmapNamed(IDR_BALLOON_CLOSE_HOVER));
+ close_button_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
+ close_button_->SetEnabledColor(SK_ColorWHITE);
+ close_button_->SetHoverColor(SK_ColorDKGRAY);
+ close_button_->set_alignment(views::TextButton::ALIGN_CENTER);
+ close_button_->set_icon_placement(views::TextButton::ICON_ON_RIGHT);
+ AddChildView(close_button_);
+
+ options_menu_button_
+ = new views::MenuButton(NULL, options_text, this, false);
+ options_menu_button_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
+ options_menu_button_->SetIcon(
+ *rb.GetBitmapNamed(IDR_BALLOON_OPTIONS_ARROW));
+ options_menu_button_->SetHoverIcon(
+ *rb.GetBitmapNamed(IDR_BALLOON_OPTIONS_ARROW_HOVER));
+ options_menu_button_->set_alignment(views::TextButton::ALIGN_CENTER);
+ options_menu_button_->set_icon_placement(views::TextButton::ICON_ON_RIGHT);
+ options_menu_button_->SetEnabledColor(SK_ColorWHITE);
+ options_menu_button_->SetHoverColor(SK_ColorDKGRAY);
+ AddChildView(options_menu_button_);
+
+ source_label_ = new views::Label(source_label_text);
+ source_label_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
+ source_label_->SetColor(SK_ColorWHITE);
+ source_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ AddChildView(source_label_);
+ }
notification_registrar_.Add(this,
NotificationType::NOTIFY_BALLOON_DISCONNECTED, Source<Balloon>(balloon));
}
+void BalloonViewImpl::Update() {
+ stale_ = false;
+ html_contents_->render_view_host()->NavigateToURL(
+ balloon_->notification().content_url());
+}
+
void BalloonViewImpl::Close(bool by_user) {
MessageLoop::current()->PostTask(
FROM_HERE,
@@ -126,7 +133,10 @@ void BalloonViewImpl::RepositionToBalloon() {
// views::View interface overrides.
void BalloonViewImpl::Layout() {
- gfx::Size button_size = close_button_->GetPreferredSize();
+ gfx::Size button_size;
+ if (close_button_) {
+ button_size = close_button_->GetPreferredSize();
+ }
SetBounds(x(), y(),
balloon_->content_size().width(),
@@ -141,12 +151,13 @@ void BalloonViewImpl::Layout() {
if (view)
view->SetSize(gfx::Size(width(), y));
}
-
- close_button_->SetBounds(x, y, button_size.width(), button_size.height());
- x -= close_button_->GetPreferredSize().width();
- options_menu_button_->SetBounds(
- x, y, button_size.width(), button_size.height());
- source_label_->SetBounds(0, y, x, button_size.height());
+ if (controls_) {
+ close_button_->SetBounds(x, y, button_size.width(), button_size.height());
+ x -= close_button_->GetPreferredSize().width();
+ options_menu_button_->SetBounds(
+ x, y, button_size.width(), button_size.height());
+ source_label_->SetBounds(0, y, x, button_size.height());
+ }
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/chromeos/notifications/balloon_view.h b/chrome/browser/chromeos/notifications/balloon_view.h
index fa51883..bd89f8b 100644
--- a/chrome/browser/chromeos/notifications/balloon_view.h
+++ b/chrome/browser/chromeos/notifications/balloon_view.h
@@ -43,27 +43,27 @@ class BalloonViewImpl : public BalloonView,
public NotificationObserver,
public views::ButtonListener {
public:
- BalloonViewImpl();
+ BalloonViewImpl(bool sticky, bool controls);
~BalloonViewImpl();
// views::View interface.
virtual void Layout();
// BalloonView interface.
- void Show(Balloon* balloon);
- void Close(bool by_user);
- void RepositionToBalloon();
+ virtual void Show(Balloon* balloon);
+ virtual void Update();
+ virtual void Close(bool by_user);
+ virtual void RepositionToBalloon();
gfx::Size GetSize() const;
// True if the notification is stale. False if the notification is new.
- bool stale() const {
- return stale_;
- }
+ bool stale() const { return stale_; }
- // Makes the notification stable.
- void set_stale() {
- stale_ = true;
- }
+ // Makes the notification stale.
+ void set_stale() { stale_ = true; }
+
+ // True if the notification is sticky.
+ bool sticky() { return sticky_; }
private:
// views::View interface.
@@ -116,6 +116,10 @@ class BalloonViewImpl : public BalloonView,
views::MenuButton* options_menu_button_;
bool stale_;
NotificationRegistrar notification_registrar_;
+ // A sticky flag. A sticky notification cannot be dismissed by a user.
+ bool sticky_;
+ // True if a notification should have info/option/dismiss label/buttons.
+ bool controls_;
DISALLOW_COPY_AND_ASSIGN(BalloonViewImpl);
};
diff --git a/chrome/browser/chromeos/notifications/desktop_notifications_unittest.cc b/chrome/browser/chromeos/notifications/desktop_notifications_unittest.cc
index 5702049..428ea3e 100644
--- a/chrome/browser/chromeos/notifications/desktop_notifications_unittest.cc
+++ b/chrome/browser/chromeos/notifications/desktop_notifications_unittest.cc
@@ -12,7 +12,8 @@ std::string DesktopNotificationsTest::log_output_;
class MockNotificationUI : public BalloonCollectionImpl::NotificationUI {
public:
virtual void Add(Balloon* balloon) {}
- virtual void Remove(Balloon* ballon) {}
+ virtual bool Update(Balloon* balloon) { return false; }
+ virtual void Remove(Balloon* balloon) {}
virtual void ResizeNotification(Balloon* balloon,
const gfx::Size& size) {}
};
@@ -30,8 +31,7 @@ void MockBalloonCollection::Add(const Notification& notification,
Notification test_notification(notification.origin_url(),
notification.content_url(),
notification.display_source(),
- log_proxy_.get(),
- notification.sticky());
+ log_proxy_.get());
BalloonCollectionImpl::Add(test_notification, profile);
}
@@ -39,8 +39,7 @@ bool MockBalloonCollection::Remove(const Notification& notification) {
Notification test_notification(notification.origin_url(),
notification.content_url(),
notification.display_source(),
- log_proxy_.get(),
- notification.sticky());
+ log_proxy_.get());
return BalloonCollectionImpl::Remove(test_notification);
}
@@ -96,25 +95,20 @@ 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, false));
+ 0, 0, DesktopNotificationService::PageNotification, 1));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
EXPECT_TRUE(service_->ShowDesktopNotification(
GURL("http://www.google.com"),
GURL("http://www.google.com/notification.html"),
- 0, 0, DesktopNotificationService::PageNotification, 2, false));
+ 0, 0, DesktopNotificationService::PageNotification, 2));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(2, balloon_collection_->count());
EXPECT_EQ("notification displayed\n"
"notification displayed\n",
log_output_);
-
- std::set<Balloon*>::iterator iter = balloon_collection_->balloons().begin();
- EXPECT_FALSE((*iter)->notification().sticky());
- iter++;
- EXPECT_FALSE((*iter)->notification().sticky());
}
TEST_F(DesktopNotificationsTest, TestClose) {
@@ -122,7 +116,7 @@ TEST_F(DesktopNotificationsTest, TestClose) {
EXPECT_TRUE(service_->ShowDesktopNotificationText(
GURL("http://www.google.com"),
GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, 1, false));
+ 0, 0, DesktopNotificationService::PageNotification, 1));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
@@ -150,7 +144,7 @@ TEST_F(DesktopNotificationsTest, TestCancel) {
GURL("http://www.google.com"),
GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
process_id, route_id, DesktopNotificationService::PageNotification,
- notification_id, false));
+ notification_id));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
@@ -179,7 +173,7 @@ TEST_F(DesktopNotificationsTest, TestManyNotifications) {
GURL("http://www.google.com"),
GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
process_id, route_id,
- DesktopNotificationService::PageNotification, id, false));
+ DesktopNotificationService::PageNotification, id));
}
MessageLoopForUI::current()->RunAllPending();
@@ -229,7 +223,7 @@ TEST_F(DesktopNotificationsTest, TestEarlyDestruction) {
EXPECT_TRUE(service_->ShowDesktopNotificationText(
GURL("http://www.google.com"),
GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, id, false));
+ 0, 0, DesktopNotificationService::PageNotification, id));
}
service_.reset(NULL);
}
@@ -242,7 +236,7 @@ TEST_F(DesktopNotificationsTest, TestUserInputEscaping) {
GURL("/icon.png"),
ASCIIToUTF16("<script>window.alert('uh oh');</script>"),
ASCIIToUTF16("<i>this text is in italics</i>"),
- 0, 0, DesktopNotificationService::PageNotification, 1, false));
+ 0, 0, DesktopNotificationService::PageNotification, 1));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
@@ -252,22 +246,4 @@ TEST_F(DesktopNotificationsTest, TestUserInputEscaping) {
EXPECT_EQ(std::string::npos, data_url.spec().find("<i>"));
}
-TEST_F(DesktopNotificationsTest, TestSticky) {
- EXPECT_TRUE(service_->ShowDesktopNotificationText(
- GURL("http://www.google.com"),
- GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, 1, true));
- MessageLoopForUI::current()->RunAllPending();
- EXPECT_TRUE(service_->ShowDesktopNotification(
- GURL("http://www.google.com"),
- GURL("http://www.google.com/notification.html"),
- 0, 0, DesktopNotificationService::PageNotification, 2, true));
- MessageLoopForUI::current()->RunAllPending();
-
- std::set<Balloon*>::iterator iter = balloon_collection_->balloons().begin();
- EXPECT_TRUE((*iter)->notification().sticky());
- iter++;
- EXPECT_TRUE((*iter)->notification().sticky());
-}
-
} // namespace chromeos
diff --git a/chrome/browser/chromeos/notifications/notification_browsertest.cc b/chrome/browser/chromeos/notifications/notification_browsertest.cc
new file mode 100644
index 0000000..c2c83ac
--- /dev/null
+++ b/chrome/browser/chromeos/notifications/notification_browsertest.cc
@@ -0,0 +1,83 @@
+// 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 "base/message_loop.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/notifications/balloon_collection_impl.h"
+#include "chrome/browser/chromeos/notifications/notification_panel.h"
+#include "chrome/browser/chromeos/notifications/system_notification_factory.h"
+#include "chrome/browser/notifications/notification_delegate.h"
+#include "chrome/browser/notifications/notification_ui_manager.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+
+namespace chromeos {
+
+class SystemNotificationDelegate : public NotificationDelegate {
+ public:
+ explicit SystemNotificationDelegate(const std::string id) : id_(id) {}
+
+ virtual void Display() {}
+ virtual void Error() {}
+ virtual void Close(bool by_user) {}
+ virtual std::string id() const { return id_; }
+
+ private:
+ std::string id_;
+
+ DISALLOW_COPY_AND_ASSIGN(SystemNotificationDelegate);
+};
+
+class NotificationTest : public InProcessBrowserTest {
+ public:
+ NotificationTest() {
+ }
+
+ protected:
+ BalloonCollectionImpl* GetBalloonCollectionImpl() {
+ return static_cast<BalloonCollectionImpl*>(
+ g_browser_process->notification_ui_manager()->balloon_collection());
+ }
+
+ NotificationPanel* GetNotificationPanel() {
+ return static_cast<NotificationPanel*>(
+ GetBalloonCollectionImpl()->notification_ui());
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(NotificationTest, TestSystemNotification) {
+ BalloonCollectionImpl* collection = GetBalloonCollectionImpl();
+ NotificationPanel* panel = GetNotificationPanel();
+ scoped_refptr<SystemNotificationDelegate> delegate(
+ new SystemNotificationDelegate("power"));
+
+ Notification notify = SystemNotificationFactory::Create(
+ GURL(), ASCIIToUTF16("Title"), ASCIIToUTF16("test"), delegate.get());
+ collection->AddSystemNotification(notify, browser()->profile(), true, false);
+
+ EXPECT_EQ(1, panel->GetNewNotificationCount());
+ EXPECT_EQ(1, panel->GetStickyNotificationCount());
+
+ Notification update = SystemNotificationFactory::Create(
+ GURL(), ASCIIToUTF16("Title"), ASCIIToUTF16("updated"), delegate.get());
+ collection->UpdateNotification(update);
+
+ EXPECT_EQ(1, panel->GetStickyNotificationCount());
+
+ // Dismiss the notification.
+ // TODO(oshima): Consider updating API to Remove(NotificationDelegate)
+ // or Remove(std::string id);
+ collection->Remove(Notification(GURL(), GURL(),
+ std::wstring(), delegate.get()));
+
+ MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ ui_test_utils::RunMessageLoop();
+
+ EXPECT_EQ(0, panel->GetStickyNotificationCount());
+ EXPECT_EQ(0, panel->GetNewNotificationCount());
+ // TODO(oshima): check content, etc..
+}
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/notifications/notification_panel.cc b/chrome/browser/chromeos/notifications/notification_panel.cc
index 724c451..0e76591 100644
--- a/chrome/browser/chromeos/notifications/notification_panel.cc
+++ b/chrome/browser/chromeos/notifications/notification_panel.cc
@@ -160,13 +160,32 @@ class BalloonContainer : public views::View {
return new_sticky.Union(new_non_sticky).size();
}
- // Add a ballon to the panel.
+ // Adds a ballon to the panel.
void Add(Balloon* balloon) {
BalloonViewImpl* view =
static_cast<BalloonViewImpl*>(balloon->view());
GetContainerFor(balloon)->AddChildView(view);
}
+ // Updates the position of the |balloon|.
+ bool Update(Balloon* balloon) {
+ BalloonViewImpl* view =
+ static_cast<BalloonViewImpl*>(balloon->view());
+ View* container = NULL;
+ if (sticky_container_->HasChildView(view)) {
+ container = sticky_container_;
+ } else if (non_sticky_container_->HasChildView(view)) {
+ container = non_sticky_container_;
+ }
+ if (container) {
+ container->RemoveChildView(view);
+ container->AddChildView(view);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
// Removes a ballon from the panel.
void Remove(Balloon* balloon) {
BalloonViewImpl* view =
@@ -180,9 +199,15 @@ class BalloonContainer : public views::View {
non_sticky_container_->GetChildViewCount();
}
- // Returns true if the container has sticky notification.
- bool HasStickyNotifications() {
- return sticky_container_->GetChildViewCount() > 0;
+ // Returns the # of new notifications.
+ bool GetNewNotificationCount() {
+ return sticky_container_->GetNewCount() +
+ non_sticky_container_->GetNewCount();
+ }
+
+ // Returns the # of sticky notifications.
+ bool GetStickyNotificationCount() {
+ return sticky_container_->GetChildViewCount();
}
// Returns true if the |view| is contained in the panel.
@@ -191,7 +216,7 @@ class BalloonContainer : public views::View {
non_sticky_container_->HasChildView(view);
}
- // Update the bounds so that all notifications are visible.
+ // Updates the bounds so that all notifications are visible.
void UpdateBounds() {
sticky_container_->UpdateBounds();
non_sticky_container_->UpdateBounds();
@@ -214,7 +239,9 @@ class BalloonContainer : public views::View {
private:
BalloonSubContainer* GetContainerFor(Balloon* balloon) const {
- return balloon->notification().sticky() ?
+ BalloonViewImpl* view =
+ static_cast<BalloonViewImpl*>(balloon->view());
+ return view->sticky() ?
sticky_container_ : non_sticky_container_;
}
@@ -279,6 +306,14 @@ void NotificationPanel::Hide() {
}
}
+int NotificationPanel::GetStickyNotificationCount() const {
+ return balloon_container_->GetStickyNotificationCount();
+}
+
+int NotificationPanel::GetNewNotificationCount() const {
+ return balloon_container_->GetNewNotificationCount();
+}
+
////////////////////////////////////////////////////////////////////////////////
// BalloonCollectionImpl::NotificationUI overrides.
@@ -291,6 +326,19 @@ void NotificationPanel::Add(Balloon* balloon) {
StartStaleTimer(balloon);
}
+bool NotificationPanel::Update(Balloon* balloon) {
+ if (balloon_container_->Update(balloon)) {
+ if (state_ == CLOSED || state_ == MINIMIZED)
+ state_ = STICKY_AND_NEW;
+ Show();
+ UpdatePanel(true);
+ StartStaleTimer(balloon);
+ return true;
+ } else {
+ return false;
+ }
+}
+
void NotificationPanel::Remove(Balloon* balloon) {
balloon_container_->Remove(balloon);
// no change to the state
@@ -425,7 +473,7 @@ void NotificationPanel::StartStaleTimer(Balloon* balloon) {
void NotificationPanel::OnStale(BalloonViewImpl* view) {
if (balloon_container_->HasBalloonView(view) && !view->stale()) {
view->set_stale();
- if (balloon_container_->HasStickyNotifications()) {
+ if (balloon_container_->GetStickyNotificationCount() > 0) {
state_ = STICKY_AND_NEW;
} else {
state_ = MINIMIZED;
diff --git a/chrome/browser/chromeos/notifications/notification_panel.h b/chrome/browser/chromeos/notifications/notification_panel.h
index cd9bf49..bbf8740 100644
--- a/chrome/browser/chromeos/notifications/notification_panel.h
+++ b/chrome/browser/chromeos/notifications/notification_panel.h
@@ -71,6 +71,7 @@ class NotificationPanel : public PanelController::Delegate,
// BalloonCollectionImpl::NotificationUI overrides..
virtual void Add(Balloon* balloon);
+ virtual bool Update(Balloon* balloon);
virtual void Remove(Balloon* balloon);
virtual void ResizeNotification(Balloon* balloon,
const gfx::Size& size);
@@ -81,6 +82,12 @@ class NotificationPanel : public PanelController::Delegate,
virtual void ClosePanel();
virtual void OnPanelStateChanged(PanelController::State state);
+ // Returns number of of sticky notifications.
+ int GetStickyNotificationCount() const;
+
+ // Returns number of new notifications.
+ int GetNewNotificationCount() const;
+
private:
enum State {
FULL, // Show all notifications
diff --git a/chrome/browser/chromeos/notifications/system_notification_factory.cc b/chrome/browser/chromeos/notifications/system_notification_factory.cc
new file mode 100644
index 0000000..1e32d84
--- /dev/null
+++ b/chrome/browser/chromeos/notifications/system_notification_factory.cc
@@ -0,0 +1,20 @@
+// 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/chromeos/notifications/system_notification_factory.h"
+
+#include "chrome/browser/notifications/desktop_notification_service.h"
+
+namespace chromeos {
+
+// static
+Notification SystemNotificationFactory::Create(
+ const GURL& icon, const string16& title,
+ const string16& text,
+ NotificationDelegate* delegate) {
+ string16 content_url = DesktopNotificationService::CreateDataUrl(
+ icon, title, text);
+ return Notification(GURL(), GURL(content_url), std::wstring(), delegate);
+}
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/notifications/system_notification_factory.h b/chrome/browser/chromeos/notifications/system_notification_factory.h
new file mode 100644
index 0000000..8dc8d93
--- /dev/null
+++ b/chrome/browser/chromeos/notifications/system_notification_factory.h
@@ -0,0 +1,29 @@
+// 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.
+
+#ifndef CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_SYSTEM_NOTIFICATION_H_
+#define CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_SYSTEM_NOTIFICATION_H_
+
+#include "base/basictypes.h"
+#include "chrome/browser/notifications/notification.h"
+
+class GURL;
+class NotificationDelegate;
+
+namespace chromeos {
+
+// A utility class for system notifications.
+class SystemNotificationFactory {
+ public:
+
+ // Creates a system notification.
+ static Notification Create(
+ const GURL& icon, const string16& title,
+ const string16& text,
+ NotificationDelegate* delegate);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_SYSTEM_NOTIFICATION_H_
diff --git a/chrome/browser/cocoa/notifications/balloon_controller_unittest.mm b/chrome/browser/cocoa/notifications/balloon_controller_unittest.mm
index d9f9c8f..7f48b1e 100644
--- a/chrome/browser/cocoa/notifications/balloon_controller_unittest.mm
+++ b/chrome/browser/cocoa/notifications/balloon_controller_unittest.mm
@@ -8,6 +8,7 @@
#include "chrome/browser/cocoa/notifications/balloon_controller.h"
#include "chrome/browser/notifications/balloon.h"
#include "chrome/browser/notifications/balloon_collection.h"
+#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/renderer_host/test/test_render_view_host.h"
#include "chrome/test/testing_profile.h"
#import "third_party/ocmock/OCMock/OCMock.h"
@@ -56,8 +57,7 @@ class BalloonControllerTest : public RenderViewHostTestHarness {
TEST_F(BalloonControllerTest, ShowAndCloseTest) {
Notification n(GURL("http://www.google.com"), GURL("http://www.google.com"),
- L"http://www.google.com", new NotificationObjectProxy(-1, -1, -1, false),
- false);
+ L"http://www.google.com", new NotificationObjectProxy(-1, -1, -1, false));
scoped_ptr<Balloon> balloon(
new Balloon(n, profile_.get(), collection_.get()));
@@ -75,8 +75,7 @@ TEST_F(BalloonControllerTest, ShowAndCloseTest) {
TEST_F(BalloonControllerTest, SizesTest) {
Notification n(GURL("http://www.google.com"), GURL("http://www.google.com"),
- L"http://www.google.com", new NotificationObjectProxy(-1, -1, -1, false),
- false);
+ L"http://www.google.com", new NotificationObjectProxy(-1, -1, -1, false));
scoped_ptr<Balloon> balloon(
new Balloon(n, profile_.get(), collection_.get()));
balloon->set_content_size(gfx::Size(100, 100));
diff --git a/chrome/browser/cocoa/notifications/balloon_view_bridge.h b/chrome/browser/cocoa/notifications/balloon_view_bridge.h
index b3c552b..5c4b927 100644
--- a/chrome/browser/cocoa/notifications/balloon_view_bridge.h
+++ b/chrome/browser/cocoa/notifications/balloon_view_bridge.h
@@ -19,6 +19,7 @@ class BalloonViewBridge : public BalloonView {
// BalloonView interface.
virtual void Show(Balloon* balloon);
+ virtual void Update() {}
virtual void RepositionToBalloon();
virtual void Close(bool by_user);
virtual gfx::Size GetSize() const;
diff --git a/chrome/browser/cocoa/notifications/balloon_view_host_mac.h b/chrome/browser/cocoa/notifications/balloon_view_host_mac.h
index aabbba8..235ab3c 100644
--- a/chrome/browser/cocoa/notifications/balloon_view_host_mac.h
+++ b/chrome/browser/cocoa/notifications/balloon_view_host_mac.h
@@ -7,6 +7,7 @@
#include "app/gfx/native_widget_types.h"
#include "chrome/browser/notifications/balloon.h"
+#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
#import "chrome/browser/renderer_host/render_widget_host_view_mac.h"
#include "chrome/browser/renderer_host/site_instance.h"
diff --git a/chrome/browser/gtk/notifications/balloon_view_gtk.h b/chrome/browser/gtk/notifications/balloon_view_gtk.h
index 9e2e871..69bd696 100644
--- a/chrome/browser/gtk/notifications/balloon_view_gtk.h
+++ b/chrome/browser/gtk/notifications/balloon_view_gtk.h
@@ -39,6 +39,7 @@ class BalloonViewImpl : public BalloonView,
// BalloonView interface.
virtual void Show(Balloon* balloon);
+ virtual void Update() {}
virtual void RepositionToBalloon();
virtual void Close(bool by_user);
virtual gfx::Size GetSize() const;
diff --git a/chrome/browser/gtk/notifications/balloon_view_host_gtk.h b/chrome/browser/gtk/notifications/balloon_view_host_gtk.h
index 4bcd5b4..43a0e7d 100644
--- a/chrome/browser/gtk/notifications/balloon_view_host_gtk.h
+++ b/chrome/browser/gtk/notifications/balloon_view_host_gtk.h
@@ -8,6 +8,7 @@
#include "app/gfx/native_widget_types.h"
#include "chrome/browser/gtk/extension_view_gtk.h"
#include "chrome/browser/notifications/balloon.h"
+#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
#include "chrome/browser/renderer_host/site_instance.h"
diff --git a/chrome/browser/notifications/balloon.cc b/chrome/browser/notifications/balloon.cc
index 040abec..4d9a94f 100644
--- a/chrome/browser/notifications/balloon.cc
+++ b/chrome/browser/notifications/balloon.cc
@@ -6,13 +6,14 @@
#include "base/logging.h"
#include "chrome/browser/notifications/balloon_collection.h"
+#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/renderer_host/site_instance.h"
#include "gfx/rect.h"
Balloon::Balloon(const Notification& notification, Profile* profile,
BalloonCollection* collection)
: profile_(profile),
- notification_(notification),
+ notification_(new Notification(notification)),
collection_(collection) {
}
@@ -34,14 +35,22 @@ void Balloon::set_view(BalloonView* balloon_view) {
}
void Balloon::Show() {
- notification_.Display();
+ notification_->Display();
if (balloon_view_.get()) {
balloon_view_->Show(this);
}
}
+void Balloon::Update(const Notification& notification) {
+ notification_.reset(new Notification(notification));
+ notification_->Display();
+ if (balloon_view_.get()) {
+ balloon_view_->Update();
+ }
+}
+
void Balloon::OnClose(bool by_user) {
- notification_.Close(by_user);
+ notification_->Close(by_user);
collection_->OnBalloonClosed(this);
}
diff --git a/chrome/browser/notifications/balloon.h b/chrome/browser/notifications/balloon.h
index 0136a9c..ddaa14d 100644
--- a/chrome/browser/notifications/balloon.h
+++ b/chrome/browser/notifications/balloon.h
@@ -11,13 +11,13 @@
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
-#include "chrome/browser/notifications/notification.h"
#include "gfx/point.h"
#include "gfx/rect.h"
#include "gfx/size.h"
class Balloon;
class BalloonCollection;
+class Notification;
class Profile;
class SiteInstance;
@@ -29,6 +29,9 @@ class BalloonView {
// Show the view on the screen.
virtual void Show(Balloon* balloon) = 0;
+ // Notify that the content of notification has chagned.
+ virtual void Update() = 0;
+
// Reposition the view to match the position of its balloon.
virtual void RepositionToBalloon() = 0;
@@ -47,7 +50,7 @@ class Balloon {
BalloonCollection* collection);
virtual ~Balloon();
- const Notification& notification() const { return notification_; }
+ const Notification& notification() const { return *notification_.get(); }
Profile* profile() const { return profile_; }
const gfx::Point& position() const { return position_; }
@@ -76,6 +79,9 @@ class Balloon {
// Shows the balloon.
virtual void Show();
+ // Notify that the content of notification has changed.
+ virtual void Update(const Notification& notification);
+
// Called when the balloon is closed, either by user (through the UI)
// or by a script.
virtual void OnClose(bool by_user);
@@ -88,7 +94,7 @@ class Balloon {
Profile* profile_;
// The notification being shown in this balloon.
- Notification notification_;
+ scoped_ptr<Notification> notification_;
// The collection that this balloon belongs to. Non-owned pointer.
BalloonCollection* collection_;
diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc
index 55613f5..d351880 100644
--- a/chrome/browser/notifications/desktop_notification_service.cc
+++ b/chrome/browser/notifications/desktop_notification_service.cc
@@ -36,14 +36,9 @@
using WebKit::WebNotificationPresenter;
-namespace {
-
-// 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 DesktopNotificationService::CreateDataUrl(
+ const GURL& icon_url, const string16& title, const string16& body) {
int resource;
string16 line_name;
string16 line;
@@ -81,8 +76,6 @@ static string16 CreateDataUrl(const GURL& icon_url, const string16& title,
return ReplaceStringPlaceholders(format_string, subst, NULL);
}
-}
-
// A task object which calls the renderer to inform the web page that the
// permission request has completed.
class NotificationPermissionCallbackTask : public Task {
@@ -334,21 +327,20 @@ bool DesktopNotificationService::CancelDesktopNotification(
scoped_refptr<NotificationObjectProxy> proxy(
new NotificationObjectProxy(process_id, route_id, notification_id,
false));
- Notification notif(GURL(), GURL(), L"", proxy, false);
+ Notification notif(GURL(), GURL(), L"", 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,
- bool sticky) {
+ DesktopNotificationSource source, int notification_id) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
NotificationObjectProxy* proxy =
new NotificationObjectProxy(process_id, route_id,
notification_id,
source == WorkerNotification);
- Notification notif(origin, url, DisplayNameForOrigin(origin), proxy, sticky);
+ Notification notif(origin, url, DisplayNameForOrigin(origin), proxy);
ShowNotification(notif);
return true;
}
@@ -356,8 +348,7 @@ bool DesktopNotificationService::ShowDesktopNotification(
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,
- bool sticky) {
+ DesktopNotificationSource source, int notification_id) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
NotificationObjectProxy* proxy =
new NotificationObjectProxy(process_id, route_id,
@@ -366,7 +357,7 @@ bool DesktopNotificationService::ShowDesktopNotificationText(
// "upconvert" the string parameters to a data: URL.
string16 data_url = CreateDataUrl(icon, title, text);
Notification notif(
- origin, GURL(data_url), DisplayNameForOrigin(origin), proxy, sticky);
+ origin, GURL(data_url), DisplayNameForOrigin(origin), proxy);
ShowNotification(notif);
return true;
}
diff --git a/chrome/browser/notifications/desktop_notification_service.h b/chrome/browser/notifications/desktop_notification_service.h
index b1050c9..6e9a6d8 100644
--- a/chrome/browser/notifications/desktop_notification_service.h
+++ b/chrome/browser/notifications/desktop_notification_service.h
@@ -49,16 +49,14 @@ class DesktopNotificationService : public NotificationObserver {
// 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. |sticky| is used to indicate that the notification
- // is sticky and cannot be dismissed by a user.
+ // this notification.
bool ShowDesktopNotification(const GURL& origin, const GURL& url,
int process_id, int route_id, DesktopNotificationSource source,
- int notification_id,
- bool sticky);
+ 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,
- bool sticky);
+ int route_id, DesktopNotificationSource source, int notification_id);
+
// 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
@@ -78,6 +76,11 @@ class DesktopNotificationService : public NotificationObserver {
const NotificationSource& source,
const NotificationDetails& details);
+ // 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);
private:
void InitPrefs();
diff --git a/chrome/browser/notifications/desktop_notifications_unittest.cc b/chrome/browser/notifications/desktop_notifications_unittest.cc
index ecc8f73..b15a46e 100644
--- a/chrome/browser/notifications/desktop_notifications_unittest.cc
+++ b/chrome/browser/notifications/desktop_notifications_unittest.cc
@@ -21,8 +21,7 @@ void MockBalloonCollection::Add(const Notification& notification,
Notification test_notification(notification.origin_url(),
notification.content_url(),
notification.display_source(),
- log_proxy_.get(),
- notification.sticky());
+ log_proxy_.get());
BalloonCollectionImpl::Add(test_notification, profile);
}
@@ -30,8 +29,7 @@ bool MockBalloonCollection::Remove(const Notification& notification) {
Notification test_notification(notification.origin_url(),
notification.content_url(),
notification.display_source(),
- log_proxy_.get(),
- notification.sticky());
+ log_proxy_.get());
return BalloonCollectionImpl::Remove(test_notification);
}
@@ -87,25 +85,20 @@ 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, false));
+ 0, 0, DesktopNotificationService::PageNotification, 1));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
EXPECT_TRUE(service_->ShowDesktopNotification(
GURL("http://www.google.com"),
GURL("http://www.google.com/notification.html"),
- 0, 0, DesktopNotificationService::PageNotification, 2, false));
+ 0, 0, DesktopNotificationService::PageNotification, 2));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(2, balloon_collection_->count());
EXPECT_EQ("notification displayed\n"
"notification displayed\n",
log_output_);
-
- std::set<Balloon*>::iterator iter = balloon_collection_->balloons().begin();
- EXPECT_FALSE((*iter)->notification().sticky());
- iter++;
- EXPECT_FALSE((*iter)->notification().sticky());
}
TEST_F(DesktopNotificationsTest, TestClose) {
@@ -113,7 +106,7 @@ TEST_F(DesktopNotificationsTest, TestClose) {
EXPECT_TRUE(service_->ShowDesktopNotificationText(
GURL("http://www.google.com"),
GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, 1, false));
+ 0, 0, DesktopNotificationService::PageNotification, 1));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
@@ -141,7 +134,7 @@ TEST_F(DesktopNotificationsTest, TestCancel) {
GURL("http://www.google.com"),
GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
process_id, route_id, DesktopNotificationService::PageNotification,
- notification_id, false));
+ notification_id));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
@@ -168,7 +161,7 @@ TEST_F(DesktopNotificationsTest, TestPositioning) {
EXPECT_TRUE(service_->ShowDesktopNotificationText(
GURL("http://www.google.com"),
GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, id, false));
+ 0, 0, DesktopNotificationService::PageNotification, id));
expected_log.append("notification displayed\n");
int top = balloon_collection_->UppermostVerticalPosition();
if (id > 0)
@@ -189,12 +182,12 @@ TEST_F(DesktopNotificationsTest, TestVariableSize) {
"Really Really Really Really Really Really "
"Really Really Really Really Really Really Really Long Title"),
ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, 0, false));
+ 0, 0, DesktopNotificationService::PageNotification, 0));
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, false));
+ 0, 0, DesktopNotificationService::PageNotification, 1));
expected_log.append("notification displayed\n");
std::set<Balloon*>& balloons = balloon_collection_->balloons();
@@ -225,7 +218,7 @@ TEST_F(DesktopNotificationsTest, TestQueueing) {
GURL("http://www.google.com"),
GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
process_id, route_id,
- DesktopNotificationService::PageNotification, id, false));
+ DesktopNotificationService::PageNotification, id));
}
MessageLoopForUI::current()->RunAllPending();
@@ -275,7 +268,7 @@ TEST_F(DesktopNotificationsTest, TestEarlyDestruction) {
EXPECT_TRUE(service_->ShowDesktopNotificationText(
GURL("http://www.google.com"),
GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, id, false));
+ 0, 0, DesktopNotificationService::PageNotification, id));
}
service_.reset(NULL);
}
@@ -288,7 +281,7 @@ TEST_F(DesktopNotificationsTest, TestUserInputEscaping) {
GURL("/icon.png"),
ASCIIToUTF16("<script>window.alert('uh oh');</script>"),
ASCIIToUTF16("<i>this text is in italics</i>"),
- 0, 0, DesktopNotificationService::PageNotification, 1, false));
+ 0, 0, DesktopNotificationService::PageNotification, 1));
MessageLoopForUI::current()->RunAllPending();
EXPECT_EQ(1, balloon_collection_->count());
@@ -297,21 +290,3 @@ TEST_F(DesktopNotificationsTest, TestUserInputEscaping) {
EXPECT_EQ(std::string::npos, data_url.spec().find("<script>"));
EXPECT_EQ(std::string::npos, data_url.spec().find("<i>"));
}
-
-TEST_F(DesktopNotificationsTest, TestSticky) {
- EXPECT_TRUE(service_->ShowDesktopNotificationText(
- GURL("http://www.google.com"),
- GURL("/icon.png"), ASCIIToUTF16("Title"), ASCIIToUTF16("Text"),
- 0, 0, DesktopNotificationService::PageNotification, 1, true));
- MessageLoopForUI::current()->RunAllPending();
- EXPECT_TRUE(service_->ShowDesktopNotification(
- GURL("http://www.google.com"),
- GURL("http://www.google.com/notification.html"),
- 0, 0, DesktopNotificationService::PageNotification, 2, true));
- MessageLoopForUI::current()->RunAllPending();
-
- std::set<Balloon*>::iterator iter = balloon_collection_->balloons().begin();
- EXPECT_TRUE((*iter)->notification().sticky());
- iter++;
- EXPECT_TRUE((*iter)->notification().sticky());
-}
diff --git a/chrome/browser/notifications/notification.h b/chrome/browser/notifications/notification.h
index f80a65f..a58c2ad 100644
--- a/chrome/browser/notifications/notification.h
+++ b/chrome/browser/notifications/notification.h
@@ -1,16 +1,16 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_H_
#define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_H_
-#include <string>
-
#include "base/basictypes.h"
#include "chrome/browser/notifications/notification_object_proxy.h"
#include "googleurl/src/gurl.h"
+class NotificationDelegate;
+
// Representation of an notification to be shown to the user. All
// notifications at this level are HTML, although they may be
// data: URLs representing simple text+icon notifications.
@@ -18,21 +18,18 @@ class Notification {
public:
Notification(const GURL& origin_url, const GURL& content_url,
const std::wstring& display_source,
- NotificationObjectProxy* proxy,
- bool sticky)
+ NotificationDelegate* delegate)
: origin_url_(origin_url),
content_url_(content_url),
display_source_(display_source),
- proxy_(proxy),
- sticky_(sticky) {
+ delegate_(delegate) {
}
Notification(const Notification& notification)
: origin_url_(notification.origin_url()),
content_url_(notification.content_url()),
display_source_(notification.display_source()),
- proxy_(notification.proxy()),
- sticky_(notification.sticky()) {
+ delegate_(notification.delegate()) {
}
// The URL (may be data:) containing the contents for the notification.
@@ -44,20 +41,16 @@ class Notification {
// A display string for the source of the notification.
const std::wstring& display_source() const { return display_source_; }
- void Display() const { proxy()->Display(); }
- void Error() const { proxy()->Error(); }
- void Close(bool by_user) const { proxy()->Close(by_user); }
-
- bool sticky() const {
- return sticky_;
- }
+ void Display() const { delegate()->Display(); }
+ void Error() const { delegate()->Error(); }
+ void Close(bool by_user) const { delegate()->Close(by_user); }
bool IsSame(const Notification& other) const {
- return (*proxy_).IsSame(*(other.proxy()));
+ return delegate()->id() == other.delegate()->id();
}
private:
- NotificationObjectProxy* proxy() const { return proxy_.get(); }
+ NotificationDelegate* delegate() const { return delegate_.get(); }
// The Origin of the page/worker which created this notification.
GURL origin_url_;
@@ -72,11 +65,7 @@ class Notification {
// A proxy object that allows access back to the JavaScript object that
// represents the notification, for firing events.
- scoped_refptr<NotificationObjectProxy> proxy_;
-
- // A sticky flag. A sticky notification cannot be dismissed by a
- // user.
- bool sticky_;
+ scoped_refptr<NotificationDelegate> delegate_;
// Disallow assign. Copy constructor written above.
void operator=(const Notification&);
diff --git a/chrome/browser/notifications/notification_delegate.h b/chrome/browser/notifications/notification_delegate.h
new file mode 100644
index 0000000..6d69335
--- /dev/null
+++ b/chrome/browser/notifications/notification_delegate.h
@@ -0,0 +1,34 @@
+// 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.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_DELEGATE_H_
+#define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_DELEGATE_H_
+
+#include <string>
+
+#include "base/ref_counted.h"
+
+// Delegate for a notification. This class has two role, to implement
+// callback methods for notification, and provides an identify of
+// the associated notification.
+class NotificationDelegate
+ : public base::RefCountedThreadSafe<NotificationDelegate> {
+ public:
+
+ // To be called when the desktop notification is actually shown.
+ virtual void Display() = 0;
+
+ // To be called when the desktop notification cannot be shown due to an
+ // error.
+ virtual void Error() = 0;
+
+ // To be called when the desktop notification is closed. If closed by a
+ // user explicitly (as opposed to timeout/script), |by_user| should be true.
+ virtual void Close(bool by_user) = 0;
+
+ // Returns unique id of the notification.
+ virtual std::string id() const = 0;
+};
+
+#endif // CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_DELEGATE_H_
diff --git a/chrome/browser/notifications/notification_object_proxy.cc b/chrome/browser/notifications/notification_object_proxy.cc
index 3b45ddf..76363e5 100644
--- a/chrome/browser/notifications/notification_object_proxy.cc
+++ b/chrome/browser/notifications/notification_object_proxy.cc
@@ -49,6 +49,12 @@ void NotificationObjectProxy::Close(bool by_user) {
}
}
+std::string NotificationObjectProxy::id() const {
+ return StringPrintf("%d:%d:%d:%d", process_id_, route_id_,
+ notification_id_, worker_);
+}
+
+
void NotificationObjectProxy::DeliverMessage(IPC::Message* message) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
ChromeThread::PostTask(
diff --git a/chrome/browser/notifications/notification_object_proxy.h b/chrome/browser/notifications/notification_object_proxy.h
index 46c56f5..a956b3a 100644
--- a/chrome/browser/notifications/notification_object_proxy.h
+++ b/chrome/browser/notifications/notification_object_proxy.h
@@ -5,7 +5,9 @@
#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_OBJECT_PROXY_H_
#define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_OBJECT_PROXY_H_
-#include "base/ref_counted.h"
+#include <string>
+
+#include "chrome/browser/notifications/notification_delegate.h"
class MessageLoop;
namespace IPC {
@@ -17,30 +19,17 @@ class Message;
// when various events occur regarding the desktop notification, and the
// attached JS listeners will be invoked in the renderer or worker process.
class NotificationObjectProxy
- : public base::RefCountedThreadSafe<NotificationObjectProxy> {
+ : public NotificationDelegate {
public:
// Creates a Proxy object with the necessary callback information.
NotificationObjectProxy(int process_id, int route_id,
int notification_id, bool worker);
- // To be called when the desktop notification is actually shown.
+ // NotificationDelegate implementation.
virtual void Display();
-
- // To be called when the desktop notification cannot be shown due to an
- // error.
virtual void Error();
-
- // To be called when the desktop notification is closed. If closed by a
- // user explicitly (as opposed to timeout/script), |by_user| should be true.
virtual void Close(bool by_user);
-
- // Compares two proxies by ids to decide if they are equal.
- bool IsSame(const NotificationObjectProxy& other) const {
- return (notification_id_ == other.notification_id_ &&
- route_id_ == other.route_id_ &&
- process_id_ == other.process_id_ &&
- worker_ == other.worker_);
- }
+ virtual std::string id() const;
protected:
friend class base::RefCountedThreadSafe<NotificationObjectProxy>;
diff --git a/chrome/browser/notifications/notification_test_util.h b/chrome/browser/notifications/notification_test_util.h
index b4530f5..95e8fd1 100644
--- a/chrome/browser/notifications/notification_test_util.h
+++ b/chrome/browser/notifications/notification_test_util.h
@@ -40,6 +40,7 @@ class MockBalloonView : public BalloonView {
explicit MockBalloonView(Balloon * balloon) :
balloon_(balloon) {}
void Show(Balloon* balloon) {}
+ void Update() {}
void RepositionToBalloon() {}
void Close(bool by_user) { balloon_->OnClose(by_user); }
gfx::Size GetSize() const { return balloon_->content_size(); }
diff --git a/chrome/browser/notifications/notification_ui_manager.h b/chrome/browser/notifications/notification_ui_manager.h
index 9e2cf18..2eaedd3 100644
--- a/chrome/browser/notifications/notification_ui_manager.h
+++ b/chrome/browser/notifications/notification_ui_manager.h
@@ -45,6 +45,11 @@ class NotificationUIManager
// Removes a notification.
virtual bool Cancel(const Notification& notification);
+ // Returns balloon collection.
+ BalloonCollection* balloon_collection() {
+ return balloon_collection_.get();
+ }
+
private:
// Attempts to display notifications from the show_queue if the user
// is active.
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 7307a82..6d62fb2 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1731,7 +1731,7 @@ void RenderViewHost::OnShowDesktopNotification(const GURL& source_origin,
process()->profile()->GetDesktopNotificationService();
service->ShowDesktopNotification(source_origin, url, process()->id(),
routing_id(), DesktopNotificationService::PageNotification,
- notification_id, false);
+ notification_id);
}
void RenderViewHost::OnShowDesktopNotificationText(const GURL& source_origin,
@@ -1741,7 +1741,7 @@ void RenderViewHost::OnShowDesktopNotificationText(const GURL& source_origin,
process()->profile()->GetDesktopNotificationService();
service->ShowDesktopNotificationText(source_origin, icon, title, text,
process()->id(), routing_id(),
- DesktopNotificationService::PageNotification, notification_id, false);
+ DesktopNotificationService::PageNotification, notification_id);
}
void RenderViewHost::OnCancelDesktopNotification(int notification_id) {
diff --git a/chrome/browser/views/notifications/balloon_view.h b/chrome/browser/views/notifications/balloon_view.h
index 1e03be1..e6853e0 100644
--- a/chrome/browser/views/notifications/balloon_view.h
+++ b/chrome/browser/views/notifications/balloon_view.h
@@ -53,10 +53,11 @@ class BalloonViewImpl : public BalloonView,
~BalloonViewImpl();
// BalloonView interface.
- void Show(Balloon* balloon);
- void RepositionToBalloon();
- void Close(bool by_user);
- gfx::Size GetSize() const;
+ virtual void Show(Balloon* balloon);
+ virtual void Update() {}
+ virtual void RepositionToBalloon();
+ virtual void Close(bool by_user);
+ virtual gfx::Size GetSize() const;
private:
// views::View interface.
diff --git a/chrome/browser/views/notifications/balloon_view_host.h b/chrome/browser/views/notifications/balloon_view_host.h
index 75f3ef7..84610a0 100644
--- a/chrome/browser/views/notifications/balloon_view_host.h
+++ b/chrome/browser/views/notifications/balloon_view_host.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_VIEWS_NOTIFICATIONS_BALLOON_VIEW_HOST_H_
#include "chrome/browser/notifications/balloon.h"
+#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
#include "chrome/browser/renderer_host/site_instance.h"
#include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index be04397..f3058c9 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -306,6 +306,8 @@
'browser/chromeos/notifications/balloon_view.cc',
'browser/chromeos/notifications/notification_panel.h',
'browser/chromeos/notifications/notification_panel.cc',
+ 'browser/chromeos/notifications/system_notification_factory.h',
+ 'browser/chromeos/notifications/system_notification_factory.cc',
'browser/chromeos/browser_notification_observers.cc',
'browser/chromeos/compact_location_bar_host.cc',
'browser/chromeos/compact_location_bar_host.h',
@@ -1545,6 +1547,7 @@
'browser/notifications/desktop_notification_service.cc',
'browser/notifications/desktop_notification_service.h',
'browser/notifications/notification.h',
+ 'browser/notifications/notification_delegate.h',
'browser/notifications/notification_object_proxy.cc',
'browser/notifications/notification_object_proxy.h',
'browser/notifications/notification_ui_manager.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index bd19489..c809459 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1189,6 +1189,7 @@
'browser/browser_browsertest.cc',
'browser/browser_init_browsertest.cc',
'browser/browsing_data_local_storage_helper_unittest.cc',
+ 'browser/chromeos/notifications/notification_browsertest.cc',
'browser/crash_recovery_browsertest.cc',
'browser/download/save_page_browsertest.cc',
'browser/extensions/autoupdate_interceptor.cc',
@@ -1245,6 +1246,11 @@
'test/render_view_test.h',
],
'conditions': [
+ ['chromeos==0', {
+ 'sources/': [
+ ['exclude', '^browser/chromeos'],
+ ],
+ }],
['OS=="win"', {
'sources': [
'app/chrome_dll.rc',