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 |