| 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 |