summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpetewil@chromium.org <petewil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-29 20:58:55 +0000
committerpetewil@chromium.org <petewil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-29 20:58:55 +0000
commit3e419d6725611bb0309ba5ef5792fe81d71b7c1b (patch)
treea2264253b8a5d8396e93af5779cf5b9aaa2e931d
parent50761e91bb7255a901c66d1336612ce40a75728b (diff)
downloadchromium_src-3e419d6725611bb0309ba5ef5792fe81d71b7c1b.zip
chromium_src-3e419d6725611bb0309ba5ef5792fe81d71b7c1b.tar.gz
chromium_src-3e419d6725611bb0309ba5ef5792fe81d71b7c1b.tar.bz2
Widen the data pipes between Synced Notifications and Rich Notifications
Update to the latest protobufs, rearranging them for maintainability. Id has been changed to Key everywhere. DefaultDestination fields added. Message_type now used. First external id removed. Functions added for buttons button count and notification count Button action fields added. Added new accessors for time priority, and button data, and associated tests We now use Dismissed instead of Read for setting a notification state. Adapt to the newer protobufs from the server side for synced notifications BUG=222077 Review URL: https://chromiumcodereview.appspot.com/12717010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191443 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/notifications/notification.h2
-rw-r--r--chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc3
-rw-r--r--chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc148
-rw-r--r--chrome/browser/notifications/sync_notifier/chrome_notifier_service.h2
-rw-r--r--chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc463
-rw-r--r--chrome/browser/notifications/sync_notifier/synced_notification.cc288
-rw-r--r--chrome/browser/notifications/sync_notifier/synced_notification.h55
-rw-r--r--chrome/browser/notifications/sync_notifier/synced_notification_unittest.cc282
-rw-r--r--sync/protocol/synced_notification_data.proto30
-rw-r--r--sync/protocol/synced_notification_render.proto143
10 files changed, 1099 insertions, 317 deletions
diff --git a/chrome/browser/notifications/notification.h b/chrome/browser/notifications/notification.h
index 0811f58..b3c5824 100644
--- a/chrome/browser/notifications/notification.h
+++ b/chrome/browser/notifications/notification.h
@@ -41,7 +41,7 @@ class Notification {
const string16& replace_id,
NotificationDelegate* delegate);
- // Initializes a notification with a given type. Takes ownership of
+ // Initializes a notification with a given type. Makes a deep copy of
// optional_fields.
Notification(message_center::NotificationType type,
const GURL& origin_url,
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc
index 1348d17..f61714e 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc
@@ -22,7 +22,8 @@ content::RenderViewHost* ChromeNotifierDelegate::GetRenderViewHost() const {
}
void ChromeNotifierDelegate::Close(bool by_user) {
- chrome_notifier_->MarkNotificationAsDismissed(id_);
+ if (by_user)
+ chrome_notifier_->MarkNotificationAsDismissed(id_);
}
} // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
index c58e0e6..1abe03a 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
@@ -21,6 +21,7 @@
#include "sync/protocol/sync.pb.h"
#include "sync/protocol/synced_notification_specifics.pb.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h"
+#include "ui/message_center/notification_types.h"
namespace notifier {
@@ -61,9 +62,9 @@ syncer::SyncMergeResult ChromeNotifierService::MergeDataAndStartSyncing(
DCHECK(incoming.get());
// Process each incoming remote notification.
- const std::string& id = incoming->notification_id();
- DCHECK_GT(id.length(), 0U);
- SyncedNotification* found = FindNotificationById(id);
+ const std::string& key = incoming->GetKey();
+ DCHECK_GT(key.length(), 0U);
+ SyncedNotification* found = FindNotificationByKey(key);
if (NULL == found) {
// If there are no conflicts, copy in the data from remote.
@@ -73,12 +74,12 @@ syncer::SyncMergeResult ChromeNotifierService::MergeDataAndStartSyncing(
// in all fields, we don't need to do anything here.
if (incoming->EqualsIgnoringReadState(*found)) {
- if (incoming->read_state() == found->read_state()) {
+ if (incoming->GetReadState() == found->GetReadState()) {
// Notification matches on the client and the server, nothing to do.
continue;
} else {
// If the read state is different, read wins for both places.
- if (incoming->read_state() == SyncedNotification::kDismissed) {
+ if (incoming->GetReadState() == SyncedNotification::kDismissed) {
// If it is marked as read on the server, but not the client.
found->NotificationHasBeenDismissed();
// TODO(petewil): Tell the Notification UI Manager to mark it read.
@@ -175,7 +176,7 @@ syncer::SyncData ChromeNotifierService::CreateSyncDataFromNotification(
const SyncedNotification& notification) {
// Construct the sync_data using the specifics from the notification.
return syncer::SyncData::CreateLocalData(
- notification.notification_id(), notification.notification_id(),
+ notification.GetKey(), notification.GetKey(),
notification.GetEntitySpecifics());
}
@@ -190,9 +191,8 @@ scoped_ptr<SyncedNotification>
// Check for mandatory fields in the sync_data object.
if (!specifics.has_coalesced_notification() ||
!specifics.coalesced_notification().has_key() ||
- !specifics.coalesced_notification().has_read_state()) {
+ !specifics.coalesced_notification().has_read_state())
return scoped_ptr<SyncedNotification>();
- }
// TODO(petewil): Is this the right set? Should I add more?
bool is_well_formed_unread_notification =
@@ -219,9 +219,8 @@ scoped_ptr<SyncedNotification>
// This returns a pointer into a vector that we own. Caller must not free it.
// Returns NULL if no match is found.
-// This uses the <app_id/coalescing_key> pair as a key.
-SyncedNotification* ChromeNotifierService::FindNotificationById(
- const std::string& id) {
+SyncedNotification* ChromeNotifierService::FindNotificationByKey(
+ const std::string& key) {
// TODO(petewil): We can make a performance trade off here.
// While the vector has good locality of reference, a map has faster lookup.
// Based on how big we expect this to get, maybe change this to a map.
@@ -230,15 +229,16 @@ SyncedNotification* ChromeNotifierService::FindNotificationById(
it != notification_data_.end();
++it) {
SyncedNotification* notification = *it;
- if (id == notification->notification_id())
+ if (key == notification->GetKey())
return *it;
}
return NULL;
}
-void ChromeNotifierService::MarkNotificationAsDismissed(const std::string& id) {
- SyncedNotification* notification = FindNotificationById(id);
+void ChromeNotifierService::MarkNotificationAsDismissed(
+ const std::string& key) {
+ SyncedNotification* notification = FindNotificationByKey(key);
CHECK(notification != NULL);
notification->NotificationHasBeenDismissed();
@@ -268,40 +268,120 @@ void ChromeNotifierService::Add(scoped_ptr<SyncedNotification> notification) {
// Send the notification to the NotificationUIManager to show to the user.
void ChromeNotifierService::Show(SyncedNotification* notification) {
// Set up the fields we need to send and create a Notification object.
- GURL origin_url(notification->origin_url());
- GURL app_icon_url(notification->app_icon_url());
- string16 title = UTF8ToUTF16(notification->title());
- string16 text = UTF8ToUTF16(notification->text());
- string16 heading = UTF8ToUTF16(notification->heading());
- string16 description = UTF8ToUTF16(notification->description());
-
+ GURL origin_url(notification->GetOriginUrl());
+ GURL app_icon_url(notification->GetAppIconUrl());
+ GURL image_url(notification->GetImageUrl());
+ string16 title = UTF8ToUTF16(notification->GetTitle());
+ string16 text = UTF8ToUTF16(notification->GetText());
+ string16 heading = UTF8ToUTF16(notification->GetHeading());
+ string16 description = UTF8ToUTF16(notification->GetDescription());
// TODO(petewil): What goes in the display source, is empty OK?
string16 display_source;
- string16 replace_id = UTF8ToUTF16(notification->notification_id());
+ string16 replace_key = UTF8ToUTF16(notification->GetKey());
+
+ // The delegate will eventually catch calls that the notification
+ // was read or deleted, and send the changes back to the server.
+ scoped_refptr<NotificationDelegate> delegate =
+ new ChromeNotifierDelegate(notification->GetKey(), this);
+
+ // Some inputs and fields are only used if there is a notification center.
+#if defined(ENABLE_MESSAGE_CENTER)
+ double creation_time = static_cast<double>(notification->GetCreationTime());
+ int priority = notification->GetPriority();
+ int notification_count = notification->GetNotificationCount();
+ int button_count = notification->GetButtonCount();
+ std::string button_one_title = notification->GetButtonOneTitle();
+ std::string button_one_icon_url = notification->GetButtonOneIconUrl();
+ std::string button_two_title = notification->GetButtonTwoTitle();
+ std::string button_two_icon_url = notification->GetButtonTwoIconUrl();
+
+ // Deduce which notification template to use from the data.
+ message_center::NotificationType notification_type =
+ message_center::NOTIFICATION_TYPE_SIMPLE;
+ if (!image_url.is_empty()) {
+ notification_type = message_center::NOTIFICATION_TYPE_IMAGE;
+ } else if (notification_count > 1) {
+ notification_type = message_center::NOTIFICATION_TYPE_MULTIPLE;
+ } else if (button_count > 0) {
+ notification_type = message_center::NOTIFICATION_TYPE_BASE_FORMAT;
+ }
+
+ // Fill the optional fields with the information we need to make a
+ // notification.
+ DictionaryValue optional_fields;
+ optional_fields.SetDouble(message_center::kTimestampKey, creation_time);
+ if (priority != SyncedNotification::kUndefinedPriority)
+ optional_fields.SetInteger(message_center::kPriorityKey, priority);
+ if (!button_one_title.empty())
+ optional_fields.SetString(message_center::kButtonOneTitleKey,
+ button_one_title);
+ if (!button_one_icon_url.empty())
+ optional_fields.SetString(message_center::kButtonOneIconUrlKey,
+ button_one_icon_url);
+ if (!button_two_title.empty())
+ optional_fields.SetString(message_center::kButtonTwoTitleKey,
+ button_two_title);
+ if (!button_two_icon_url.empty())
+ optional_fields.SetString(message_center::kButtonTwoIconUrlKey,
+ button_two_icon_url);
+
+ // Fill the individual notification fields for a multiple notification.
+ if (notification_count > 1) {
+ base::ListValue* items = new base::ListValue();
+
+ for (int ii = 0; ii < notification_count; ++ii) {
+ DictionaryValue* item = new DictionaryValue();
+ item->SetString(message_center::kItemTitleKey,
+ UTF8ToUTF16(notification->GetContainedNotificationTitle(
+ ii)));
+ item->SetString(message_center::kItemMessageKey,
+ UTF8ToUTF16(notification->GetContainedNotificationMessage(
+ ii)));
+ items->Append(item);
+ }
+
+ optional_fields.Set(message_center::kItemsKey, items);
+ }
// TODO(petewil): For now, just punt on dismissed notifications until
// I change the interface to let NotificationUIManager know the right way.
- if (SyncedNotification::kRead == notification->read_state() ||
- SyncedNotification::kDismissed == notification->read_state() ) {
- DVLOG(2) << "Not showing dismissed notification"
- << notification->title() << " " << notification->text();
+ if (SyncedNotification::kRead == notification->GetReadState() ||
+ SyncedNotification::kDismissed == notification->GetReadState() ) {
+ DVLOG(2) << "Dismissed notification arrived"
+ << notification->GetTitle() << " " << notification->GetText();
return;
}
- // The delegate will eventually catch calls that the notification
- // was read or deleted, and send the changes back to the server.
- scoped_refptr<NotificationDelegate> delegate =
- new ChromeNotifierDelegate(notification->notification_id(), this);
+ Notification ui_notification(notification_type,
+ origin_url,
+ app_icon_url,
+ heading,
+ text,
+ WebKit::WebTextDirectionDefault,
+ display_source,
+ replace_key,
+ &optional_fields,
+ delegate);
+
- Notification ui_notification(origin_url, app_icon_url, heading, description,
+#else // ENABLE_MESSAGE_CENTER
+
+ Notification ui_notification(origin_url,
+ app_icon_url,
+ heading,
+ text,
WebKit::WebTextDirectionDefault,
- display_source, replace_id, delegate);
+ display_source,
+ replace_key,
+ delegate);
+
+#endif // ENABLE_MESSAGE_CENTER
notification_manager_->Add(ui_notification, profile_);
DVLOG(1) << "Synced Notification arrived! " << title << " " << text
- << " " << app_icon_url << " " << replace_id << " "
- << notification->read_state();
+ << " " << app_icon_url << " " << replace_key << " "
+ << notification->GetReadState();
return;
}
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
index 4332e51..d2809a0 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
@@ -54,7 +54,7 @@ class ChromeNotifierService : public syncer::SyncableService,
// Get a pointer to a notification. ChromeNotifierService owns this pointer.
// The caller must not free it.
- notifier::SyncedNotification* FindNotificationById(const std::string& id);
+ notifier::SyncedNotification* FindNotificationByKey(const std::string& key);
// Called when we dismiss a notification.
void MarkNotificationAsDismissed(const std::string& id);
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
index f9322e2..3656f64 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
@@ -5,6 +5,9 @@
#include <map>
#include "base/memory/scoped_ptr.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
#include "chrome/browser/notifications/sync_notifier/synced_notification.h"
@@ -42,7 +45,61 @@ const char kKey4[] = "baz";
const char kKey5[] = "foobar";
const char kKey6[] = "fu";
const char kKey7[] = "meta";
+const char kIconUrl[] = "http://www.google.com/icon1.jpg";
+const char kTitle1[] = "New appointment at 2:15";
+const char kTitle2[] = "Email from Mark: Upcoming Ski trip";
+const char kTitle3[] = "Weather alert - light rain tonight.";
+const char kTitle4[] = "Zombie Alert on I-405";
+const char kTitle5[] = "5-dimensional plutonian steam hockey scores";
+const char kTitle6[] = "Conterfactuals Inc Stock report";
+const char kTitle7[] = "Push Messaging app updated";
+const char kText1[] = "Space Needle, 12:00 pm";
+const char kText2[] = "Stevens Pass is our first choice.";
+const char kText3[] = "More rain expected in the Seattle area tonight.";
+const char kText4[] = "Traffic slowdown as motorists are hitting zombies";
+const char kText5[] = "Neptune wins, pi to e";
+const char kText6[] = "Beef flavored base for soups";
+const char kText7[] = "You now have the latest version of Push Messaging App.";
+const char kIconUrl1[] = "http://www.google.com/icon1.jpg";
+const char kIconUrl2[] = "http://www.google.com/icon2.jpg";
+const char kIconUrl3[] = "http://www.google.com/icon3.jpg";
+const char kIconUrl4[] = "http://www.google.com/icon4.jpg";
+const char kIconUrl5[] = "http://www.google.com/icon5.jpg";
+const char kIconUrl6[] = "http://www.google.com/icon6.jpg";
+const char kIconUrl7[] = "http://www.google.com/icon7.jpg";
+const char kImageUrl1[] = "http://www.google.com/image1.jpg";
+const char kImageUrl2[] = "http://www.google.com/image2.jpg";
+const char kImageUrl3[] = "http://www.google.com/image3.jpg";
+const char kImageUrl4[] = "http://www.google.com/image4.jpg";
+const char kImageUrl5[] = "http://www.google.com/image5.jpg";
+const char kImageUrl6[] = "http://www.google.com/image6.jpg";
+const char kImageUrl7[] = "http://www.google.com/image7.jpg";
+const char kExpectedOriginUrl[] =
+ "chrome-extension://fboilmbenheemaomgaeehigklolhkhnf/";
+const char kDefaultDestinationTitle[] = "Open web page";
+const char kDefaultDestinationIconUrl[] = "http://www.google.com/image4.jpg";
+const char kDefaultDestinationUrl[] = "http://www.google.com";
+const char kButtonOneTitle[] = "Read";
+const char kButtonOneIconUrl[] = "http://www.google.com/image8.jpg";
+const char kButtonOneUrl[] = "http://www.google.com/do-something1";
+const char kButtonTwoTitle[] = "Reply";
+const char kButtonTwoIconUrl[] = "http://www.google.com/image9.jpg";
+const char kButtonTwoUrl[] = "http://www.google.com/do-something2";
+const char kContainedTitle1[] = "Today's Picnic moved";
+const char kContainedTitle2[] = "Group Run Today";
+const char kContainedTitle3[] = "Starcraft Tonight";
+const char kContainedMessage1[] = "Due to rain, we will be inside the cafe.";
+const char kContainedMessage2[] = "Meet at noon in the Gym.";
+const char kContainedMessage3[] = "Let's play starcraft tonight on the LAN.";
const int64 kFakeCreationTime = 42;
+const int kProtobufPriority = static_cast<int>(
+ sync_pb::CoalescedSyncedNotification_Priority_LOW);
+#if defined (ENABLE_MESSAGE_CENTER)
+const int kNotificationPriority = static_cast<int>(
+ message_center::LOW_PRIORITY);
+#else // ENABLE_MESSAGE_CENTER
+const int kNotificationPriority = 1;
+#endif // ENABLE_MESSAGE_CENTER
const sync_pb::CoalescedSyncedNotification_ReadState kDismissed =
sync_pb::CoalescedSyncedNotification_ReadState_DISMISSED;
const sync_pb::CoalescedSyncedNotification_ReadState kUnread =
@@ -52,18 +109,23 @@ const sync_pb::CoalescedSyncedNotification_ReadState kUnread =
std::string GetNotificationId(const SyncData& sync_data) {
SyncedNotificationSpecifics specifics = sync_data.GetSpecifics().
synced_notification();
+
return specifics.coalesced_notification().key();
}
// Stub out the NotificationUIManager for unit testing.
class StubNotificationUIManager : public NotificationUIManager {
public:
- StubNotificationUIManager() {}
+ StubNotificationUIManager() : notification_(GURL(), GURL(), string16(),
+ string16(), NULL) {}
virtual ~StubNotificationUIManager() {}
// Adds a notification to be displayed. Virtual for unit test override.
virtual void Add(const Notification& notification, Profile* profile)
- OVERRIDE {}
+ OVERRIDE {
+ // Make a deep copy of the notification that we can inspect.
+ notification_ = notification;
+ }
// Returns true if any notifications match the supplied ID, either currently
// displayed or in the queue.
@@ -92,8 +154,12 @@ class StubNotificationUIManager : public NotificationUIManager {
// Used when the app is terminating.
virtual void CancelAll() OVERRIDE {}
+ // Test hook to get the notification so we can check it
+ const Notification& notification() const { return notification_; }
+
private:
DISALLOW_COPY_AND_ASSIGN(StubNotificationUIManager);
+ Notification notification_;
};
// Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
@@ -180,13 +246,15 @@ class ChromeNotifierServiceTest : public testing::Test {
}
SyncedNotification* CreateNotification(
- const std::string& message,
+ const std::string& title,
+ const std::string& text,
+ const std::string& app_icon_url,
+ const std::string& image_url,
const std::string& app_id,
const std::string& key,
- const std::string& external_id,
sync_pb::CoalescedSyncedNotification_ReadState read_state) {
- SyncData sync_data = CreateSyncData(message, app_id, key,
- external_id, read_state);
+ SyncData sync_data = CreateSyncData(title, text, app_icon_url, image_url,
+ app_id, key, read_state);
// Set enough fields in sync_data, including specifics, for our tests
// to pass.
return new SyncedNotification(sync_data);
@@ -207,15 +275,19 @@ class ChromeNotifierServiceTest : public testing::Test {
// Helper to create syncer::SyncData.
static SyncData CreateSyncData(
- const std::string& message,
+ const std::string& title,
+ const std::string& text,
+ const std::string& app_icon_url,
+ const std::string& image_url,
const std::string& app_id,
const std::string& key,
- const std::string& external_id,
- sync_pb::CoalescedSyncedNotification_ReadState read_state) {
+ const sync_pb::CoalescedSyncedNotification_ReadState read_state) {
// CreateLocalData makes a copy of this, so this can safely live
// on the stack.
EntitySpecifics entity_specifics;
+ // Get a writeable pointer to the sync notifications specifics inside the
+ // entity specifics.
SyncedNotificationSpecifics* specifics =
entity_specifics.mutable_synced_notification();
@@ -226,27 +298,210 @@ class ChromeNotifierServiceTest : public testing::Test {
set_key(key);
specifics->mutable_coalesced_notification()->
+ set_priority(static_cast<sync_pb::CoalescedSyncedNotification_Priority>(
+ kProtobufPriority));
+
+ // Set the title.
+ specifics->mutable_coalesced_notification()->
mutable_render_info()->
mutable_expanded_info()->
mutable_simple_expanded_layout()->
- set_title(message);
+ set_title(title);
+ // Set the text.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_simple_expanded_layout()->
+ set_text(text);
+
+ // Set the heading.
specifics->
mutable_coalesced_notification()->
- set_creation_time_msec(kFakeCreationTime);
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_simple_collapsed_layout()->
+ set_heading(title);
+ // Add the collapsed info and set the app_icon_url on it.
specifics->
mutable_coalesced_notification()->
- add_notification();
-
+ mutable_render_info()->
+ mutable_expanded_info()->
+ add_collapsed_info();
specifics->
mutable_coalesced_notification()->
- mutable_notification(0)->set_external_id(external_id);
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(0)->
+ mutable_simple_collapsed_layout()->
+ mutable_app_icon()->
+ set_url(app_icon_url);
+ // Add the media object and set the image url on it.
specifics->
mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_simple_expanded_layout()->
+ add_media();
+ specifics->
+ mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_simple_expanded_layout()->
+ mutable_media(0)->
+ mutable_image()->
+ set_url(image_url);
+
+ specifics->mutable_coalesced_notification()->
+ set_creation_time_msec(kFakeCreationTime);
+
+ specifics->mutable_coalesced_notification()->
set_read_state(read_state);
+ // Contained notification one.
+ // We re-use the collapsed info we added for the app_icon_url,
+ // so no need to create another one here.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(0)->
+ mutable_simple_collapsed_layout()->
+ set_heading(kContainedTitle1);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(0)->
+ mutable_simple_collapsed_layout()->
+ set_description(kContainedMessage1);
+
+ // Contained notification two.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ add_collapsed_info();
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(1)->
+ mutable_simple_collapsed_layout()->
+ set_heading(kContainedTitle2);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(1)->
+ mutable_simple_collapsed_layout()->
+ set_description(kContainedMessage2);
+
+ // Contained notification three.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ add_collapsed_info();
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(2)->
+ mutable_simple_collapsed_layout()->
+ set_heading(kContainedTitle3);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(2)->
+ mutable_simple_collapsed_layout()->
+ set_description(kContainedMessage3);
+
+ // Default Destination.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_default_destination()->
+ set_text(kDefaultDestinationTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_default_destination()->
+ mutable_icon()->
+ set_url(kDefaultDestinationIconUrl);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_default_destination()->
+ mutable_icon()->
+ set_alt_text(kDefaultDestinationTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_default_destination()->
+ set_url(kDefaultDestinationUrl);
+
+ // Buttons are represented as targets.
+
+ // Button One.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ add_target();
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(0)->
+ mutable_action()->
+ set_text(kButtonOneTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(0)->
+ mutable_action()->
+ mutable_icon()->
+ set_url(kButtonOneIconUrl);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(0)->
+ mutable_action()->
+ mutable_icon()->
+ set_alt_text(kButtonOneTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(0)->
+ mutable_action()->
+ set_url(kButtonOneUrl);
+
+ // Button Two.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ add_target();
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(1)->
+ mutable_action()->
+ set_text(kButtonTwoTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(1)->
+ mutable_action()->
+ mutable_icon()->
+ set_url(kButtonTwoIconUrl);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(1)->
+ mutable_action()->
+ mutable_icon()->
+ set_alt_text(kButtonTwoTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(1)->
+ mutable_action()->
+ set_url(kButtonTwoUrl);
+
SyncData sync_data = SyncData::CreateLocalData(
"syncer::SYNCED_NOTIFICATIONS",
"ChromeNotifierServiceUnitTest",
@@ -268,14 +523,15 @@ class ChromeNotifierServiceTest : public testing::Test {
// Create a Notification, convert it to SyncData and convert it back.
TEST_F(ChromeNotifierServiceTest, NotificationToSyncDataToNotification) {
scoped_ptr<SyncedNotification> notification1(
- CreateNotification("1", kAppId1, kKey1, "11", kUnread));
+ CreateNotification(kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1,
+ kKey1, kUnread));
SyncData sync_data =
ChromeNotifierService::CreateSyncDataFromNotification(*notification1);
scoped_ptr<SyncedNotification> notification2(
ChromeNotifierService::CreateNotificationFromSyncData(sync_data));
EXPECT_TRUE(notification2.get());
EXPECT_TRUE(notification1->EqualsIgnoringReadState(*notification2));
- EXPECT_EQ(notification1->read_state(), notification2->read_state());
+ EXPECT_EQ(notification1->GetReadState(), notification2->GetReadState());
}
// Model assocation: We have no local data, and no remote data.
@@ -309,13 +565,13 @@ TEST_F(ChromeNotifierServiceTest, ProcessSyncChangesEmptyModel) {
SyncChangeList changes;
changes.push_back(CreateSyncChange(
SyncChange::ACTION_ADD, CreateNotification(
- "1", kAppId1, kKey1, "11", kUnread)));
+ kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread)));
changes.push_back(CreateSyncChange(
SyncChange::ACTION_ADD, CreateNotification(
- "2", kAppId2, kKey2, "22", kUnread)));
+ kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread)));
changes.push_back(CreateSyncChange(
SyncChange::ACTION_ADD, CreateNotification(
- "3", kAppId3, kKey3, "33", kUnread)));
+ kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kUnread)));
notifier.ProcessSyncChanges(FROM_HERE, changes);
@@ -332,25 +588,25 @@ TEST_F(ChromeNotifierServiceTest, LocalRemoteBothNonEmptyNoOverlap) {
// Create some local fake data.
scoped_ptr<SyncedNotification> n1(CreateNotification(
- "1", kAppId1, kKey1, "11", kUnread));
+ kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
notifier.AddForTest(n1.Pass());
scoped_ptr<SyncedNotification> n2(CreateNotification(
- "2", kAppId2, kKey2, "22", kUnread));
+ kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
notifier.AddForTest(n2.Pass());
scoped_ptr<SyncedNotification> n3(CreateNotification(
- "3", kAppId3, kKey3, "33", kUnread));
+ kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kUnread));
notifier.AddForTest(n3.Pass());
// Create some remote fake data.
SyncDataList initial_data;
- initial_data.push_back(CreateSyncData("4", kAppId4, kKey4,
- "44", kUnread));
- initial_data.push_back(CreateSyncData("5", kAppId5, kKey5,
- "55", kUnread));
- initial_data.push_back(CreateSyncData("6", kAppId6, kKey6,
- "66", kUnread));
- initial_data.push_back(CreateSyncData("7", kAppId7, kKey7,
- "77", kUnread));
+ initial_data.push_back(CreateSyncData(kTitle4, kText4, kIconUrl4, kImageUrl4,
+ kAppId4, kKey4, kUnread));
+ initial_data.push_back(CreateSyncData(kTitle5, kText5, kIconUrl5, kImageUrl5,
+ kAppId5, kKey5, kUnread));
+ initial_data.push_back(CreateSyncData(kTitle6, kText6, kIconUrl6, kImageUrl6,
+ kAppId6, kKey6, kUnread));
+ initial_data.push_back(CreateSyncData(kTitle7, kText7, kIconUrl7, kImageUrl7,
+ kAppId7, kKey7, kUnread));
// Merge the local and remote data.
notifier.MergeDataAndStartSyncing(
@@ -361,13 +617,13 @@ TEST_F(ChromeNotifierServiceTest, LocalRemoteBothNonEmptyNoOverlap) {
// Ensure the local store now has all local and remote notifications.
EXPECT_EQ(7U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
- EXPECT_TRUE(notifier.FindNotificationById(kKey1));
- EXPECT_TRUE(notifier.FindNotificationById(kKey2));
- EXPECT_TRUE(notifier.FindNotificationById(kKey3));
- EXPECT_TRUE(notifier.FindNotificationById(kKey4));
- EXPECT_TRUE(notifier.FindNotificationById(kKey5));
- EXPECT_TRUE(notifier.FindNotificationById(kKey6));
- EXPECT_TRUE(notifier.FindNotificationById(kKey7));
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey1));
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey2));
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey3));
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey4));
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey5));
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey6));
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey7));
// Test the type conversion and construction functions.
for (SyncDataList::const_iterator iter = initial_data.begin();
@@ -375,15 +631,16 @@ TEST_F(ChromeNotifierServiceTest, LocalRemoteBothNonEmptyNoOverlap) {
scoped_ptr<SyncedNotification> notification1(
ChromeNotifierService::CreateNotificationFromSyncData(*iter));
// TODO(petewil): Revisit this when we add version info to notifications.
- const std::string& id = notification1->notification_id();
- const SyncedNotification* notification2 = notifier.FindNotificationById(id);
+ const std::string& key = notification1->GetKey();
+ const SyncedNotification* notification2 =
+ notifier.FindNotificationByKey(key);
EXPECT_TRUE(NULL != notification2);
EXPECT_TRUE(notification1->EqualsIgnoringReadState(*notification2));
- EXPECT_EQ(notification1->read_state(), notification2->read_state());
+ EXPECT_EQ(notification1->GetReadState(), notification2->GetReadState());
}
- EXPECT_TRUE(notifier.FindNotificationById(kKey1));
- EXPECT_TRUE(notifier.FindNotificationById(kKey2));
- EXPECT_TRUE(notifier.FindNotificationById(kKey3));
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey1));
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey2));
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey3));
}
// Test the local store having the read bit unset, the remote store having
@@ -394,16 +651,16 @@ TEST_F(ChromeNotifierServiceTest, ModelAssocBothNonEmptyReadMismatch1) {
// Create some local fake data.
scoped_ptr<SyncedNotification> n1(CreateNotification(
- "1", kAppId1, kKey1, "11", kUnread));
+ kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
notifier.AddForTest(n1.Pass());
scoped_ptr<SyncedNotification> n2(CreateNotification(
- "2", kAppId2, kKey2, "22", kUnread));
+ kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
notifier.AddForTest(n2.Pass());
// Create some remote fake data, item 1 matches except for the read state.
syncer::SyncDataList initial_data;
- initial_data.push_back(CreateSyncData("1", kAppId1, kKey1,
- "11", kDismissed));
+ initial_data.push_back(CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
+ kAppId1, kKey1, kDismissed));
// Merge the local and remote data.
notifier.MergeDataAndStartSyncing(
syncer::SYNCED_NOTIFICATIONS,
@@ -415,11 +672,11 @@ TEST_F(ChromeNotifierServiceTest, ModelAssocBothNonEmptyReadMismatch1) {
// state of the first is now read.
EXPECT_EQ(2U, notifier.GetAllSyncData(syncer::SYNCED_NOTIFICATIONS).size());
SyncedNotification* notification1 =
- notifier.FindNotificationById(kKey1);
+ notifier.FindNotificationByKey(kKey1);
EXPECT_FALSE(NULL == notification1);
- EXPECT_EQ(SyncedNotification::kDismissed, notification1->read_state());
- EXPECT_TRUE(notifier.FindNotificationById(kKey2));
- EXPECT_FALSE(notifier.FindNotificationById(kKey3));
+ EXPECT_EQ(SyncedNotification::kDismissed, notification1->GetReadState());
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey2));
+ EXPECT_FALSE(notifier.FindNotificationByKey(kKey3));
// Ensure no new data will be sent to the remote store for notification1.
EXPECT_EQ(0U, processor()->change_list_size());
@@ -434,16 +691,16 @@ TEST_F(ChromeNotifierServiceTest, ModelAssocBothNonEmptyReadMismatch2) {
// Create some local fake data.
scoped_ptr<SyncedNotification> n1(CreateNotification(
- "1", kAppId1, kKey1, "11", kDismissed));
+ kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kDismissed));
notifier.AddForTest(n1.Pass());
scoped_ptr<SyncedNotification> n2(CreateNotification(
- "2", kAppId2, kKey2, "22", kUnread));
+ kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
notifier.AddForTest(n2.Pass());
// Create some remote fake data, item 1 matches except for the read state.
syncer::SyncDataList initial_data;
- initial_data.push_back(CreateSyncData("1", kAppId1, kKey1,
- "11", kUnread));
+ initial_data.push_back(CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
+ kAppId1, kKey1, kUnread));
// Merge the local and remote data.
notifier.MergeDataAndStartSyncing(
syncer::SYNCED_NOTIFICATIONS,
@@ -455,11 +712,11 @@ TEST_F(ChromeNotifierServiceTest, ModelAssocBothNonEmptyReadMismatch2) {
// state of the first is now read.
EXPECT_EQ(2U, notifier.GetAllSyncData(syncer::SYNCED_NOTIFICATIONS).size());
SyncedNotification* notification1 =
- notifier.FindNotificationById(kKey1);
+ notifier.FindNotificationByKey(kKey1);
EXPECT_FALSE(NULL == notification1);
- EXPECT_EQ(SyncedNotification::kDismissed, notification1->read_state());
- EXPECT_TRUE(notifier.FindNotificationById(kKey2));
- EXPECT_FALSE(notifier.FindNotificationById(kKey3));
+ EXPECT_EQ(SyncedNotification::kDismissed, notification1->GetReadState());
+ EXPECT_TRUE(notifier.FindNotificationByKey(kKey2));
+ EXPECT_FALSE(notifier.FindNotificationByKey(kKey3));
// Ensure the new data will be sent to the remote store for notification1.
EXPECT_EQ(1U, processor()->change_list_size());
@@ -476,13 +733,13 @@ TEST_F(ChromeNotifierServiceTest, ModelAssocBothNonEmptyWithUpdate) {
// Create some local fake data.
scoped_ptr<SyncedNotification> n1(CreateNotification(
- "1", kAppId1, kKey1, "11", kDismissed));
+ kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kDismissed));
notifier.AddForTest(n1.Pass());
// Create some remote fake data, item 1 matches the ID, but has different data
syncer::SyncDataList initial_data;
- initial_data.push_back(CreateSyncData("One", kAppId1, kKey1,
- "Eleven", kUnread));
+ initial_data.push_back(CreateSyncData(kTitle2, kText2, kIconUrl2, kImageUrl2,
+ kAppId1, kKey1, kUnread));
// Merge the local and remote data.
notifier.MergeDataAndStartSyncing(
syncer::SYNCED_NOTIFICATIONS,
@@ -493,17 +750,91 @@ TEST_F(ChromeNotifierServiceTest, ModelAssocBothNonEmptyWithUpdate) {
// Ensure the local store still has only one notification
EXPECT_EQ(1U, notifier.GetAllSyncData(syncer::SYNCED_NOTIFICATIONS).size());
SyncedNotification* notification1 =
- notifier.FindNotificationById(kKey1);
+ notifier.FindNotificationByKey(kKey1);
+
EXPECT_FALSE(NULL == notification1);
- EXPECT_EQ(SyncedNotification::kUnread, notification1->read_state());
- EXPECT_EQ("One", notification1->title());
- EXPECT_EQ("Eleven", notification1->first_external_id());
+ EXPECT_EQ(SyncedNotification::kUnread, notification1->GetReadState());
+ EXPECT_EQ(kTitle2, notification1->GetTitle());
// Ensure no new data will be sent to the remote store for notification1.
EXPECT_EQ(0U, processor()->change_list_size());
EXPECT_FALSE(processor()->ContainsId(kKey1));
}
+#if defined (ENABLE_MESSAGE_CENTER)
+TEST_F(ChromeNotifierServiceTest, ShowTest) {
+ StubNotificationUIManager notification_manager;
+ ChromeNotifierService notifier(NULL, &notification_manager);
+
+ // Create some remote fake data
+ syncer::SyncDataList initial_data;
+ initial_data.push_back(CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
+ kAppId1, kKey1, kUnread));
+ // Merge the local and remote data.
+ notifier.MergeDataAndStartSyncing(
+ syncer::SYNCED_NOTIFICATIONS,
+ initial_data,
+ PassProcessor(),
+ scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
+
+ // Check the base fields of the notification.
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_IMAGE,
+ notification_manager.notification().type());
+ EXPECT_EQ(kTitle1,
+ UTF16ToUTF8(notification_manager.notification().title()));
+ EXPECT_EQ(kText1,
+ UTF16ToUTF8(notification_manager.notification().body()));
+ EXPECT_EQ(kExpectedOriginUrl,
+ notification_manager.notification().origin_url().spec());
+ EXPECT_EQ(kIconUrl, notification_manager.notification().icon_url().spec());
+ EXPECT_EQ(kKey1,
+ UTF16ToUTF8(notification_manager.notification().replace_id()));
+ const DictionaryValue* actual_fields =
+ notification_manager.notification().optional_fields();
+
+ // Check the optional fields of the notification.
+ // Make an optional fields struct like we expect, compare it with actual.
+ DictionaryValue expected_fields;
+ expected_fields.SetDouble(message_center::kTimestampKey, kFakeCreationTime);
+ expected_fields.SetInteger(message_center::kPriorityKey,
+ kNotificationPriority);
+ expected_fields.SetString(message_center::kButtonOneTitleKey,
+ kButtonOneTitle);
+ expected_fields.SetString(message_center::kButtonOneIconUrlKey,
+ kButtonOneIconUrl);
+ expected_fields.SetString(message_center::kButtonTwoTitleKey,
+ kButtonTwoTitle);
+ expected_fields.SetString(message_center::kButtonTwoIconUrlKey,
+ kButtonTwoIconUrl);
+
+ // Fill the individual notification fields for a mutiple notification.
+ base::ListValue* items = new base::ListValue();
+ DictionaryValue* item1 = new DictionaryValue();
+ DictionaryValue* item2 = new DictionaryValue();
+ DictionaryValue* item3 = new DictionaryValue();
+ item1->SetString(message_center::kItemTitleKey,
+ UTF8ToUTF16(kContainedTitle1));
+ item1->SetString(message_center::kItemMessageKey,
+ UTF8ToUTF16(kContainedMessage1));
+ item2->SetString(message_center::kItemTitleKey,
+ UTF8ToUTF16(kContainedTitle2));
+ item2->SetString(message_center::kItemMessageKey,
+ UTF8ToUTF16(kContainedMessage2));
+ item3->SetString(message_center::kItemTitleKey,
+ UTF8ToUTF16(kContainedTitle3));
+ item3->SetString(message_center::kItemMessageKey,
+ UTF8ToUTF16(kContainedMessage3));
+ items->Append(item1);
+ items->Append(item2);
+ items->Append(item3);
+ expected_fields.Set(message_center::kItemsKey, items);
+
+ EXPECT_TRUE(expected_fields.Equals(actual_fields))
+ << "Expected: " << expected_fields
+ << ", but actual: " << *actual_fields;
+}
+#endif // ENABLE_MESSAGE_CENTER
+
// TODO(petewil): There are more tests to add, such as when we add an API
// to allow data entry from the client, we might have a more up to date
// item on the client than the server, or we might have a merge conflict.
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.cc b/chrome/browser/notifications/sync_notifier/synced_notification.cc
index 951a50d..cc6f27d 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.cc
@@ -6,6 +6,7 @@
#include "sync/protocol/sync.pb.h"
#include "sync/protocol/synced_notification_specifics.pb.h"
+#include "ui/message_center/notification_types.h"
namespace {
const char kExtensionScheme[] = "chrome-extension://";
@@ -33,6 +34,7 @@ SyncedNotification::SyncedNotification(const syncer::SyncData& sync_data) {
SyncedNotification::~SyncedNotification() {}
void SyncedNotification::Update(const syncer::SyncData& sync_data) {
+ // TODO(petewil): Let's add checking that the notification looks valid.
specifics_.CopyFrom(sync_data.GetSpecifics().synced_notification());
}
@@ -42,70 +44,17 @@ sync_pb::EntitySpecifics SyncedNotification::GetEntitySpecifics() const {
return entity_specifics;
}
-std::string SyncedNotification::title() const {
- return ExtractTitle();
-}
-
-std::string SyncedNotification::heading() const {
- return ExtractHeading();
-}
-
-std::string SyncedNotification::description() const {
- return ExtractDescription();
-}
-
-std::string SyncedNotification::app_id() const {
- return ExtractAppId();
-}
-
-std::string SyncedNotification::key() const {
- return ExtractKey();
-}
-
-GURL SyncedNotification::origin_url() const {
- return ExtractOriginUrl();
-}
-
-GURL SyncedNotification::app_icon_url() const {
- return ExtractAppIconUrl();
-}
-
-GURL SyncedNotification::image_url() const {
- return ExtractImageUrl();
-}
-
-std::string SyncedNotification::first_external_id() const {
- return ExtractFirstExternalId();
-}
-
-std::string SyncedNotification::notification_id() const {
- return ExtractNotificationId();
-}
-
-std::string SyncedNotification::text() const {
- return ExtractText();
-}
-
-SyncedNotification::ReadState SyncedNotification::read_state() const {
- return ExtractReadState();
-}
-
// TODO(petewil): Consider the timestamp too once it gets added to the protobuf.
+// TODO: add more fields in here
bool SyncedNotification::EqualsIgnoringReadState(
const SyncedNotification& other) const {
- return (title() == other.title() &&
- app_id() == other.app_id() &&
- key() == other.key() &&
- text() == other.text() &&
- origin_url() == other.origin_url() &&
- app_icon_url() == other.app_icon_url() &&
- image_url() == other.image_url() );
-}
-
-bool SyncedNotification::IdMatches(const SyncedNotification& other) const {
- // Two notifications have the same ID if the <appId/coalescingKey> pair
- // matches.
- return (notification_id() == other.notification_id());
+ return (GetTitle() == other.GetTitle() &&
+ GetAppId() == other.GetAppId() &&
+ GetKey() == other.GetKey() &&
+ GetText() == other.GetText() &&
+ GetOriginUrl() == other.GetOriginUrl() &&
+ GetAppIconUrl() == other.GetAppIconUrl() &&
+ GetImageUrl() == other.GetImageUrl() );
}
// Set the read state on the notification, returns true for success.
@@ -125,69 +74,58 @@ void SyncedNotification::SetReadState(const ReadState& read_state) {
NOTREACHED();
}
-void SyncedNotification::NotificationHasBeenRead() {
- SetReadState(kRead);
-}
-
void SyncedNotification::NotificationHasBeenDismissed() {
SetReadState(kDismissed);
}
-std::string SyncedNotification::ExtractFirstExternalId() const {
- if (!specifics_.has_coalesced_notification() ||
- specifics_.coalesced_notification().notification_size() < 1 ||
- !specifics_.coalesced_notification().notification(0).has_external_id())
- return std::string();
-
- return specifics_.coalesced_notification().notification(0).external_id();
-}
-
-std::string SyncedNotification::ExtractTitle() const {
+std::string SyncedNotification::GetTitle() const {
if (!specifics_.coalesced_notification().render_info().expanded_info().
simple_expanded_layout().has_title())
- return "";
+ return std::string();
return specifics_.coalesced_notification().render_info().expanded_info().
simple_expanded_layout().title();
}
-std::string SyncedNotification::ExtractHeading() const {
+std::string SyncedNotification::GetHeading() const {
if (!specifics_.coalesced_notification().render_info().collapsed_info().
simple_collapsed_layout().has_heading())
- return "";
+ return std::string();
return specifics_.coalesced_notification().render_info().collapsed_info().
simple_collapsed_layout().heading();
}
-std::string SyncedNotification::ExtractDescription() const {
+std::string SyncedNotification::GetDescription() const {
if (!specifics_.coalesced_notification().render_info().collapsed_info().
simple_collapsed_layout().has_description())
- return "";
+ return std::string();
return specifics_.coalesced_notification().render_info().collapsed_info().
simple_collapsed_layout().description();
}
-std::string SyncedNotification::ExtractAppId() const {
+std::string SyncedNotification::GetAppId() const {
if (!specifics_.coalesced_notification().has_app_id())
- return "";
+ return std::string();
return specifics_.coalesced_notification().app_id();
}
-std::string SyncedNotification::ExtractKey() const {
+std::string SyncedNotification::GetKey() const {
if (!specifics_.coalesced_notification().has_key())
- return "";
+ return std::string();
return specifics_.coalesced_notification().key();
}
-GURL SyncedNotification::ExtractOriginUrl() const {
+GURL SyncedNotification::GetOriginUrl() const {
std::string origin_url(kExtensionScheme);
- origin_url += app_id();
+ origin_url += GetAppId();
return GURL(origin_url);
}
-GURL SyncedNotification::ExtractAppIconUrl() const {
+// TODO(petewil): This only returns the first icon. We should make all the
+// icons available.
+GURL SyncedNotification::GetAppIconUrl() const {
if (specifics_.coalesced_notification().render_info().expanded_info().
collapsed_info_size() == 0)
return GURL();
@@ -203,7 +141,7 @@ GURL SyncedNotification::ExtractAppIconUrl() const {
// TODO(petewil): This currenly only handles the first image from the first
// collapsed item, someday return all images.
-GURL SyncedNotification::ExtractImageUrl() const {
+GURL SyncedNotification::GetImageUrl() const {
if (specifics_.coalesced_notification().render_info().expanded_info().
simple_expanded_layout().media_size() == 0)
return GURL();
@@ -216,16 +154,16 @@ GURL SyncedNotification::ExtractImageUrl() const {
expanded_info().simple_expanded_layout().media(0).image().url());
}
-std::string SyncedNotification::ExtractText() const {
+std::string SyncedNotification::GetText() const {
if (!specifics_.coalesced_notification().render_info().expanded_info().
simple_expanded_layout().has_text())
- return "";
+ return std::string();
return specifics_.coalesced_notification().render_info().expanded_info().
simple_expanded_layout().text();
}
-SyncedNotification::ReadState SyncedNotification::ExtractReadState() const {
+SyncedNotification::ReadState SyncedNotification::GetReadState() const {
DCHECK(specifics_.coalesced_notification().has_read_state());
sync_pb::CoalescedSyncedNotification_ReadState found_read_state =
@@ -246,8 +184,172 @@ SyncedNotification::ReadState SyncedNotification::ExtractReadState() const {
}
}
-std::string SyncedNotification::ExtractNotificationId() const {
- return key();
+// Time in milliseconds since the unix epoch, or 0 if not available.
+uint64 SyncedNotification::GetCreationTime() const {
+ if (!specifics_.coalesced_notification().has_creation_time_msec())
+ return 0;
+
+ return specifics_.coalesced_notification().creation_time_msec();
+}
+
+int SyncedNotification::GetPriority() const {
+ if (!specifics_.coalesced_notification().has_priority())
+ return kUndefinedPriority;
+ int protobuf_priority = specifics_.coalesced_notification().priority();
+
+#if defined(ENABLE_MESSAGE_CENTER)
+ // Convert the prioroty to the scheme used by the notification center.
+ if (protobuf_priority ==
+ sync_pb::CoalescedSyncedNotification_Priority_LOW) {
+ return message_center::LOW_PRIORITY;
+ } else if (protobuf_priority ==
+ sync_pb::CoalescedSyncedNotification_Priority_STANDARD) {
+ return message_center::DEFAULT_PRIORITY;
+ } else if (protobuf_priority ==
+ sync_pb::CoalescedSyncedNotification_Priority_HIGH) {
+ return message_center::HIGH_PRIORITY;
+ } else {
+ // Complain if this is a new priority we have not seen before.
+ DCHECK(protobuf_priority <
+ sync_pb::CoalescedSyncedNotification_Priority_LOW ||
+ sync_pb::CoalescedSyncedNotification_Priority_HIGH <
+ protobuf_priority);
+ return kUndefinedPriority;
+ }
+
+#else // ENABLE_MESSAGE_CENTER
+ return protobuf_priority;
+
+#endif // ENABLE_MESSAGE_CENTER
+}
+
+int SyncedNotification::GetNotificationCount() const {
+ return specifics_.coalesced_notification().render_info().
+ expanded_info().collapsed_info_size();
+}
+
+int SyncedNotification::GetButtonCount() const {
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ target_size();
+}
+
+std::string SyncedNotification::GetDefaultDestinationTitle() const {
+ if (!specifics_.coalesced_notification().render_info().collapsed_info().
+ default_destination().icon().has_alt_text()) {
+ return std::string();
+ }
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ default_destination().icon().alt_text();
+}
+
+std::string SyncedNotification::GetDefaultDestinationIconUrl() const {
+ if (!specifics_.coalesced_notification().render_info().collapsed_info().
+ default_destination().icon().has_url()) {
+ return std::string();
+ }
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ default_destination().icon().url();
+}
+
+std::string SyncedNotification::GetDefaultDestinationUrl() const {
+ if (!specifics_.coalesced_notification().render_info().collapsed_info().
+ default_destination().has_url()) {
+ return std::string();
+ }
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ default_destination().url();
+}
+
+std::string SyncedNotification::GetButtonOneTitle() const {
+ // Must ensure that we have a target before trying to access it.
+ if (GetButtonCount() < 1)
+ return std::string();
+ if (!specifics_.coalesced_notification().render_info().collapsed_info().
+ target(0).action().icon().has_alt_text()) {
+ return std::string();
+ }
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ target(0).action().icon().alt_text();
+}
+
+std::string SyncedNotification::GetButtonOneIconUrl() const {
+ // Must ensure that we have a target before trying to access it.
+ if (GetButtonCount() < 1)
+ return std::string();
+ if (!specifics_.coalesced_notification().render_info().collapsed_info().
+ target(0).action().icon().has_url()) {
+ return std::string();
+ }
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ target(0).action().icon().url();
+}
+
+std::string SyncedNotification::GetButtonOneUrl() const {
+ // Must ensure that we have a target before trying to access it.
+ if (GetButtonCount() < 1)
+ return std::string();
+ if (!specifics_.coalesced_notification().render_info().collapsed_info().
+ target(0).action().has_url()) {
+ return std::string();
+ }
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ target(0).action().url();
+}
+
+std::string SyncedNotification::GetButtonTwoTitle() const {
+ // Must ensure that we have a target before trying to access it.
+ if (GetButtonCount() < 2)
+ return std::string();
+ if (!specifics_.coalesced_notification().render_info().collapsed_info().
+ target(1).action().icon().has_alt_text()) {
+ return std::string();
+ }
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ target(1).action().icon().alt_text();
+}
+
+std::string SyncedNotification::GetButtonTwoIconUrl() const {
+ // Must ensure that we have a target before trying to access it.
+ if (GetButtonCount() < 2)
+ return std::string();
+ if (!specifics_.coalesced_notification().render_info().collapsed_info().
+ target(1).action().icon().has_url()) {
+ return std::string();
+ }
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ target(1).action().icon().url();
+}
+
+std::string SyncedNotification::GetButtonTwoUrl() const {
+ // Must ensure that we have a target before trying to access it.
+ if (GetButtonCount() < 2)
+ return std::string();
+ if (!specifics_.coalesced_notification().render_info().collapsed_info().
+ target(1).action().has_url()) {
+ return std::string();
+ }
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ target(1).action().url();
+}
+
+std::string SyncedNotification::GetContainedNotificationTitle(
+ int index) const {
+ if (specifics_.coalesced_notification().render_info().expanded_info().
+ collapsed_info_size() < index + 1)
+ return std::string();
+
+ return specifics_.coalesced_notification().render_info().expanded_info().
+ collapsed_info(index).simple_collapsed_layout().heading();
+}
+
+std::string SyncedNotification::GetContainedNotificationMessage(
+ int index) const {
+ if (specifics_.coalesced_notification().render_info().expanded_info().
+ collapsed_info_size() < index + 1)
+ return std::string();
+
+ return specifics_.coalesced_notification().render_info().expanded_info().
+ collapsed_info(index).simple_collapsed_layout().description();
}
} // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.h b/chrome/browser/notifications/sync_notifier/synced_notification.h
index b7eb805..cd40c99 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.h
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.h
@@ -34,28 +34,41 @@ class SyncedNotification {
kDismissed = 3,
};
+ static const int kUndefinedPriority = 65535;
+
void Update(const syncer::SyncData& sync_data);
// Here are some helper functions to get individual data parts out of a
// SyncedNotification.
- // TODO(petewil): Add more types as we expand support for the protobuf.
- std::string title() const;
- std::string heading() const;
- std::string description() const;
- std::string app_id() const;
- std::string key() const;
- GURL origin_url() const;
- GURL app_icon_url() const;
- GURL image_url() const;
- std::string first_external_id() const;
- std::string notification_id() const;
- std::string text() const;
- ReadState read_state() const;
+ std::string GetTitle() const;
+ std::string GetHeading() const;
+ std::string GetDescription() const;
+ std::string GetAppId() const;
+ std::string GetKey() const;
+ GURL GetOriginUrl() const;
+ GURL GetAppIconUrl() const;
+ GURL GetImageUrl() const;
+ std::string GetText() const;
+ ReadState GetReadState() const;
+ uint64 GetCreationTime() const;
+ int GetPriority() const;
+ std::string GetDefaultDestinationTitle() const;
+ std::string GetDefaultDestinationIconUrl() const;
+ std::string GetDefaultDestinationUrl() const;
+ std::string GetButtonOneTitle() const;
+ std::string GetButtonOneIconUrl() const;
+ std::string GetButtonOneUrl() const;
+ std::string GetButtonTwoTitle() const;
+ std::string GetButtonTwoIconUrl() const;
+ std::string GetButtonTwoUrl() const;
+ int GetNotificationCount() const;
+ int GetButtonCount() const;
+ std::string GetContainedNotificationTitle(int index) const;
+ std::string GetContainedNotificationMessage(int index) const;
+
bool EqualsIgnoringReadState(const SyncedNotification& other) const;
- bool IdMatches(const SyncedNotification& other) const;
- void NotificationHasBeenRead();
void NotificationHasBeenDismissed();
// This gets a pointer to the SyncedNotificationSpecifics part
@@ -68,18 +81,6 @@ class SyncedNotification {
// Parsing functions to get this information out of the sync_data and into
// our local variables.
- std::string ExtractTitle() const;
- std::string ExtractHeading() const;
- std::string ExtractDescription() const;
- std::string ExtractAppId() const;
- std::string ExtractKey() const;
- GURL ExtractOriginUrl() const;
- GURL ExtractAppIconUrl() const;
- GURL ExtractImageUrl() const;
- std::string ExtractFirstExternalId() const;
- std::string ExtractNotificationId() const;
- std::string ExtractText() const;
- ReadState ExtractReadState() const;
sync_pb::SyncedNotificationSpecifics specifics_;
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification_unittest.cc b/chrome/browser/notifications/sync_notifier/synced_notification_unittest.cc
index f77af5e..d508e1a 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification_unittest.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification_unittest.cc
@@ -10,6 +10,7 @@
#include "sync/protocol/sync.pb.h"
#include "sync/protocol/synced_notification_specifics.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/message_center/notification_types.h"
using syncer::SyncData;
using notifier::SyncedNotification;
@@ -18,7 +19,16 @@ using sync_pb::SyncedNotificationSpecifics;
namespace {
-const int64 kFakeCreationTime = 42;
+const uint64 kFakeCreationTime = 42;
+const int kProtobufPriority = static_cast<int>(
+ sync_pb::CoalescedSyncedNotification_Priority_LOW);
+#if defined (ENABLE_MESSAGE_CENTER)
+const int kNotificationPriority = static_cast<int>(
+ message_center::LOW_PRIORITY);
+#else // ENABLE_MESSAGE_CENTER
+const int kNotificationPriority = 1;
+#endif // ENABLE_MESSAGE_CENTER
+
const char kTitle1[] = "New appointment at 2:15";
const char kTitle2[] = "Email from Mark: Upcoming Ski trip";
@@ -36,6 +46,22 @@ const char kIconUrl3[] = "http://www.google.com/icon3.jpg";
const char kImageUrl1[] = "http://www.google.com/image1.jpg";
const char kImageUrl2[] = "http://www.google.com/image2.jpg";
const char kImageUrl3[] = "http://www.google.com/image3.jpg";
+const char kDefaultDestinationTitle[] = "Open web page";
+const char kDefaultDestinationIconUrl[] = "http://www.google.com/image4.jpg";
+const char kDefaultDestinationUrl[] = "http://www.google.com";
+const char kButtonOneTitle[] = "Read";
+const char kButtonOneIconUrl[] = "http://www.google.com/image5.jpg";
+const char kButtonOneUrl[] = "http://www.google.com/do-something1";
+const char kButtonTwoTitle[] = "Reply";
+const char kButtonTwoIconUrl[] = "http://www.google.com/image6.jpg";
+const char kButtonTwoUrl[] = "http://www.google.com/do-something2";
+const char kContainedTitle1[] = "Today's Picnic moved";
+const char kContainedTitle2[] = "Group Run Today";
+const char kContainedTitle3[] = "Starcraft Tonight";
+const char kContainedMessage1[] = "Due to rain, we will be inside the cafe.";
+const char kContainedMessage2[] = "Meet at noon in the Gym.";
+const char kContainedMessage3[] = "Let's play starcraft tonight on the LAN.";
+
const sync_pb::CoalescedSyncedNotification_ReadState kRead =
sync_pb::CoalescedSyncedNotification_ReadState_READ;
const sync_pb::CoalescedSyncedNotification_ReadState kUnread =
@@ -54,11 +80,11 @@ class SyncedNotificationTest : public testing::Test {
virtual void SetUp() OVERRIDE {
sync_data1_ = CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
kAppId1, kKey1, kUnread);
- sync_data2_ = CreateSyncData(kTitle2, kText2, kIconUrl2, kImageUrl1,
+ sync_data2_ = CreateSyncData(kTitle2, kText2, kIconUrl2, kImageUrl2,
kAppId2, kKey2, kUnread);
// Notification 3 will have the same ID as notification1, but different
// data inside.
- sync_data3_ = CreateSyncData(kTitle3, kText3, kIconUrl3, kImageUrl1,
+ sync_data3_ = CreateSyncData(kTitle3, kText3, kIconUrl3, kImageUrl3,
kAppId1, kKey1, kUnread);
// Notification 4 will be the same as 1, but the read state will be 'read'.
sync_data4_ = CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
@@ -108,17 +134,24 @@ class SyncedNotificationTest : public testing::Test {
set_key(key);
specifics->mutable_coalesced_notification()->
+ set_priority(static_cast<sync_pb::CoalescedSyncedNotification_Priority>(
+ kProtobufPriority));
+
+ // Set the title.
+ specifics->mutable_coalesced_notification()->
mutable_render_info()->
mutable_expanded_info()->
mutable_simple_expanded_layout()->
set_title(title);
+ // Set the text.
specifics->mutable_coalesced_notification()->
mutable_render_info()->
mutable_expanded_info()->
mutable_simple_expanded_layout()->
set_text(text);
+ // Add the collapsed info and set the app_icon_url on it.
specifics->mutable_coalesced_notification()->
mutable_render_info()->
mutable_expanded_info()->
@@ -131,6 +164,7 @@ class SyncedNotificationTest : public testing::Test {
mutable_app_icon()->
set_url(app_icon_url);
+ // Add the media object and set the image url on it.
specifics->mutable_coalesced_notification()->
mutable_render_info()->
mutable_expanded_info()->
@@ -148,13 +182,150 @@ class SyncedNotificationTest : public testing::Test {
set_creation_time_msec(kFakeCreationTime);
specifics->mutable_coalesced_notification()->
- add_notification();
+ set_read_state(read_state);
+ // Contained notification one.
+ // We re-use the collapsed info we added for the app_icon_url,
+ // so no need to create another one here.
specifics->mutable_coalesced_notification()->
- set_read_state(read_state);
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(0)->
+ mutable_simple_collapsed_layout()->
+ set_heading(kContainedTitle1);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(0)->
+ mutable_simple_collapsed_layout()->
+ set_description(kContainedMessage1);
+
+ // Contained notification two.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ add_collapsed_info();
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(1)->
+ mutable_simple_collapsed_layout()->
+ set_heading(kContainedTitle2);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(1)->
+ mutable_simple_collapsed_layout()->
+ set_description(kContainedMessage2);
+
+ // Contained notification three.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ add_collapsed_info();
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(2)->
+ mutable_simple_collapsed_layout()->
+ set_heading(kContainedTitle3);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_expanded_info()->
+ mutable_collapsed_info(2)->
+ mutable_simple_collapsed_layout()->
+ set_description(kContainedMessage3);
+
+ // Default Destination.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_default_destination()->
+ set_text(kDefaultDestinationTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_default_destination()->
+ mutable_icon()->
+ set_url(kDefaultDestinationIconUrl);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_default_destination()->
+ mutable_icon()->
+ set_alt_text(kDefaultDestinationTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_default_destination()->
+ set_url(kDefaultDestinationUrl);
+
+ // Buttons are represented as targets.
+
+ // Button One.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ add_target();
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(0)->
+ mutable_action()->
+ set_text(kButtonOneTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(0)->
+ mutable_action()->
+ mutable_icon()->
+ set_url(kButtonOneIconUrl);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(0)->
+ mutable_action()->
+ mutable_icon()->
+ set_alt_text(kButtonOneTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(0)->
+ mutable_action()->
+ set_url(kButtonOneUrl);
+
+ // Button Two.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ add_target();
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(1)->
+ mutable_action()->
+ set_text(kButtonTwoTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(1)->
+ mutable_action()->
+ mutable_icon()->
+ set_url(kButtonTwoIconUrl);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(1)->
+ mutable_action()->
+ mutable_icon()->
+ set_alt_text(kButtonTwoTitle);
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_collapsed_info()->
+ mutable_target(1)->
+ mutable_action()->
+ set_url(kButtonTwoUrl);
- // TODO(petewil): Improve ctor to pass in an image and type so this test can
- // pass on actual data.
SyncData sync_data = SyncData::CreateLocalData(
"syncer::SYNCED_NOTIFICATIONS",
"SyncedNotificationTest",
@@ -170,28 +341,28 @@ class SyncedNotificationTest : public testing::Test {
// test simple accessors
TEST_F(SyncedNotificationTest, GetAppIdTest) {
- std::string found_app_id = notification1_->app_id();
+ std::string found_app_id = notification1_->GetAppId();
std::string expected_app_id(kAppId1);
EXPECT_EQ(found_app_id, expected_app_id);
}
TEST_F(SyncedNotificationTest, GetKeyTest) {
- std::string found_key = notification1_->key();
+ std::string found_key = notification1_->GetKey();
std::string expected_key(kKey1);
EXPECT_EQ(expected_key, found_key);
}
TEST_F(SyncedNotificationTest, GetTitleTest) {
- std::string found_title = notification1_->title();
+ std::string found_title = notification1_->GetTitle();
std::string expected_title(kTitle1);
EXPECT_EQ(expected_title, found_title);
}
TEST_F(SyncedNotificationTest, GetIconURLTest) {
- std::string found_icon_url = notification1_->app_icon_url().spec();
+ std::string found_icon_url = notification1_->GetAppIconUrl().spec();
std::string expected_icon_url(kIconUrl1);
EXPECT_EQ(expected_icon_url, found_icon_url);
@@ -199,13 +370,13 @@ TEST_F(SyncedNotificationTest, GetIconURLTest) {
TEST_F(SyncedNotificationTest, GetReadStateTest) {
SyncedNotification::ReadState found_state1 =
- notification1_->read_state();
+ notification1_->GetReadState();
SyncedNotification::ReadState expected_state1(SyncedNotification::kUnread);
EXPECT_EQ(expected_state1, found_state1);
SyncedNotification::ReadState found_state2 =
- notification4_->read_state();
+ notification4_->GetReadState();
SyncedNotification::ReadState expected_state2(SyncedNotification::kDismissed);
EXPECT_EQ(expected_state2, found_state2);
@@ -214,7 +385,7 @@ TEST_F(SyncedNotificationTest, GetReadStateTest) {
// TODO(petewil): Improve ctor to pass in an image and type so this test can
// pass on actual data.
TEST_F(SyncedNotificationTest, GetImageURLTest) {
- std::string found_image_url = notification1_->image_url().spec();
+ std::string found_image_url = notification1_->GetImageUrl().spec();
std::string expected_image_url = kImageUrl1;
EXPECT_EQ(expected_image_url, found_image_url);
@@ -222,26 +393,80 @@ TEST_F(SyncedNotificationTest, GetImageURLTest) {
// TODO(petewil): test with a multi-line body
TEST_F(SyncedNotificationTest, GetTextTest) {
- std::string found_text = notification1_->text();
+ std::string found_text = notification1_->GetText();
std::string expected_text(kText1);
EXPECT_EQ(expected_text, found_text);
}
-TEST_F(SyncedNotificationTest, GetNotificationIdTest) {
- std::string found_id = notification1_->notification_id();
- std::string expected_id(kKey1);
+TEST_F(SyncedNotificationTest, GetCreationTimeTest) {
+ uint64 found_time = notification1_->GetCreationTime();
+ EXPECT_EQ(kFakeCreationTime, found_time);
+}
+
+TEST_F(SyncedNotificationTest, GetPriorityTest) {
+ double found_priority = notification1_->GetPriority();
+ EXPECT_EQ(static_cast<double>(kNotificationPriority), found_priority);
+}
+
+TEST_F(SyncedNotificationTest, GetButtonCountTest) {
+ int found_button_count = notification1_->GetButtonCount();
+ EXPECT_EQ(2, found_button_count);
+}
+
+TEST_F(SyncedNotificationTest, GetNotificationCountTest) {
+ int found_notification_count = notification1_->GetNotificationCount();
+ EXPECT_EQ(3, found_notification_count);
+}
+
+TEST_F(SyncedNotificationTest, GetDefaultDestinationDataTest) {
+ std::string default_destination_title =
+ notification1_->GetDefaultDestinationTitle();
+ std::string default_destination_icon_url =
+ notification1_->GetDefaultDestinationIconUrl();
+ std::string default_destination_url =
+ notification1_->GetDefaultDestinationUrl();
+ EXPECT_EQ(std::string(kDefaultDestinationTitle), default_destination_title);
+ EXPECT_EQ(std::string(kDefaultDestinationIconUrl),
+ default_destination_icon_url);
+ EXPECT_EQ(std::string(kDefaultDestinationUrl), default_destination_url);
+}
- EXPECT_EQ(expected_id, found_id);
+TEST_F(SyncedNotificationTest, GetButtonDataTest) {
+ std::string button_one_title = notification1_->GetButtonOneTitle();
+ std::string button_one_icon_url = notification1_->GetButtonOneIconUrl();
+ std::string button_one_url = notification1_->GetButtonOneUrl();
+ std::string button_two_title = notification1_->GetButtonTwoTitle();
+ std::string button_two_icon_url = notification1_->GetButtonTwoIconUrl();
+ std::string button_two_url = notification1_->GetButtonTwoUrl();
+ EXPECT_EQ(std::string(kButtonOneTitle), button_one_title);
+ EXPECT_EQ(std::string(kButtonOneIconUrl), button_one_icon_url);
+ EXPECT_EQ(std::string(kButtonOneUrl), button_one_url);
+ EXPECT_EQ(std::string(kButtonTwoTitle), button_two_title);
+ EXPECT_EQ(std::string(kButtonTwoIconUrl), button_two_icon_url);
+ EXPECT_EQ(std::string(kButtonTwoUrl), button_two_url);
}
-// test that the ID match function works as we expect
-TEST_F(SyncedNotificationTest, IdMatchesTest) {
- EXPECT_TRUE(notification1_->IdMatches(*notification1_));
- EXPECT_TRUE(notification2_->IdMatches(*notification2_));
- EXPECT_FALSE(notification1_->IdMatches(*notification2_));
- EXPECT_TRUE(notification1_->IdMatches(*notification3_));
- EXPECT_TRUE(notification1_->IdMatches(*notification4_));
+TEST_F(SyncedNotificationTest, ContainedNotificationTest) {
+ std::string notification_title1 =
+ notification1_->GetContainedNotificationTitle(0);
+ std::string notification_title2 =
+ notification1_->GetContainedNotificationTitle(1);
+ std::string notification_title3 =
+ notification1_->GetContainedNotificationTitle(2);
+ std::string notification_message1 =
+ notification1_->GetContainedNotificationMessage(0);
+ std::string notification_message2 =
+ notification1_->GetContainedNotificationMessage(1);
+ std::string notification_message3 =
+ notification1_->GetContainedNotificationMessage(2);
+
+ EXPECT_EQ(std::string(kContainedTitle1), notification_title1);
+ EXPECT_EQ(std::string(kContainedTitle2), notification_title2);
+ EXPECT_EQ(std::string(kContainedTitle3), notification_title3);
+ EXPECT_EQ(std::string(kContainedMessage1), notification_message1);
+ EXPECT_EQ(std::string(kContainedMessage2), notification_message2);
+ EXPECT_EQ(std::string(kContainedMessage3), notification_message3);
}
// test that EqualsIgnoringReadState works as we expect
@@ -260,9 +485,8 @@ TEST_F(SyncedNotificationTest, UpdateTest) {
// update with the sync data from notification2, and ensure they are equal.
notification5->Update(sync_data2_);
EXPECT_TRUE(notification5->EqualsIgnoringReadState(*notification2_));
- EXPECT_EQ(notification5->read_state(), notification2_->read_state());
+ EXPECT_EQ(notification5->GetReadState(), notification2_->GetReadState());
EXPECT_FALSE(notification5->EqualsIgnoringReadState(*notification1_));
}
-// Add a test for set_local_changes and has_local_changes together
-// Add a test for a notification being read and or deleted
+// Add a test for a notification being read and or deleted.
diff --git a/sync/protocol/synced_notification_data.proto b/sync/protocol/synced_notification_data.proto
index fed7ee7..72c612d 100644
--- a/sync/protocol/synced_notification_data.proto
+++ b/sync/protocol/synced_notification_data.proto
@@ -63,8 +63,8 @@ message SyncedNotification {
// The creator of the notification.
optional SyncedNotificationCreator creator = 3;
- // TODO(petewil): This won't build. Import the relevant protobuf.
- // optional MapData client_data = 4;
+ // Client specific data.
+ optional MapData client_data = 4;
}
message CoalescedSyncedNotification {
@@ -103,4 +103,28 @@ message CoalescedSyncedNotification {
message SyncedNotificationList {
repeated CoalescedSyncedNotification coalesced_notification = 1;
-} \ No newline at end of file
+}
+
+// MapData, Data, and ListData are used to sending aribitrary payloads
+// between instances of applications using Synced Notifications. The
+// schema atop MapData will be defined by the client application.
+message MapData {
+ message Entry {
+ optional string key = 1;
+ optional Data value = 2;
+ };
+ repeated Entry entry = 1;
+};
+
+message Data {
+ optional bool boolean_value = 1;
+ optional int32 int_value = 2;
+ optional double float_value = 3;
+ optional string string_value = 4;
+ optional ListData list_value = 5;
+ optional MapData map_value = 6;
+};
+
+message ListData {
+ repeated Data value = 1;
+}; \ No newline at end of file
diff --git a/sync/protocol/synced_notification_render.proto b/sync/protocol/synced_notification_render.proto
index ce5a721..46d890f 100644
--- a/sync/protocol/synced_notification_render.proto
+++ b/sync/protocol/synced_notification_render.proto
@@ -16,70 +16,89 @@ package sync_pb;
// Data that is used directly by endpoints to render notifications in the case
// where no "native" app can handle the notification.
message SyncedNotificationRenderInfo {
-
- // Render information for the collapsed (summary) view of a coalesced
- // notification.
- message CollapsedInfo {
- message SimpleCollapsedLayout {
- // Application icon.
- optional SyncedNotificationImage app_icon = 1;
-
- // Profile image(s) of the notification creator(s) to show in the
- // collapsed UI.
- repeated SyncedNotificationProfileImage profile_image = 2;
-
- // Heading - often the name(s) of the notification creator(s).
- optional string heading = 3;
-
- // Description - often the action that generated the notification.
- optional string description = 4;
- }
- optional SimpleCollapsedLayout simple_collapsed_layout = 1;
-
- // The creation time of the notification in microseconds since the UNIX
- // epoch.
- optional uint64 creation_timestamp_usec = 2;
-
- // The default destination target.
- optional SyncedNotificationDestination default_destination = 3;
-
- // Secondary destinations and actions grouped into a message to account for
- // ordering.
- message Target {
- optional SyncedNotificationDestination destination = 1;
- optional SyncedNotificationAction action = 2;
- }
- repeated Target target = 4;
- }
+ // Render information for the collapsed (summary) view of a notification.
optional CollapsedInfo collapsed_info = 1;
- // Render information for the expanded (detail) view of a coalesced
- // notification.
- message ExpandedInfo {
- message SimpleExpandedLayout {
- // Title - often the title of the underlying entity referred to by the
- // notification(s).
- optional string title = 1;
-
- // Text content - often a snippet of text from the underlying entity
- // reference or the notification.
- optional string text = 2;
-
- // Media.
- message Media {
- // TOOD(jro): Do we need other media types?
- optional SyncedNotificationImage image = 1;
- }
- repeated Media media = 3;
- }
- optional SimpleExpandedLayout simple_expanded_layout = 1;
-
- // Collapsed information for each notification in the coalesced group.
- repeated CollapsedInfo collapsed_info = 2;
- }
+ // Render information for the expanded view of a notification.
optional ExpandedInfo expanded_info = 2;
}
+// Render information for the collapsed (summary) view of a coalesced
+// notification.
+message CollapsedInfo {
+ optional SimpleCollapsedLayout simple_collapsed_layout = 1;
+
+ // The creation time of the notification in microseconds since the UNIX
+ // epoch.
+ optional uint64 creation_timestamp_usec = 2;
+
+ // The default destination target.
+ optional SyncedNotificationDestination default_destination = 3;
+
+ repeated Target target = 4;
+}
+
+// Render information for the expanded (detail) view of a coalesced
+// notification.
+message ExpandedInfo {
+ optional SimpleExpandedLayout simple_expanded_layout = 1;
+
+ // Collapsed information for each notification in the coalesced group.
+ repeated CollapsedInfo collapsed_info = 2;
+}
+
+message SimpleCollapsedLayout {
+ // Application icon.
+ optional SyncedNotificationImage app_icon = 1;
+
+ // Profile image(s) of the notification creator(s) to show in the
+ // collapsed UI.
+ repeated SyncedNotificationProfileImage profile_image = 2;
+
+ // Heading - often the name(s) of the notification creator(s).
+ optional string heading = 3;
+
+ // Description - often the action that generated the notification.
+ optional string description = 4;
+}
+
+message SimpleExpandedLayout {
+ // Title - often the title of the underlying entity referred to by the
+ // notification(s).
+ optional string title = 1;
+
+ // Text content - often a snippet of text from the underlying entity
+ // reference or the notification.
+ optional string text = 2;
+
+ repeated Media media = 3;
+
+ // Profile image, usually this is the creator of the referenced entity.
+ optional SyncedNotificationProfileImage profile_image = 4;
+
+ // A set of targets for actions the user can take, or destinations the
+ // viewer can be taken to. Usually these relate to the referenced entity.
+ repeated Target target = 5;
+}
+
+// Media.
+message Media {
+ // TOOD(jro): Do we need other media types?
+ optional SyncedNotificationImage image = 1;
+}
+
+// Secondary destinations and actions grouped into a message to account for
+// ordering.
+message Target {
+ // URL that the user will be taken to by clicking on the notification.
+ optional SyncedNotificationDestination destination = 1;
+ // URI to POST if the user clicks on a button.
+ optional SyncedNotificationAction action = 2;
+
+ // A key to identify this target within a group of targets.
+ optional string target_key = 3;
+}
+
// A Destination is a target URL that the user can be taken to by clicking on or
// selecting the notification or part thereof.
message SyncedNotificationDestination {
@@ -101,8 +120,8 @@ message SyncedNotificationDestination {
// action button associated with the notification on native mobile, a link, or
// even the notification card itself.
message SyncedNotificationAction {
- // The description for the Action.
- optional string text = 1;
+ // The description for the Action.
+ optional string text = 1;
// The icon to use for the Action.
optional SyncedNotificationImage icon = 2;
@@ -133,4 +152,4 @@ message SyncedNotificationProfileImage {
optional string oid = 2;
// Name to display for this image.
optional string display_name = 3;
-} \ No newline at end of file
+}