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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 | 113 |
114 return app_icon_ready && images_ready && sender_picture_ready && | 114 return app_icon_ready && images_ready && sender_picture_ready && |
115 button_bitmaps_ready; | 115 button_bitmaps_ready; |
116 } | 116 } |
117 | 117 |
118 // TODO(petewil): The fetch mechanism appears to be returning two bitmaps on the | 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 | 119 // mac - perhaps one is regular, one is high dpi? If so, ensure we use the high |
120 // dpi bitmap when appropriate. | 120 // dpi bitmap when appropriate. |
121 void SyncedNotification::OnFetchComplete(const GURL url, | 121 void SyncedNotification::OnFetchComplete(const GURL url, |
122 const SkBitmap* bitmap) { | 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. | 123 // Make sure we are on the thread we expect. |
126 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 124 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
127 | 125 |
128 gfx::Image downloaded_image; | 126 gfx::Image downloaded_image; |
129 if (bitmap != NULL) | 127 if (bitmap != NULL) |
130 downloaded_image = gfx::Image::CreateFrom1xBitmap(*bitmap); | 128 downloaded_image = gfx::Image::CreateFrom1xBitmap(*bitmap); |
131 | 129 |
132 // Match the incoming bitmaps to URLs. In case this is a dup, make sure to | 130 // Match the incoming bitmaps to URLs. In case this is a dup, make sure to |
133 // try all potentially matching urls. | 131 // try all potentially matching urls. |
134 if (GetAppIconUrl() == url) { | 132 if (GetAppIconUrl() == url) { |
(...skipping 19 matching lines...) Expand all Loading... |
154 button_bitmaps_[i] = gfx::Image::CreateFrom1xBitmap(*bitmap); | 152 button_bitmaps_[i] = gfx::Image::CreateFrom1xBitmap(*bitmap); |
155 } | 153 } |
156 button_bitmaps_fetch_pending_[i] = false; | 154 button_bitmaps_fetch_pending_[i] = false; |
157 } | 155 } |
158 } | 156 } |
159 | 157 |
160 DVLOG(2) << __FUNCTION__ << " popping bitmap " << url; | 158 DVLOG(2) << __FUNCTION__ << " popping bitmap " << url; |
161 | 159 |
162 // See if all bitmaps are already accounted for, if so call Show. | 160 // See if all bitmaps are already accounted for, if so call Show. |
163 if (AreAllBitmapsFetched()) { | 161 if (AreAllBitmapsFetched()) { |
164 Show(notification_manager_, notifier_service_, profile_); | 162 Show(profile_); |
165 } | 163 } |
166 } | 164 } |
167 | 165 |
168 void SyncedNotification::QueueBitmapFetchJobs( | 166 void SyncedNotification::QueueBitmapFetchJobs( |
169 NotificationUIManager* notification_manager, | |
170 ChromeNotifierService* notifier_service, | 167 ChromeNotifierService* notifier_service, |
171 Profile* profile) { | 168 Profile* profile) { |
172 // If we are not using the MessageCenter, call show now, and the existing | 169 // If we are not using the MessageCenter, call show now, and the existing |
173 // code will handle the bitmap fetch for us. | 170 // code will handle the bitmap fetch for us. |
174 if (!UseRichNotifications()) { | 171 if (!UseRichNotifications()) { |
175 Show(notification_manager, notifier_service, profile); | 172 Show(profile); |
176 return; | 173 return; |
177 } | 174 } |
178 | 175 |
179 // Save off the arguments for the call to Show. | 176 // Save off the arguments for the call to Show. |
180 notification_manager_ = notification_manager; | |
181 notifier_service_ = notifier_service; | 177 notifier_service_ = notifier_service; |
182 profile_ = profile; | 178 profile_ = profile; |
183 | 179 |
184 // Ensure our bitmap vector has as many entries as there are buttons, | 180 // 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. | 181 // so that when the bitmaps arrive the vector has a slot for them. |
186 for (unsigned int i = 0; i < GetButtonCount(); ++i) { | 182 for (unsigned int i = 0; i < GetButtonCount(); ++i) { |
187 button_bitmaps_.push_back(gfx::Image()); | 183 button_bitmaps_.push_back(gfx::Image()); |
188 button_bitmaps_fetch_pending_.push_back(true); | 184 button_bitmaps_fetch_pending_.push_back(true); |
189 AddBitmapToFetchQueue(GetButtonIconUrl(i)); | 185 CreateBitmapFetcher(GetButtonIconUrl(i)); |
190 } | 186 } |
191 | 187 |
192 // If there is a profile image bitmap, fetch it | 188 // If there is a profile image bitmap, fetch it |
193 if (GetProfilePictureCount() > 0) { | 189 if (GetProfilePictureCount() > 0) { |
194 // TODO(petewil): When we have the capacity to display more than one bitmap, | 190 // 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 | 191 // modify this code to fetch as many as we can display |
196 AddBitmapToFetchQueue(GetProfilePictureUrl(0)); | 192 CreateBitmapFetcher(GetProfilePictureUrl(0)); |
197 } | 193 } |
198 | 194 |
199 // If the URL is non-empty, add it to our queue of URLs to fetch. | 195 // If the URL is non-empty, add it to our queue of URLs to fetch. |
200 AddBitmapToFetchQueue(GetAppIconUrl()); | 196 CreateBitmapFetcher(GetAppIconUrl()); |
201 AddBitmapToFetchQueue(GetImageUrl()); | 197 CreateBitmapFetcher(GetImageUrl()); |
202 | 198 |
203 // Check to see if we don't need to fetch images, either because we already | 199 // 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. | 200 // did, or because the URLs are empty. If so, we can display the notification. |
205 | 201 |
206 // See if all bitmaps are accounted for, if so call Show(). | 202 // See if all bitmaps are accounted for, if so call Show(). |
207 if (AreAllBitmapsFetched()) { | 203 if (AreAllBitmapsFetched()) { |
208 Show(notification_manager_, notifier_service_, profile_); | 204 Show(profile_); |
209 } | 205 } |
210 } | 206 } |
211 | 207 |
212 void SyncedNotification::StartBitmapFetch() { | 208 void SyncedNotification::StartBitmapFetch() { |
213 // Now that we have queued and counted them all, start the fetching. | 209 // Now that we have queued and counted them all, start the fetching. |
214 ScopedVector<chrome::BitmapFetcher>::iterator iter; | 210 ScopedVector<chrome::BitmapFetcher>::iterator iter; |
215 for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) { | 211 for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) { |
216 (*iter)->Start(profile_); | 212 (*iter)->Start(profile_); |
217 } | 213 } |
218 } | 214 } |
219 | 215 |
220 void SyncedNotification::AddBitmapToFetchQueue(const GURL& url) { | 216 void SyncedNotification::CreateBitmapFetcher(const GURL& url) { |
221 // Check for dups, ignore any request for a dup. | 217 // Check for dups, ignore any request for a dup. |
222 ScopedVector<chrome::BitmapFetcher>::iterator iter; | 218 ScopedVector<chrome::BitmapFetcher>::iterator iter; |
223 for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) { | 219 for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) { |
224 if ((*iter)->url() == url) | 220 if ((*iter)->url() == url) |
225 return; | 221 return; |
226 } | 222 } |
227 | 223 |
228 if (url.is_valid()) { | 224 if (url.is_valid()) { |
229 fetchers_.push_back(new chrome::BitmapFetcher(url, this)); | 225 fetchers_.push_back(new chrome::BitmapFetcher(url, this)); |
230 DVLOG(2) << __FUNCTION__ << "Pushing bitmap " << url; | 226 DVLOG(2) << __FUNCTION__ << "Pushing bitmap " << url; |
231 } | 227 } |
232 } | 228 } |
233 | 229 |
234 void SyncedNotification::Show(NotificationUIManager* notification_manager, | 230 void SyncedNotification::Show(Profile* profile) { |
235 ChromeNotifierService* notifier_service, | |
236 Profile* profile) { | |
237 // Let NotificationUIManager know that the notification has been dismissed. | 231 // Let NotificationUIManager know that the notification has been dismissed. |
238 if (SyncedNotification::kRead == GetReadState() || | 232 if (SyncedNotification::kRead == GetReadState() || |
239 SyncedNotification::kDismissed == GetReadState() ) { | 233 SyncedNotification::kDismissed == GetReadState() ) { |
240 notification_manager->CancelById(GetKey()); | 234 notification_manager_->CancelById(GetKey()); |
241 DVLOG(2) << "Dismissed or read notification arrived" | 235 DVLOG(2) << "Dismissed or read notification arrived" |
242 << GetHeading() << " " << GetText(); | 236 << GetHeading() << " " << GetText(); |
243 return; | 237 return; |
244 } | 238 } |
245 | 239 |
246 // |notifier_service| can be NULL in tests. | 240 // |notifier_service| can be NULL in tests. |
247 if (UseRichNotifications() && notifier_service) { | 241 if (UseRichNotifications() && notifier_service_) { |
248 notifier_service->ShowWelcomeToastIfNecessary(this, notification_manager); | 242 notifier_service_->ShowWelcomeToastIfNecessary(this, notification_manager_); |
249 } | 243 } |
250 | 244 |
251 // Set up the fields we need to send and create a Notification object. | 245 // Set up the fields we need to send and create a Notification object. |
252 GURL image_url = GetImageUrl(); | 246 GURL image_url = GetImageUrl(); |
253 base::string16 text = base::UTF8ToUTF16(GetText()); | 247 base::string16 text = base::UTF8ToUTF16(GetText()); |
254 base::string16 heading = base::UTF8ToUTF16(GetHeading()); | 248 base::string16 heading = base::UTF8ToUTF16(GetHeading()); |
255 base::string16 description = base::UTF8ToUTF16(GetDescription()); | 249 base::string16 description = base::UTF8ToUTF16(GetDescription()); |
256 base::string16 annotation = base::UTF8ToUTF16(GetAnnotation()); | 250 base::string16 annotation = base::UTF8ToUTF16(GetAnnotation()); |
257 // TODO(petewil): Eventually put the display name of the sending service here. | 251 // TODO(petewil): Eventually put the display name of the sending service here. |
258 base::string16 display_source = base::UTF8ToUTF16(GetAppId()); | 252 base::string16 display_source = base::UTF8ToUTF16(GetAppId()); |
259 base::string16 replace_key = base::UTF8ToUTF16(GetKey()); | 253 base::string16 replace_key = base::UTF8ToUTF16(GetKey()); |
260 base::string16 notification_heading = heading; | 254 base::string16 notification_heading = heading; |
261 base::string16 notification_text = description; | 255 base::string16 notification_text = description; |
262 base::string16 newline = base::UTF8ToUTF16("\n"); | 256 base::string16 newline = base::UTF8ToUTF16("\n"); |
263 | 257 |
264 // The delegate will eventually catch calls that the notification | 258 // The delegate will eventually catch calls that the notification |
265 // was read or deleted, and send the changes back to the server. | 259 // was read or deleted, and send the changes back to the server. |
266 scoped_refptr<NotificationDelegate> delegate = | 260 scoped_refptr<NotificationDelegate> delegate = |
267 new ChromeNotifierDelegate(GetKey(), notifier_service); | 261 new ChromeNotifierDelegate(GetKey(), notifier_service_); |
268 | 262 |
269 // Some inputs and fields are only used if there is a notification center. | 263 // Some inputs and fields are only used if there is a notification center. |
270 if (UseRichNotifications()) { | 264 if (UseRichNotifications()) { |
271 base::Time creation_time = | 265 base::Time creation_time = |
272 base::Time::FromDoubleT(static_cast<double>(GetCreationTime())); | 266 base::Time::FromDoubleT(static_cast<double>(GetCreationTime())); |
273 int priority = GetPriority(); | 267 int priority = GetPriority(); |
274 unsigned int button_count = GetButtonCount(); | 268 unsigned int button_count = GetButtonCount(); |
275 | 269 |
276 // Deduce which notification template to use from the data. | 270 // Deduce which notification template to use from the data. |
277 message_center::NotificationType notification_type = | 271 message_center::NotificationType notification_type = |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 blink::WebTextDirectionDefault, | 351 blink::WebTextDirectionDefault, |
358 message_center::NotifierId(GetOriginUrl()), | 352 message_center::NotifierId(GetOriginUrl()), |
359 display_source, | 353 display_source, |
360 replace_key, | 354 replace_key, |
361 rich_notification_data, | 355 rich_notification_data, |
362 delegate.get()); | 356 delegate.get()); |
363 // In case the notification is not supposed to be toasted, pretend that it | 357 // In case the notification is not supposed to be toasted, pretend that it |
364 // has already been shown. | 358 // has already been shown. |
365 ui_notification.set_shown_as_popup(!toast_state_); | 359 ui_notification.set_shown_as_popup(!toast_state_); |
366 | 360 |
367 notification_manager->Add(ui_notification, profile); | 361 notification_manager_->Add(ui_notification, profile); |
368 } else { | 362 } else { |
369 // In this case we have a Webkit Notification, not a Rich Notification. | 363 // In this case we have a Webkit Notification, not a Rich Notification. |
370 Notification ui_notification(GetOriginUrl(), | 364 Notification ui_notification(GetOriginUrl(), |
371 GetAppIconUrl(), | 365 GetAppIconUrl(), |
372 notification_heading, | 366 notification_heading, |
373 notification_text, | 367 notification_text, |
374 blink::WebTextDirectionDefault, | 368 blink::WebTextDirectionDefault, |
375 display_source, | 369 display_source, |
376 replace_key, | 370 replace_key, |
377 delegate.get()); | 371 delegate.get()); |
378 | 372 |
379 notification_manager->Add(ui_notification, profile); | 373 notification_manager_->Add(ui_notification, profile); |
380 } | 374 } |
381 | 375 |
382 DVLOG(1) << "Showing Synced Notification! " << heading << " " << text | 376 DVLOG(1) << "Showing Synced Notification! " << heading << " " << text |
383 << " " << GetAppIconUrl() << " " << replace_key << " " | 377 << " " << GetAppIconUrl() << " " << replace_key << " " |
384 << GetProfilePictureUrl(0) << " " << GetReadState(); | 378 << GetProfilePictureUrl(0) << " " << GetReadState(); |
385 | 379 |
386 return; | 380 return; |
387 } | 381 } |
388 | 382 |
| 383 // Display the notification if it has the specified app_id_name. |
| 384 void SyncedNotification::ShowAllForAppId(Profile* profile, |
| 385 std::string app_id_name) { |
| 386 if (app_id_name == GetAppId()) |
| 387 Show(profile); |
| 388 } |
| 389 |
| 390 // Remove the notification if it has the specified app_id_name. |
| 391 void SyncedNotification::HideAllForAppId(std::string app_id_name) { |
| 392 if (app_id_name == GetAppId()) { |
| 393 notification_manager_->CancelById(GetKey()); |
| 394 } |
| 395 } |
| 396 |
389 // This should detect even small changes in case the server updated the | 397 // This should detect even small changes in case the server updated the |
390 // notification. We ignore the timestamp if other fields match. | 398 // notification. We ignore the timestamp if other fields match. |
391 bool SyncedNotification::EqualsIgnoringReadState( | 399 bool SyncedNotification::EqualsIgnoringReadState( |
392 const SyncedNotification& other) const { | 400 const SyncedNotification& other) const { |
393 if (GetTitle() == other.GetTitle() && | 401 if (GetTitle() == other.GetTitle() && |
394 GetHeading() == other.GetHeading() && | 402 GetHeading() == other.GetHeading() && |
395 GetDescription() == other.GetDescription() && | 403 GetDescription() == other.GetDescription() && |
396 GetAnnotation() == other.GetAnnotation() && | 404 GetAnnotation() == other.GetAnnotation() && |
397 GetAppId() == other.GetAppId() && | 405 GetAppId() == other.GetAppId() && |
398 GetKey() == other.GetKey() && | 406 GetKey() == other.GetKey() && |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 std::string SyncedNotification::GetContainedNotificationMessage( | 747 std::string SyncedNotification::GetContainedNotificationMessage( |
740 int index) const { | 748 int index) const { |
741 if (specifics_.coalesced_notification().render_info().expanded_info(). | 749 if (specifics_.coalesced_notification().render_info().expanded_info(). |
742 collapsed_info_size() < index + 1) | 750 collapsed_info_size() < index + 1) |
743 return std::string(); | 751 return std::string(); |
744 | 752 |
745 return specifics_.coalesced_notification().render_info().expanded_info(). | 753 return specifics_.coalesced_notification().render_info().expanded_info(). |
746 collapsed_info(index).simple_collapsed_layout().description(); | 754 collapsed_info(index).simple_collapsed_layout().description(); |
747 } | 755 } |
748 | 756 |
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 { | 757 const gfx::Image& SyncedNotification::GetAppIcon() const { |
758 return app_icon_bitmap_; | 758 return app_icon_bitmap_; |
759 } | 759 } |
760 | 760 |
761 void SyncedNotification::SetToastState(bool toast_state) { | 761 void SyncedNotification::SetToastState(bool toast_state) { |
762 toast_state_ = toast_state; | 762 toast_state_ = toast_state; |
763 } | 763 } |
764 | 764 |
765 } // namespace notifier | 765 } // namespace notifier |
OLD | NEW |