chrome_notifier_service.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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) 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// SyncedNotificationAppInfo is a class that contains the information necessary 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 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. 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class SyncedNotificationAppInfo { 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) explicit SyncedNotificationAppInfo(const std::string& app_id, 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& service_name); 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~SyncedNotificationAppInfo(); 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) 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SyncedNotificationAppInfo::SyncedNotificationAppInfo( 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) 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SyncedNotificationAppInfo::~SyncedNotificationAppInfo() {} 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const message_center::NotifierId SyncedNotificationAppInfo::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) { 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(petewil): Replace this temporary hardcoding with a new sync datatype 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // to dynamically get the name and icon for each synced notification sending 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // service. Until then, we use hardcoded service icons for all services. 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // crbug.com/248337 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncedNotificationAppInfo* temp_app_info = new SyncedNotificationAppInfo( 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kFirstSyncedNotificationServiceId, 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_FIRST_SYNCED_NOTIFICATION_SERVICE_NAME)); 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) temp_app_info->set_small_icon( 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::ResourceBundle::GetSharedInstance().GetImageNamed( 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IDR_TEMPORARY_GOOGLE_PLUS_ICON)); 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info_data_.push_back(temp_app_info); 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) InitializePrefs(); 122a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch} 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ChromeNotifierService::~ChromeNotifierService() {} 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Methods from BrowserContextKeyedService. 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromeNotifierService::Shutdown() {} 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// syncer::SyncableService implementation. 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is called at startup to sync with the server. 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This code is not thread safe. 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncMergeResult ChromeNotifierService::MergeDataAndStartSyncing( 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::ModelType type, 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncDataList& initial_sync_data, 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<syncer::SyncErrorFactory> error_handler) { 138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncMergeResult merge_result(syncer::SYNCED_NOTIFICATIONS); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A list of local changes to send up to the sync server. 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList new_changes; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_processor_ = sync_processor.Pass(); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (syncer::SyncDataList::const_iterator it = initial_sync_data.begin(); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != initial_sync_data.end(); ++it) { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const syncer::SyncData& sync_data = *it; 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, sync_data.GetDataType()); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Build a local notification object from the sync data. 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> incoming(CreateNotificationFromSyncData( 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!incoming) { 154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // TODO(petewil): Turn this into a NOTREACHED() call once we fix the 155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // underlying problem causing bad data. 156b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) LOG(WARNING) << "Badly formed sync data in incoming notification"; 157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Process each incoming remote notification. 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& key = incoming->GetKey(); 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GT(key.length(), 0U); 1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SyncedNotification* found = FindNotificationById(key); 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (NULL == found) { 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there are no conflicts, copy in the data from remote. 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Add(incoming.Pass()); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the incoming (remote) and stored (local) notifications match 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in all fields, we don't need to do anything here. 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (incoming->EqualsIgnoringReadState(*found)) { 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (incoming->GetReadState() == found->GetReadState()) { 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Notification matches on the client and the server, nothing to do. 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the read state is different, read wins for both places. 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (incoming->GetReadState() == SyncedNotification::kDismissed) { 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If it is marked as read on the server, but not the client. 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found->NotificationHasBeenDismissed(); 181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the Notification UI Manager to remove it. 182ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_manager_->CancelById(found->GetKey()); 183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else if (incoming->GetReadState() == SyncedNotification::kRead) { 184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If it is marked as read on the server, but not the client. 185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch found->NotificationHasBeenRead(); 186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the Notification UI Manager to remove it. 1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch notification_manager_->CancelById(found->GetKey()); 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If it is marked as read on the client, but not the server. 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = CreateSyncDataFromNotification(*found); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_changes.push_back( 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE, 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If local state changed, notify Notification UI Manager. 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If different, just replace the local with the remote. 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(petewil): Someday we may allow changes from the client to 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // flow upwards, when we do, we will need better merge resolution. 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found->Update(sync_data); 2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Tell the notification manager to update the notification. 205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(found); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send up the changes that were made locally. 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_changes.size() > 0) { 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.set_error(sync_processor_->ProcessSyncChanges( 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, new_changes)); 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Once we complete our first sync, we mark "first run" as false, 2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // subsequent runs of Synced Notifications will get normal treatment. 2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (synced_notification_first_run_) { 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = false; 2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->SetBoolean(prefs::kSyncedNotificationFirstRun, false); 2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return merge_result; 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeNotifierService::StopSyncing(syncer::ModelType type) { 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Since this data type is not user-unselectable, we chose not to implement 229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the stop syncing method, and instead do nothing here. 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncDataList ChromeNotifierService::GetAllSyncData( 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::ModelType type) const { 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncDataList sync_data; 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy our native format data into a SyncDataList format. 238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::const_iterator it = 239ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.begin(); 240ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data.push_back(CreateSyncDataFromNotification(**it)); 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return sync_data; 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This method is called when there is an incoming sync change from the server. 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncError ChromeNotifierService::ProcessSyncChanges( 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const tracked_objects::Location& from_here, 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncChangeList& change_list) { 251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncError error; 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (syncer::SyncChangeList::const_iterator it = change_list.begin(); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != change_list.end(); ++it) { 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = it->sync_data(); 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, sync_data.GetDataType()); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::SyncChangeType change_type = it->change_type(); 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> new_notification( 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNotificationFromSyncData(sync_data)); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!new_notification.get()) { 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "Failed to read notification."; 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 267ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const std::string& key = new_notification->GetKey(); 268ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK_GT(key.length(), 0U); 269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* found = FindNotificationById(key); 270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (change_type) { 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case syncer::SyncChange::ACTION_ADD: 273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Intentional fall through, cases are identical. 274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case syncer::SyncChange::ACTION_UPDATE: 275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (found == NULL) { 276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Add(new_notification.Pass()); 277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Update it in our store. 280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch found->Update(sync_data); 281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the notification manager to update the notification. 282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(found); 283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case syncer::SyncChange::ACTION_DELETE: 286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (found == NULL) { 287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Remove it from our store. 290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FreeNotificationById(key); 291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Remove it from the message center. 292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(new_notification.get()); 293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // TODO(petewil): Do I need to remember that it was deleted in case the 294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // add arrives after the delete? If so, how long do I need to remember? 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch NOTREACHED(); 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return error; 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Support functions for data type conversion. 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Static method. Get to the sync data in our internal format. 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncData ChromeNotifierService::CreateSyncDataFromNotification( 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SyncedNotification& notification) { 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Construct the sync_data using the specifics from the notification. 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return syncer::SyncData::CreateLocalData( 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) notification.GetKey(), notification.GetKey(), 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notification.GetEntitySpecifics()); 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Static Method. Convert from SyncData to our internal format. 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<SyncedNotification> 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ChromeNotifierService::CreateNotificationFromSyncData( 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncData& sync_data) { 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get a pointer to our data within the sync_data object. 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::SyncedNotificationSpecifics specifics = 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data.GetSpecifics().synced_notification(); 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check for mandatory fields in the sync_data object. 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!specifics.has_coalesced_notification() || 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !specifics.coalesced_notification().has_key() || 328b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) !specifics.coalesced_notification().has_read_state()) { 329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DVLOG(1) << "Synced Notification missing mandatory fields " 330b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << "has coalesced notification? " 331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << specifics.has_coalesced_notification() 332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " has key? " << specifics.coalesced_notification().has_key() 333b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " has read state? " 334b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << specifics.coalesced_notification().has_read_state(); 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_ptr<SyncedNotification>(); 336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_well_formed_unread_notification = 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (static_cast<SyncedNotification::ReadState>( 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().read_state()) == 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification::kUnread && 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().has_render_info()); 343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool is_well_formed_read_notification = 344ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (static_cast<SyncedNotification::ReadState>( 345ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch specifics.coalesced_notification().read_state()) == 346424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SyncedNotification::kRead); 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_well_formed_dismissed_notification = 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (static_cast<SyncedNotification::ReadState>( 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().read_state()) == 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification::kDismissed); 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If the notification is poorly formed, return a null pointer. 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_well_formed_unread_notification && 354ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch !is_well_formed_read_notification && 355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) !is_well_formed_dismissed_notification) { 356b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DVLOG(1) << "Synced Notification is not well formed." 357b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " unread well formed? " 358b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << is_well_formed_unread_notification 359b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " dismissed well formed? " 360ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << is_well_formed_dismissed_notification 361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << " read well formed? " 362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << is_well_formed_read_notification; 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_ptr<SyncedNotification>(); 364b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a new notification object based on the supplied sync_data. 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> notification( 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new SyncedNotification(sync_data)); 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return notification.Pass(); 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This returns a pointer into a vector that we own. Caller must not free it. 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns NULL if no match is found. 3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSyncedNotification* ChromeNotifierService::FindNotificationById( 3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& notification_id) { 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(petewil): We can make a performance trade off here. 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // While the vector has good locality of reference, a map has faster lookup. 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Based on how big we expect this to get, maybe change this to a map. 380ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::const_iterator it = 381ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.begin(); 382ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification* notification = *it; 3847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (notification_id == notification->GetKey()) 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return *it; 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 391ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::FreeNotificationById( 392ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const std::string& notification_id) { 393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::iterator it = notification_data_.begin(); 394ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* notification = *it; 396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (notification_id == notification->GetKey()) { 397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.erase(it); 398ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 400ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 401ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 402ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ChromeNotifierService::GetSyncedNotificationServices( 404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<message_center::Notifier*>* notifiers) { 4057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(mukai|petewil): Check the profile's eligibility before adding the 4067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // sample app. 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedVector<SyncedNotificationAppInfo>::iterator it = app_info_data_.begin(); 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (; it != app_info_data_.end(); ++it) { 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncedNotificationAppInfo* app_info = *it; 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NotifierId notifier_id = app_info->GetNotifierId(); 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Enable or disable the sending service per saved settings. 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool app_enabled = false; 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::set<std::string>::iterator iter; 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter = find(enabled_sending_services_.begin(), 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_sending_services_.end(), 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notifier_id.id); 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_enabled = iter != enabled_sending_services_.end(); 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::Notifier* app_info_notifier = new message_center::Notifier( 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notifier_id, app_info->service_name(), app_enabled); 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info_notifier->icon = app_info->small_icon(); 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // |notifiers| takes ownership of |app_info_notifier|. 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notifiers->push_back(app_info_notifier); 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 430ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::MarkNotificationAsRead( 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& key) { 432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 4337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SyncedNotification* notification = FindNotificationById(key); 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(notification != NULL); 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 436ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification->NotificationHasBeenRead(); 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList new_changes; 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = CreateSyncDataFromNotification(*notification); 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_changes.push_back( 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE, 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send up the changes that were made locally. 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Add a new notification to our data structure. This takes ownership 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// of the passed in pointer. 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeNotifierService::Add(scoped_ptr<SyncedNotification> notification) { 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification* notification_copy = notification.get(); 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Take ownership of the object and put it into our local storage. 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notification_data_.push_back(notification.release()); 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 456a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // If the user is not interested in this type of notification, ignore it. 457d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter = 458a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch find(enabled_sending_services_.begin(), 459a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch enabled_sending_services_.end(), 460a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch notification_copy->GetSendingServiceId()); 461a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (iter == enabled_sending_services_.end()) { 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter = find(initialized_sending_services_.begin(), 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) initialized_sending_services_.end(), 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification_copy->GetSendingServiceId()); 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (iter != initialized_sending_services_.end()) 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 467a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 468a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 469ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(notification_copy); 4707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 4717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ChromeNotifierService::AddForTest( 4737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch scoped_ptr<notifier::SyncedNotification> notification) { 474ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.push_back(notification.release()); 475ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 4767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 477ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::UpdateInMessageCenter( 478ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* notification) { 4792385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // If the feature is disabled, exit now. 4802385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (!notifier::ChromeNotifierServiceFactory::UseSyncedNotifications( 481ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch CommandLine::ForCurrentProcess())) 4822385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return; 483a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 484ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification->LogNotification(); 485ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 486ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (notification->GetReadState() == SyncedNotification::kUnread) { 487ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the message is unread, update it. 488ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Display(notification); 489ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 490ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the message is read or deleted, dismiss it from the center. 491ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // We intentionally ignore errors if it is not in the center. 492ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_manager_->CancelById(notification->GetKey()); 493ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 494ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 495ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 496ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::Display(SyncedNotification* notification) { 4974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If this is the first run for the feature, don't surprise the user. 4984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Instead, place all backlogged notifications into the notification 4994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // center. 5004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (synced_notification_first_run_) { 5014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Setting the toast state to false will prevent toasting the notification. 5024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) notification->SetToastState(false); 5034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 5044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Our tests cannot use the network for reliability reasons. 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (avoid_bitmap_fetching_for_test_) { 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification->Show(notification_manager_, this, profile_); 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Set up to fetch the bitmaps. 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification->QueueBitmapFetchJobs(notification_manager_, this, profile_); 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Start the bitmap fetching, Show() will be called when the last bitmap 515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // either arrives or times out. 5167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch notification->StartBitmapFetch(); 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ChromeNotifierService::OnSyncedNotificationServiceEnabled( 520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& notifier_id, bool enabled) { 521d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 522d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 523d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Make a copy of the notifier_id, which might not have lifetime long enough 524d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // for this function to finish all of its work. 525d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string notifier_id_copy(notifier_id); 526a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 527a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch iter = find(enabled_sending_services_.begin(), 528a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch enabled_sending_services_.end(), 529d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) notifier_id_copy); 530d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 5314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue synced_notification_services; 532a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 533a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // Add the notifier_id if it is enabled and not already there. 534a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (iter == enabled_sending_services_.end() && enabled) { 535d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_.insert(notifier_id_copy); 5363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Check now for any outstanding notifications. 5373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DisplayUnreadNotificationsFromSource(notifier_id); 538d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 539d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &synced_notification_services); 540d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Add this preference to the enabled list. 5414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, 5424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_services); 5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Remove the notifier_id if it is disabled and present. 544a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } else if (iter != enabled_sending_services_.end() && !enabled) { 545a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch enabled_sending_services_.erase(iter); 546d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 547d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &synced_notification_services); 548d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Remove this peference from the enabled list. 5494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, 5504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_services); 551d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) RemoveUnreadNotificationsFromSource(notifier_id_copy); 552a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 553a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 5548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Collect UMA statistics when a service is enabled or disabled. 5558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (enabled) { 5568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) content::RecordAction( 5578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UserMetricsAction("SyncedNotifications.SendingServiceEnabled")); 5588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else { 5598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) content::RecordAction( 5608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UserMetricsAction("SyncedNotifications.SendingServiceDisabled")); 5618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 5628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Collect individual service enabling/disabling statistics. 5648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CollectPerServiceEnablingStatistics(notifier_id, enabled); 5658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 566a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch return; 567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ChromeNotifierService::CollectPerServiceEnablingStatistics( 5708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const std::string& notifier_id, 5718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool enabled) { 5728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(petewil) - This approach does not scale well as we add new services, 5738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // but we are limited to using predefined ENUM values in histogram based UMA 5748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // data, which does not permit arbitrary strings. 5758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find a way to make it scale, or remove enum value this when we have enough 5768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // data. 5778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ChromeNotifierServiceActionType action = 5798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CHROME_NOTIFIER_SERVICE_ACTION_UNKNOWN; 5808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Derive action type from notifier_id and enabled. 5828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(petewil): Add more sending services as they are enabled. 5838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (notifier_id == std::string(kFirstSyncedNotificationServiceId)) { 5848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) action = enabled 5858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ? CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_ENABLED 5868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_DISABLED; 5878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 5888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("ChromeNotifierService.Actions", 5908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) action, 5918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CHROME_NOTIFIER_SERVICE_ACTION_COUNT); 5928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 5938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 594d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::BuildServiceListValueInplace( 5954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::set<std::string> services, base::ListValue* list_value) { 596d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 597d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 598d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Iterate over the strings, adding each one to the list value 599d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (iter = services.begin(); 600d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) iter != services.end(); 601d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ++iter) { 6024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::StringValue* string_value(new base::StringValue(*iter)); 6034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) list_value->Append(string_value); 604d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 605d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 606d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ChromeNotifierService::DisplayUnreadNotificationsFromSource( 608d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& notifier_id) { 6093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (std::vector<SyncedNotification*>::const_iterator iter = 6103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_data_.begin(); 6113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) iter != notification_data_.end(); 6123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ++iter) { 6133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if ((*iter)->GetSendingServiceId() == notifier_id && 6143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) (*iter)->GetReadState() == SyncedNotification::kUnread) 6153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Display(*iter); 6163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 6173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 6183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 6193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ChromeNotifierService::RemoveUnreadNotificationsFromSource( 620d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& notifier_id) { 6213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (std::vector<SyncedNotification*>::const_iterator iter = 6223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_data_.begin(); 6233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) iter != notification_data_.end(); 6243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ++iter) { 6253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if ((*iter)->GetSendingServiceId() == notifier_id && 626d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (*iter)->GetReadState() == SyncedNotification::kUnread) { 6273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_manager_->CancelById((*iter)->GetKey()); 628d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 6293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 6303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 6313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 632d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::OnEnabledSendingServiceListPrefChanged( 633d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>* ids_field) { 634d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->clear(); 635d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<std::string> pref_list = 636d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_prefs_.GetValue(); 637d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (size_t i = 0; i < pref_list.size(); ++i) { 638d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string element = pref_list[i]; 639d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!element.empty()) 640d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->insert(element); 641d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) else 642d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(WARNING) << i << "-th element is not a string " 643d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << prefs::kEnabledSyncedNotificationSendingServices; 644d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 645d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 646d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 647d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::OnInitializedSendingServiceListPrefChanged( 648d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>* ids_field) { 649d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->clear(); 650d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<std::string> pref_list = 651d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_prefs_.GetValue(); 652d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (size_t i = 0; i < pref_list.size(); ++i) { 653d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string element = pref_list[i]; 654d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!element.empty()) 655d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->insert(element); 656d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) else 657d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(WARNING) << i << "-th element is not a string for " 658d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << prefs::kInitializedSyncedNotificationSendingServices; 659d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 660d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 661d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ChromeNotifierService::OnSyncedNotificationFirstRunBooleanPrefChanged( 6634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool* new_value) { 6644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = *new_value; 6654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 6664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 667d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::RegisterProfilePrefs( 668d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) user_prefs::PrefRegistrySyncable* registry) { 669d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Register the pref for the list of enabled services. 670d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) registry->RegisterListPref( 671d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kEnabledSyncedNotificationSendingServices, 6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 673d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Register the pref for the list of initialized services. 674d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) registry->RegisterListPref( 675d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 6774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Register the preference for first run status, defaults to "true", 6784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // meaning that this is the first run of the Synced Notification feature. 6794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) registry->RegisterBooleanPref( 6804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kSyncedNotificationFirstRun, true, 6814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 682d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 683d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 684d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::InitializePrefs() { 685d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Set up any pref changes to update our list of services. 686d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_prefs_.Init( 687d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kEnabledSyncedNotificationSendingServices, 688d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) profile_->GetPrefs(), 689d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind( 690d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &ChromeNotifierService::OnEnabledSendingServiceListPrefChanged, 691d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(this), 692d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(&enabled_sending_services_))); 693d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_prefs_.Init( 694d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 695d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) profile_->GetPrefs(), 696d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind( 697d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &ChromeNotifierService::OnInitializedSendingServiceListPrefChanged, 698d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(this), 699d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(&initialized_sending_services_))); 7004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_prefs_.Init( 7014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kSyncedNotificationFirstRun, 7024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs(), 7034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind( 7044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &ChromeNotifierService:: 7054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OnSyncedNotificationFirstRunBooleanPrefChanged, 7064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Unretained(this), 7074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Unretained(&synced_notification_first_run_))); 708d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 709d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Get the prefs from last session into our memeber varilables 710d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) OnEnabledSendingServiceListPrefChanged(&enabled_sending_services_); 711d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) OnInitializedSendingServiceListPrefChanged(&initialized_sending_services_); 7128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 7134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = 7144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->GetBoolean(prefs::kSyncedNotificationFirstRun); 715d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 716d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ChromeNotifierService::ShowWelcomeToastIfNecessary( 7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const SyncedNotification* synced_notification, 7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NotificationUIManager* notification_ui_manager) { 7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& sending_service_id = 7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) synced_notification->GetSendingServiceId(); 722d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 723d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 724d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) iter = find(initialized_sending_services_.begin(), 725d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_.end(), 7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sending_service_id); 7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If we already initialized the sending service, then return early since no 7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // welcome toast is necessary. 7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (iter != initialized_sending_services_.end()) 731d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 732d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If there is no app info, we can't show a welcome toast. Ideally all synced 7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // notifications will be delayed until an app_info data structure can be 7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // constructed for them. 7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(dewittj): Refactor when app_info is populated asynchronously. 7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncedNotificationAppInfo* app_info = FindAppInfo(sending_service_id); 7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!app_info) 7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(dewittj): Ensure that the app info icon is set before this point. 7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_info->icon().IsEmpty()) { 7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Image notification_app_icon = synced_notification->GetAppIcon(); 7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!notification_app_icon.IsEmpty()) { 7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info->set_icon(notification_app_icon); 7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This block should only be reached in tests since the downloads are 7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // already finished for |synced_notification|. 7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Unable to find the app icon for the welcome notification. " 7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "Service ID: " << sending_service_id; 7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NotifierId notifier_id( 7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE, 7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sending_service_id); 7575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Notification notification = CreateWelcomeNotificationForService(app_info); 7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification_ui_manager->Add(notification, profile_); 7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_sending_services_.insert(sending_service_id); 7625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) initialized_sending_services_.insert(sending_service_id); 7635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 764d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Build a ListValue with the list of services to be enabled. 7654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue enabled_sending_services; 7664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue initialized_sending_services; 767d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 768d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Mark any new services as enabled in preferences. 7694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 7704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &enabled_sending_services); 7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, 7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_sending_services); 7735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Mark any new services as initialized in preferences. 7744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BuildServiceListValueInplace(initialized_sending_services_, 7754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &initialized_sending_services); 7764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set( 7774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 7784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) initialized_sending_services); 779d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 7803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SyncedNotificationAppInfo* ChromeNotifierService::FindAppInfo( 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id) const { 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedVector<SyncedNotificationAppInfo>::const_iterator iter = 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info_data_.begin(); 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (iter != app_info_data_.end()) { 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((*iter)->app_id() == app_id) 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return (*iter); 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++iter; 7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const Notification ChromeNotifierService::CreateWelcomeNotificationForService( 7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncedNotificationAppInfo* app_info) { 7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string welcome_notification_id = base::GenerateGUID(); 7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<WelcomeDelegate> delegate(new WelcomeDelegate( 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) welcome_notification_id, profile_, app_info->GetNotifierId())); 8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::ButtonInfo button_info( 8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BUTTON)); 8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) button_info.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( 8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IDR_NOTIFIER_BLOCK_BUTTON); 8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::RichNotificationData rich_notification_data; 8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rich_notification_data.buttons.push_back(button_info); 8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return Notification( 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NOTIFICATION_TYPE_BASE_FORMAT, 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL(kSyncedNotificationsWelcomeOrigin), 8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info->title(), 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BODY), 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info->icon(), 8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blink::WebTextDirectionDefault, 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info->GetNotifierId(), 8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_DISPLAY_SOURCE), 8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(welcome_notification_id), 8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rich_notification_data, 8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate.get()); 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace notifier 823