chrome_notifier_service.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
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) 11a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include <string> 12a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include <vector> 13a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "base/command_line.h" 158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/metrics/histogram.h" 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/prefs/pref_service.h" 17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/values.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/notifications/desktop_notification_service.h" 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/notifications/desktop_notification_service_factory.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/notifications/notification.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/notifications/notification_ui_manager.h" 222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/common/pref_names.h" 25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "components/user_prefs/pref_registry_syncable.h" 26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "content/public/browser/user_metrics.h" 28a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "grit/generated_resources.h" 29a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "grit/theme_resources.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_change.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_change_processor.h" 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_error_factory.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/protocol/sync.pb.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/protocol/synced_notification_specifics.pb.h" 357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebTextDirection.h" 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/l10n/l10n_util.h" 37a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "ui/base/resource/resource_bundle.h" 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/message_center/notifier_settings.h" 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)using content::UserMetricsAction; 428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace notifier { 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 45a3f7b4e666c476898878fa745f637129375cd889Ben Murdochconst char kFirstSyncedNotificationServiceId[] = "Google+"; 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ChromeNotifierService::avoid_bitmap_fetching_for_test_ = false; 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ChromeNotifierService::ChromeNotifierService(Profile* profile, 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NotificationUIManager* manager) 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : profile_(profile), notification_manager_(manager), 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_(false) { 53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) InitializePrefs(); 54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AddNewSendingServices(); 55a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch} 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ChromeNotifierService::~ChromeNotifierService() {} 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Methods from BrowserContextKeyedService. 59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromeNotifierService::Shutdown() {} 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// syncer::SyncableService implementation. 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is called at startup to sync with the server. 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This code is not thread safe. 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncMergeResult ChromeNotifierService::MergeDataAndStartSyncing( 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ModelType type, 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const syncer::SyncDataList& initial_sync_data, 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<syncer::SyncErrorFactory> error_handler) { 70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncMergeResult merge_result(syncer::SYNCED_NOTIFICATIONS); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A list of local changes to send up to the sync server. 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList new_changes; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_processor_ = sync_processor.Pass(); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (syncer::SyncDataList::const_iterator it = initial_sync_data.begin(); 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != initial_sync_data.end(); ++it) { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const syncer::SyncData& sync_data = *it; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, sync_data.GetDataType()); 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Build a local notification object from the sync data. 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> incoming(CreateNotificationFromSyncData( 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!incoming) { 86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // TODO(petewil): Turn this into a NOTREACHED() call once we fix the 87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // underlying problem causing bad data. 88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) LOG(WARNING) << "Badly formed sync data in incoming notification"; 89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Process each incoming remote notification. 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& key = incoming->GetKey(); 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GT(key.length(), 0U); 957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SyncedNotification* found = FindNotificationById(key); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (NULL == found) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there are no conflicts, copy in the data from remote. 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Add(incoming.Pass()); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the incoming (remote) and stored (local) notifications match 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in all fields, we don't need to do anything here. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (incoming->EqualsIgnoringReadState(*found)) { 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (incoming->GetReadState() == found->GetReadState()) { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Notification matches on the client and the server, nothing to do. 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the read state is different, read wins for both places. 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (incoming->GetReadState() == SyncedNotification::kDismissed) { 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If it is marked as read on the server, but not the client. 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found->NotificationHasBeenDismissed(); 113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the Notification UI Manager to remove it. 114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_manager_->CancelById(found->GetKey()); 115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else if (incoming->GetReadState() == SyncedNotification::kRead) { 116ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If it is marked as read on the server, but not the client. 117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch found->NotificationHasBeenRead(); 118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the Notification UI Manager to remove it. 1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch notification_manager_->CancelById(found->GetKey()); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If it is marked as read on the client, but not the server. 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = CreateSyncDataFromNotification(*found); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_changes.push_back( 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE, 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If local state changed, notify Notification UI Manager. 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // For any other conflict besides read state, treat it as an update. 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If different, just replace the local with the remote. 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(petewil): Someday we may allow changes from the client to 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // flow upwards, when we do, we will need better merge resolution. 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found->Update(sync_data); 1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Tell the notification manager to update the notification. 138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(found); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send up the changes that were made locally. 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_changes.size() > 0) { 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.set_error(sync_processor_->ProcessSyncChanges( 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, new_changes)); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Once we complete our first sync, we mark "first run" as false, 1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // subsequent runs of Synced Notifications will get normal treatment. 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (synced_notification_first_run_) { 1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = false; 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->SetBoolean(prefs::kSyncedNotificationFirstRun, false); 1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return merge_result; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeNotifierService::StopSyncing(syncer::ModelType type) { 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Since this data type is not user-unselectable, we chose not to implement 162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the stop syncing method, and instead do nothing here. 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncDataList ChromeNotifierService::GetAllSyncData( 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ModelType type) const { 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncDataList sync_data; 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy our native format data into a SyncDataList format. 171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::const_iterator it = 172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.begin(); 173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data.push_back(CreateSyncDataFromNotification(**it)); 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return sync_data; 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This method is called when there is an incoming sync change from the server. 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncError ChromeNotifierService::ProcessSyncChanges( 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const tracked_objects::Location& from_here, 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const syncer::SyncChangeList& change_list) { 184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncError error; 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (syncer::SyncChangeList::const_iterator it = change_list.begin(); 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != change_list.end(); ++it) { 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = it->sync_data(); 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, sync_data.GetDataType()); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::SyncChangeType change_type = it->change_type(); 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> new_notification( 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNotificationFromSyncData(sync_data)); 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!new_notification.get()) { 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "Failed to read notification."; 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const std::string& key = new_notification->GetKey(); 201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK_GT(key.length(), 0U); 202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* found = FindNotificationById(key); 203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (change_type) { 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case syncer::SyncChange::ACTION_ADD: 206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Intentional fall through, cases are identical. 207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case syncer::SyncChange::ACTION_UPDATE: 208ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (found == NULL) { 209ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Add(new_notification.Pass()); 210ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 211ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Update it in our store. 213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch found->Update(sync_data); 214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the notification manager to update the notification. 215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(found); 216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case syncer::SyncChange::ACTION_DELETE: 219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (found == NULL) { 220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Remove it from our store. 223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FreeNotificationById(key); 224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Remove it from the message center. 225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(new_notification.get()); 226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // TODO(petewil): Do I need to remember that it was deleted in case the 227ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // add arrives after the delete? If so, how long do I need to remember? 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 231ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch NOTREACHED(); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return error; 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Support functions for data type conversion. 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Static method. Get to the sync data in our internal format. 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncData ChromeNotifierService::CreateSyncDataFromNotification( 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SyncedNotification& notification) { 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Construct the sync_data using the specifics from the notification. 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return syncer::SyncData::CreateLocalData( 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) notification.GetKey(), notification.GetKey(), 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notification.GetEntitySpecifics()); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Static Method. Convert from SyncData to our internal format. 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<SyncedNotification> 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ChromeNotifierService::CreateNotificationFromSyncData( 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const syncer::SyncData& sync_data) { 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get a pointer to our data within the sync_data object. 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::SyncedNotificationSpecifics specifics = 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data.GetSpecifics().synced_notification(); 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check for mandatory fields in the sync_data object. 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!specifics.has_coalesced_notification() || 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !specifics.coalesced_notification().has_key() || 261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) !specifics.coalesced_notification().has_read_state()) { 262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DVLOG(1) << "Synced Notification missing mandatory fields " 263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << "has coalesced notification? " 264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << specifics.has_coalesced_notification() 265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " has key? " << specifics.coalesced_notification().has_key() 266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " has read state? " 267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << specifics.coalesced_notification().has_read_state(); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_ptr<SyncedNotification>(); 269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_well_formed_unread_notification = 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (static_cast<SyncedNotification::ReadState>( 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().read_state()) == 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification::kUnread && 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().has_render_info()); 276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool is_well_formed_read_notification = 277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (static_cast<SyncedNotification::ReadState>( 278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch specifics.coalesced_notification().read_state()) == 279424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SyncedNotification::kRead); 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_well_formed_dismissed_notification = 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (static_cast<SyncedNotification::ReadState>( 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().read_state()) == 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification::kDismissed); 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If the notification is poorly formed, return a null pointer. 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_well_formed_unread_notification && 287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch !is_well_formed_read_notification && 288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) !is_well_formed_dismissed_notification) { 289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DVLOG(1) << "Synced Notification is not well formed." 290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " unread well formed? " 291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << is_well_formed_unread_notification 292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " dismissed well formed? " 293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << is_well_formed_dismissed_notification 294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << " read well formed? " 295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << is_well_formed_read_notification; 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_ptr<SyncedNotification>(); 297b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a new notification object based on the supplied sync_data. 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> notification( 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new SyncedNotification(sync_data)); 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return notification.Pass(); 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This returns a pointer into a vector that we own. Caller must not free it. 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns NULL if no match is found. 3087dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSyncedNotification* ChromeNotifierService::FindNotificationById( 3097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& notification_id) { 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(petewil): We can make a performance trade off here. 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // While the vector has good locality of reference, a map has faster lookup. 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Based on how big we expect this to get, maybe change this to a map. 313ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::const_iterator it = 314ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.begin(); 315ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification* notification = *it; 3177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (notification_id == notification->GetKey()) 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return *it; 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 324ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::FreeNotificationById( 325ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const std::string& notification_id) { 326ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::iterator it = notification_data_.begin(); 327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 328ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* notification = *it; 329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (notification_id == notification->GetKey()) { 330ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.erase(it); 331ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 332ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 333ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 334ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 335ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ChromeNotifierService::GetSyncedNotificationServices( 337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<message_center::Notifier*>* notifiers) { 3387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(mukai|petewil): Check the profile's eligibility before adding the 3397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // sample app. 340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 341a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // TODO(petewil): Really obtain the list of synced notification sending 342a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // services from the server and create the list of ids here. Until then, we 343a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // are hardcoding the service names. Once that is done, remove this 344a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // hardcoding. 345a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // crbug.com/248337 346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DesktopNotificationService* desktop_notification_service = 347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DesktopNotificationServiceFactory::GetForProfile(profile_); 348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch message_center::NotifierId notifier_id( 349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE, 350a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch kFirstSyncedNotificationServiceId); 351a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch message_center::Notifier* notifier_service = new message_center::Notifier( 352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch notifier_id, 353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch l10n_util::GetStringUTF16( 354a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch IDS_FIRST_SYNCED_NOTIFICATION_SERVICE_NAME), 355a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch desktop_notification_service->IsNotifierEnabled(notifier_id)); 356a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 357a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // Add icons for our sending services. 358a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // TODO(petewil): Replace this temporary hardcoding with a new sync datatype 359a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // to dynamically get the name and icon for each synced notification sending 360a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // service. Until then, we use hardcoded service icons for all services. 361a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // crbug.com/248337 362a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch notifier_service->icon = ui::ResourceBundle::GetSharedInstance(). 363a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch GetImageNamed(IDR_TEMPORARY_GOOGLE_PLUS_ICON); 364a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 365d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Enable or disable the sending service per saved settings. 366d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 367d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 368d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) iter = find(enabled_sending_services_.begin(), 369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_.end(), 370d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) notifier_id.id); 371d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (iter != enabled_sending_services_.end()) 372d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) notifier_service->enabled = true; 373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) else 374d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) notifier_service->enabled = false; 375d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 376a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch notifiers->push_back(notifier_service); 377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 379ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::MarkNotificationAsRead( 380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& key) { 381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 3827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SyncedNotification* notification = FindNotificationById(key); 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(notification != NULL); 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 385ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification->NotificationHasBeenRead(); 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList new_changes; 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = CreateSyncDataFromNotification(*notification); 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_changes.push_back( 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE, 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send up the changes that were made locally. 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Add a new notification to our data structure. This takes ownership 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// of the passed in pointer. 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeNotifierService::Add(scoped_ptr<SyncedNotification> notification) { 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification* notification_copy = notification.get(); 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Take ownership of the object and put it into our local storage. 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notification_data_.push_back(notification.release()); 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 405a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // If the user is not interested in this type of notification, ignore it. 406d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter = 407a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch find(enabled_sending_services_.begin(), 408a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch enabled_sending_services_.end(), 409a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch notification_copy->GetSendingServiceId()); 410a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (iter == enabled_sending_services_.end()) { 411a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch return; 412a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 413a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 414ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(notification_copy); 4157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 4167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ChromeNotifierService::AddForTest( 4187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch scoped_ptr<notifier::SyncedNotification> notification) { 419ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.push_back(notification.release()); 420ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 4217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 422ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::UpdateInMessageCenter( 423ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* notification) { 4242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // If the feature is disabled, exit now. 4252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (!notifier::ChromeNotifierServiceFactory::UseSyncedNotifications( 426ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch CommandLine::ForCurrentProcess())) 4272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return; 428a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 429ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification->LogNotification(); 430ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 431ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (notification->GetReadState() == SyncedNotification::kUnread) { 432ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the message is unread, update it. 433ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Display(notification); 434ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 435ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the message is read or deleted, dismiss it from the center. 436ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // We intentionally ignore errors if it is not in the center. 437ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_manager_->CancelById(notification->GetKey()); 438ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 439ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 440ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 441ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::Display(SyncedNotification* notification) { 442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Set up to fetch the bitmaps. 4437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch notification->QueueBitmapFetchJobs(notification_manager_, 444ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch this, 445ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch profile_); 446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Our tests cannot use the network for reliability reasons. 448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (avoid_bitmap_fetching_for_test_) { 449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If this is the first run for the feature, don't surprise the user. 4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Instead, place all backlogged notifications into the notification 4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // center. 4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (synced_notification_first_run_) { 4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Setting the toast state to false will prevent toasting the notification. 4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) notification->SetToastState(false); 4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Start the bitmap fetching, Show() will be called when the last bitmap 461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // either arrives or times out. 4627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch notification->StartBitmapFetch(); 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ChromeNotifierService::OnSyncedNotificationServiceEnabled( 466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& notifier_id, bool enabled) { 467d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 468d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 469d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Make a copy of the notifier_id, which might not have lifetime long enough 470d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // for this function to finish all of its work. 471d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string notifier_id_copy(notifier_id); 472a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 473a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch iter = find(enabled_sending_services_.begin(), 474a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch enabled_sending_services_.end(), 475d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) notifier_id_copy); 476d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue synced_notification_services; 478a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 479a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // Add the notifier_id if it is enabled and not already there. 480a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (iter == enabled_sending_services_.end() && enabled) { 481d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_.insert(notifier_id_copy); 4823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Check now for any outstanding notifications. 4833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DisplayUnreadNotificationsFromSource(notifier_id); 484d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 485d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &synced_notification_services); 486d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Add this preference to the enabled list. 4874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, 4884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_services); 489a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // Remove the notifier_id if it is disabled and present. 490a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } else if (iter != enabled_sending_services_.end() && !enabled) { 491a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch enabled_sending_services_.erase(iter); 492d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 493d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &synced_notification_services); 494d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Remove this peference from the enabled list. 4954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, 4964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_services); 497d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) RemoveUnreadNotificationsFromSource(notifier_id_copy); 498a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 499a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 5008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Collect UMA statistics when a service is enabled or disabled. 5018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (enabled) { 5028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) content::RecordAction( 5038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UserMetricsAction("SyncedNotifications.SendingServiceEnabled")); 5048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else { 5058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) content::RecordAction( 5068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UserMetricsAction("SyncedNotifications.SendingServiceDisabled")); 5078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 5088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Collect individual service enabling/disabling statistics. 5108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CollectPerServiceEnablingStatistics(notifier_id, enabled); 5118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 512a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch return; 513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ChromeNotifierService::CollectPerServiceEnablingStatistics( 5168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const std::string& notifier_id, 5178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool enabled) { 5188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(petewil) - This approach does not scale well as we add new services, 5198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // but we are limited to using predefined ENUM values in histogram based UMA 5208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // data, which does not permit arbitrary strings. 5218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find a way to make it scale, or remove enum value this when we have enough 5228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // data. 5238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ChromeNotifierServiceActionType action = 5258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CHROME_NOTIFIER_SERVICE_ACTION_UNKNOWN; 5268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Derive action type from notifier_id and enabled. 5288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(petewil): Add more sending services as they are enabled. 5298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (notifier_id == std::string(kFirstSyncedNotificationServiceId)) { 5308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) action = enabled 5318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ? CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_ENABLED 5328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_DISABLED; 5338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 5348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("ChromeNotifierService.Actions", 5368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) action, 5378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CHROME_NOTIFIER_SERVICE_ACTION_COUNT); 5388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 5398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 540d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::BuildServiceListValueInplace( 5414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::set<std::string> services, base::ListValue* list_value) { 542d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 543d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 544d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Iterate over the strings, adding each one to the list value 545d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (iter = services.begin(); 546d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) iter != services.end(); 547d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ++iter) { 5484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::StringValue* string_value(new base::StringValue(*iter)); 5494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) list_value->Append(string_value); 550d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 551d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 552d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 553d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 5543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ChromeNotifierService::DisplayUnreadNotificationsFromSource( 555d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& notifier_id) { 5563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (std::vector<SyncedNotification*>::const_iterator iter = 5573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_data_.begin(); 5583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) iter != notification_data_.end(); 5593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ++iter) { 5603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if ((*iter)->GetSendingServiceId() == notifier_id && 5613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) (*iter)->GetReadState() == SyncedNotification::kUnread) 5623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Display(*iter); 5633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 5643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 5653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 5663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ChromeNotifierService::RemoveUnreadNotificationsFromSource( 567d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& notifier_id) { 5683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (std::vector<SyncedNotification*>::const_iterator iter = 5693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_data_.begin(); 5703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) iter != notification_data_.end(); 5713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ++iter) { 5723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if ((*iter)->GetSendingServiceId() == notifier_id && 573d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (*iter)->GetReadState() == SyncedNotification::kUnread) { 5743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_manager_->CancelById((*iter)->GetKey()); 575d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 5763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 5773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 5783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 579d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::OnEnabledSendingServiceListPrefChanged( 580d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>* ids_field) { 581d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->clear(); 582d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<std::string> pref_list = 583d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_prefs_.GetValue(); 584d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (size_t i = 0; i < pref_list.size(); ++i) { 585d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string element = pref_list[i]; 586d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!element.empty()) 587d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->insert(element); 588d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) else 589d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(WARNING) << i << "-th element is not a string " 590d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << prefs::kEnabledSyncedNotificationSendingServices; 591d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 592d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 593d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 594d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::OnInitializedSendingServiceListPrefChanged( 595d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>* ids_field) { 596d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->clear(); 597d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<std::string> pref_list = 598d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_prefs_.GetValue(); 599d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (size_t i = 0; i < pref_list.size(); ++i) { 600d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string element = pref_list[i]; 601d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!element.empty()) 602d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->insert(element); 603d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) else 604d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(WARNING) << i << "-th element is not a string for " 605d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << prefs::kInitializedSyncedNotificationSendingServices; 606d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 607d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 608d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ChromeNotifierService::OnSyncedNotificationFirstRunBooleanPrefChanged( 6104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool* new_value) { 6114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = *new_value; 6124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 6134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 614d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::RegisterProfilePrefs( 615d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) user_prefs::PrefRegistrySyncable* registry) { 616d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Register the pref for the list of enabled services. 617d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) registry->RegisterListPref( 618d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kEnabledSyncedNotificationSendingServices, 619d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 620d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Register the pref for the list of initialized services. 621d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) registry->RegisterListPref( 622d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 623d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 6244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Register the preference for first run status, defaults to "true", 6254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // meaning that this is the first run of the Synced Notification feature. 6264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) registry->RegisterBooleanPref( 6274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kSyncedNotificationFirstRun, true, 6284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 629d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 630d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 631d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::InitializePrefs() { 632d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Set up any pref changes to update our list of services. 633d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_prefs_.Init( 634d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kEnabledSyncedNotificationSendingServices, 635d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) profile_->GetPrefs(), 636d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind( 637d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &ChromeNotifierService::OnEnabledSendingServiceListPrefChanged, 638d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(this), 639d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(&enabled_sending_services_))); 640d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_prefs_.Init( 641d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 642d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) profile_->GetPrefs(), 643d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind( 644d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &ChromeNotifierService::OnInitializedSendingServiceListPrefChanged, 645d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(this), 646d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(&initialized_sending_services_))); 6474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_prefs_.Init( 6484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kSyncedNotificationFirstRun, 6494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs(), 6504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind( 6514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &ChromeNotifierService:: 6524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OnSyncedNotificationFirstRunBooleanPrefChanged, 6534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Unretained(this), 6544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Unretained(&synced_notification_first_run_))); 655d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 656d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Get the prefs from last session into our memeber varilables 657d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) OnEnabledSendingServiceListPrefChanged(&enabled_sending_services_); 658d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) OnInitializedSendingServiceListPrefChanged(&initialized_sending_services_); 6598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 6604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = 6614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->GetBoolean(prefs::kSyncedNotificationFirstRun); 662d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 663d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 664d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::AddNewSendingServices() { 665d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(petewil): When we have the new sync datatype for senders, use it 666d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // instead of hardcoding the service name. 667d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 668d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Check to see if all known services are in the initialized list. 669d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // If so, we can exit. 670d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 671d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string first_synced_notification_service_id( 672d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) kFirstSyncedNotificationServiceId); 673d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 674d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) iter = find(initialized_sending_services_.begin(), 675d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_.end(), 676d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) first_synced_notification_service_id); 677d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (initialized_sending_services_.end() != iter) 678d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 679d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 680d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Build a ListValue with the list of services to be enabled. 6814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue enabled_sending_services; 6824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue initialized_sending_services; 683d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 684d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Mark any new services as enabled in preferences. 685d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_.insert(first_synced_notification_service_id); 6864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 6874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &enabled_sending_services); 6884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set( 6894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kEnabledSyncedNotificationSendingServices, 6904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) enabled_sending_services); 691d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Mark it as having been initialized, so we don't try to turn it on again. 692d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_.insert(first_synced_notification_service_id); 6934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BuildServiceListValueInplace(initialized_sending_services_, 6944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &initialized_sending_services); 6954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set( 6964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 6974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) initialized_sending_services); 698d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 6993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace notifier 701