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 // The ChromeNotifierService works together with sync to maintain the state of | 5 // The ChromeNotifierService works together with sync to maintain the state of |
6 // user notifications, which can then be presented in the notification center, | 6 // user notifications, which can then be presented in the notification center, |
7 // via the Notification UI Manager. | 7 // via the Notification UI Manager. |
8 | 8 |
9 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h" | 9 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h" |
10 | 10 |
11 #include <set> | 11 #include <set> |
12 #include <string> | 12 #include <string> |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
16 #include "base/guid.h" | 16 #include "base/guid.h" |
17 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
18 #include "base/prefs/pref_service.h" | 18 #include "base/prefs/pref_service.h" |
19 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
20 #include "base/values.h" | 20 #include "base/values.h" |
21 #include "chrome/browser/notifications/desktop_notification_service.h" | 21 #include "chrome/browser/notifications/desktop_notification_service.h" |
22 #include "chrome/browser/notifications/desktop_notification_service_factory.h" | 22 #include "chrome/browser/notifications/desktop_notification_service_factory.h" |
23 #include "chrome/browser/notifications/notification.h" | 23 #include "chrome/browser/notifications/notification.h" |
24 #include "chrome/browser/notifications/notification_ui_manager.h" | 24 #include "chrome/browser/notifications/notification_ui_manager.h" |
25 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.h" | 25 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.h" |
26 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_fac
tory.h" | 26 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_fac
tory.h" |
| 27 #include "chrome/browser/notifications/sync_notifier/synced_notification_app_inf
o.h" |
| 28 #include "chrome/browser/notifications/sync_notifier/synced_notification_app_inf
o_service.h" |
| 29 #include "chrome/browser/notifications/sync_notifier/synced_notification_app_inf
o_service_factory.h" |
27 #include "chrome/browser/notifications/sync_notifier/welcome_delegate.h" | 30 #include "chrome/browser/notifications/sync_notifier/welcome_delegate.h" |
28 #include "chrome/browser/profiles/profile.h" | 31 #include "chrome/browser/profiles/profile.h" |
29 #include "chrome/common/pref_names.h" | 32 #include "chrome/common/pref_names.h" |
30 #include "components/user_prefs/pref_registry_syncable.h" | 33 #include "components/user_prefs/pref_registry_syncable.h" |
31 #include "content/public/browser/browser_thread.h" | 34 #include "content/public/browser/browser_thread.h" |
32 #include "content/public/browser/user_metrics.h" | 35 #include "content/public/browser/user_metrics.h" |
33 #include "grit/generated_resources.h" | 36 #include "grit/generated_resources.h" |
34 #include "grit/theme_resources.h" | 37 #include "grit/theme_resources.h" |
35 #include "sync/api/sync_change.h" | 38 #include "sync/api/sync_change.h" |
36 #include "sync/api/sync_change_processor.h" | 39 #include "sync/api/sync_change_processor.h" |
37 #include "sync/api/sync_error_factory.h" | 40 #include "sync/api/sync_error_factory.h" |
38 #include "sync/protocol/sync.pb.h" | 41 #include "sync/protocol/sync.pb.h" |
39 #include "sync/protocol/synced_notification_specifics.pb.h" | 42 #include "sync/protocol/synced_notification_specifics.pb.h" |
40 #include "third_party/WebKit/public/web/WebTextDirection.h" | 43 #include "third_party/WebKit/public/web/WebTextDirection.h" |
41 #include "ui/base/l10n/l10n_util.h" | 44 #include "ui/base/l10n/l10n_util.h" |
42 #include "ui/base/resource/resource_bundle.h" | 45 #include "ui/base/resource/resource_bundle.h" |
43 #include "ui/message_center/notifier_settings.h" | 46 #include "ui/message_center/notifier_settings.h" |
44 #include "url/gurl.h" | 47 #include "url/gurl.h" |
45 | 48 |
46 using base::UserMetricsAction; | 49 using base::UserMetricsAction; |
47 | 50 |
48 namespace notifier { | 51 namespace notifier { |
49 const char kFirstSyncedNotificationServiceId[] = "Google+"; | 52 const char kFirstSyncedNotificationServiceId[] = "Google+"; |
50 const char kSyncedNotificationsWelcomeOrigin[] = | 53 const char kSyncedNotificationsWelcomeOrigin[] = |
51 "synced-notifications://welcome"; | 54 "synced-notifications://welcome"; |
52 | 55 |
53 // SyncedNotificationAppInfoTemp is a class that contains the information | |
54 // necessary to produce a welcome notification and the app badges for all synced | |
55 // notification. | |
56 // TODO(dewittj): Convert this into a sync protobuf-backed data structure. | |
57 class SyncedNotificationAppInfoTemp { | |
58 public: | |
59 explicit SyncedNotificationAppInfoTemp(const std::string& app_id, | |
60 const base::string16& service_name); | |
61 ~SyncedNotificationAppInfoTemp(); | |
62 | |
63 const std::string& app_id() const { return app_id_; } | |
64 const base::string16& service_name() const { return service_name_; } | |
65 const base::string16& title() const { return title_; } | |
66 | |
67 void set_icon(const gfx::Image& icon) { icon_ = icon; } | |
68 const gfx::Image& icon() const { return icon_; } | |
69 | |
70 void set_small_icon(const gfx::Image& small_icon) { | |
71 small_icon_ = small_icon; | |
72 } | |
73 const gfx::Image& small_icon() const { return small_icon_; } | |
74 | |
75 const message_center::NotifierId GetNotifierId() const; | |
76 | |
77 private: | |
78 std::string app_id_; | |
79 base::string16 service_name_; | |
80 gfx::Image icon_; | |
81 gfx::Image small_icon_; | |
82 base::string16 title_; | |
83 base::string16 message_; | |
84 }; | |
85 | |
86 SyncedNotificationAppInfoTemp::SyncedNotificationAppInfoTemp( | |
87 const std::string& app_id, | |
88 const base::string16& service_name) | |
89 : app_id_(app_id), service_name_(service_name) { | |
90 title_ = | |
91 l10n_util::GetStringFUTF16(IDS_NOTIFIER_WELCOME_TITLE, service_name_); | |
92 } | |
93 | |
94 SyncedNotificationAppInfoTemp::~SyncedNotificationAppInfoTemp() {} | |
95 | |
96 const message_center::NotifierId SyncedNotificationAppInfoTemp::GetNotifierId() | |
97 const { | |
98 return message_center::NotifierId( | |
99 message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE, app_id()); | |
100 } | |
101 | |
102 bool ChromeNotifierService::avoid_bitmap_fetching_for_test_ = false; | 56 bool ChromeNotifierService::avoid_bitmap_fetching_for_test_ = false; |
103 | 57 |
104 ChromeNotifierService::ChromeNotifierService(Profile* profile, | 58 ChromeNotifierService::ChromeNotifierService(Profile* profile, |
105 NotificationUIManager* manager) | 59 NotificationUIManager* manager) |
106 : profile_(profile), | 60 : profile_(profile), |
107 notification_manager_(manager), | 61 notification_manager_(manager), |
108 synced_notification_first_run_(false) { | 62 synced_notification_first_run_(false) { |
109 SyncedNotificationAppInfoTemp* temp_app_info = | |
110 new SyncedNotificationAppInfoTemp( | |
111 kFirstSyncedNotificationServiceId, | |
112 l10n_util::GetStringUTF16(IDS_FIRST_SYNCED_NOTIFICATION_SERVICE_NAME)); | |
113 temp_app_info->set_small_icon( | |
114 ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
115 IDR_TEMPORARY_GOOGLE_PLUS_ICON)); | |
116 app_info_data_.push_back(temp_app_info); | |
117 | 63 |
118 InitializePrefs(); | 64 InitializePrefs(); |
| 65 |
| 66 // Get a pointer to the app info service so we can get app info data. |
| 67 synced_notification_app_info_service_ = |
| 68 SyncedNotificationAppInfoServiceFactory::GetForProfile( |
| 69 profile_, Profile::IMPLICIT_ACCESS); |
| 70 |
| 71 DCHECK(synced_notification_app_info_service_ != NULL); |
| 72 |
| 73 synced_notification_app_info_service_->set_chrome_notifier_service(this); |
| 74 |
119 } | 75 } |
120 | 76 |
121 ChromeNotifierService::~ChromeNotifierService() {} | 77 ChromeNotifierService::~ChromeNotifierService() { |
| 78 if (synced_notification_app_info_service_) |
| 79 synced_notification_app_info_service_->set_chrome_notifier_service(NULL); |
| 80 } |
122 | 81 |
123 // Methods from BrowserContextKeyedService. | 82 // Methods from BrowserContextKeyedService. |
124 void ChromeNotifierService::Shutdown() {} | 83 void ChromeNotifierService::Shutdown() {} |
125 | 84 |
126 // syncer::SyncableService implementation. | 85 // syncer::SyncableService implementation. |
127 | 86 |
128 // This is called at startup to sync with the server. | 87 // This is called at startup to sync with the server. |
129 // This code is not thread safe. | 88 // This code is not thread safe. |
130 syncer::SyncMergeResult ChromeNotifierService::MergeDataAndStartSyncing( | 89 syncer::SyncMergeResult ChromeNotifierService::MergeDataAndStartSyncing( |
131 syncer::ModelType type, | 90 syncer::ModelType type, |
132 const syncer::SyncDataList& initial_sync_data, | 91 const syncer::SyncDataList& initial_sync_data, |
133 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, | 92 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, |
134 scoped_ptr<syncer::SyncErrorFactory> error_handler) { | 93 scoped_ptr<syncer::SyncErrorFactory> error_handler) { |
135 thread_checker_.CalledOnValidThread(); | 94 thread_checker_.CalledOnValidThread(); |
136 DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); | 95 DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); |
137 syncer::SyncMergeResult merge_result(syncer::SYNCED_NOTIFICATIONS); | 96 syncer::SyncMergeResult merge_result(syncer::SYNCED_NOTIFICATIONS); |
138 // A list of local changes to send up to the sync server. | 97 // A list of local changes to send up to the sync server. |
139 syncer::SyncChangeList new_changes; | 98 syncer::SyncChangeList new_changes; |
140 sync_processor_ = sync_processor.Pass(); | 99 sync_processor_ = sync_processor.Pass(); |
141 | 100 |
142 for (syncer::SyncDataList::const_iterator it = initial_sync_data.begin(); | 101 for (syncer::SyncDataList::const_iterator it = initial_sync_data.begin(); |
143 it != initial_sync_data.end(); ++it) { | 102 it != initial_sync_data.end(); ++it) { |
144 const syncer::SyncData& sync_data = *it; | 103 const syncer::SyncData& sync_data = *it; |
145 DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, sync_data.GetDataType()); | 104 DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, sync_data.GetDataType()); |
146 | 105 |
147 // Build a local notification object from the sync data. | 106 // Build a local notification object from the sync data. |
148 scoped_ptr<SyncedNotification> incoming(CreateNotificationFromSyncData( | 107 scoped_ptr<SyncedNotification> incoming(CreateNotificationFromSyncData( |
149 sync_data)); | 108 sync_data)); |
150 if (!incoming) { | 109 if (!incoming) { |
151 // TODO(petewil): Turn this into a NOTREACHED() call once we fix the | 110 NOTREACHED(); |
152 // underlying problem causing bad data. | |
153 LOG(WARNING) << "Badly formed sync data in incoming notification"; | |
154 continue; | 111 continue; |
155 } | 112 } |
156 | 113 |
157 // Process each incoming remote notification. | 114 // Process each incoming remote notification. |
158 const std::string& key = incoming->GetKey(); | 115 const std::string& key = incoming->GetKey(); |
159 DCHECK_GT(key.length(), 0U); | 116 DCHECK_GT(key.length(), 0U); |
160 SyncedNotification* found = FindNotificationById(key); | 117 SyncedNotification* found = FindNotificationById(key); |
161 | 118 |
162 if (NULL == found) { | 119 if (NULL == found) { |
163 // If there are no conflicts, copy in the data from remote. | 120 // If there are no conflicts, copy in the data from remote. |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 | 261 |
305 // Static method. Get to the sync data in our internal format. | 262 // Static method. Get to the sync data in our internal format. |
306 syncer::SyncData ChromeNotifierService::CreateSyncDataFromNotification( | 263 syncer::SyncData ChromeNotifierService::CreateSyncDataFromNotification( |
307 const SyncedNotification& notification) { | 264 const SyncedNotification& notification) { |
308 // Construct the sync_data using the specifics from the notification. | 265 // Construct the sync_data using the specifics from the notification. |
309 return syncer::SyncData::CreateLocalData( | 266 return syncer::SyncData::CreateLocalData( |
310 notification.GetKey(), notification.GetKey(), | 267 notification.GetKey(), notification.GetKey(), |
311 notification.GetEntitySpecifics()); | 268 notification.GetEntitySpecifics()); |
312 } | 269 } |
313 | 270 |
314 // Static Method. Convert from SyncData to our internal format. | 271 // Convert from SyncData to our internal format. |
315 scoped_ptr<SyncedNotification> | 272 scoped_ptr<SyncedNotification> |
316 ChromeNotifierService::CreateNotificationFromSyncData( | 273 ChromeNotifierService::CreateNotificationFromSyncData( |
317 const syncer::SyncData& sync_data) { | 274 const syncer::SyncData& sync_data) { |
318 // Get a pointer to our data within the sync_data object. | 275 // Get a pointer to our data within the sync_data object. |
319 sync_pb::SyncedNotificationSpecifics specifics = | 276 sync_pb::SyncedNotificationSpecifics specifics = |
320 sync_data.GetSpecifics().synced_notification(); | 277 sync_data.GetSpecifics().synced_notification(); |
321 | 278 |
322 // Check for mandatory fields in the sync_data object. | 279 // Check for mandatory fields in the sync_data object. |
323 if (!specifics.has_coalesced_notification() || | 280 if (!specifics.has_coalesced_notification() || |
324 !specifics.coalesced_notification().has_key() || | 281 !specifics.coalesced_notification().has_key() || |
(...skipping 30 matching lines...) Expand all Loading... |
355 << is_well_formed_unread_notification | 312 << is_well_formed_unread_notification |
356 << " dismissed well formed? " | 313 << " dismissed well formed? " |
357 << is_well_formed_dismissed_notification | 314 << is_well_formed_dismissed_notification |
358 << " read well formed? " | 315 << " read well formed? " |
359 << is_well_formed_read_notification; | 316 << is_well_formed_read_notification; |
360 return scoped_ptr<SyncedNotification>(); | 317 return scoped_ptr<SyncedNotification>(); |
361 } | 318 } |
362 | 319 |
363 // Create a new notification object based on the supplied sync_data. | 320 // Create a new notification object based on the supplied sync_data. |
364 scoped_ptr<SyncedNotification> notification( | 321 scoped_ptr<SyncedNotification> notification( |
365 new SyncedNotification(sync_data)); | 322 new SyncedNotification(sync_data, this, notification_manager_)); |
366 | 323 |
367 return notification.Pass(); | 324 return notification.Pass(); |
368 } | 325 } |
369 | 326 |
370 // This returns a pointer into a vector that we own. Caller must not free it. | 327 // This returns a pointer into a vector that we own. Caller must not free it. |
371 // Returns NULL if no match is found. | 328 // Returns NULL if no match is found. |
372 SyncedNotification* ChromeNotifierService::FindNotificationById( | 329 SyncedNotification* ChromeNotifierService::FindNotificationById( |
373 const std::string& notification_id) { | 330 const std::string& notification_id) { |
374 // TODO(petewil): We can make a performance trade off here. | 331 // TODO(petewil): We can make a performance trade off here. |
375 // While the vector has good locality of reference, a map has faster lookup. | 332 // While the vector has good locality of reference, a map has faster lookup. |
(...skipping 18 matching lines...) Expand all Loading... |
394 notification_data_.erase(it); | 351 notification_data_.erase(it); |
395 return; | 352 return; |
396 } | 353 } |
397 } | 354 } |
398 } | 355 } |
399 | 356 |
400 void ChromeNotifierService::GetSyncedNotificationServices( | 357 void ChromeNotifierService::GetSyncedNotificationServices( |
401 std::vector<message_center::Notifier*>* notifiers) { | 358 std::vector<message_center::Notifier*>* notifiers) { |
402 // TODO(mukai|petewil): Check the profile's eligibility before adding the | 359 // TODO(mukai|petewil): Check the profile's eligibility before adding the |
403 // sample app. | 360 // sample app. |
404 ScopedVector<SyncedNotificationAppInfoTemp>::iterator it = | 361 std::vector<SyncedNotificationSendingServiceSettingsData> |
405 app_info_data_.begin(); | 362 sending_service_settings_data; |
406 for (; it != app_info_data_.end(); ++it) { | |
407 SyncedNotificationAppInfoTemp* app_info = *it; | |
408 message_center::NotifierId notifier_id = app_info->GetNotifierId(); | |
409 | 363 |
410 // Enable or disable the sending service per saved settings. | 364 if (synced_notification_app_info_service_ == NULL) |
| 365 return; |
| 366 |
| 367 sending_service_settings_data = |
| 368 synced_notification_app_info_service_->GetAllSendingServiceSettingsData(); |
| 369 |
| 370 for (size_t ii = 0; ii < sending_service_settings_data.size(); ++ii) { |
| 371 |
| 372 // Enable or disable the sending service per saved preferences. |
411 bool app_enabled = false; | 373 bool app_enabled = false; |
412 std::set<std::string>::iterator iter; | 374 std::set<std::string>::iterator iter; |
413 iter = find(enabled_sending_services_.begin(), | 375 iter = find(enabled_sending_services_.begin(), |
414 enabled_sending_services_.end(), | 376 enabled_sending_services_.end(), |
415 notifier_id.id); | 377 sending_service_settings_data[ii].notifier_id.id); |
416 app_enabled = iter != enabled_sending_services_.end(); | 378 app_enabled = iter != enabled_sending_services_.end(); |
417 | 379 |
418 message_center::Notifier* app_info_notifier = new message_center::Notifier( | 380 message_center::Notifier* app_info_notifier = new message_center::Notifier( |
419 notifier_id, app_info->service_name(), app_enabled); | 381 sending_service_settings_data[ii].notifier_id, |
| 382 base::UTF8ToUTF16( |
| 383 sending_service_settings_data[ii].settings_display_name), |
| 384 app_enabled); |
420 | 385 |
421 app_info_notifier->icon = app_info->small_icon(); | 386 app_info_notifier->icon = sending_service_settings_data[ii].settings_icon; |
422 | 387 |
423 // |notifiers| takes ownership of |app_info_notifier|. | 388 // |notifiers| takes ownership of |app_info_notifier|. |
424 notifiers->push_back(app_info_notifier); | 389 notifiers->push_back(app_info_notifier); |
425 } | 390 } |
426 } | 391 } |
427 | 392 |
| 393 void ChromeNotifierService::OnAddedAppIds( |
| 394 std::vector<std::string> added_app_ids) { |
| 395 |
| 396 std::vector<std::string>::const_iterator app_id_iter; |
| 397 for (app_id_iter = added_app_ids.begin(); app_id_iter != added_app_ids.end(); |
| 398 ++app_id_iter) { |
| 399 // Make sure this is not a dup, if it is, do nothing. |
| 400 // TODO(petewil): consider a case insensitive compare. |
| 401 std::set<std::string>::iterator sending_service_iter; |
| 402 sending_service_iter = enabled_sending_services_.find(*app_id_iter); |
| 403 if (sending_service_iter != enabled_sending_services_.end()) |
| 404 continue; |
| 405 |
| 406 // Find any newly enabled notifications and call display on them. |
| 407 // Show the welcome toast if required. |
| 408 ScopedVector<SyncedNotification>::iterator notification_iter; |
| 409 for (notification_iter = notification_data_.begin(); |
| 410 notification_iter != notification_data_.end(); |
| 411 ++notification_iter) { |
| 412 (*notification_iter)->ShowAllForAppId(profile_, *app_id_iter); |
| 413 } |
| 414 } |
| 415 } |
| 416 |
| 417 void ChromeNotifierService::OnRemovedAppIds( |
| 418 std::vector<std::string> removed_app_ids) { |
| 419 // Remove from enabled sending services. |
| 420 // Don't remove from initialized sending services. If it gets re-added later, |
| 421 // we want to remember the user's decision, so we also leave prefs intact. |
| 422 |
| 423 // Find any displayed notifications and remove them from the notification |
| 424 // center. |
| 425 std::vector<std::string>::const_iterator app_id_iter; |
| 426 for (app_id_iter = removed_app_ids.begin(); |
| 427 app_id_iter != removed_app_ids.end(); |
| 428 ++app_id_iter) { |
| 429 // Find any newly disabled notifications and remove them. |
| 430 ScopedVector<SyncedNotification>::iterator notification_iter; |
| 431 for (notification_iter = notification_data_.begin(); |
| 432 notification_iter != notification_data_.end(); |
| 433 ++notification_iter) { |
| 434 (*notification_iter)->HideAllForAppId(*app_id_iter); |
| 435 } |
| 436 } |
| 437 } |
| 438 |
428 void ChromeNotifierService::MarkNotificationAsRead( | 439 void ChromeNotifierService::MarkNotificationAsRead( |
429 const std::string& key) { | 440 const std::string& key) { |
430 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 441 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
431 SyncedNotification* notification = FindNotificationById(key); | 442 SyncedNotification* notification = FindNotificationById(key); |
432 CHECK(notification != NULL); | 443 CHECK(notification != NULL); |
433 | 444 |
434 notification->NotificationHasBeenRead(); | 445 notification->NotificationHasBeenRead(); |
435 syncer::SyncChangeList new_changes; | 446 syncer::SyncChangeList new_changes; |
436 | 447 |
437 syncer::SyncData sync_data = CreateSyncDataFromNotification(*notification); | 448 syncer::SyncData sync_data = CreateSyncDataFromNotification(*notification); |
438 new_changes.push_back( | 449 new_changes.push_back( |
439 syncer::SyncChange(FROM_HERE, | 450 syncer::SyncChange(FROM_HERE, |
440 syncer::SyncChange::ACTION_UPDATE, | 451 syncer::SyncChange::ACTION_UPDATE, |
441 sync_data)); | 452 sync_data)); |
442 | 453 |
443 // Send up the changes that were made locally. | 454 // Send up the changes that were made locally. |
444 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); | 455 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); |
445 } | 456 } |
446 | 457 |
447 // Add a new notification to our data structure. This takes ownership | 458 // Add a new notification to our data structure. This takes ownership |
448 // of the passed in pointer. | 459 // of the passed in pointer. |
449 void ChromeNotifierService::Add(scoped_ptr<SyncedNotification> notification) { | 460 void ChromeNotifierService::Add(scoped_ptr<SyncedNotification> notification) { |
450 SyncedNotification* notification_copy = notification.get(); | 461 SyncedNotification* notification_copy = notification.get(); |
451 // Take ownership of the object and put it into our local storage. | 462 // Take ownership of the object and put it into our local storage. |
452 notification_data_.push_back(notification.release()); | 463 notification_data_.push_back(notification.release()); |
453 | 464 |
454 // If the user is not interested in this type of notification, ignore it. | 465 // If the user is not interested in this type of notification, ignore it. |
455 std::set<std::string>::iterator iter = | 466 std::string sending_service_id = GetSendingServiceId(notification_copy); |
456 find(enabled_sending_services_.begin(), | 467 std::set<std::string>::iterator iter = find(enabled_sending_services_.begin(), |
457 enabled_sending_services_.end(), | 468 enabled_sending_services_.end(), |
458 notification_copy->GetSendingServiceId()); | 469 sending_service_id); |
459 if (iter == enabled_sending_services_.end()) { | 470 if (iter == enabled_sending_services_.end()) { |
460 iter = find(initialized_sending_services_.begin(), | 471 iter = find(initialized_sending_services_.begin(), |
461 initialized_sending_services_.end(), | 472 initialized_sending_services_.end(), |
462 notification_copy->GetSendingServiceId()); | 473 sending_service_id); |
463 if (iter != initialized_sending_services_.end()) | 474 if (iter != initialized_sending_services_.end()) |
464 return; | 475 return; |
465 } | 476 } |
466 | 477 |
467 UpdateInMessageCenter(notification_copy); | 478 UpdateInMessageCenter(notification_copy); |
468 } | 479 } |
469 | 480 |
| 481 std::string ChromeNotifierService::GetSendingServiceId( |
| 482 const SyncedNotification* synced_notification) { |
| 483 // Get the App Id from the notification, and look it up in the synced |
| 484 // notification app info service. |
| 485 std::string app_id = synced_notification->GetAppId(); |
| 486 |
| 487 DCHECK(synced_notification_app_info_service_ != NULL); |
| 488 |
| 489 return synced_notification_app_info_service_->FindSendingServiceNameFromAppId( |
| 490 app_id); |
| 491 } |
| 492 |
470 void ChromeNotifierService::AddForTest( | 493 void ChromeNotifierService::AddForTest( |
471 scoped_ptr<notifier::SyncedNotification> notification) { | 494 scoped_ptr<notifier::SyncedNotification> notification) { |
472 notification_data_.push_back(notification.release()); | 495 notification_data_.push_back(notification.release()); |
473 } | 496 } |
474 | 497 |
| 498 void ChromeNotifierService::SetSyncedNotificationAppInfoServiceForTest( |
| 499 SyncedNotificationAppInfoService* synced_notification_app_info_service) { |
| 500 // If there already is a service attached, clear their reference to us. |
| 501 if (synced_notification_app_info_service_) |
| 502 synced_notification_app_info_service_->set_chrome_notifier_service(NULL); |
| 503 |
| 504 synced_notification_app_info_service_ = synced_notification_app_info_service; |
| 505 synced_notification_app_info_service_->set_chrome_notifier_service(this); |
| 506 } |
| 507 |
475 void ChromeNotifierService::UpdateInMessageCenter( | 508 void ChromeNotifierService::UpdateInMessageCenter( |
476 SyncedNotification* notification) { | 509 SyncedNotification* notification) { |
477 // If the feature is disabled, exit now. | 510 // If the feature is disabled, exit now. |
478 if (!notifier::ChromeNotifierServiceFactory::UseSyncedNotifications( | 511 if (!notifier::ChromeNotifierServiceFactory::UseSyncedNotifications( |
479 CommandLine::ForCurrentProcess())) | 512 CommandLine::ForCurrentProcess())) |
480 return; | 513 return; |
481 | 514 |
482 notification->LogNotification(); | 515 notification->LogNotification(); |
483 | 516 |
484 if (notification->GetReadState() == SyncedNotification::kUnread) { | 517 if (notification->GetReadState() == SyncedNotification::kUnread) { |
485 // If the message is unread, update it. | 518 // If the message is unread, update it. |
486 Display(notification); | 519 Display(notification); |
487 } else { | 520 } else { |
488 // If the message is read or deleted, dismiss it from the center. | 521 // If the message is read or deleted, dismiss it from the center. |
489 // We intentionally ignore errors if it is not in the center. | 522 // We intentionally ignore errors if it is not in the center. |
490 notification_manager_->CancelById(notification->GetKey()); | 523 notification_manager_->CancelById(notification->GetKey()); |
491 } | 524 } |
492 } | 525 } |
493 | 526 |
494 void ChromeNotifierService::Display(SyncedNotification* notification) { | 527 void ChromeNotifierService::Display(SyncedNotification* notification) { |
495 // If this is the first run for the feature, don't surprise the user. | 528 // If this is the first run for the feature, don't surprise the user. |
496 // Instead, place all backlogged notifications into the notification | 529 // Instead, place all backlogged notifications into the notification |
497 // center. | 530 // center. |
498 if (synced_notification_first_run_) { | 531 if (synced_notification_first_run_) { |
499 // Setting the toast state to false will prevent toasting the notification. | 532 // Setting the toast state to false will prevent toasting the notification. |
500 notification->SetToastState(false); | 533 notification->set_toast_state(false); |
501 } | 534 } |
502 | 535 |
503 // Our tests cannot use the network for reliability reasons. | 536 // Our tests cannot use the network for reliability reasons. |
504 if (avoid_bitmap_fetching_for_test_) { | 537 if (avoid_bitmap_fetching_for_test_) { |
505 notification->Show(notification_manager_, this, profile_); | 538 notification->Show(profile_); |
506 return; | 539 return; |
507 } | 540 } |
508 | 541 |
509 // Set up to fetch the bitmaps. | 542 // Set up to fetch the bitmaps. |
510 notification->QueueBitmapFetchJobs(notification_manager_, this, profile_); | 543 notification->QueueBitmapFetchJobs(this, profile_); |
511 | 544 |
512 // Start the bitmap fetching, Show() will be called when the last bitmap | 545 // Start the bitmap fetching, Show() will be called when the last bitmap |
513 // either arrives or times out. | 546 // either arrives or times out. |
514 notification->StartBitmapFetch(); | 547 notification->StartBitmapFetch(); |
515 } | 548 } |
516 | 549 |
517 void ChromeNotifierService::OnSyncedNotificationServiceEnabled( | 550 void ChromeNotifierService::OnSyncedNotificationServiceEnabled( |
518 const std::string& notifier_id, bool enabled) { | 551 const std::string& notifier_id, bool enabled) { |
519 std::set<std::string>::iterator iter; | 552 std::set<std::string>::iterator iter; |
520 | 553 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 list_value->Append(string_value); | 634 list_value->Append(string_value); |
602 } | 635 } |
603 } | 636 } |
604 | 637 |
605 void ChromeNotifierService::DisplayUnreadNotificationsFromSource( | 638 void ChromeNotifierService::DisplayUnreadNotificationsFromSource( |
606 const std::string& notifier_id) { | 639 const std::string& notifier_id) { |
607 for (std::vector<SyncedNotification*>::const_iterator iter = | 640 for (std::vector<SyncedNotification*>::const_iterator iter = |
608 notification_data_.begin(); | 641 notification_data_.begin(); |
609 iter != notification_data_.end(); | 642 iter != notification_data_.end(); |
610 ++iter) { | 643 ++iter) { |
611 if ((*iter)->GetSendingServiceId() == notifier_id && | 644 if (GetSendingServiceId(*iter) == notifier_id && |
612 (*iter)->GetReadState() == SyncedNotification::kUnread) | 645 (*iter)->GetReadState() == SyncedNotification::kUnread) |
613 Display(*iter); | 646 Display(*iter); |
614 } | 647 } |
615 } | 648 } |
616 | 649 |
617 void ChromeNotifierService::RemoveUnreadNotificationsFromSource( | 650 void ChromeNotifierService::RemoveUnreadNotificationsFromSource( |
618 const std::string& notifier_id) { | 651 const std::string& notifier_id) { |
619 for (std::vector<SyncedNotification*>::const_iterator iter = | 652 for (std::vector<SyncedNotification*>::const_iterator iter = |
620 notification_data_.begin(); | 653 notification_data_.begin(); |
621 iter != notification_data_.end(); | 654 iter != notification_data_.end(); |
622 ++iter) { | 655 ++iter) { |
623 if ((*iter)->GetSendingServiceId() == notifier_id && | 656 if (GetSendingServiceId(*iter) == notifier_id && |
624 (*iter)->GetReadState() == SyncedNotification::kUnread) { | 657 (*iter)->GetReadState() == SyncedNotification::kUnread) { |
625 notification_manager_->CancelById((*iter)->GetKey()); | 658 notification_manager_->CancelById((*iter)->GetKey()); |
626 } | 659 } |
627 } | 660 } |
628 } | 661 } |
629 | 662 |
630 void ChromeNotifierService::OnEnabledSendingServiceListPrefChanged( | 663 void ChromeNotifierService::OnEnabledSendingServiceListPrefChanged( |
631 std::set<std::string>* ids_field) { | 664 std::set<std::string>* ids_field) { |
632 ids_field->clear(); | 665 ids_field->clear(); |
633 const std::vector<std::string> pref_list = | 666 const std::vector<std::string> pref_list = |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 OnInitializedSendingServiceListPrefChanged(&initialized_sending_services_); | 742 OnInitializedSendingServiceListPrefChanged(&initialized_sending_services_); |
710 | 743 |
711 synced_notification_first_run_ = | 744 synced_notification_first_run_ = |
712 profile_->GetPrefs()->GetBoolean(prefs::kSyncedNotificationFirstRun); | 745 profile_->GetPrefs()->GetBoolean(prefs::kSyncedNotificationFirstRun); |
713 } | 746 } |
714 | 747 |
715 void ChromeNotifierService::ShowWelcomeToastIfNecessary( | 748 void ChromeNotifierService::ShowWelcomeToastIfNecessary( |
716 const SyncedNotification* synced_notification, | 749 const SyncedNotification* synced_notification, |
717 NotificationUIManager* notification_ui_manager) { | 750 NotificationUIManager* notification_ui_manager) { |
718 const std::string& sending_service_id = | 751 const std::string& sending_service_id = |
719 synced_notification->GetSendingServiceId(); | 752 GetSendingServiceId(synced_notification); |
720 | 753 |
721 std::set<std::string>::iterator iter; | 754 std::set<std::string>::iterator iter; |
722 iter = find(initialized_sending_services_.begin(), | 755 iter = find(initialized_sending_services_.begin(), |
723 initialized_sending_services_.end(), | 756 initialized_sending_services_.end(), |
724 sending_service_id); | 757 sending_service_id); |
725 | 758 |
726 // If we already initialized the sending service, then return early since no | 759 // If we already initialized the sending service, then return early since no |
727 // welcome toast is necessary. | 760 // welcome toast is necessary. |
728 if (iter != initialized_sending_services_.end()) | 761 if (iter != initialized_sending_services_.end()) |
729 return; | 762 return; |
730 | 763 |
731 // If there is no app info, we can't show a welcome toast. Ideally all synced | 764 // If there is no app info, we can't show a welcome toast. All synced |
732 // notifications will be delayed until an app_info data structure can be | 765 // notifications will be delayed until an app_info data structure can be |
733 // constructed for them. | 766 // constructed for them. |
734 // TODO(dewittj): Refactor when app_info is populated asynchronously. | 767 notifier::SyncedNotificationAppInfo* app_info = |
735 SyncedNotificationAppInfoTemp* app_info = FindAppInfo(sending_service_id); | 768 FindAppInfoByAppId(synced_notification->GetAppId()); |
736 if (!app_info) | 769 if (!app_info) |
737 return; | 770 return; |
738 | 771 |
739 // TODO(dewittj): Ensure that the app info icon is set before this point. | 772 if (app_info->settings_icon_url().is_empty()) { |
740 if (app_info->icon().IsEmpty()) { | |
741 gfx::Image notification_app_icon = synced_notification->GetAppIcon(); | 773 gfx::Image notification_app_icon = synced_notification->GetAppIcon(); |
742 if (!notification_app_icon.IsEmpty()) { | 774 if (notification_app_icon.IsEmpty()) { |
743 app_info->set_icon(notification_app_icon); | |
744 } else { | |
745 // This block should only be reached in tests since the downloads are | 775 // This block should only be reached in tests since the downloads are |
746 // already finished for |synced_notification|. | 776 // already finished for |synced_notification|. |
747 DVLOG(1) << "Unable to find the app icon for the welcome notification. " | 777 DVLOG(1) << "Unable to find the app icon for the welcome notification. " |
748 << "Service ID: " << sending_service_id; | 778 << "Service ID: " << sending_service_id; |
749 } | 779 } |
750 } | 780 } |
751 | 781 |
752 message_center::NotifierId notifier_id( | 782 message_center::NotifierId notifier_id( |
753 message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE, | 783 message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE, |
754 sending_service_id); | 784 sending_service_id); |
(...skipping 14 matching lines...) Expand all Loading... |
769 profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, | 799 profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, |
770 enabled_sending_services); | 800 enabled_sending_services); |
771 // Mark any new services as initialized in preferences. | 801 // Mark any new services as initialized in preferences. |
772 BuildServiceListValueInplace(initialized_sending_services_, | 802 BuildServiceListValueInplace(initialized_sending_services_, |
773 &initialized_sending_services); | 803 &initialized_sending_services); |
774 profile_->GetPrefs()->Set( | 804 profile_->GetPrefs()->Set( |
775 prefs::kInitializedSyncedNotificationSendingServices, | 805 prefs::kInitializedSyncedNotificationSendingServices, |
776 initialized_sending_services); | 806 initialized_sending_services); |
777 } | 807 } |
778 | 808 |
779 SyncedNotificationAppInfoTemp* ChromeNotifierService::FindAppInfo( | 809 notifier::SyncedNotificationAppInfo* ChromeNotifierService::FindAppInfoByAppId( |
780 const std::string& app_id) const { | 810 const std::string& app_id) const { |
781 ScopedVector<SyncedNotificationAppInfoTemp>::const_iterator iter = | 811 if (NULL == synced_notification_app_info_service_) |
782 app_info_data_.begin(); | 812 return NULL; |
783 while (iter != app_info_data_.end()) { | |
784 if ((*iter)->app_id() == app_id) | |
785 return (*iter); | |
786 | 813 |
787 ++iter; | 814 return synced_notification_app_info_service_-> |
788 } | 815 FindSyncedNotificationAppInfoByAppId(app_id); |
789 | |
790 return NULL; | |
791 } | 816 } |
792 | 817 |
793 const Notification ChromeNotifierService::CreateWelcomeNotificationForService( | 818 const Notification ChromeNotifierService::CreateWelcomeNotificationForService( |
794 SyncedNotificationAppInfoTemp* app_info) { | 819 SyncedNotificationAppInfo* app_info) { |
795 std::string welcome_notification_id = base::GenerateGUID(); | 820 std::string welcome_notification_id = base::GenerateGUID(); |
796 scoped_refptr<WelcomeDelegate> delegate(new WelcomeDelegate( | 821 message_center::NotifierId notifier_id = app_info->GetNotifierId(); |
797 welcome_notification_id, profile_, app_info->GetNotifierId())); | 822 scoped_refptr<WelcomeDelegate> delegate( |
| 823 new WelcomeDelegate(welcome_notification_id, profile_, notifier_id)); |
798 | 824 |
799 message_center::ButtonInfo button_info( | 825 message_center::ButtonInfo button_info( |
800 l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BUTTON)); | 826 l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BUTTON)); |
801 button_info.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( | 827 button_info.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
802 IDR_NOTIFIER_BLOCK_BUTTON); | 828 IDR_NOTIFIER_BLOCK_BUTTON); |
803 | 829 |
804 message_center::RichNotificationData rich_notification_data; | 830 message_center::RichNotificationData rich_notification_data; |
805 rich_notification_data.buttons.push_back(button_info); | 831 rich_notification_data.buttons.push_back(button_info); |
806 return Notification( | 832 return Notification( |
807 message_center::NOTIFICATION_TYPE_BASE_FORMAT, | 833 message_center::NOTIFICATION_TYPE_BASE_FORMAT, |
808 GURL(kSyncedNotificationsWelcomeOrigin), | 834 GURL(kSyncedNotificationsWelcomeOrigin), |
809 app_info->title(), | 835 base::UTF8ToUTF16(app_info->settings_display_name()), |
810 l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BODY), | 836 l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BODY), |
811 app_info->icon(), | 837 app_info->icon(), |
812 blink::WebTextDirectionDefault, | 838 blink::WebTextDirectionDefault, |
813 app_info->GetNotifierId(), | 839 notifier_id, |
814 l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_DISPLAY_SOURCE), | 840 l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_DISPLAY_SOURCE), |
815 base::UTF8ToUTF16(welcome_notification_id), | 841 base::UTF8ToUTF16(welcome_notification_id), |
816 rich_notification_data, | 842 rich_notification_data, |
817 delegate.get()); | 843 delegate.get()); |
818 } | 844 } |
819 | 845 |
820 } // namespace notifier | 846 } // namespace notifier |
OLD | NEW |