| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/notifications/sync_notifier/synced_notification.h" | 5 #include "chrome/browser/notifications/sync_notifier/synced_notification.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
| 9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #include "ui/message_center/notification_types.h" | 30 #include "ui/message_center/notification_types.h" |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 const char kExtensionScheme[] = "synced-notification://"; | 33 const char kExtensionScheme[] = "synced-notification://"; |
| 34 const char kDefaultSyncedNotificationScheme[] = "https:"; | 34 const char kDefaultSyncedNotificationScheme[] = "https:"; |
| 35 | 35 |
| 36 // Today rich notifications only supports two buttons, make sure we don't | 36 // Today rich notifications only supports two buttons, make sure we don't |
| 37 // try to supply them with more than this number of buttons. | 37 // try to supply them with more than this number of buttons. |
| 38 const unsigned int kMaxNotificationButtonIndex = 2; | 38 const unsigned int kMaxNotificationButtonIndex = 2; |
| 39 | 39 |
| 40 bool UseRichNotifications() { | |
| 41 return message_center::IsRichNotificationEnabled(); | |
| 42 } | |
| 43 | |
| 44 // Schema-less specs default badly in windows. If we find one, add the schema | 40 // Schema-less specs default badly in windows. If we find one, add the schema |
| 45 // we expect instead of allowing windows specific GURL code to make it default | 41 // we expect instead of allowing windows specific GURL code to make it default |
| 46 // to "file:". | 42 // to "file:". |
| 47 GURL AddDefaultSchemaIfNeeded(std::string& url_spec) { | 43 GURL AddDefaultSchemaIfNeeded(std::string& url_spec) { |
| 48 if (StartsWithASCII(url_spec, std::string("//"), false)) | 44 if (StartsWithASCII(url_spec, std::string("//"), false)) |
| 49 return GURL(std::string(kDefaultSyncedNotificationScheme) + url_spec); | 45 return GURL(std::string(kDefaultSyncedNotificationScheme) + url_spec); |
| 50 | 46 |
| 51 return GURL(url_spec); | 47 return GURL(url_spec); |
| 52 } | 48 } |
| 53 | 49 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 // Let NotificationUIManager know that the notification has been dismissed. | 89 // Let NotificationUIManager know that the notification has been dismissed. |
| 94 if (SyncedNotification::kRead == GetReadState() || | 90 if (SyncedNotification::kRead == GetReadState() || |
| 95 SyncedNotification::kDismissed == GetReadState() ) { | 91 SyncedNotification::kDismissed == GetReadState() ) { |
| 96 notification_manager_->CancelById(GetKey()); | 92 notification_manager_->CancelById(GetKey()); |
| 97 DVLOG(2) << "Dismissed or read notification arrived" | 93 DVLOG(2) << "Dismissed or read notification arrived" |
| 98 << GetHeading() << " " << GetText(); | 94 << GetHeading() << " " << GetText(); |
| 99 return; | 95 return; |
| 100 } | 96 } |
| 101 | 97 |
| 102 // |notifier_service| can be NULL in tests. | 98 // |notifier_service| can be NULL in tests. |
| 103 if (UseRichNotifications() && notifier_service_) { | 99 if (notifier_service_) { |
| 104 notifier_service_->ShowWelcomeToastIfNecessary(this, notification_manager_); | 100 notifier_service_->ShowWelcomeToastIfNecessary(this, notification_manager_); |
| 105 } | 101 } |
| 106 | 102 |
| 107 // Set up the fields we need to send and create a Notification object. | 103 // Set up the fields we need to send and create a Notification object. |
| 108 GURL image_url = GetImageUrl(); | 104 GURL image_url = GetImageUrl(); |
| 109 base::string16 text = base::UTF8ToUTF16(GetText()); | 105 base::string16 text = base::UTF8ToUTF16(GetText()); |
| 110 base::string16 heading = base::UTF8ToUTF16(GetHeading()); | 106 base::string16 heading = base::UTF8ToUTF16(GetHeading()); |
| 111 base::string16 description = base::UTF8ToUTF16(GetDescription()); | 107 base::string16 description = base::UTF8ToUTF16(GetDescription()); |
| 112 base::string16 annotation = base::UTF8ToUTF16(GetAnnotation()); | 108 base::string16 annotation = base::UTF8ToUTF16(GetAnnotation()); |
| 113 // TODO(petewil): Eventually put the display name of the sending service here. | 109 // TODO(petewil): Eventually put the display name of the sending service here. |
| 114 base::string16 display_source = base::UTF8ToUTF16(GetAppId()); | 110 base::string16 display_source = base::UTF8ToUTF16(GetAppId()); |
| 115 base::string16 replace_key = base::UTF8ToUTF16(GetKey()); | 111 base::string16 replace_key = base::UTF8ToUTF16(GetKey()); |
| 116 base::string16 notification_heading = heading; | 112 base::string16 notification_heading = heading; |
| 117 base::string16 notification_text = description; | 113 base::string16 notification_text = description; |
| 118 base::string16 newline = base::UTF8ToUTF16("\n"); | 114 base::string16 newline = base::UTF8ToUTF16("\n"); |
| 119 | 115 |
| 120 // The delegate will eventually catch calls that the notification | 116 // The delegate will eventually catch calls that the notification |
| 121 // was read or deleted, and send the changes back to the server. | 117 // was read or deleted, and send the changes back to the server. |
| 122 scoped_refptr<NotificationDelegate> delegate = | 118 scoped_refptr<NotificationDelegate> delegate = |
| 123 new ChromeNotifierDelegate(GetKey(), notifier_service_); | 119 new ChromeNotifierDelegate(GetKey(), notifier_service_); |
| 124 | 120 |
| 125 // Some inputs and fields are only used if there is a notification center. | 121 // Some inputs and fields are only used if there is a notification center. |
| 126 if (UseRichNotifications()) { | 122 base::Time creation_time = |
| 127 base::Time creation_time = | 123 base::Time::FromDoubleT(static_cast<double>(GetCreationTime())); |
| 128 base::Time::FromDoubleT(static_cast<double>(GetCreationTime())); | 124 int priority = GetPriority(); |
| 129 int priority = GetPriority(); | 125 unsigned int button_count = GetButtonCount(); |
| 130 unsigned int button_count = GetButtonCount(); | |
| 131 | 126 |
| 132 // Deduce which notification template to use from the data. | 127 // Deduce which notification template to use from the data. |
| 133 message_center::NotificationType notification_type = | 128 message_center::NotificationType notification_type = |
| 134 message_center::NOTIFICATION_TYPE_BASE_FORMAT; | 129 message_center::NOTIFICATION_TYPE_BASE_FORMAT; |
| 135 if (!image_url.is_empty()) { | 130 if (!image_url.is_empty()) { |
| 136 notification_type = message_center::NOTIFICATION_TYPE_IMAGE; | 131 notification_type = message_center::NOTIFICATION_TYPE_IMAGE; |
| 137 } else if (button_count > 0) { | 132 } else if (button_count > 0) { |
| 138 notification_type = message_center::NOTIFICATION_TYPE_BASE_FORMAT; | 133 notification_type = message_center::NOTIFICATION_TYPE_BASE_FORMAT; |
| 139 } | 134 } |
| 140 | 135 |
| 141 // Fill the optional fields with the information we need to make a | 136 // Fill the optional fields with the information we need to make a |
| 142 // notification. | 137 // notification. |
| 143 message_center::RichNotificationData rich_notification_data; | 138 message_center::RichNotificationData rich_notification_data; |
| 144 rich_notification_data.timestamp = creation_time; | 139 rich_notification_data.timestamp = creation_time; |
| 145 if (priority != SyncedNotification::kUndefinedPriority) | 140 if (priority != SyncedNotification::kUndefinedPriority) |
| 146 rich_notification_data.priority = priority; | 141 rich_notification_data.priority = priority; |
| 147 | 142 |
| 148 // Fill in the button data. | 143 // Fill in the button data. |
| 149 // TODO(petewil): Today Rich notifiations are limited to two buttons. | 144 // TODO(petewil): Today Rich notifiations are limited to two buttons. |
| 150 // When rich notifications supports more, remove the | 145 // When rich notifications supports more, remove the |
| 151 // "&& i < kMaxNotificationButtonIndex" clause below. | 146 // "&& i < kMaxNotificationButtonIndex" clause below. |
| 152 for (unsigned int i = 0; | 147 for (unsigned int i = 0; |
| 153 i < button_count | 148 i < button_count |
| 154 && i < button_bitmaps_.size() | 149 && i < button_bitmaps_.size() |
| 155 && i < kMaxNotificationButtonIndex; | 150 && i < kMaxNotificationButtonIndex; |
| 156 ++i) { | 151 ++i) { |
| 157 // Stop at the first button with no title | 152 // Stop at the first button with no title |
| 158 std::string title = GetButtonTitle(i); | 153 std::string title = GetButtonTitle(i); |
| 159 if (title.empty()) | 154 if (title.empty()) |
| 160 break; | 155 break; |
| 161 message_center::ButtonInfo button_info(base::UTF8ToUTF16(title)); | 156 message_center::ButtonInfo button_info(base::UTF8ToUTF16(title)); |
| 162 if (!button_bitmaps_[i].IsEmpty()) | 157 if (!button_bitmaps_[i].IsEmpty()) |
| 163 button_info.icon = button_bitmaps_[i]; | 158 button_info.icon = button_bitmaps_[i]; |
| 164 rich_notification_data.buttons.push_back(button_info); | 159 rich_notification_data.buttons.push_back(button_info); |
| 165 } | 160 } |
| 166 | 161 |
| 167 // Fill in the bitmap images. | 162 // Fill in the bitmap images. |
| 168 if (!image_bitmap_.IsEmpty()) | 163 if (!image_bitmap_.IsEmpty()) |
| 169 rich_notification_data.image = image_bitmap_; | 164 rich_notification_data.image = image_bitmap_; |
| 170 | 165 |
| 171 if (!app_icon_bitmap_.IsEmpty()) { | 166 if (!app_icon_bitmap_.IsEmpty()) { |
| 172 // Since we can't control the size of images we download, resize using a | 167 // Since we can't control the size of images we download, resize using a |
| 173 // high quality filter down to the appropriate icon size. | 168 // high quality filter down to the appropriate icon size. |
| 174 // TODO(dewittj): Remove this when correct resources are sent via the | 169 // TODO(dewittj): Remove this when correct resources are sent via the |
| 175 // protobuf. | 170 // protobuf. |
| 176 SkBitmap new_app_icon = | 171 SkBitmap new_app_icon = |
| 177 skia::ImageOperations::Resize(app_icon_bitmap_.AsBitmap(), | 172 skia::ImageOperations::Resize(app_icon_bitmap_.AsBitmap(), |
| 178 skia::ImageOperations::RESIZE_BEST, | 173 skia::ImageOperations::RESIZE_BEST, |
| 179 message_center::kSmallImageSize, | 174 message_center::kSmallImageSize, |
| 180 message_center::kSmallImageSize); | 175 message_center::kSmallImageSize); |
| 181 | 176 |
| 182 // The app icon should be in grayscale. | 177 // The app icon should be in grayscale. |
| 183 // TODO(dewittj): Remove this when correct resources are sent via the | 178 // TODO(dewittj): Remove this when correct resources are sent via the |
| 184 // protobuf. | 179 // protobuf. |
| 185 color_utils::HSL shift = {-1, 0, 0.6}; | 180 color_utils::HSL shift = {-1, 0, 0.6}; |
| 186 SkBitmap grayscale = | 181 SkBitmap grayscale = |
| 187 SkBitmapOperations::CreateHSLShiftedBitmap(new_app_icon, shift); | 182 SkBitmapOperations::CreateHSLShiftedBitmap(new_app_icon, shift); |
| 188 gfx::Image small_image = | 183 gfx::Image small_image = |
| 189 gfx::Image(gfx::ImageSkia(gfx::ImageSkiaRep(grayscale, 1.0f))); | 184 gfx::Image(gfx::ImageSkia(gfx::ImageSkiaRep(grayscale, 1.0f))); |
| 190 rich_notification_data.small_image = small_image; | 185 rich_notification_data.small_image = small_image; |
| 191 } | 186 } |
| 192 | 187 |
| 193 // Set the ContextMessage inside the rich notification data for the | 188 // Set the ContextMessage inside the rich notification data for the |
| 194 // annotation. | 189 // annotation. |
| 195 rich_notification_data.context_message = annotation; | 190 rich_notification_data.context_message = annotation; |
| 196 | 191 |
| 197 // Set the clickable flag to change the cursor on hover if a valid | 192 // Set the clickable flag to change the cursor on hover if a valid |
| 198 // destination is found. | 193 // destination is found. |
| 199 rich_notification_data.clickable = GetDefaultDestinationUrl().is_valid(); | 194 rich_notification_data.clickable = GetDefaultDestinationUrl().is_valid(); |
| 200 | 195 |
| 201 // If there is at least one person sending, use the first picture. | 196 // If there is at least one person sending, use the first picture. |
| 202 // TODO(petewil): Someday combine multiple profile photos here. | 197 // TODO(petewil): Someday combine multiple profile photos here. |
| 203 gfx::Image icon_bitmap = app_icon_bitmap_; | 198 gfx::Image icon_bitmap = app_icon_bitmap_; |
| 204 if (GetProfilePictureCount() >= 1) { | 199 if (GetProfilePictureCount() >= 1) { |
| 205 icon_bitmap = sender_bitmap_; | 200 icon_bitmap = sender_bitmap_; |
| 206 } | 201 } |
| 207 | 202 |
| 208 Notification ui_notification(notification_type, | 203 Notification ui_notification(notification_type, |
| 209 GetOriginUrl(), | 204 GetOriginUrl(), |
| 210 notification_heading, | 205 notification_heading, |
| 211 notification_text, | 206 notification_text, |
| 212 icon_bitmap, | 207 icon_bitmap, |
| 213 blink::WebTextDirectionDefault, | 208 blink::WebTextDirectionDefault, |
| 214 message_center::NotifierId(GetOriginUrl()), | 209 message_center::NotifierId(GetOriginUrl()), |
| 215 display_source, | 210 display_source, |
| 216 replace_key, | 211 replace_key, |
| 217 rich_notification_data, | 212 rich_notification_data, |
| 218 delegate.get()); | 213 delegate.get()); |
| 219 // In case the notification is not supposed to be toasted, pretend that it | 214 // In case the notification is not supposed to be toasted, pretend that it |
| 220 // has already been shown. | 215 // has already been shown. |
| 221 ui_notification.set_shown_as_popup(!toast_state_); | 216 ui_notification.set_shown_as_popup(!toast_state_); |
| 222 | 217 |
| 223 notification_manager_->Add(ui_notification, profile); | 218 notification_manager_->Add(ui_notification, profile); |
| 224 } else { | |
| 225 // In this case we have a Webkit Notification, not a Rich Notification. | |
| 226 Notification ui_notification(GetOriginUrl(), | |
| 227 GetAppIconUrl(), | |
| 228 notification_heading, | |
| 229 notification_text, | |
| 230 blink::WebTextDirectionDefault, | |
| 231 display_source, | |
| 232 replace_key, | |
| 233 delegate.get()); | |
| 234 | |
| 235 notification_manager_->Add(ui_notification, profile); | |
| 236 } | |
| 237 | 219 |
| 238 DVLOG(1) << "Showing Synced Notification! " << heading << " " << text | 220 DVLOG(1) << "Showing Synced Notification! " << heading << " " << text |
| 239 << " " << GetAppIconUrl() << " " << replace_key << " " | 221 << " " << GetAppIconUrl() << " " << replace_key << " " |
| 240 << GetProfilePictureUrl(0) << " " << GetReadState(); | 222 << GetProfilePictureUrl(0) << " " << GetReadState(); |
| 241 | 223 |
| 242 return; | 224 return; |
| 243 } | 225 } |
| 244 | 226 |
| 245 sync_pb::EntitySpecifics SyncedNotification::GetEntitySpecifics() const { | 227 sync_pb::EntitySpecifics SyncedNotification::GetEntitySpecifics() const { |
| 246 sync_pb::EntitySpecifics entity_specifics; | 228 sync_pb::EntitySpecifics entity_specifics; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 258 // Remove the notification if it has the specified app_id_name. | 240 // Remove the notification if it has the specified app_id_name. |
| 259 void SyncedNotification::HideAllForAppId(std::string app_id_name) { | 241 void SyncedNotification::HideAllForAppId(std::string app_id_name) { |
| 260 if (app_id_name == GetAppId()) { | 242 if (app_id_name == GetAppId()) { |
| 261 notification_manager_->CancelById(GetKey()); | 243 notification_manager_->CancelById(GetKey()); |
| 262 } | 244 } |
| 263 } | 245 } |
| 264 | 246 |
| 265 void SyncedNotification::QueueBitmapFetchJobs( | 247 void SyncedNotification::QueueBitmapFetchJobs( |
| 266 ChromeNotifierService* notifier_service, | 248 ChromeNotifierService* notifier_service, |
| 267 Profile* profile) { | 249 Profile* profile) { |
| 268 // If we are not using the MessageCenter, call show now, and the existing | |
| 269 // code will handle the bitmap fetch for us. | |
| 270 if (!UseRichNotifications()) { | |
| 271 Show(profile); | |
| 272 return; | |
| 273 } | |
| 274 | |
| 275 // Save off the arguments for the call to Show. | 250 // Save off the arguments for the call to Show. |
| 276 notifier_service_ = notifier_service; | 251 notifier_service_ = notifier_service; |
| 277 profile_ = profile; | 252 profile_ = profile; |
| 278 | 253 |
| 279 // Ensure our bitmap vector has as many entries as there are buttons, | 254 // Ensure our bitmap vector has as many entries as there are buttons, |
| 280 // so that when the bitmaps arrive the vector has a slot for them. | 255 // so that when the bitmaps arrive the vector has a slot for them. |
| 281 for (unsigned int i = 0; i < GetButtonCount(); ++i) { | 256 for (unsigned int i = 0; i < GetButtonCount(); ++i) { |
| 282 button_bitmaps_.push_back(gfx::Image()); | 257 button_bitmaps_.push_back(gfx::Image()); |
| 283 button_bitmaps_fetch_pending_.push_back(true); | 258 button_bitmaps_fetch_pending_.push_back(true); |
| 284 CreateBitmapFetcher(GetButtonIconUrl(i)); | 259 CreateBitmapFetcher(GetButtonIconUrl(i)); |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 specifics_.mutable_coalesced_notification()->set_read_state( | 732 specifics_.mutable_coalesced_notification()->set_read_state( |
| 758 sync_pb::CoalescedSyncedNotification_ReadState_UNREAD); | 733 sync_pb::CoalescedSyncedNotification_ReadState_UNREAD); |
| 759 else if (kRead == read_state) | 734 else if (kRead == read_state) |
| 760 specifics_.mutable_coalesced_notification()->set_read_state( | 735 specifics_.mutable_coalesced_notification()->set_read_state( |
| 761 sync_pb::CoalescedSyncedNotification_ReadState_READ); | 736 sync_pb::CoalescedSyncedNotification_ReadState_READ); |
| 762 else | 737 else |
| 763 NOTREACHED(); | 738 NOTREACHED(); |
| 764 } | 739 } |
| 765 | 740 |
| 766 } // namespace notifier | 741 } // namespace notifier |
| OLD | NEW |