chrome_notifier_service.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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" 27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info.h" 28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h" 29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service_factory.h" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/notifications/sync_notifier/welcome_delegate.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/common/pref_names.h" 33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "components/user_prefs/pref_registry_syncable.h" 34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "content/public/browser/user_metrics.h" 36a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "grit/generated_resources.h" 37a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "grit/theme_resources.h" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_change.h" 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_change_processor.h" 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_error_factory.h" 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/protocol/sync.pb.h" 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/protocol/synced_notification_specifics.pb.h" 437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebTextDirection.h" 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/l10n/l10n_util.h" 45a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "ui/base/resource/resource_bundle.h" 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/message_center/notifier_settings.h" 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::UserMetricsAction; 508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace notifier { 52a3f7b4e666c476898878fa745f637129375cd889Ben Murdochconst char kFirstSyncedNotificationServiceId[] = "Google+"; 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSyncedNotificationsWelcomeOrigin[] = 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "synced-notifications://welcome"; 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ChromeNotifierService::avoid_bitmap_fetching_for_test_ = false; 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ChromeNotifierService::ChromeNotifierService(Profile* profile, 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NotificationUIManager* manager) 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : profile_(profile), 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification_manager_(manager), 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_(false) { 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) InitializePrefs(); 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Get a pointer to the app info service so we can get app info data. 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch synced_notification_app_info_service_ = 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SyncedNotificationAppInfoServiceFactory::GetForProfile( 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch profile_, Profile::IMPLICIT_ACCESS); 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(synced_notification_app_info_service_ != NULL); 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch synced_notification_app_info_service_->set_chrome_notifier_service(this); 74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 75a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch} 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 77effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochChromeNotifierService::~ChromeNotifierService() { 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (synced_notification_app_info_service_) 79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch synced_notification_app_info_service_->set_chrome_notifier_service(NULL); 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Methods from KeyedService. 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromeNotifierService::Shutdown() {} 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// syncer::SyncableService implementation. 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is called at startup to sync with the server. 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This code is not thread safe. 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncMergeResult ChromeNotifierService::MergeDataAndStartSyncing( 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::ModelType type, 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncDataList& initial_sync_data, 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<syncer::SyncErrorFactory> error_handler) { 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) thread_checker_.CalledOnValidThread(); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncMergeResult merge_result(syncer::SYNCED_NOTIFICATIONS); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A list of local changes to send up to the sync server. 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList new_changes; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_processor_ = sync_processor.Pass(); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (syncer::SyncDataList::const_iterator it = initial_sync_data.begin(); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != initial_sync_data.end(); ++it) { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const syncer::SyncData& sync_data = *it; 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, sync_data.GetDataType()); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Build a local notification object from the sync data. 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> incoming(CreateNotificationFromSyncData( 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 109b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!incoming) { 110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NOTREACHED(); 111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Process each incoming remote notification. 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& key = incoming->GetKey(); 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GT(key.length(), 0U); 1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SyncedNotification* found = FindNotificationById(key); 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (NULL == found) { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there are no conflicts, copy in the data from remote. 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Add(incoming.Pass()); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the incoming (remote) and stored (local) notifications match 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in all fields, we don't need to do anything here. 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (incoming->EqualsIgnoringReadState(*found)) { 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (incoming->GetReadState() == found->GetReadState()) { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Notification matches on the client and the server, nothing to do. 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the read state is different, read wins for both places. 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (incoming->GetReadState() == SyncedNotification::kDismissed) { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If it is marked as read on the server, but not the client. 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found->NotificationHasBeenDismissed(); 135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the Notification UI Manager to remove it. 136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_manager_->CancelById(found->GetKey()); 137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else if (incoming->GetReadState() == SyncedNotification::kRead) { 138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If it is marked as read on the server, but not the client. 139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch found->NotificationHasBeenRead(); 140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the Notification UI Manager to remove it. 1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch notification_manager_->CancelById(found->GetKey()); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If it is marked as read on the client, but not the server. 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = CreateSyncDataFromNotification(*found); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_changes.push_back( 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE, 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If local state changed, notify Notification UI Manager. 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If different, just replace the local with the remote. 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(petewil): Someday we may allow changes from the client to 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // flow upwards, when we do, we will need better merge resolution. 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found->Update(sync_data); 1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Tell the notification manager to update the notification. 159ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(found); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send up the changes that were made locally. 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_changes.size() > 0) { 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.set_error(sync_processor_->ProcessSyncChanges( 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, new_changes)); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Once we complete our first sync, we mark "first run" as false, 1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // subsequent runs of Synced Notifications will get normal treatment. 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (synced_notification_first_run_) { 1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = false; 1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->SetBoolean(prefs::kSyncedNotificationFirstRun, false); 1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return merge_result; 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeNotifierService::StopSyncing(syncer::ModelType type) { 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Since this data type is not user-unselectable, we chose not to implement 183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the stop syncing method, and instead do nothing here. 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncDataList ChromeNotifierService::GetAllSyncData( 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::ModelType type) const { 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, type); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncDataList sync_data; 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy our native format data into a SyncDataList format. 192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::const_iterator it = 193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.begin(); 194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data.push_back(CreateSyncDataFromNotification(**it)); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return sync_data; 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This method is called when there is an incoming sync change from the server. 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncError ChromeNotifierService::ProcessSyncChanges( 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const tracked_objects::Location& from_here, 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncChangeList& change_list) { 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) thread_checker_.CalledOnValidThread(); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncError error; 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (syncer::SyncChangeList::const_iterator it = change_list.begin(); 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != change_list.end(); ++it) { 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = it->sync_data(); 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(syncer::SYNCED_NOTIFICATIONS, sync_data.GetDataType()); 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::SyncChangeType change_type = it->change_type(); 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> new_notification( 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNotificationFromSyncData(sync_data)); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!new_notification.get()) { 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "Failed to read notification."; 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const std::string& key = new_notification->GetKey(); 222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK_GT(key.length(), 0U); 223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* found = FindNotificationById(key); 224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (change_type) { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case syncer::SyncChange::ACTION_ADD: 227ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Intentional fall through, cases are identical. 228ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case syncer::SyncChange::ACTION_UPDATE: 229ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (found == NULL) { 230ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Add(new_notification.Pass()); 231ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 232ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Update it in our store. 234ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch found->Update(sync_data); 235ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Tell the notification manager to update the notification. 236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(found); 237ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 239ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case syncer::SyncChange::ACTION_DELETE: 240ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (found == NULL) { 241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 243ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Remove it from our store. 244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FreeNotificationById(key); 245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Remove it from the message center. 246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(new_notification.get()); 247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // TODO(petewil): Do I need to remember that it was deleted in case the 248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // add arrives after the delete? If so, how long do I need to remember? 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch NOTREACHED(); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return error; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Support functions for data type conversion. 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Static method. Get to the sync data in our internal format. 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncData ChromeNotifierService::CreateSyncDataFromNotification( 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SyncedNotification& notification) { 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Construct the sync_data using the specifics from the notification. 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return syncer::SyncData::CreateLocalData( 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) notification.GetKey(), notification.GetKey(), 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notification.GetEntitySpecifics()); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 271effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Convert from SyncData to our internal format. 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<SyncedNotification> 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ChromeNotifierService::CreateNotificationFromSyncData( 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncData& sync_data) { 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get a pointer to our data within the sync_data object. 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::SyncedNotificationSpecifics specifics = 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data.GetSpecifics().synced_notification(); 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check for mandatory fields in the sync_data object. 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!specifics.has_coalesced_notification() || 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !specifics.coalesced_notification().has_key() || 282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) !specifics.coalesced_notification().has_read_state()) { 283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DVLOG(1) << "Synced Notification missing mandatory fields " 284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << "has coalesced notification? " 285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << specifics.has_coalesced_notification() 286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " has key? " << specifics.coalesced_notification().has_key() 287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " has read state? " 288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << specifics.coalesced_notification().has_read_state(); 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_ptr<SyncedNotification>(); 290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_well_formed_unread_notification = 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (static_cast<SyncedNotification::ReadState>( 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().read_state()) == 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification::kUnread && 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().has_render_info()); 297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool is_well_formed_read_notification = 298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (static_cast<SyncedNotification::ReadState>( 299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch specifics.coalesced_notification().read_state()) == 300424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SyncedNotification::kRead); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_well_formed_dismissed_notification = 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (static_cast<SyncedNotification::ReadState>( 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.coalesced_notification().read_state()) == 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification::kDismissed); 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If the notification is poorly formed, return a null pointer. 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_well_formed_unread_notification && 308ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch !is_well_formed_read_notification && 309b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) !is_well_formed_dismissed_notification) { 310b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DVLOG(1) << "Synced Notification is not well formed." 311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " unread well formed? " 312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << is_well_formed_unread_notification 313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) << " dismissed well formed? " 314ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << is_well_formed_dismissed_notification 315ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << " read well formed? " 316ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << is_well_formed_read_notification; 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_ptr<SyncedNotification>(); 318b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a new notification object based on the supplied sync_data. 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SyncedNotification> notification( 322effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new SyncedNotification(sync_data, this, notification_manager_)); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return notification.Pass(); 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This returns a pointer into a vector that we own. Caller must not free it. 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns NULL if no match is found. 3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSyncedNotification* ChromeNotifierService::FindNotificationById( 3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& notification_id) { 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(petewil): We can make a performance trade off here. 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // While the vector has good locality of reference, a map has faster lookup. 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Based on how big we expect this to get, maybe change this to a map. 334ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::const_iterator it = 335ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.begin(); 336ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification* notification = *it; 3387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (notification_id == notification->GetKey()) 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return *it; 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 345ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::FreeNotificationById( 346ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const std::string& notification_id) { 347ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ScopedVector<SyncedNotification>::iterator it = notification_data_.begin(); 348ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (; it != notification_data_.end(); ++it) { 349ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* notification = *it; 350ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (notification_id == notification->GetKey()) { 351ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.erase(it); 352ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 353ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 354ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 355ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 356ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ChromeNotifierService::GetSyncedNotificationServices( 358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<message_center::Notifier*>* notifiers) { 3597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(mukai|petewil): Check the profile's eligibility before adding the 3607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // sample app. 361effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::vector<SyncedNotificationSendingServiceSettingsData> 362effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sending_service_settings_data; 363effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 364effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (synced_notification_app_info_service_ == NULL) 365effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 367effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sending_service_settings_data = 368effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch synced_notification_app_info_service_->GetAllSendingServiceSettingsData(); 369effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 370effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (size_t ii = 0; ii < sending_service_settings_data.size(); ++ii) { 371effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Enable or disable the sending service per saved preferences. 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool app_enabled = false; 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::set<std::string>::iterator iter; 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter = find(enabled_sending_services_.begin(), 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_sending_services_.end(), 377effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sending_service_settings_data[ii].notifier_id.id); 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_enabled = iter != enabled_sending_services_.end(); 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::Notifier* app_info_notifier = new message_center::Notifier( 381effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sending_service_settings_data[ii].notifier_id, 382effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::UTF8ToUTF16( 383effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sending_service_settings_data[ii].settings_display_name), 384effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_enabled); 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 386effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_info_notifier->icon = sending_service_settings_data[ii].settings_icon; 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // |notifiers| takes ownership of |app_info_notifier|. 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notifiers->push_back(app_info_notifier); 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 393effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ChromeNotifierService::OnAddedAppIds( 394effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::vector<std::string> added_app_ids) { 395effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 396effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::vector<std::string>::const_iterator app_id_iter; 397effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (app_id_iter = added_app_ids.begin(); app_id_iter != added_app_ids.end(); 398effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++app_id_iter) { 399effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Make sure this is not a dup, if it is, do nothing. 400effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // TODO(petewil): consider a case insensitive compare. 401effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::set<std::string>::iterator sending_service_iter; 402effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sending_service_iter = enabled_sending_services_.find(*app_id_iter); 403effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (sending_service_iter != enabled_sending_services_.end()) 404effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch continue; 405effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 406effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Find any newly enabled notifications and call display on them. 407effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Show the welcome toast if required. 408effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ScopedVector<SyncedNotification>::iterator notification_iter; 409effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (notification_iter = notification_data_.begin(); 410effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch notification_iter != notification_data_.end(); 411effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++notification_iter) { 412effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch (*notification_iter)->ShowAllForAppId(profile_, *app_id_iter); 413effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 414effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 415effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 416effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 417effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ChromeNotifierService::OnRemovedAppIds( 418effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::vector<std::string> removed_app_ids) { 419effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Remove from enabled sending services. 420effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Don't remove from initialized sending services. If it gets re-added later, 421effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // we want to remember the user's decision, so we also leave prefs intact. 422effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 423effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Find any displayed notifications and remove them from the notification 424effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // center. 425effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::vector<std::string>::const_iterator app_id_iter; 426effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (app_id_iter = removed_app_ids.begin(); 427effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_id_iter != removed_app_ids.end(); 428effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++app_id_iter) { 429effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Find any newly disabled notifications and remove them. 430effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ScopedVector<SyncedNotification>::iterator notification_iter; 431effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (notification_iter = notification_data_.begin(); 432effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch notification_iter != notification_data_.end(); 433effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++notification_iter) { 434effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch (*notification_iter)->HideAllForAppId(*app_id_iter); 435effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 436effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 437effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 438effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 439ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::MarkNotificationAsRead( 440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& key) { 441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 4427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SyncedNotification* notification = FindNotificationById(key); 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(notification != NULL); 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 445ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification->NotificationHasBeenRead(); 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList new_changes; 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData sync_data = CreateSyncDataFromNotification(*notification); 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_changes.push_back( 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE, 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_data)); 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send up the changes that were made locally. 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Add a new notification to our data structure. This takes ownership 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// of the passed in pointer. 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeNotifierService::Add(scoped_ptr<SyncedNotification> notification) { 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedNotification* notification_copy = notification.get(); 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Take ownership of the object and put it into our local storage. 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notification_data_.push_back(notification.release()); 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 465a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // If the user is not interested in this type of notification, ignore it. 466effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string sending_service_id = GetSendingServiceId(notification_copy); 467effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::set<std::string>::iterator iter = find(enabled_sending_services_.begin(), 468effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch enabled_sending_services_.end(), 469effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sending_service_id); 470a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (iter == enabled_sending_services_.end()) { 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter = find(initialized_sending_services_.begin(), 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) initialized_sending_services_.end(), 473effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sending_service_id); 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (iter != initialized_sending_services_.end()) 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 476a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 477a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 478ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UpdateInMessageCenter(notification_copy); 4797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 4807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 481effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstd::string ChromeNotifierService::GetSendingServiceId( 482effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const SyncedNotification* synced_notification) { 483effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Get the App Id from the notification, and look it up in the synced 484effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // notification app info service. 485effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string app_id = synced_notification->GetAppId(); 486effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 487effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(synced_notification_app_info_service_ != NULL); 488effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 489effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return synced_notification_app_info_service_->FindSendingServiceNameFromAppId( 490effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_id); 491effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 492effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 4937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ChromeNotifierService::AddForTest( 4947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch scoped_ptr<notifier::SyncedNotification> notification) { 495ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_data_.push_back(notification.release()); 496ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 4977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 498effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ChromeNotifierService::SetSyncedNotificationAppInfoServiceForTest( 499effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SyncedNotificationAppInfoService* synced_notification_app_info_service) { 500effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If there already is a service attached, clear their reference to us. 501effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (synced_notification_app_info_service_) 502effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch synced_notification_app_info_service_->set_chrome_notifier_service(NULL); 503effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 504effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch synced_notification_app_info_service_ = synced_notification_app_info_service; 505effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch synced_notification_app_info_service_->set_chrome_notifier_service(this); 506effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 507effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 508ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::UpdateInMessageCenter( 509ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SyncedNotification* notification) { 5102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // If the feature is disabled, exit now. 5112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (!notifier::ChromeNotifierServiceFactory::UseSyncedNotifications( 512ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch CommandLine::ForCurrentProcess())) 5132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return; 514a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 515ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification->LogNotification(); 516ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 517ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (notification->GetReadState() == SyncedNotification::kUnread) { 518ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the message is unread, update it. 519ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Display(notification); 520ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 521ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the message is read or deleted, dismiss it from the center. 522ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // We intentionally ignore errors if it is not in the center. 523ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch notification_manager_->CancelById(notification->GetKey()); 524ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 525ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 526ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 527ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromeNotifierService::Display(SyncedNotification* notification) { 5284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If this is the first run for the feature, don't surprise the user. 5294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Instead, place all backlogged notifications into the notification 5304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // center. 5314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (synced_notification_first_run_) { 5324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Setting the toast state to false will prevent toasting the notification. 533effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch notification->set_toast_state(false); 5344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 5354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Our tests cannot use the network for reliability reasons. 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (avoid_bitmap_fetching_for_test_) { 538effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch notification->Show(profile_); 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Set up to fetch the bitmaps. 543effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch notification->QueueBitmapFetchJobs(this, profile_); 5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Start the bitmap fetching, Show() will be called when the last bitmap 546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // either arrives or times out. 5477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch notification->StartBitmapFetch(); 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ChromeNotifierService::OnSyncedNotificationServiceEnabled( 551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& notifier_id, bool enabled) { 552d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 553d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 554d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Make a copy of the notifier_id, which might not have lifetime long enough 555d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // for this function to finish all of its work. 556d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string notifier_id_copy(notifier_id); 557a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 558a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch iter = find(enabled_sending_services_.begin(), 559a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch enabled_sending_services_.end(), 560d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) notifier_id_copy); 561d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 5624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue synced_notification_services; 563a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 564a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // Add the notifier_id if it is enabled and not already there. 565a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (iter == enabled_sending_services_.end() && enabled) { 566d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_.insert(notifier_id_copy); 5673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Check now for any outstanding notifications. 5683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DisplayUnreadNotificationsFromSource(notifier_id); 569d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 570d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &synced_notification_services); 571d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Add this preference to the enabled list. 5724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, 5734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_services); 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Remove the notifier_id if it is disabled and present. 575a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } else if (iter != enabled_sending_services_.end() && !enabled) { 576a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch enabled_sending_services_.erase(iter); 577d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 578d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &synced_notification_services); 579d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Remove this peference from the enabled list. 5804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, 5814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_services); 582d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) RemoveUnreadNotificationsFromSource(notifier_id_copy); 583a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 584a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 5858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Collect UMA statistics when a service is enabled or disabled. 5868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (enabled) { 5878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) content::RecordAction( 5888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UserMetricsAction("SyncedNotifications.SendingServiceEnabled")); 5898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else { 5908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) content::RecordAction( 5918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UserMetricsAction("SyncedNotifications.SendingServiceDisabled")); 5928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 5938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Collect individual service enabling/disabling statistics. 5958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CollectPerServiceEnablingStatistics(notifier_id, enabled); 5968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 597a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch return; 598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 6008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ChromeNotifierService::CollectPerServiceEnablingStatistics( 6018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const std::string& notifier_id, 6028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool enabled) { 6038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(petewil) - This approach does not scale well as we add new services, 6048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // but we are limited to using predefined ENUM values in histogram based UMA 6058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // data, which does not permit arbitrary strings. 6068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find a way to make it scale, or remove enum value this when we have enough 6078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // data. 6088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 6098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ChromeNotifierServiceActionType action = 6108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CHROME_NOTIFIER_SERVICE_ACTION_UNKNOWN; 6118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 6128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Derive action type from notifier_id and enabled. 6138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(petewil): Add more sending services as they are enabled. 6148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (notifier_id == std::string(kFirstSyncedNotificationServiceId)) { 6158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) action = enabled 6168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ? CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_ENABLED 6178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_DISABLED; 6188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 6198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 6208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("ChromeNotifierService.Actions", 6218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) action, 6228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CHROME_NOTIFIER_SERVICE_ACTION_COUNT); 6238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 6248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 625d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::BuildServiceListValueInplace( 6264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::set<std::string> services, base::ListValue* list_value) { 627d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 628d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 629d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Iterate over the strings, adding each one to the list value 630d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (iter = services.begin(); 631d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) iter != services.end(); 632d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ++iter) { 6334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::StringValue* string_value(new base::StringValue(*iter)); 6344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) list_value->Append(string_value); 635d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 636d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 637d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ChromeNotifierService::DisplayUnreadNotificationsFromSource( 639d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& notifier_id) { 6403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (std::vector<SyncedNotification*>::const_iterator iter = 6413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_data_.begin(); 6423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) iter != notification_data_.end(); 6433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ++iter) { 644effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (GetSendingServiceId(*iter) == notifier_id && 6453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) (*iter)->GetReadState() == SyncedNotification::kUnread) 6463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Display(*iter); 6473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 6483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 6493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 6503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ChromeNotifierService::RemoveUnreadNotificationsFromSource( 651d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& notifier_id) { 6523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (std::vector<SyncedNotification*>::const_iterator iter = 6533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_data_.begin(); 6543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) iter != notification_data_.end(); 6553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ++iter) { 656effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (GetSendingServiceId(*iter) == notifier_id && 657d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (*iter)->GetReadState() == SyncedNotification::kUnread) { 6583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notification_manager_->CancelById((*iter)->GetKey()); 659d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 6603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 6613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 6623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 663d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::OnEnabledSendingServiceListPrefChanged( 664d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>* ids_field) { 665d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->clear(); 666d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<std::string> pref_list = 667d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_prefs_.GetValue(); 668d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (size_t i = 0; i < pref_list.size(); ++i) { 669d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string element = pref_list[i]; 670d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!element.empty()) 671d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->insert(element); 672d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) else 673d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(WARNING) << i << "-th element is not a string " 674d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << prefs::kEnabledSyncedNotificationSendingServices; 675d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 676d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 677d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 678d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::OnInitializedSendingServiceListPrefChanged( 679d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>* ids_field) { 680d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->clear(); 681d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<std::string> pref_list = 682d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_prefs_.GetValue(); 683d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (size_t i = 0; i < pref_list.size(); ++i) { 684d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string element = pref_list[i]; 685d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!element.empty()) 686d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ids_field->insert(element); 687d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) else 688d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(WARNING) << i << "-th element is not a string for " 689d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << prefs::kInitializedSyncedNotificationSendingServices; 690d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 691d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 692d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ChromeNotifierService::OnSyncedNotificationFirstRunBooleanPrefChanged( 6944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool* new_value) { 6954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = *new_value; 6964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 6974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 698d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::RegisterProfilePrefs( 699d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) user_prefs::PrefRegistrySyncable* registry) { 700d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Register the pref for the list of enabled services. 701d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) registry->RegisterListPref( 702d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kEnabledSyncedNotificationSendingServices, 7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 704d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Register the pref for the list of initialized services. 705d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) registry->RegisterListPref( 706d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 7084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Register the preference for first run status, defaults to "true", 7094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // meaning that this is the first run of the Synced Notification feature. 7104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) registry->RegisterBooleanPref( 7114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kSyncedNotificationFirstRun, true, 7124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 713d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 714d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 715d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromeNotifierService::InitializePrefs() { 716d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Set up any pref changes to update our list of services. 717d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) enabled_sending_services_prefs_.Init( 718d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kEnabledSyncedNotificationSendingServices, 719d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) profile_->GetPrefs(), 720d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind( 721d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &ChromeNotifierService::OnEnabledSendingServiceListPrefChanged, 722d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(this), 723d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(&enabled_sending_services_))); 724d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_prefs_.Init( 725d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 726d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) profile_->GetPrefs(), 727d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind( 728d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &ChromeNotifierService::OnInitializedSendingServiceListPrefChanged, 729d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(this), 730d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(&initialized_sending_services_))); 7314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_prefs_.Init( 7324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kSyncedNotificationFirstRun, 7334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs(), 7344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind( 7354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &ChromeNotifierService:: 7364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OnSyncedNotificationFirstRunBooleanPrefChanged, 7374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Unretained(this), 7384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Unretained(&synced_notification_first_run_))); 739d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 740d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Get the prefs from last session into our memeber varilables 741d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) OnEnabledSendingServiceListPrefChanged(&enabled_sending_services_); 742d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) OnInitializedSendingServiceListPrefChanged(&initialized_sending_services_); 7438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 7444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) synced_notification_first_run_ = 7454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->GetBoolean(prefs::kSyncedNotificationFirstRun); 746d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 747d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ChromeNotifierService::ShowWelcomeToastIfNecessary( 7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const SyncedNotification* synced_notification, 7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NotificationUIManager* notification_ui_manager) { 7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& sending_service_id = 752effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch GetSendingServiceId(synced_notification); 753d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 754d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string>::iterator iter; 755d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) iter = find(initialized_sending_services_.begin(), 756d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) initialized_sending_services_.end(), 7575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sending_service_id); 7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If we already initialized the sending service, then return early since no 7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // welcome toast is necessary. 7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (iter != initialized_sending_services_.end()) 762d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 763d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 764effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If there is no app info, we can't show a welcome toast. All synced 7655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // notifications will be delayed until an app_info data structure can be 7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // constructed for them. 767effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch notifier::SyncedNotificationAppInfo* app_info = 768effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FindAppInfoByAppId(synced_notification->GetAppId()); 7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!app_info) 7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 772effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (app_info->settings_icon_url().is_empty()) { 7735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Image notification_app_icon = synced_notification->GetAppIcon(); 774effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (notification_app_icon.IsEmpty()) { 7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This block should only be reached in tests since the downloads are 7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // already finished for |synced_notification|. 7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Unable to find the app icon for the welcome notification. " 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "Service ID: " << sending_service_id; 7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NotifierId notifier_id( 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE, 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sending_service_id); 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Notification notification = CreateWelcomeNotificationForService(app_info); 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification_ui_manager->Add(notification, profile_); 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_sending_services_.insert(sending_service_id); 7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) initialized_sending_services_.insert(sending_service_id); 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 792d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Build a ListValue with the list of services to be enabled. 7934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue enabled_sending_services; 7944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue initialized_sending_services; 795d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 796d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Mark any new services as enabled in preferences. 7974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BuildServiceListValueInplace(enabled_sending_services_, 7984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &enabled_sending_services); 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile_->GetPrefs()->Set(prefs::kEnabledSyncedNotificationSendingServices, 8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_sending_services); 8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Mark any new services as initialized in preferences. 8024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BuildServiceListValueInplace(initialized_sending_services_, 8034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &initialized_sending_services); 8044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile_->GetPrefs()->Set( 8054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prefs::kInitializedSyncedNotificationSendingServices, 8064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) initialized_sending_services); 807d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 8083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 809effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnotifier::SyncedNotificationAppInfo* ChromeNotifierService::FindAppInfoByAppId( 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id) const { 811effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (NULL == synced_notification_app_info_service_) 812effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return NULL; 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 814effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return synced_notification_app_info_service_-> 815effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FindSyncedNotificationAppInfoByAppId(app_id); 8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const Notification ChromeNotifierService::CreateWelcomeNotificationForService( 819effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SyncedNotificationAppInfo* app_info) { 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string welcome_notification_id = base::GenerateGUID(); 821effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch message_center::NotifierId notifier_id = app_info->GetNotifierId(); 822effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_refptr<WelcomeDelegate> delegate( 823effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new WelcomeDelegate(welcome_notification_id, profile_, notifier_id)); 8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::ButtonInfo button_info( 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BUTTON)); 8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) button_info.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( 8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IDR_NOTIFIER_BLOCK_BUTTON); 8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::RichNotificationData rich_notification_data; 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rich_notification_data.buttons.push_back(button_info); 8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return Notification( 8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_center::NOTIFICATION_TYPE_BASE_FORMAT, 8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL(kSyncedNotificationsWelcomeOrigin), 835effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::UTF8ToUTF16(app_info->settings_display_name()), 8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BODY), 8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_info->icon(), 8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blink::WebTextDirectionDefault, 839effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch notifier_id, 8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_DISPLAY_SOURCE), 8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(welcome_notification_id), 8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rich_notification_data, 8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate.get()); 8445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace notifier 847