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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 local_enum_must_match_protobuf_enum); | 61 local_enum_must_match_protobuf_enum); |
62 COMPILE_ASSERT(static_cast<sync_pb::CoalescedSyncedNotification_ReadState>( | 62 COMPILE_ASSERT(static_cast<sync_pb::CoalescedSyncedNotification_ReadState>( |
63 SyncedNotification::kRead) == | 63 SyncedNotification::kRead) == |
64 sync_pb::CoalescedSyncedNotification_ReadState_READ, | 64 sync_pb::CoalescedSyncedNotification_ReadState_READ, |
65 local_enum_must_match_protobuf_enum); | 65 local_enum_must_match_protobuf_enum); |
66 COMPILE_ASSERT(static_cast<sync_pb::CoalescedSyncedNotification_ReadState>( | 66 COMPILE_ASSERT(static_cast<sync_pb::CoalescedSyncedNotification_ReadState>( |
67 SyncedNotification::kDismissed) == | 67 SyncedNotification::kDismissed) == |
68 sync_pb::CoalescedSyncedNotification_ReadState_DISMISSED, | 68 sync_pb::CoalescedSyncedNotification_ReadState_DISMISSED, |
69 local_enum_must_match_protobuf_enum); | 69 local_enum_must_match_protobuf_enum); |
70 | 70 |
71 SyncedNotification::SyncedNotification(const syncer::SyncData& sync_data) | 71 SyncedNotification::SyncedNotification( |
72 : notification_manager_(NULL), | 72 const syncer::SyncData& sync_data, |
73 notifier_service_(NULL), | 73 ChromeNotifierService* notifier_service, |
| 74 NotificationUIManager* notification_manager) |
| 75 : notification_manager_(notification_manager), |
| 76 notifier_service_(notifier_service), |
74 profile_(NULL), | 77 profile_(NULL), |
75 toast_state_(true), | 78 toast_state_(true), |
76 app_icon_bitmap_fetch_pending_(true), | 79 app_icon_bitmap_fetch_pending_(true), |
77 sender_bitmap_fetch_pending_(true), | 80 sender_bitmap_fetch_pending_(true), |
78 image_bitmap_fetch_pending_(true) { | 81 image_bitmap_fetch_pending_(true) { |
79 Update(sync_data); | 82 Update(sync_data); |
80 } | 83 } |
81 | 84 |
82 SyncedNotification::~SyncedNotification() {} | 85 SyncedNotification::~SyncedNotification() {} |
83 | 86 |
84 void SyncedNotification::Update(const syncer::SyncData& sync_data) { | 87 void SyncedNotification::Update(const syncer::SyncData& sync_data) { |
85 // TODO(petewil): Add checking that the notification looks valid. | 88 // TODO(petewil): Add checking that the notification looks valid. |
86 specifics_.CopyFrom(sync_data.GetSpecifics().synced_notification()); | 89 specifics_.CopyFrom(sync_data.GetSpecifics().synced_notification()); |
87 } | 90 } |
88 | 91 |
89 sync_pb::EntitySpecifics SyncedNotification::GetEntitySpecifics() const { | 92 void SyncedNotification::Show(Profile* profile) { |
90 sync_pb::EntitySpecifics entity_specifics; | |
91 entity_specifics.mutable_synced_notification()->CopyFrom(specifics_); | |
92 return entity_specifics; | |
93 } | |
94 | |
95 // Check that we have either fetched or gotten an error on all the bitmaps we | |
96 // asked for. | |
97 bool SyncedNotification::AreAllBitmapsFetched() { | |
98 bool app_icon_ready = GetAppIconUrl().is_empty() || | |
99 !app_icon_bitmap_.IsEmpty() || !app_icon_bitmap_fetch_pending_; | |
100 bool images_ready = GetImageUrl().is_empty() || !image_bitmap_.IsEmpty() || | |
101 !image_bitmap_fetch_pending_; | |
102 bool sender_picture_ready = GetProfilePictureUrl(0).is_empty() || | |
103 !sender_bitmap_.IsEmpty() || !sender_bitmap_fetch_pending_; | |
104 bool button_bitmaps_ready = true; | |
105 for (unsigned int j = 0; j < GetButtonCount(); ++j) { | |
106 if (!GetButtonIconUrl(j).is_empty() | |
107 && button_bitmaps_[j].IsEmpty() | |
108 && button_bitmaps_fetch_pending_[j]) { | |
109 button_bitmaps_ready = false; | |
110 break; | |
111 } | |
112 } | |
113 | |
114 return app_icon_ready && images_ready && sender_picture_ready && | |
115 button_bitmaps_ready; | |
116 } | |
117 | |
118 // TODO(petewil): The fetch mechanism appears to be returning two bitmaps on the | |
119 // mac - perhaps one is regular, one is high dpi? If so, ensure we use the high | |
120 // dpi bitmap when appropriate. | |
121 void SyncedNotification::OnFetchComplete(const GURL url, | |
122 const SkBitmap* bitmap) { | |
123 // TODO(petewil): Add timeout mechanism in case bitmaps take too long. Do we | |
124 // already have one built into URLFetcher? | |
125 // Make sure we are on the thread we expect. | |
126 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
127 | |
128 gfx::Image downloaded_image; | |
129 if (bitmap != NULL) | |
130 downloaded_image = gfx::Image::CreateFrom1xBitmap(*bitmap); | |
131 | |
132 // Match the incoming bitmaps to URLs. In case this is a dup, make sure to | |
133 // try all potentially matching urls. | |
134 if (GetAppIconUrl() == url) { | |
135 app_icon_bitmap_ = downloaded_image; | |
136 if (app_icon_bitmap_.IsEmpty()) | |
137 app_icon_bitmap_fetch_pending_ = false; | |
138 } | |
139 if (GetImageUrl() == url) { | |
140 image_bitmap_ = downloaded_image; | |
141 if (image_bitmap_.IsEmpty()) | |
142 image_bitmap_fetch_pending_ = false; | |
143 } | |
144 if (GetProfilePictureUrl(0) == url) { | |
145 sender_bitmap_ = downloaded_image; | |
146 if (sender_bitmap_.IsEmpty()) | |
147 sender_bitmap_fetch_pending_ = false; | |
148 } | |
149 | |
150 // If this URL matches one or more button bitmaps, save them off. | |
151 for (unsigned int i = 0; i < GetButtonCount(); ++i) { | |
152 if (GetButtonIconUrl(i) == url) { | |
153 if (bitmap != NULL) { | |
154 button_bitmaps_[i] = gfx::Image::CreateFrom1xBitmap(*bitmap); | |
155 } | |
156 button_bitmaps_fetch_pending_[i] = false; | |
157 } | |
158 } | |
159 | |
160 DVLOG(2) << __FUNCTION__ << " popping bitmap " << url; | |
161 | |
162 // See if all bitmaps are already accounted for, if so call Show. | |
163 if (AreAllBitmapsFetched()) { | |
164 Show(notification_manager_, notifier_service_, profile_); | |
165 } | |
166 } | |
167 | |
168 void SyncedNotification::QueueBitmapFetchJobs( | |
169 NotificationUIManager* notification_manager, | |
170 ChromeNotifierService* notifier_service, | |
171 Profile* profile) { | |
172 // If we are not using the MessageCenter, call show now, and the existing | |
173 // code will handle the bitmap fetch for us. | |
174 if (!UseRichNotifications()) { | |
175 Show(notification_manager, notifier_service, profile); | |
176 return; | |
177 } | |
178 | |
179 // Save off the arguments for the call to Show. | |
180 notification_manager_ = notification_manager; | |
181 notifier_service_ = notifier_service; | |
182 profile_ = profile; | |
183 | |
184 // Ensure our bitmap vector has as many entries as there are buttons, | |
185 // so that when the bitmaps arrive the vector has a slot for them. | |
186 for (unsigned int i = 0; i < GetButtonCount(); ++i) { | |
187 button_bitmaps_.push_back(gfx::Image()); | |
188 button_bitmaps_fetch_pending_.push_back(true); | |
189 AddBitmapToFetchQueue(GetButtonIconUrl(i)); | |
190 } | |
191 | |
192 // If there is a profile image bitmap, fetch it | |
193 if (GetProfilePictureCount() > 0) { | |
194 // TODO(petewil): When we have the capacity to display more than one bitmap, | |
195 // modify this code to fetch as many as we can display | |
196 AddBitmapToFetchQueue(GetProfilePictureUrl(0)); | |
197 } | |
198 | |
199 // If the URL is non-empty, add it to our queue of URLs to fetch. | |
200 AddBitmapToFetchQueue(GetAppIconUrl()); | |
201 AddBitmapToFetchQueue(GetImageUrl()); | |
202 | |
203 // Check to see if we don't need to fetch images, either because we already | |
204 // did, or because the URLs are empty. If so, we can display the notification. | |
205 | |
206 // See if all bitmaps are accounted for, if so call Show(). | |
207 if (AreAllBitmapsFetched()) { | |
208 Show(notification_manager_, notifier_service_, profile_); | |
209 } | |
210 } | |
211 | |
212 void SyncedNotification::StartBitmapFetch() { | |
213 // Now that we have queued and counted them all, start the fetching. | |
214 ScopedVector<chrome::BitmapFetcher>::iterator iter; | |
215 for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) { | |
216 (*iter)->Start(profile_); | |
217 } | |
218 } | |
219 | |
220 void SyncedNotification::AddBitmapToFetchQueue(const GURL& url) { | |
221 // Check for dups, ignore any request for a dup. | |
222 ScopedVector<chrome::BitmapFetcher>::iterator iter; | |
223 for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) { | |
224 if ((*iter)->url() == url) | |
225 return; | |
226 } | |
227 | |
228 if (url.is_valid()) { | |
229 fetchers_.push_back(new chrome::BitmapFetcher(url, this)); | |
230 DVLOG(2) << __FUNCTION__ << "Pushing bitmap " << url; | |
231 } | |
232 } | |
233 | |
234 void SyncedNotification::Show(NotificationUIManager* notification_manager, | |
235 ChromeNotifierService* notifier_service, | |
236 Profile* profile) { | |
237 // Let NotificationUIManager know that the notification has been dismissed. | 93 // Let NotificationUIManager know that the notification has been dismissed. |
238 if (SyncedNotification::kRead == GetReadState() || | 94 if (SyncedNotification::kRead == GetReadState() || |
239 SyncedNotification::kDismissed == GetReadState() ) { | 95 SyncedNotification::kDismissed == GetReadState() ) { |
240 notification_manager->CancelById(GetKey()); | 96 notification_manager_->CancelById(GetKey()); |
241 DVLOG(2) << "Dismissed or read notification arrived" | 97 DVLOG(2) << "Dismissed or read notification arrived" |
242 << GetHeading() << " " << GetText(); | 98 << GetHeading() << " " << GetText(); |
243 return; | 99 return; |
244 } | 100 } |
245 | 101 |
246 // |notifier_service| can be NULL in tests. | 102 // |notifier_service| can be NULL in tests. |
247 if (UseRichNotifications() && notifier_service) { | 103 if (UseRichNotifications() && notifier_service_) { |
248 notifier_service->ShowWelcomeToastIfNecessary(this, notification_manager); | 104 notifier_service_->ShowWelcomeToastIfNecessary(this, notification_manager_); |
249 } | 105 } |
250 | 106 |
251 // Set up the fields we need to send and create a Notification object. | 107 // Set up the fields we need to send and create a Notification object. |
252 GURL image_url = GetImageUrl(); | 108 GURL image_url = GetImageUrl(); |
253 base::string16 text = base::UTF8ToUTF16(GetText()); | 109 base::string16 text = base::UTF8ToUTF16(GetText()); |
254 base::string16 heading = base::UTF8ToUTF16(GetHeading()); | 110 base::string16 heading = base::UTF8ToUTF16(GetHeading()); |
255 base::string16 description = base::UTF8ToUTF16(GetDescription()); | 111 base::string16 description = base::UTF8ToUTF16(GetDescription()); |
256 base::string16 annotation = base::UTF8ToUTF16(GetAnnotation()); | 112 base::string16 annotation = base::UTF8ToUTF16(GetAnnotation()); |
257 // TODO(petewil): Eventually put the display name of the sending service here. | 113 // TODO(petewil): Eventually put the display name of the sending service here. |
258 base::string16 display_source = base::UTF8ToUTF16(GetAppId()); | 114 base::string16 display_source = base::UTF8ToUTF16(GetAppId()); |
259 base::string16 replace_key = base::UTF8ToUTF16(GetKey()); | 115 base::string16 replace_key = base::UTF8ToUTF16(GetKey()); |
260 base::string16 notification_heading = heading; | 116 base::string16 notification_heading = heading; |
261 base::string16 notification_text = description; | 117 base::string16 notification_text = description; |
262 base::string16 newline = base::UTF8ToUTF16("\n"); | 118 base::string16 newline = base::UTF8ToUTF16("\n"); |
263 | 119 |
264 // The delegate will eventually catch calls that the notification | 120 // The delegate will eventually catch calls that the notification |
265 // was read or deleted, and send the changes back to the server. | 121 // was read or deleted, and send the changes back to the server. |
266 scoped_refptr<NotificationDelegate> delegate = | 122 scoped_refptr<NotificationDelegate> delegate = |
267 new ChromeNotifierDelegate(GetKey(), notifier_service); | 123 new ChromeNotifierDelegate(GetKey(), notifier_service_); |
268 | 124 |
269 // Some inputs and fields are only used if there is a notification center. | 125 // Some inputs and fields are only used if there is a notification center. |
270 if (UseRichNotifications()) { | 126 if (UseRichNotifications()) { |
271 base::Time creation_time = | 127 base::Time creation_time = |
272 base::Time::FromDoubleT(static_cast<double>(GetCreationTime())); | 128 base::Time::FromDoubleT(static_cast<double>(GetCreationTime())); |
273 int priority = GetPriority(); | 129 int priority = GetPriority(); |
274 unsigned int button_count = GetButtonCount(); | 130 unsigned int button_count = GetButtonCount(); |
275 | 131 |
276 // Deduce which notification template to use from the data. | 132 // Deduce which notification template to use from the data. |
277 message_center::NotificationType notification_type = | 133 message_center::NotificationType notification_type = |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 blink::WebTextDirectionDefault, | 213 blink::WebTextDirectionDefault, |
358 message_center::NotifierId(GetOriginUrl()), | 214 message_center::NotifierId(GetOriginUrl()), |
359 display_source, | 215 display_source, |
360 replace_key, | 216 replace_key, |
361 rich_notification_data, | 217 rich_notification_data, |
362 delegate.get()); | 218 delegate.get()); |
363 // In case the notification is not supposed to be toasted, pretend that it | 219 // In case the notification is not supposed to be toasted, pretend that it |
364 // has already been shown. | 220 // has already been shown. |
365 ui_notification.set_shown_as_popup(!toast_state_); | 221 ui_notification.set_shown_as_popup(!toast_state_); |
366 | 222 |
367 notification_manager->Add(ui_notification, profile); | 223 notification_manager_->Add(ui_notification, profile); |
368 } else { | 224 } else { |
369 // In this case we have a Webkit Notification, not a Rich Notification. | 225 // In this case we have a Webkit Notification, not a Rich Notification. |
370 Notification ui_notification(GetOriginUrl(), | 226 Notification ui_notification(GetOriginUrl(), |
371 GetAppIconUrl(), | 227 GetAppIconUrl(), |
372 notification_heading, | 228 notification_heading, |
373 notification_text, | 229 notification_text, |
374 blink::WebTextDirectionDefault, | 230 blink::WebTextDirectionDefault, |
375 display_source, | 231 display_source, |
376 replace_key, | 232 replace_key, |
377 delegate.get()); | 233 delegate.get()); |
378 | 234 |
379 notification_manager->Add(ui_notification, profile); | 235 notification_manager_->Add(ui_notification, profile); |
380 } | 236 } |
381 | 237 |
382 DVLOG(1) << "Showing Synced Notification! " << heading << " " << text | 238 DVLOG(1) << "Showing Synced Notification! " << heading << " " << text |
383 << " " << GetAppIconUrl() << " " << replace_key << " " | 239 << " " << GetAppIconUrl() << " " << replace_key << " " |
384 << GetProfilePictureUrl(0) << " " << GetReadState(); | 240 << GetProfilePictureUrl(0) << " " << GetReadState(); |
385 | 241 |
386 return; | 242 return; |
387 } | 243 } |
388 | 244 |
| 245 sync_pb::EntitySpecifics SyncedNotification::GetEntitySpecifics() const { |
| 246 sync_pb::EntitySpecifics entity_specifics; |
| 247 entity_specifics.mutable_synced_notification()->CopyFrom(specifics_); |
| 248 return entity_specifics; |
| 249 } |
| 250 |
| 251 // Display the notification if it has the specified app_id_name. |
| 252 void SyncedNotification::ShowAllForAppId(Profile* profile, |
| 253 std::string app_id_name) { |
| 254 if (app_id_name == GetAppId()) |
| 255 Show(profile); |
| 256 } |
| 257 |
| 258 // Remove the notification if it has the specified app_id_name. |
| 259 void SyncedNotification::HideAllForAppId(std::string app_id_name) { |
| 260 if (app_id_name == GetAppId()) { |
| 261 notification_manager_->CancelById(GetKey()); |
| 262 } |
| 263 } |
| 264 |
| 265 void SyncedNotification::QueueBitmapFetchJobs( |
| 266 ChromeNotifierService* notifier_service, |
| 267 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. |
| 276 notifier_service_ = notifier_service; |
| 277 profile_ = profile; |
| 278 |
| 279 // 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. |
| 281 for (unsigned int i = 0; i < GetButtonCount(); ++i) { |
| 282 button_bitmaps_.push_back(gfx::Image()); |
| 283 button_bitmaps_fetch_pending_.push_back(true); |
| 284 CreateBitmapFetcher(GetButtonIconUrl(i)); |
| 285 } |
| 286 |
| 287 // If there is a profile image bitmap, fetch it |
| 288 if (GetProfilePictureCount() > 0) { |
| 289 // TODO(petewil): When we have the capacity to display more than one bitmap, |
| 290 // modify this code to fetch as many as we can display |
| 291 CreateBitmapFetcher(GetProfilePictureUrl(0)); |
| 292 } |
| 293 |
| 294 // If the URL is non-empty, add it to our queue of URLs to fetch. |
| 295 CreateBitmapFetcher(GetAppIconUrl()); |
| 296 CreateBitmapFetcher(GetImageUrl()); |
| 297 |
| 298 // Check to see if we don't need to fetch images, either because we already |
| 299 // did, or because the URLs are empty. If so, we can display the notification. |
| 300 |
| 301 // See if all bitmaps are accounted for, if so call Show(). |
| 302 if (AreAllBitmapsFetched()) { |
| 303 Show(profile_); |
| 304 } |
| 305 } |
| 306 |
| 307 void SyncedNotification::StartBitmapFetch() { |
| 308 // Now that we have queued and counted them all, start the fetching. |
| 309 ScopedVector<chrome::BitmapFetcher>::iterator iter; |
| 310 for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) { |
| 311 (*iter)->Start(profile_); |
| 312 } |
| 313 } |
| 314 |
389 // This should detect even small changes in case the server updated the | 315 // This should detect even small changes in case the server updated the |
390 // notification. We ignore the timestamp if other fields match. | 316 // notification. We ignore the timestamp if other fields match. |
391 bool SyncedNotification::EqualsIgnoringReadState( | 317 bool SyncedNotification::EqualsIgnoringReadState( |
392 const SyncedNotification& other) const { | 318 const SyncedNotification& other) const { |
393 if (GetTitle() == other.GetTitle() && | 319 if (GetTitle() == other.GetTitle() && |
394 GetHeading() == other.GetHeading() && | 320 GetHeading() == other.GetHeading() && |
395 GetDescription() == other.GetDescription() && | 321 GetDescription() == other.GetDescription() && |
396 GetAnnotation() == other.GetAnnotation() && | 322 GetAnnotation() == other.GetAnnotation() && |
397 GetAppId() == other.GetAppId() && | 323 GetAppId() == other.GetAppId() && |
398 GetKey() == other.GetKey() && | 324 GetKey() == other.GetKey() && |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 return false; | 363 return false; |
438 } | 364 } |
439 | 365 |
440 // If buttons and notifications matched, they are equivalent. | 366 // If buttons and notifications matched, they are equivalent. |
441 return true; | 367 return true; |
442 } | 368 } |
443 | 369 |
444 return false; | 370 return false; |
445 } | 371 } |
446 | 372 |
447 void SyncedNotification::LogNotification() { | |
448 std::string readStateString("Unread"); | |
449 if (SyncedNotification::kRead == GetReadState()) | |
450 readStateString = "Read"; | |
451 else if (SyncedNotification::kDismissed == GetReadState()) | |
452 readStateString = "Dismissed"; | |
453 | |
454 DVLOG(2) << " Notification: Heading is " << GetHeading() | |
455 << " description is " << GetDescription() | |
456 << " key is " << GetKey() | |
457 << " read state is " << readStateString; | |
458 } | |
459 | |
460 // Set the read state on the notification, returns true for success. | |
461 void SyncedNotification::SetReadState(const ReadState& read_state) { | |
462 | |
463 // Convert the read state to the protobuf type for read state. | |
464 if (kDismissed == read_state) | |
465 specifics_.mutable_coalesced_notification()->set_read_state( | |
466 sync_pb::CoalescedSyncedNotification_ReadState_DISMISSED); | |
467 else if (kUnread == read_state) | |
468 specifics_.mutable_coalesced_notification()->set_read_state( | |
469 sync_pb::CoalescedSyncedNotification_ReadState_UNREAD); | |
470 else if (kRead == read_state) | |
471 specifics_.mutable_coalesced_notification()->set_read_state( | |
472 sync_pb::CoalescedSyncedNotification_ReadState_READ); | |
473 else | |
474 NOTREACHED(); | |
475 } | |
476 | |
477 void SyncedNotification::NotificationHasBeenRead() { | 373 void SyncedNotification::NotificationHasBeenRead() { |
478 SetReadState(kRead); | 374 SetReadState(kRead); |
479 } | 375 } |
480 | 376 |
481 void SyncedNotification::NotificationHasBeenDismissed() { | 377 void SyncedNotification::NotificationHasBeenDismissed() { |
482 SetReadState(kDismissed); | 378 SetReadState(kDismissed); |
483 } | 379 } |
484 | 380 |
485 std::string SyncedNotification::GetTitle() const { | 381 std::string SyncedNotification::GetTitle() const { |
486 if (!specifics_.coalesced_notification().render_info().expanded_info(). | 382 if (!specifics_.coalesced_notification().render_info().expanded_info(). |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 } else { | 516 } else { |
621 // Complain if this is a new priority we have not seen before. | 517 // Complain if this is a new priority we have not seen before. |
622 DCHECK(protobuf_priority < | 518 DCHECK(protobuf_priority < |
623 sync_pb::CoalescedSyncedNotification_Priority_LOW || | 519 sync_pb::CoalescedSyncedNotification_Priority_LOW || |
624 sync_pb::CoalescedSyncedNotification_Priority_HIGH < | 520 sync_pb::CoalescedSyncedNotification_Priority_HIGH < |
625 protobuf_priority); | 521 protobuf_priority); |
626 return kUndefinedPriority; | 522 return kUndefinedPriority; |
627 } | 523 } |
628 } | 524 } |
629 | 525 |
630 size_t SyncedNotification::GetNotificationCount() const { | |
631 return specifics_.coalesced_notification().render_info(). | |
632 expanded_info().collapsed_info_size(); | |
633 } | |
634 | |
635 size_t SyncedNotification::GetButtonCount() const { | |
636 return specifics_.coalesced_notification().render_info().collapsed_info(). | |
637 target_size(); | |
638 } | |
639 | |
640 size_t SyncedNotification::GetProfilePictureCount() const { | |
641 return specifics_.coalesced_notification().render_info().collapsed_info(). | |
642 simple_collapsed_layout().profile_image_size(); | |
643 } | |
644 | |
645 GURL SyncedNotification::GetProfilePictureUrl(unsigned int which_url) const { | |
646 if (GetProfilePictureCount() <= which_url) | |
647 return GURL(); | |
648 | |
649 std::string url_spec = specifics_.coalesced_notification().render_info(). | |
650 collapsed_info().simple_collapsed_layout().profile_image(which_url). | |
651 image_url(); | |
652 | |
653 return AddDefaultSchemaIfNeeded(url_spec); | |
654 } | |
655 | |
656 | |
657 std::string SyncedNotification::GetDefaultDestinationTitle() const { | 526 std::string SyncedNotification::GetDefaultDestinationTitle() const { |
658 if (!specifics_.coalesced_notification().render_info().collapsed_info(). | 527 if (!specifics_.coalesced_notification().render_info().collapsed_info(). |
659 default_destination().icon().has_alt_text()) { | 528 default_destination().icon().has_alt_text()) { |
660 return std::string(); | 529 return std::string(); |
661 } | 530 } |
662 return specifics_.coalesced_notification().render_info().collapsed_info(). | 531 return specifics_.coalesced_notification().render_info().collapsed_info(). |
663 default_destination().icon().alt_text(); | 532 default_destination().icon().alt_text(); |
664 } | 533 } |
665 | 534 |
666 GURL SyncedNotification::GetDefaultDestinationIconUrl() const { | 535 GURL SyncedNotification::GetDefaultDestinationIconUrl() const { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 if (!specifics_.coalesced_notification().render_info().collapsed_info(). | 588 if (!specifics_.coalesced_notification().render_info().collapsed_info(). |
720 target(which_button).action().has_url()) { | 589 target(which_button).action().has_url()) { |
721 return GURL(); | 590 return GURL(); |
722 } | 591 } |
723 std::string url_spec = specifics_.coalesced_notification().render_info(). | 592 std::string url_spec = specifics_.coalesced_notification().render_info(). |
724 collapsed_info().target(which_button).action().url(); | 593 collapsed_info().target(which_button).action().url(); |
725 | 594 |
726 return AddDefaultSchemaIfNeeded(url_spec); | 595 return AddDefaultSchemaIfNeeded(url_spec); |
727 } | 596 } |
728 | 597 |
| 598 GURL SyncedNotification::GetProfilePictureUrl(unsigned int which_url) const { |
| 599 if (GetProfilePictureCount() <= which_url) |
| 600 return GURL(); |
| 601 |
| 602 std::string url_spec = specifics_.coalesced_notification().render_info(). |
| 603 collapsed_info().simple_collapsed_layout().profile_image(which_url). |
| 604 image_url(); |
| 605 |
| 606 return AddDefaultSchemaIfNeeded(url_spec); |
| 607 } |
| 608 |
| 609 size_t SyncedNotification::GetProfilePictureCount() const { |
| 610 return specifics_.coalesced_notification().render_info().collapsed_info(). |
| 611 simple_collapsed_layout().profile_image_size(); |
| 612 } |
| 613 |
| 614 size_t SyncedNotification::GetNotificationCount() const { |
| 615 return specifics_.coalesced_notification().render_info(). |
| 616 expanded_info().collapsed_info_size(); |
| 617 } |
| 618 |
| 619 size_t SyncedNotification::GetButtonCount() const { |
| 620 return specifics_.coalesced_notification().render_info().collapsed_info(). |
| 621 target_size(); |
| 622 } |
729 std::string SyncedNotification::GetContainedNotificationTitle( | 623 std::string SyncedNotification::GetContainedNotificationTitle( |
730 int index) const { | 624 int index) const { |
731 if (specifics_.coalesced_notification().render_info().expanded_info(). | 625 if (specifics_.coalesced_notification().render_info().expanded_info(). |
732 collapsed_info_size() < index + 1) | 626 collapsed_info_size() < index + 1) |
733 return std::string(); | 627 return std::string(); |
734 | 628 |
735 return specifics_.coalesced_notification().render_info().expanded_info(). | 629 return specifics_.coalesced_notification().render_info().expanded_info(). |
736 collapsed_info(index).simple_collapsed_layout().heading(); | 630 collapsed_info(index).simple_collapsed_layout().heading(); |
737 } | 631 } |
738 | 632 |
739 std::string SyncedNotification::GetContainedNotificationMessage( | 633 std::string SyncedNotification::GetContainedNotificationMessage( |
740 int index) const { | 634 int index) const { |
741 if (specifics_.coalesced_notification().render_info().expanded_info(). | 635 if (specifics_.coalesced_notification().render_info().expanded_info(). |
742 collapsed_info_size() < index + 1) | 636 collapsed_info_size() < index + 1) |
743 return std::string(); | 637 return std::string(); |
744 | 638 |
745 return specifics_.coalesced_notification().render_info().expanded_info(). | 639 return specifics_.coalesced_notification().render_info().expanded_info(). |
746 collapsed_info(index).simple_collapsed_layout().description(); | 640 collapsed_info(index).simple_collapsed_layout().description(); |
747 } | 641 } |
748 | 642 |
749 std::string SyncedNotification::GetSendingServiceId() const { | |
750 // TODO(petewil): We are building a new protocol (a new sync datatype) to send | |
751 // the service name and icon from the server. For now this method is | |
752 // hardcoded to the name of our first service using synced notifications. | |
753 // Once the new protocol is built, remove this hardcoding. | |
754 return kFirstSyncedNotificationServiceId; | |
755 } | |
756 | |
757 const gfx::Image& SyncedNotification::GetAppIcon() const { | 643 const gfx::Image& SyncedNotification::GetAppIcon() const { |
758 return app_icon_bitmap_; | 644 return app_icon_bitmap_; |
759 } | 645 } |
760 | 646 |
761 void SyncedNotification::SetToastState(bool toast_state) { | 647 void SyncedNotification::set_toast_state(bool toast_state) { |
762 toast_state_ = toast_state; | 648 toast_state_ = toast_state; |
763 } | 649 } |
764 | 650 |
| 651 void SyncedNotification::LogNotification() { |
| 652 std::string readStateString("Unread"); |
| 653 if (SyncedNotification::kRead == GetReadState()) |
| 654 readStateString = "Read"; |
| 655 else if (SyncedNotification::kDismissed == GetReadState()) |
| 656 readStateString = "Dismissed"; |
| 657 |
| 658 DVLOG(2) << " Notification: Heading is " << GetHeading() |
| 659 << " description is " << GetDescription() |
| 660 << " key is " << GetKey() |
| 661 << " read state is " << readStateString; |
| 662 } |
| 663 |
| 664 // TODO(petewil): The fetch mechanism appears to be returning two bitmaps on the |
| 665 // mac - perhaps one is regular, one is high dpi? If so, ensure we use the high |
| 666 // dpi bitmap when appropriate. |
| 667 void SyncedNotification::OnFetchComplete(const GURL url, |
| 668 const SkBitmap* bitmap) { |
| 669 // Make sure we are on the thread we expect. |
| 670 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 671 |
| 672 gfx::Image downloaded_image; |
| 673 if (bitmap != NULL) |
| 674 downloaded_image = gfx::Image::CreateFrom1xBitmap(*bitmap); |
| 675 |
| 676 // Match the incoming bitmaps to URLs. In case this is a dup, make sure to |
| 677 // try all potentially matching urls. |
| 678 if (GetAppIconUrl() == url) { |
| 679 app_icon_bitmap_ = downloaded_image; |
| 680 if (app_icon_bitmap_.IsEmpty()) |
| 681 app_icon_bitmap_fetch_pending_ = false; |
| 682 } |
| 683 if (GetImageUrl() == url) { |
| 684 image_bitmap_ = downloaded_image; |
| 685 if (image_bitmap_.IsEmpty()) |
| 686 image_bitmap_fetch_pending_ = false; |
| 687 } |
| 688 if (GetProfilePictureUrl(0) == url) { |
| 689 sender_bitmap_ = downloaded_image; |
| 690 if (sender_bitmap_.IsEmpty()) |
| 691 sender_bitmap_fetch_pending_ = false; |
| 692 } |
| 693 |
| 694 // If this URL matches one or more button bitmaps, save them off. |
| 695 for (unsigned int i = 0; i < GetButtonCount(); ++i) { |
| 696 if (GetButtonIconUrl(i) == url) { |
| 697 if (bitmap != NULL) { |
| 698 button_bitmaps_[i] = gfx::Image::CreateFrom1xBitmap(*bitmap); |
| 699 } |
| 700 button_bitmaps_fetch_pending_[i] = false; |
| 701 } |
| 702 } |
| 703 |
| 704 DVLOG(2) << __FUNCTION__ << " popping bitmap " << url; |
| 705 |
| 706 // See if all bitmaps are already accounted for, if so call Show. |
| 707 if (AreAllBitmapsFetched()) { |
| 708 Show(profile_); |
| 709 } |
| 710 } |
| 711 |
| 712 void SyncedNotification::CreateBitmapFetcher(const GURL& url) { |
| 713 // Check for dups, ignore any request for a dup. |
| 714 ScopedVector<chrome::BitmapFetcher>::iterator iter; |
| 715 for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) { |
| 716 if ((*iter)->url() == url) |
| 717 return; |
| 718 } |
| 719 |
| 720 if (url.is_valid()) { |
| 721 fetchers_.push_back(new chrome::BitmapFetcher(url, this)); |
| 722 DVLOG(2) << __FUNCTION__ << "Pushing bitmap " << url; |
| 723 } |
| 724 } |
| 725 |
| 726 // Check that we have either fetched or gotten an error on all the bitmaps we |
| 727 // asked for. |
| 728 bool SyncedNotification::AreAllBitmapsFetched() { |
| 729 bool app_icon_ready = GetAppIconUrl().is_empty() || |
| 730 !app_icon_bitmap_.IsEmpty() || !app_icon_bitmap_fetch_pending_; |
| 731 bool images_ready = GetImageUrl().is_empty() || !image_bitmap_.IsEmpty() || |
| 732 !image_bitmap_fetch_pending_; |
| 733 bool sender_picture_ready = GetProfilePictureUrl(0).is_empty() || |
| 734 !sender_bitmap_.IsEmpty() || !sender_bitmap_fetch_pending_; |
| 735 bool button_bitmaps_ready = true; |
| 736 for (unsigned int j = 0; j < GetButtonCount(); ++j) { |
| 737 if (!GetButtonIconUrl(j).is_empty() |
| 738 && button_bitmaps_[j].IsEmpty() |
| 739 && button_bitmaps_fetch_pending_[j]) { |
| 740 button_bitmaps_ready = false; |
| 741 break; |
| 742 } |
| 743 } |
| 744 |
| 745 return app_icon_ready && images_ready && sender_picture_ready && |
| 746 button_bitmaps_ready; |
| 747 } |
| 748 |
| 749 // Set the read state on the notification, returns true for success. |
| 750 void SyncedNotification::SetReadState(const ReadState& read_state) { |
| 751 |
| 752 // Convert the read state to the protobuf type for read state. |
| 753 if (kDismissed == read_state) |
| 754 specifics_.mutable_coalesced_notification()->set_read_state( |
| 755 sync_pb::CoalescedSyncedNotification_ReadState_DISMISSED); |
| 756 else if (kUnread == read_state) |
| 757 specifics_.mutable_coalesced_notification()->set_read_state( |
| 758 sync_pb::CoalescedSyncedNotification_ReadState_UNREAD); |
| 759 else if (kRead == read_state) |
| 760 specifics_.mutable_coalesced_notification()->set_read_state( |
| 761 sync_pb::CoalescedSyncedNotification_ReadState_READ); |
| 762 else |
| 763 NOTREACHED(); |
| 764 } |
| 765 |
765 } // namespace notifier | 766 } // namespace notifier |
OLD | NEW |