Commit 5dd19912 authored by stevenjb@chromium.org's avatar stevenjb@chromium.org

Fix Ash notification updates

In Chrome, it turns out that every Notification has a unique id. In the Ash implementation we need to track and update that id when an existing Bubble is updated.

This also ensures that the UI is safely created initially (in case the initial asynchronous Update is delayed) to prevent crashes and to make Layout more consistent.

Also includes some cleanup of the WebNotificationTray API.

BUG=141285


Review URL: https://chromiumcodereview.appspot.com/10855079

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150979 0039d316-1c4b-4281-b951-d872f2087c98
parent 97dc9396
......@@ -27,7 +27,10 @@ namespace ash {
namespace internal {
class StatusAreaWidget;
class WebNotificationButtonView;
class WebNotificationList;
class WebNotificationMenuModel;
class WebNotificationView;
}
// Status area tray for showing browser and app notifications. The client
......@@ -85,34 +88,25 @@ class ASH_EXPORT WebNotificationTray : public internal::TrayBackgroundView {
const string16& display_source,
const std::string& extension_id);
// Update an existing notification.
void UpdateNotification(const std::string& id,
// Update an existing notification with id = old_id and set its id to new_id.
void UpdateNotification(const std::string& old_id,
const std::string& new_id,
const string16& title,
const string16& message);
// Remove an existing notification and notify the delegate.
// Remove an existing notification.
void RemoveNotification(const std::string& id);
// Remove all notifications and notify the delegate.
void RemoveAllNotifications();
// Set the notification image.
void SetNotificationImage(const std::string& id,
const gfx::ImageSkia& image);
// Disable all notifications matching notification |id|.
void DisableByExtension(const std::string& id);
void DisableByUrl(const std::string& id);
// Show the message center bubble. Should only be called by StatusAreaWidget.
void ShowMessageCenterBubble();
// Hide the message center bubble. Should only be called by StatusAreaWidget.
void HideMessageCenterBubble();
// Hide the message center bubble if there are no notifications.
void HideMessageCenterBubbleIfEmpty();
// Show a single notification bubble for the most recent notification.
void ShowNotificationBubble();
......@@ -122,26 +116,42 @@ class ASH_EXPORT WebNotificationTray : public internal::TrayBackgroundView {
// Updates tray visibility login status of the system changes.
void UpdateAfterLoginStatusChange(user::LoginStatus login_status);
// Request the Delegate to the settings dialog.
void ShowSettings(const std::string& id);
// Called when a notification is clicked on. Event is passed to the Delegate.
void OnClicked(const std::string& id);
// Overridden from TrayBackgroundView.
virtual void SetShelfAlignment(ShelfAlignment alignment) OVERRIDE;
// Overridden from internal::ActionableView.
virtual bool PerformAction(const views::Event& event) OVERRIDE;
protected:
// Send a remove request to the delegate.
void SendRemoveNotification(const std::string& id);
// Send a remove request for all notifications to the delegate.
void SendRemoveAllNotifications();
// Disable all notifications matching notification |id|.
void DisableByExtension(const std::string& id);
void DisableByUrl(const std::string& id);
// Request the Delegate to the settings dialog.
void ShowSettings(const std::string& id);
// Called when a notification is clicked on. Event is passed to the Delegate.
void OnClicked(const std::string& id);
private:
class Bubble;
friend class internal::WebNotificationButtonView;
friend class internal::WebNotificationMenuModel;
friend class internal::WebNotificationView;
FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, WebNotifications);
FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, WebNotificationBubble);
int GetNotificationCount() const;
void UpdateTray();
void UpdateTrayAndBubble();
void HideBubble(Bubble* bubble);
bool HasNotificationForTest(const std::string& id) const;
const internal::WebNotificationList* notification_list() const {
return notification_list_.get();
......
......@@ -55,8 +55,19 @@ class TestDelegate : public WebNotificationTray::Delegate {
"" /* extension id */);
}
void UpdateNotification(WebNotificationTray* tray,
const std::string& old_id,
const std::string& new_id) {
notification_ids_.erase(old_id);
notification_ids_.insert(new_id);
tray->UpdateNotification(old_id, new_id,
ASCIIToUTF16("Updated Web Notification"),
ASCIIToUTF16("Updated message body."));
}
void RemoveNotification(WebNotificationTray* tray, const std::string& id) {
tray->RemoveNotification(id);
notification_ids_.erase(id);
}
bool HasNotificationId(const std::string& id) {
......@@ -80,23 +91,57 @@ TEST_F(WebNotificationTrayTest, WebNotifications) {
ASSERT_TRUE(tray->GetWidget());
// Adding a notification should show the bubble.
// Add a notification.
delegate->AddNotification(tray, "test_id1");
EXPECT_TRUE(tray->notification_bubble() != NULL);
EXPECT_EQ(1, tray->GetNotificationCount());
EXPECT_TRUE(tray->HasNotificationForTest("test_id1"));
delegate->AddNotification(tray, "test_id2");
delegate->AddNotification(tray, "test_id2");
EXPECT_EQ(2, tray->GetNotificationCount());
// Ensure that removing a notification removes it from the tray, and signals
// the delegate.
EXPECT_TRUE(delegate->HasNotificationId("test_id2"));
delegate->RemoveNotification(tray, "test_id2");
EXPECT_TRUE(tray->HasNotificationForTest("test_id2"));
// Ensure that updating a notification does not affect the count.
delegate->UpdateNotification(tray, "test_id2", "test_id3");
delegate->UpdateNotification(tray, "test_id3", "test_id3");
EXPECT_EQ(2, tray->GetNotificationCount());
EXPECT_FALSE(delegate->HasNotificationId("test_id2"));
EXPECT_EQ(1, tray->GetNotificationCount());
EXPECT_FALSE(tray->HasNotificationForTest("test_id2"));
EXPECT_TRUE(delegate->HasNotificationId("test_id3"));
// Removing the last notification should hide the bubble.
// Ensure that Removing the first notification removes it from the tray.
delegate->RemoveNotification(tray, "test_id1");
EXPECT_FALSE(delegate->HasNotificationId("test_id1"));
EXPECT_FALSE(tray->HasNotificationForTest("test_id1"));
EXPECT_EQ(1, tray->GetNotificationCount());
// Remove the remianing notification.
delegate->RemoveNotification(tray, "test_id3");
EXPECT_EQ(0, tray->GetNotificationCount());
EXPECT_FALSE(tray->HasNotificationForTest("test_id3"));
}
TEST_F(WebNotificationTrayTest, WebNotificationBubble) {
WebNotificationTray* tray = GetWebNotificationTray();
scoped_ptr<TestDelegate> delegate(new TestDelegate);
tray->SetDelegate(delegate.get());
ASSERT_TRUE(tray->GetWidget());
// Adding a notification should show the bubble.
delegate->AddNotification(tray, "test_id1");
EXPECT_TRUE(tray->notification_bubble() != NULL);
// Updating a notification should not hide the bubble.
delegate->AddNotification(tray, "test_id2");
delegate->UpdateNotification(tray, "test_id2", "test_id3");
EXPECT_TRUE(tray->notification_bubble() != NULL);
// Removing the first notification should not hide the bubble.
delegate->RemoveNotification(tray, "test_id1");
EXPECT_TRUE(tray->notification_bubble() != NULL);
// Removing the visible notification should hide the bubble.
delegate->RemoveNotification(tray, "test_id3");
EXPECT_TRUE(tray->notification_bubble() == NULL);
}
......
......@@ -93,8 +93,9 @@ BalloonViewAsh::~BalloonViewAsh() {
void BalloonViewAsh::Show(Balloon* balloon) {
balloon_ = balloon;
const Notification& notification = balloon_->notification();
current_notification_id_ = notification.notification_id();
std::string extension_id = GetExtensionId(balloon);
GetWebNotificationTray()->AddNotification(notification.notification_id(),
GetWebNotificationTray()->AddNotification(current_notification_id_,
notification.title(),
notification.body(),
notification.display_source(),
......@@ -104,9 +105,12 @@ void BalloonViewAsh::Show(Balloon* balloon) {
void BalloonViewAsh::Update() {
const Notification& notification = balloon_->notification();
GetWebNotificationTray()->UpdateNotification(notification.notification_id(),
std::string new_notification_id = notification.notification_id();
GetWebNotificationTray()->UpdateNotification(current_notification_id_,
new_notification_id,
notification.title(),
notification.body());
current_notification_id_ = new_notification_id;
FetchIcon(notification);
}
......
......@@ -30,6 +30,8 @@ class BalloonViewAsh : public BalloonView {
BalloonCollection* collection_;
Balloon* balloon_;
scoped_ptr<IconFetcher> icon_fetcher_;
// Track the current notification id so that it can be updated properly.
std::string current_notification_id_;
DISALLOW_COPY_AND_ASSIGN(BalloonViewAsh);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment