| Index: chrome/browser/notifications/sync_notifier/synced_notification.cc
|
| diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.cc b/chrome/browser/notifications/sync_notifier/synced_notification.cc
|
| index 851c5d68ac105da38c1426ee8ece1706c6df0fe3..530703d7284ef90f836981713267367efbcf26f9 100644
|
| --- a/chrome/browser/notifications/sync_notifier/synced_notification.cc
|
| +++ b/chrome/browser/notifications/sync_notifier/synced_notification.cc
|
| @@ -5,6 +5,7 @@
|
| #include "chrome/browser/notifications/sync_notifier/synced_notification.h"
|
|
|
| #include "base/basictypes.h"
|
| +#include "base/strings/string_util.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/time/time.h"
|
| #include "base/values.h"
|
| @@ -21,6 +22,7 @@
|
|
|
| namespace {
|
| const char kExtensionScheme[] = "chrome-extension://";
|
| +const char kDefaultSyncedNotificationScheme[] = "https:";
|
|
|
| // Today rich notifications only supports two buttons, make sure we don't
|
| // try to supply them with more than this number of buttons.
|
| @@ -30,6 +32,16 @@ bool UseRichNotifications() {
|
| return message_center::IsRichNotificationEnabled();
|
| }
|
|
|
| +// Schema-less specs default badly in windows. If we find one, add the schema
|
| +// we expect instead of allowing windows specific GURL code to make it default
|
| +// to "file:".
|
| +GURL AddDefaultSchemaIfNeeded(std::string& url_spec) {
|
| + if (StartsWithASCII(url_spec, std::string("//"), false))
|
| + return GURL(std::string(kDefaultSyncedNotificationScheme) + url_spec);
|
| +
|
| + return GURL(url_spec);
|
| +}
|
| +
|
| } // namespace
|
|
|
| namespace notifier {
|
| @@ -76,13 +88,16 @@ void SyncedNotification::OnFetchComplete(const GURL url,
|
| DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
|
|
| // Match the incoming bitmaps to URLs. In case this is a dup, make sure to
|
| - // Try all potentially matching urls.
|
| + // try all potentially matching urls.
|
| if (GetAppIconUrl() == url && bitmap != NULL) {
|
| app_icon_bitmap_ = gfx::Image::CreateFrom1xBitmap(*bitmap);
|
| }
|
| if (GetImageUrl() == url && bitmap != NULL) {
|
| image_bitmap_ = gfx::Image::CreateFrom1xBitmap(*bitmap);
|
| }
|
| + if (GetProfilePictureUrl(0) == url && bitmap != NULL) {
|
| + sender_bitmap_ = gfx::Image::CreateFrom1xBitmap(*bitmap);
|
| + }
|
|
|
| // If this URL matches one or more button bitmaps, save them off.
|
| for (unsigned int i = 0; i < GetButtonCount(); ++i) {
|
| @@ -123,6 +138,13 @@ void SyncedNotification::QueueBitmapFetchJobs(
|
| AddBitmapToFetchQueue(GetButtonIconUrl(i));
|
| }
|
|
|
| + // If there is a profile image bitmap, fetch it
|
| + if (GetProfilePictureCount() > 0) {
|
| + // TODO(petewil): When we have the capacity to display more than one bitmap,
|
| + // modify this code to fetch as many as we can display
|
| + AddBitmapToFetchQueue(GetProfilePictureUrl(0));
|
| + }
|
| +
|
| // If the URL is non-empty, add it to our queue of URLs to fetch.
|
| AddBitmapToFetchQueue(GetAppIconUrl());
|
| AddBitmapToFetchQueue(GetImageUrl());
|
| @@ -171,9 +193,13 @@ void SyncedNotification::Show(NotificationUIManager* notification_manager,
|
| GURL image_url = GetImageUrl();
|
| string16 text = UTF8ToUTF16(GetText());
|
| string16 heading = UTF8ToUTF16(GetHeading());
|
| + string16 description = UTF8ToUTF16(GetDescription());
|
| + string16 annotation = UTF8ToUTF16(GetAnnotation());
|
| // TODO(petewil): Eventually put the display name of the sending service here.
|
| string16 display_source = UTF8ToUTF16(GetOriginUrl().spec());
|
| string16 replace_key = UTF8ToUTF16(GetKey());
|
| + string16 notification_heading = heading;
|
| + string16 notification_text = text;
|
|
|
| // The delegate will eventually catch calls that the notification
|
| // was read or deleted, and send the changes back to the server.
|
| @@ -209,7 +235,7 @@ void SyncedNotification::Show(NotificationUIManager* notification_manager,
|
| // Fill in the button data.
|
| // TODO(petewil): Today Rich notifiations are limited to two buttons.
|
| // When rich notifications supports more, remove the
|
| - // "&& i < kMaxNotificationButtonIndex" below.
|
| + // "&& i < kMaxNotificationButtonIndex" clause below.
|
| for (unsigned int i = 0;
|
| i < button_count
|
| && i < button_bitmaps_.size()
|
| @@ -239,11 +265,33 @@ void SyncedNotification::Show(NotificationUIManager* notification_manager,
|
| }
|
| }
|
|
|
| + // Set the heading and text appropriately for the message type.
|
| + notification_text = annotation;
|
| + if (notification_type == message_center::NOTIFICATION_TYPE_IMAGE) {
|
| + // For an image, fill in the description field.
|
| + notification_text = description;
|
| + } else if (notification_count == 1) {
|
| + // For a single collapsed info entry, use the contained message if any.
|
| + std::string comment_body = GetContainedNotificationMessage(0);
|
| + std::string comment_header = GetContainedNotificationTitle(0);
|
| + if (!comment_header.empty() && !comment_body.empty())
|
| + notification_text = UTF8ToUTF16(comment_header) + UTF8ToUTF16(" ") +
|
| + UTF8ToUTF16(comment_body);
|
| + }
|
| +
|
| + // If there is a single person sending, use their picture instead of the app
|
| + // icon.
|
| + // TODO(petewil): Someday combine multiple profile photos here.
|
| + gfx::Image icon_bitmap = app_icon_bitmap_;
|
| + if (GetProfilePictureCount() == 1) {
|
| + icon_bitmap = sender_bitmap_;
|
| + }
|
| +
|
| Notification ui_notification(notification_type,
|
| GetOriginUrl(),
|
| - heading,
|
| - text,
|
| - app_icon_bitmap_,
|
| + notification_heading,
|
| + notification_text,
|
| + icon_bitmap,
|
| WebKit::WebTextDirectionDefault,
|
| display_source,
|
| replace_key,
|
| @@ -251,11 +299,11 @@ void SyncedNotification::Show(NotificationUIManager* notification_manager,
|
| delegate.get());
|
| notification_manager->Add(ui_notification, profile);
|
| } else {
|
| -
|
| + // In this case we have a Webkit Notification, not a Rich Notification.
|
| Notification ui_notification(GetOriginUrl(),
|
| GetAppIconUrl(),
|
| - heading,
|
| - text,
|
| + notification_heading,
|
| + notification_text,
|
| WebKit::WebTextDirectionDefault,
|
| display_source,
|
| replace_key,
|
| @@ -272,13 +320,13 @@ void SyncedNotification::Show(NotificationUIManager* notification_manager,
|
| }
|
|
|
| // This should detect even small changes in case the server updated the
|
| -// notification.
|
| -// TODO(petewil): Should I also ignore the timestamp if other fields match?
|
| +// notification. We ignore the timestamp if other fields match.
|
| bool SyncedNotification::EqualsIgnoringReadState(
|
| const SyncedNotification& other) const {
|
| if (GetTitle() == other.GetTitle() &&
|
| GetHeading() == other.GetHeading() &&
|
| GetDescription() == other.GetDescription() &&
|
| + GetAnnotation() == other.GetAnnotation() &&
|
| GetAppId() == other.GetAppId() &&
|
| GetKey() == other.GetKey() &&
|
| GetOriginUrl() == other.GetOriginUrl() &&
|
| @@ -291,7 +339,8 @@ bool SyncedNotification::EqualsIgnoringReadState(
|
| GetDefaultDestinationTitle() == other.GetDefaultDestinationTitle() &&
|
| GetDefaultDestinationIconUrl() == other.GetDefaultDestinationIconUrl() &&
|
| GetNotificationCount() == other.GetNotificationCount() &&
|
| - GetButtonCount() == other.GetButtonCount()) {
|
| + GetButtonCount() == other.GetButtonCount() &&
|
| + GetProfilePictureCount() == other.GetProfilePictureCount()) {
|
|
|
| // If all the surface data matched, check, to see if contained data also
|
| // matches, titles and messages.
|
| @@ -314,6 +363,13 @@ bool SyncedNotification::EqualsIgnoringReadState(
|
| return false;
|
| }
|
|
|
| + // Make sure profile icons match
|
| + count = GetButtonCount();
|
| + for (size_t kk = 0; kk < count; ++kk) {
|
| + if (GetProfilePictureUrl(kk) != other.GetProfilePictureUrl(kk))
|
| + return false;
|
| + }
|
| +
|
| // If buttons and notifications matched, they are equivalent.
|
| return true;
|
| }
|
| @@ -369,6 +425,15 @@ std::string SyncedNotification::GetDescription() const {
|
| simple_collapsed_layout().description();
|
| }
|
|
|
| +std::string SyncedNotification::GetAnnotation() const {
|
| + if (!specifics_.coalesced_notification().render_info().collapsed_info().
|
| + simple_collapsed_layout().has_annotation())
|
| + return std::string();
|
| +
|
| + return specifics_.coalesced_notification().render_info().collapsed_info().
|
| + simple_collapsed_layout().annotation();
|
| +}
|
| +
|
| std::string SyncedNotification::GetAppId() const {
|
| if (!specifics_.coalesced_notification().has_app_id())
|
| return std::string();
|
| @@ -387,35 +452,32 @@ GURL SyncedNotification::GetOriginUrl() const {
|
| return GURL(origin_url);
|
| }
|
|
|
| -// TODO(petewil): This only returns the first icon. Make all the icons
|
| -// available.
|
| GURL SyncedNotification::GetAppIconUrl() const {
|
| - if (specifics_.coalesced_notification().render_info().expanded_info().
|
| - collapsed_info_size() == 0)
|
| + if (!specifics_.coalesced_notification().render_info().collapsed_info().
|
| + simple_collapsed_layout().has_app_icon())
|
| return GURL();
|
|
|
| - if (!specifics_.coalesced_notification().render_info().expanded_info().
|
| - collapsed_info(0).simple_collapsed_layout().has_app_icon())
|
| - return GURL();
|
| + std::string url_spec = specifics_.coalesced_notification().render_info().
|
| + collapsed_info().simple_collapsed_layout().app_icon().url();
|
|
|
| - return GURL(specifics_.coalesced_notification().render_info().
|
| - expanded_info().collapsed_info(0).simple_collapsed_layout().
|
| - app_icon().url());
|
| + return AddDefaultSchemaIfNeeded(url_spec);
|
| }
|
|
|
| -// TODO(petewil): This currenly only handles the first image from the first
|
| -// collapsed item, someday return all images.
|
| +// TODO(petewil): This ignores all but the first image. If Rich Notifications
|
| +// supports more images someday, then fetch all images.
|
| GURL SyncedNotification::GetImageUrl() const {
|
| - if (specifics_.coalesced_notification().render_info().expanded_info().
|
| - simple_expanded_layout().media_size() == 0)
|
| + if (specifics_.coalesced_notification().render_info().collapsed_info().
|
| + simple_collapsed_layout().media_size() == 0)
|
| return GURL();
|
|
|
| - if (!specifics_.coalesced_notification().render_info().expanded_info().
|
| - simple_expanded_layout().media(0).image().has_url())
|
| + if (!specifics_.coalesced_notification().render_info().collapsed_info().
|
| + simple_collapsed_layout().media(0).image().has_url())
|
| return GURL();
|
|
|
| - return GURL(specifics_.coalesced_notification().render_info().
|
| - expanded_info().simple_expanded_layout().media(0).image().url());
|
| + std::string url_spec = specifics_.coalesced_notification().render_info().
|
| + collapsed_info().simple_collapsed_layout().media(0).image().url();
|
| +
|
| + return AddDefaultSchemaIfNeeded(url_spec);
|
| }
|
|
|
| std::string SyncedNotification::GetText() const {
|
| @@ -491,6 +553,23 @@ size_t SyncedNotification::GetButtonCount() const {
|
| target_size();
|
| }
|
|
|
| +size_t SyncedNotification::GetProfilePictureCount() const {
|
| + return specifics_.coalesced_notification().render_info().collapsed_info().
|
| + simple_collapsed_layout().profile_image_size();
|
| +}
|
| +
|
| +GURL SyncedNotification::GetProfilePictureUrl(unsigned int which_url) const {
|
| + if (GetProfilePictureCount() <= which_url)
|
| + return GURL();
|
| +
|
| + std::string url_spec = specifics_.coalesced_notification().render_info().
|
| + collapsed_info().simple_collapsed_layout().profile_image(which_url).
|
| + image_url();
|
| +
|
| + return AddDefaultSchemaIfNeeded(url_spec);
|
| +}
|
| +
|
| +
|
| std::string SyncedNotification::GetDefaultDestinationTitle() const {
|
| if (!specifics_.coalesced_notification().render_info().collapsed_info().
|
| default_destination().icon().has_alt_text()) {
|
| @@ -505,8 +584,10 @@ GURL SyncedNotification::GetDefaultDestinationIconUrl() const {
|
| default_destination().icon().has_url()) {
|
| return GURL();
|
| }
|
| - return GURL(specifics_.coalesced_notification().render_info().
|
| - collapsed_info().default_destination().icon().url());
|
| + std::string url_spec = specifics_.coalesced_notification().render_info().
|
| + collapsed_info().default_destination().icon().url();
|
| +
|
| + return AddDefaultSchemaIfNeeded(url_spec);
|
| }
|
|
|
| GURL SyncedNotification::GetDefaultDestinationUrl() const {
|
| @@ -514,8 +595,10 @@ GURL SyncedNotification::GetDefaultDestinationUrl() const {
|
| default_destination().has_url()) {
|
| return GURL();
|
| }
|
| - return GURL(specifics_.coalesced_notification().render_info().
|
| - collapsed_info().default_destination().url());
|
| + std::string url_spec = specifics_.coalesced_notification().render_info().
|
| + collapsed_info().default_destination().url();
|
| +
|
| + return AddDefaultSchemaIfNeeded(url_spec);
|
| }
|
|
|
| std::string SyncedNotification::GetButtonTitle(
|
| @@ -539,8 +622,10 @@ GURL SyncedNotification::GetButtonIconUrl(unsigned int which_button) const {
|
| target(which_button).action().icon().has_url()) {
|
| return GURL();
|
| }
|
| - return GURL(specifics_.coalesced_notification().render_info().
|
| - collapsed_info().target(which_button).action().icon().url());
|
| + std::string url_spec = specifics_.coalesced_notification().render_info().
|
| + collapsed_info().target(which_button).action().icon().url();
|
| +
|
| + return AddDefaultSchemaIfNeeded(url_spec);
|
| }
|
|
|
| GURL SyncedNotification::GetButtonUrl(unsigned int which_button) const {
|
| @@ -551,8 +636,10 @@ GURL SyncedNotification::GetButtonUrl(unsigned int which_button) const {
|
| target(which_button).action().has_url()) {
|
| return GURL();
|
| }
|
| - return GURL(specifics_.coalesced_notification().render_info().
|
| - collapsed_info().target(which_button).action().url());
|
| + std::string url_spec = specifics_.coalesced_notification().render_info().
|
| + collapsed_info().target(which_button).action().url();
|
| +
|
| + return AddDefaultSchemaIfNeeded(url_spec);
|
| }
|
|
|
| std::string SyncedNotification::GetContainedNotificationTitle(
|
|
|