chrome_notifier_service.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The ChromeNotifierService works together with sync to maintain the state of 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// user notifications, which can then be presented in the notification center, 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// via the Notification UI Manager. 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <set> 12a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include <string> 13a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include <vector> 14a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "base/command_line.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/guid.h" 178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/metrics/histogram.h" 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/prefs/pref_service.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/values.h" 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/notifications/desktop_notification_service.h" 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/notifications/desktop_notification_service_factory.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/notifications/notification.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/notifications/notification_ui_manager.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.h" 262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/notifications/sync_notifier/welcome_delegate.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/common/pref_names.h" 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "components/user_prefs/pref_registry_syncable.h" 31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "content/public/browser/user_metrics.h" 33a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "grit/generated_resources.h" 34a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "grit/theme_resources.h" 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_change.h" 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_change_processor.h" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_error_factory.h" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/protocol/sync.pb.h" 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/protocol/synced_notification_specifics.pb.h" 407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebTextDirection.h" 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/l10n/l10n_util.h" 42a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "ui/base/resource/resource_bundle.h" 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/message_center/notifier_settings.h" 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::UserMetricsAction; 478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace notifier { 49a3f7b4e666c476898878fa745f637129375cd889Ben Murdochconst char kFirstSyncedNotificationServiceId[] = "Google+"; 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSyncedNotificationsWelcomeOrigin[] = 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "synced-notifications://welcome"; 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// SyncedNotificationAppInfoTemp is a class that contains the information 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// necessary to produce a welcome notification and the app badges for all synced 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// notification. 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(dewittj): Convert this into a sync protobuf-backed data structure. 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class SyncedNotificationAppInfoTemp { 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) explicit SyncedNotificationAppInfoTemp(const std::string& app_id, 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::string16& service_name); 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ~SyncedNotificationAppInfoTemp(); 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id() const { return app_id_; } 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& service_name() const { return service_name_; } 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& title() const { return title_; } 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void set_icon(const gfx::Image& icon) { icon_ = icon; } 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Image& icon() const { return icon_; } 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void set_small_icon(const gfx::Image& small_icon) { 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) small_icon_ = small_icon; 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Image& small_icon() const { return small_icon_; } 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const message_center::NotifierId GetNotifierId() const; 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string app_id_; 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 service_name_; 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Image icon_; 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Image small_icon_; 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 title_; 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 message_; 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SyncedNotificationAppInfoTemp::SyncedNotificationAppInfoTemp( 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id, 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& service_name) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : app_id_(app_id), service_name_(service_name) { 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) title_ = 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringFUTF16(IDS_NOTIFIER_WELCOME_TITLE, service_name_); 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SyncedNotificationAppInfoTemp::~SyncedNotificationAppInfoTemp() {} 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const message_center::NotifierId SyncedNotificationAppInfoTemp::GetNotifierId() 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const { 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return message_center::NotifierId( 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE, app_id()); 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ChromeNotifierService::avoid_bitmap_fetching_for_test_ = false; 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ChromeNotifierService::ChromeNotifierService(Profile* profile, 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NotificationUIManager* manager) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : profile_(profile), 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification_manager_(manager), 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_(false) { 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SyncedNotificationAppInfoTemp* temp_app_info = 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new SyncedNotificationAppInfoTemp( 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kFirstSyncedNotificationServiceId, 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_FIRST_SYNCED_NOTIFICATION_SERVICE_NAME)); 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) temp_app_info->set_small_icon( 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::ResourceBundle::GetSharedInstance().GetImageNamed( 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IDR_TEMPORARY_GOOGLE_PLUS_ICON)); 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info_data_.push_back(temp_app_info); 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) InitializePrefs(); 119a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch} 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ChromeNotifierService::~ChromeNotifierService() {} 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Methods from KeyedService. 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromeNotifierService::Shutdown() {} 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// syncer::SyncableService implementation. 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is called at startup to sync with the server. 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This code is not thread safe. 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncMergeResult ChromeNotifierService::MergeDataAndStartSyncing( 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::ModelType type, 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncDataList& initial_sync_data, 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<syncer::SyncErrorFactory> error_handler) { 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) thread_checker_.CalledOnValidThread(); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncMergeResult merge_result(syncer::SYNCED_NOTIFICATIONS); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A list of local changes to send up to the sync server. 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList new_changes; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_processor_ = sync_processor.Pass(); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (syncer::SyncDataList::const_iterator it = initial_sync_data.begin(); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != initial_sync_data.end(); ++it) { 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const syncer::SyncData& sync_data = *it; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, sync_data.GetDataType()); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Build a local notification object from the sync data. 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> incoming(CreateNotificationFromSyncData( 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!incoming) { 151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // TODO(petewil): Turn this into a NOTREACHED() call once we fix the 152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // underlying problem causing bad data. 153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) LOG(WARNING) << "Badly formed sync data in incoming notification"; 154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Process each incoming remote notification. 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& key = incoming->GetKey(); 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GT(key.length(), 0U); 1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SyncedNotification* found = FindNotificationById(key); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (NULL == found) { 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there are no conflicts, copy in the data from remote. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Add(incoming.Pass()); 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the incoming (remote) and stored (local) notifications match 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in all fields, we don't need to do anything here. 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (incoming->EqualsIgnoringReadState(*found)) { 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (incoming->GetReadState() == found->GetReadState()) { 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Notification matches on the client and the server, nothing to do. 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the read state is different, read wins for both places. 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (incoming->GetReadState() == SyncedNotification::kDismissed) { 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If it is marked as read on the server, but not the client. 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found->NotificationHasBeenDismissed(); 178ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the Notification UI Manager to remove it. 179ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_manager_->CancelById(found->GetKey()); 180ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else if (incoming->GetReadState() == SyncedNotification::kRead) { 181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If it is marked as read on the server, but not the client. 182ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch found->NotificationHasBeenRead(); 183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the Notification UI Manager to remove it. 1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch notification_manager_->CancelById(found->GetKey()); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If it is marked as read on the client, but not the server. 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = CreateSyncDataFromNotification(*found); 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_changes.push_back( 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE, 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If local state changed, notify Notification UI Manager. 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If different, just replace the local with the remote. 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(petewil): Someday we may allow changes from the client to 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // flow upwards, when we do, we will need better merge resolution. 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found->Update(sync_data); 2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Tell the notification manager to update the notification. 202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(found); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send up the changes that were made locally. 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_changes.size() > 0) { 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.set_error(sync_processor_->ProcessSyncChanges( 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, new_changes)); 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Once we complete our first sync, we mark "first run" as false, 2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // subsequent runs of Synced Notifications will get normal treatment. 2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (synced_notification_first_run_) { 2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = false; 2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->SetBoolean(prefs::kSyncedNotificationFirstRun, false); 2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return merge_result; 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeNotifierService::StopSyncing(syncer::ModelType type) { 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Since this data type is not user-unselectable, we chose not to implement 226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the stop syncing method, and instead do nothing here. 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncDataList ChromeNotifierService::GetAllSyncData( 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::ModelType type) const { 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncDataList sync_data; 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy our native format data into a SyncDataList format. 235ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::const_iterator it = 236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.begin(); 237ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data.push_back(CreateSyncDataFromNotification(**it)); 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return sync_data; 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This method is called when there is an incoming sync change from the server. 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncError ChromeNotifierService::ProcessSyncChanges( 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const tracked_objects::Location& from_here, 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncChangeList& change_list) { 248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) thread_checker_.CalledOnValidThread(); 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncError error; 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (syncer::SyncChangeList::const_iterator it = change_list.begin(); 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != change_list.end(); ++it) { 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = it->sync_data(); 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, sync_data.GetDataType()); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::SyncChangeType change_type = it->change_type(); 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> new_notification( 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNotificationFromSyncData(sync_data)); 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!new_notification.get()) { 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "Failed to read notification."; 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 264ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const std::string& key = new_notification->GetKey(); 265ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK_GT(key.length(), 0U); 266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* found = FindNotificationById(key); 267ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (change_type) { 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case syncer::SyncChange::ACTION_ADD: 270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Intentional fall through, cases are identical. 271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case syncer::SyncChange::ACTION_UPDATE: 272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (found == NULL) { 273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Add(new_notification.Pass()); 274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Update it in our store. 277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch found->Update(sync_data); 278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the notification manager to update the notification. 279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(found); 280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case syncer::SyncChange::ACTION_DELETE: 283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (found == NULL) { 284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Remove it from our store. 287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FreeNotificationById(key); 288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Remove it from the message center. 289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(new_notification.get()); 290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // TODO(petewil): Do I need to remember that it was deleted in case the 291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // add arrives after the delete? If so, how long do I need to remember? 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch NOTREACHED(); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return error; 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Support functions for data type conversion. 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Static method. Get to the sync data in our internal format. 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncData ChromeNotifierService::CreateSyncDataFromNotification( 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SyncedNotification& notification) { 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Construct the sync_data using the specifics from the notification. 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return syncer::SyncData::CreateLocalData( 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) notification.GetKey(), notification.GetKey(), 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notification.GetEntitySpecifics()); 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Static Method. Convert from SyncData to our internal format. 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<SyncedNotification> 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ChromeNotifierService::CreateNotificationFromSyncData( 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncData& sync_data) { 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get a pointer to our data within the sync_data object. 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::SyncedNotificationSpecifics specifics = 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data.GetSpecifics().synced_notification(); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check for mandatory fields in the sync_data object. 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!specifics.has_coalesced_notification() || 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !specifics.coalesced_notification().has_key() || 325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) !specifics.coalesced_notification().has_read_state()) { 326b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DVLOG(1) << "Synced Notification missing mandatory fields " 327b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << "has coalesced notification? " 328b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << specifics.has_coalesced_notification() 329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " has key? " << specifics.coalesced_notification().has_key() 330b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " has read state? " 331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << specifics.coalesced_notification().has_read_state(); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_ptr<SyncedNotification>(); 333b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_well_formed_unread_notification = 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (static_cast<SyncedNotification::ReadState>( 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().read_state()) == 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification::kUnread && 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().has_render_info()); 340ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool is_well_formed_read_notification = 341ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (static_cast<SyncedNotification::ReadState>( 342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch specifics.coalesced_notification().read_state()) == 343424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SyncedNotification::kRead); 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_well_formed_dismissed_notification = 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (static_cast<SyncedNotification::ReadState>( 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().read_state()) == 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification::kDismissed); 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If the notification is poorly formed, return a null pointer. 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_well_formed_unread_notification && 351ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch !is_well_formed_read_notification && 352b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) !is_well_formed_dismissed_notification) { 353b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DVLOG(1) << "Synced Notification is not well formed." 354b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " unread well formed? " 355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << is_well_formed_unread_notification 356b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " dismissed well formed? " 357ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << is_well_formed_dismissed_notification 358ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << " read well formed? " 359ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << is_well_formed_read_notification; 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_ptr<SyncedNotification>(); 361b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a new notification object based on the supplied sync_data. 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> notification( 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new SyncedNotification(sync_data)); 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return notification.Pass(); 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This returns a pointer into a vector that we own. Caller must not free it. 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns NULL if no match is found. 3727dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSyncedNotification* ChromeNotifierService::FindNotificationById( 3737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& notification_id) { 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(petewil): We can make a performance trade off here. 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // While the vector has good locality of reference, a map has faster lookup. 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Based on how big we expect this to get, maybe change this to a map. 377ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::const_iterator it = 378ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.begin(); 379ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification* notification = *it; 3817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (notification_id == notification->GetKey()) 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return *it; 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::FreeNotificationById( 389ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const std::string& notification_id) { 390ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::iterator it = notification_data_.begin(); 391ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 392ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* notification = *it; 393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (notification_id == notification->GetKey()) { 394ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.erase(it); 395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 398ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ChromeNotifierService::GetSyncedNotificationServices( 401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<message_center::Notifier*>* notifiers) { 4027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(mukai|petewil): Check the profile's eligibility before adding the 4037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // sample app. 404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ScopedVector<SyncedNotificationAppInfoTemp>::iterator it = 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) app_info_data_.begin(); 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (; it != app_info_data_.end(); ++it) { 407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SyncedNotificationAppInfoTemp* app_info = *it; 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NotifierId notifier_id = app_info->GetNotifierId(); 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Enable or disable the sending service per saved settings. 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool app_enabled = false; 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::set<std::string>::iterator iter; 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter = find(enabled_sending_services_.begin(), 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_sending_services_.end(), 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notifier_id.id); 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_enabled = iter != enabled_sending_services_.end(); 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::Notifier* app_info_notifier = new message_center::Notifier( 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notifier_id, app_info->service_name(), app_enabled); 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info_notifier->icon = app_info->small_icon(); 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // |notifiers| takes ownership of |app_info_notifier|. 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notifiers->push_back(app_info_notifier); 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 428ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::MarkNotificationAsRead( 429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& key) { 430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 4317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SyncedNotification* notification = FindNotificationById(key); 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(notification != NULL); 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 434ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification->NotificationHasBeenRead(); 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList new_changes; 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = CreateSyncDataFromNotification(*notification); 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_changes.push_back( 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE, 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send up the changes that were made locally. 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Add a new notification to our data structure. This takes ownership 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// of the passed in pointer. 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeNotifierService::Add(scoped_ptr<SyncedNotification> notification) { 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification* notification_copy = notification.get(); 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Take ownership of the object and put it into our local storage. 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notification_data_.push_back(notification.release()); 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 454a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // If the user is not interested in this type of notification, ignore it. 455d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter = 456a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch find(enabled_sending_services_.begin(), 457a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch enabled_sending_services_.end(), 458a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch notification_copy->GetSendingServiceId()); 459a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (iter == enabled_sending_services_.end()) { 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter = find(initialized_sending_services_.begin(), 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) initialized_sending_services_.end(), 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification_copy->GetSendingServiceId()); 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (iter != initialized_sending_services_.end()) 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 465a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 466a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 467ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(notification_copy); 4687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 4697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ChromeNotifierService::AddForTest( 4717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch scoped_ptr<notifier::SyncedNotification> notification) { 472ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.push_back(notification.release()); 473ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 4747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 475ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::UpdateInMessageCenter( 476ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* notification) { 4772385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // If the feature is disabled, exit now. 4782385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (!notifier::ChromeNotifierServiceFactory::UseSyncedNotifications( 479ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch CommandLine::ForCurrentProcess())) 4802385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return; 481a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 482ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification->LogNotification(); 483ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 484ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (notification->GetReadState() == SyncedNotification::kUnread) { 485ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the message is unread, update it. 486ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Display(notification); 487ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 488ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the message is read or deleted, dismiss it from the center. 489ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // We intentionally ignore errors if it is not in the center. 490ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_manager_->CancelById(notification->GetKey()); 491ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 492ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 493ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 494ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::Display(SyncedNotification* notification) { 4954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If this is the first run for the feature, don't surprise the user. 4964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Instead, place all backlogged notifications into the notification 4974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // center. 4984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (synced_notification_first_run_) { 4994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Setting the toast state to false will prevent toasting the notification. 5004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) notification->SetToastState(false); 5014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 5024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Our tests cannot use the network for reliability reasons. 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (avoid_bitmap_fetching_for_test_) { 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification->Show(notification_manager_, this, profile_); 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Set up to fetch the bitmaps. 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification->QueueBitmapFetchJobs(notification_manager_, this, profile_); 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Start the bitmap fetching, Show() will be called when the last bitmap 513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // either arrives or times out. 5147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch notification->StartBitmapFetch(); 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ChromeNotifierService::OnSyncedNotificationServiceEnabled( 518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& notifier_id, bool enabled) { 519d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 520d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 521d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Make a copy of the notifier_id, which might not have lifetime long enough 522d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // for this function to finish all of its work. 523d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string notifier_id_copy(notifier_id); 524a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 525a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch iter = find(enabled_sending_services_.begin(), 526a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch enabled_sending_services_.end(), 527d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) notifier_id_copy); 528d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 5294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue synced_notification_services; 530a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 531a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // Add the notifier_id if it is enabled and not already there. 532a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (iter == enabled_sending_services_.end() && enabled) { 533d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_.insert(notifier_id_copy); 5343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Check now for any outstanding notifications. 5353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DisplayUnreadNotificationsFromSource(notifier_id); 536d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 537d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &synced_notification_services); 538d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Add this preference to the enabled list. 5394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, 5404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_services); 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Remove the notifier_id if it is disabled and present. 542a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } else if (iter != enabled_sending_services_.end() && !enabled) { 543a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch enabled_sending_services_.erase(iter); 544d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 545d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &synced_notification_services); 546d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Remove this peference from the enabled list. 5474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, 5484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_services); 549d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) RemoveUnreadNotificationsFromSource(notifier_id_copy); 550a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 551a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 5528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Collect UMA statistics when a service is enabled or disabled. 5538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (enabled) { 5548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) content::RecordAction( 5558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UserMetricsAction("SyncedNotifications.SendingServiceEnabled")); 5568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else { 5578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) content::RecordAction( 5588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UserMetricsAction("SyncedNotifications.SendingServiceDisabled")); 5598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 5608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Collect individual service enabling/disabling statistics. 5628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CollectPerServiceEnablingStatistics(notifier_id, enabled); 5638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 564a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch return; 565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ChromeNotifierService::CollectPerServiceEnablingStatistics( 5688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const std::string& notifier_id, 5698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool enabled) { 5708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(petewil) - This approach does not scale well as we add new services, 5718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // but we are limited to using predefined ENUM values in histogram based UMA 5728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // data, which does not permit arbitrary strings. 5738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find a way to make it scale, or remove enum value this when we have enough 5748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // data. 5758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ChromeNotifierServiceActionType action = 5778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CHROME_NOTIFIER_SERVICE_ACTION_UNKNOWN; 5788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Derive action type from notifier_id and enabled. 5808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(petewil): Add more sending services as they are enabled. 5818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (notifier_id == std::string(kFirstSyncedNotificationServiceId)) { 5828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) action = enabled 5838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ? CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_ENABLED 5848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_DISABLED; 5858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 5868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("ChromeNotifierService.Actions", 5888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) action, 5898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CHROME_NOTIFIER_SERVICE_ACTION_COUNT); 5908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 5918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 592d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::BuildServiceListValueInplace( 5934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::set<std::string> services, base::ListValue* list_value) { 594d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 595d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 596d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Iterate over the strings, adding each one to the list value 597d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (iter = services.begin(); 598d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) iter != services.end(); 599d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ++iter) { 6004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::StringValue* string_value(new base::StringValue(*iter)); 6014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) list_value->Append(string_value); 602d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 603d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 604d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ChromeNotifierService::DisplayUnreadNotificationsFromSource( 606d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& notifier_id) { 6073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (std::vector<SyncedNotification*>::const_iterator iter = 6083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_data_.begin(); 6093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) iter != notification_data_.end(); 6103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ++iter) { 6113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if ((*iter)->GetSendingServiceId() == notifier_id && 6123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) (*iter)->GetReadState() == SyncedNotification::kUnread) 6133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Display(*iter); 6143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 6153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 6163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 6173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ChromeNotifierService::RemoveUnreadNotificationsFromSource( 618d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& notifier_id) { 6193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (std::vector<SyncedNotification*>::const_iterator iter = 6203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_data_.begin(); 6213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) iter != notification_data_.end(); 6223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ++iter) { 6233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if ((*iter)->GetSendingServiceId() == notifier_id && 624d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (*iter)->GetReadState() == SyncedNotification::kUnread) { 6253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_manager_->CancelById((*iter)->GetKey()); 626d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 6273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 6283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 6293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 630d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::OnEnabledSendingServiceListPrefChanged( 631d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>* ids_field) { 632d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->clear(); 633d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<std::string> pref_list = 634d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_prefs_.GetValue(); 635d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (size_t i = 0; i < pref_list.size(); ++i) { 636d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string element = pref_list[i]; 637d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!element.empty()) 638d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->insert(element); 639d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) else 640d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(WARNING) << i << "-th element is not a string " 641d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << prefs::kEnabledSyncedNotificationSendingServices; 642d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 643d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 644d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 645d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::OnInitializedSendingServiceListPrefChanged( 646d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>* ids_field) { 647d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->clear(); 648d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<std::string> pref_list = 649d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_prefs_.GetValue(); 650d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (size_t i = 0; i < pref_list.size(); ++i) { 651d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string element = pref_list[i]; 652d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!element.empty()) 653d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->insert(element); 654d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) else 655d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(WARNING) << i << "-th element is not a string for " 656d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << prefs::kInitializedSyncedNotificationSendingServices; 657d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 658d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 659d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ChromeNotifierService::OnSyncedNotificationFirstRunBooleanPrefChanged( 6614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool* new_value) { 6624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = *new_value; 6634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 6644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 665d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::RegisterProfilePrefs( 666d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) user_prefs::PrefRegistrySyncable* registry) { 667d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Register the pref for the list of enabled services. 668d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) registry->RegisterListPref( 669d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kEnabledSyncedNotificationSendingServices, 6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 671d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Register the pref for the list of initialized services. 672d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) registry->RegisterListPref( 673d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 6754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Register the preference for first run status, defaults to "true", 6764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // meaning that this is the first run of the Synced Notification feature. 6774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) registry->RegisterBooleanPref( 6784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kSyncedNotificationFirstRun, true, 6794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 680d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 681d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 682d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::InitializePrefs() { 683d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Set up any pref changes to update our list of services. 684d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_prefs_.Init( 685d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kEnabledSyncedNotificationSendingServices, 686d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) profile_->GetPrefs(), 687d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind( 688d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &ChromeNotifierService::OnEnabledSendingServiceListPrefChanged, 689d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(this), 690d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(&enabled_sending_services_))); 691d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_prefs_.Init( 692d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 693d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) profile_->GetPrefs(), 694d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind( 695d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &ChromeNotifierService::OnInitializedSendingServiceListPrefChanged, 696d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(this), 697d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(&initialized_sending_services_))); 6984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_prefs_.Init( 6994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kSyncedNotificationFirstRun, 7004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs(), 7014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind( 7024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &ChromeNotifierService:: 7034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OnSyncedNotificationFirstRunBooleanPrefChanged, 7044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Unretained(this), 7054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Unretained(&synced_notification_first_run_))); 706d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 707d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Get the prefs from last session into our memeber varilables 708d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) OnEnabledSendingServiceListPrefChanged(&enabled_sending_services_); 709d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) OnInitializedSendingServiceListPrefChanged(&initialized_sending_services_); 7108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 7114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = 7124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->GetBoolean(prefs::kSyncedNotificationFirstRun); 713d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 714d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ChromeNotifierService::ShowWelcomeToastIfNecessary( 7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const SyncedNotification* synced_notification, 7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NotificationUIManager* notification_ui_manager) { 7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& sending_service_id = 7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) synced_notification->GetSendingServiceId(); 720d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 721d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 722d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) iter = find(initialized_sending_services_.begin(), 723d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_.end(), 7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sending_service_id); 7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If we already initialized the sending service, then return early since no 7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // welcome toast is necessary. 7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (iter != initialized_sending_services_.end()) 729d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 730d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If there is no app info, we can't show a welcome toast. Ideally all synced 7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // notifications will be delayed until an app_info data structure can be 7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // constructed for them. 7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(dewittj): Refactor when app_info is populated asynchronously. 735a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SyncedNotificationAppInfoTemp* app_info = FindAppInfo(sending_service_id); 7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!app_info) 7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(dewittj): Ensure that the app info icon is set before this point. 7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_info->icon().IsEmpty()) { 7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Image notification_app_icon = synced_notification->GetAppIcon(); 7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!notification_app_icon.IsEmpty()) { 7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info->set_icon(notification_app_icon); 7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This block should only be reached in tests since the downloads are 7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // already finished for |synced_notification|. 7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Unable to find the app icon for the welcome notification. " 7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "Service ID: " << sending_service_id; 7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NotifierId notifier_id( 7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE, 7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sending_service_id); 7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Notification notification = CreateWelcomeNotificationForService(app_info); 7575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification_ui_manager->Add(notification, profile_); 7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_sending_services_.insert(sending_service_id); 7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) initialized_sending_services_.insert(sending_service_id); 7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 762d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Build a ListValue with the list of services to be enabled. 7634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue enabled_sending_services; 7644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue initialized_sending_services; 765d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 766d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Mark any new services as enabled in preferences. 7674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 7684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &enabled_sending_services); 7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, 7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_sending_services); 7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Mark any new services as initialized in preferences. 7724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BuildServiceListValueInplace(initialized_sending_services_, 7734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &initialized_sending_services); 7744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set( 7754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 7764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) initialized_sending_services); 777d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 7783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 779a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SyncedNotificationAppInfoTemp* ChromeNotifierService::FindAppInfo( 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id) const { 781a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ScopedVector<SyncedNotificationAppInfoTemp>::const_iterator iter = 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info_data_.begin(); 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (iter != app_info_data_.end()) { 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((*iter)->app_id() == app_id) 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return (*iter); 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++iter; 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const Notification ChromeNotifierService::CreateWelcomeNotificationForService( 794a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SyncedNotificationAppInfoTemp* app_info) { 7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string welcome_notification_id = base::GenerateGUID(); 7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<WelcomeDelegate> delegate(new WelcomeDelegate( 7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) welcome_notification_id, profile_, app_info->GetNotifierId())); 7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::ButtonInfo button_info( 8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BUTTON)); 8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) button_info.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( 8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IDR_NOTIFIER_BLOCK_BUTTON); 8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::RichNotificationData rich_notification_data; 8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rich_notification_data.buttons.push_back(button_info); 8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return Notification( 8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NOTIFICATION_TYPE_BASE_FORMAT, 8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL(kSyncedNotificationsWelcomeOrigin), 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info->title(), 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BODY), 8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info->icon(), 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blink::WebTextDirectionDefault, 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info->GetNotifierId(), 8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_DISPLAY_SOURCE), 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(welcome_notification_id), 8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rich_notification_data, 8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate.get()); 8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace notifier 821