diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-10 04:07:19 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-10 04:07:19 +0000 |
commit | 6529382867932acbf83e49bc107fbe4ea28ad311 (patch) | |
tree | 9baba790501b4c0e95b59ca72b5c769ca5a28190 /sync/notifier/sync_notifier_registrar.cc | |
parent | bfe14502edd281a935198917fc49e30fbef47792 (diff) | |
download | chromium_src-6529382867932acbf83e49bc107fbe4ea28ad311.zip chromium_src-6529382867932acbf83e49bc107fbe4ea28ad311.tar.gz chromium_src-6529382867932acbf83e49bc107fbe4ea28ad311.tar.bz2 |
[Sync] Avoid unregistering object IDs on shutdown
Add RegisterHandler() and UnregisterHandler(), which should be called before and after calls to UpdateRegisteredIds(). Use UnregisterHandler() on
shutdown instead of UpdateRegisteredIds(_, ObjectIdSet()).
Make SyncNotifierHelper non-thread-safe. Fix test breakages that this revealed. Also add GetAllRegisteredIds() instead of making it the return value of UpdateRegisteredIds().
Propagate UpdateRegisteredIds()/RegisterHandler()/UnregisterHandler() all
the way up to ProfileSyncService.
Make FakeSyncManager be created on the sync thread.
Clean up SyncBackendHost startup/shutdown behavior a bit.
BUG=140325
Review URL: https://chromiumcodereview.appspot.com/10824161
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150990 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sync/notifier/sync_notifier_registrar.cc')
-rw-r--r-- | sync/notifier/sync_notifier_registrar.cc | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/sync/notifier/sync_notifier_registrar.cc b/sync/notifier/sync_notifier_registrar.cc new file mode 100644 index 0000000..02c00b6 --- /dev/null +++ b/sync/notifier/sync_notifier_registrar.cc @@ -0,0 +1,129 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sync/notifier/sync_notifier_registrar.h" + +#include <cstddef> +#include <utility> + +#include "base/logging.h" + +namespace syncer { + +SyncNotifierRegistrar::SyncNotifierRegistrar() {} + +SyncNotifierRegistrar::~SyncNotifierRegistrar() { + DCHECK(thread_checker_.CalledOnValidThread()); +} + +void SyncNotifierRegistrar::RegisterHandler(SyncNotifierObserver* handler) { + DCHECK(thread_checker_.CalledOnValidThread()); + CHECK(handler); + CHECK(!handlers_.HasObserver(handler)); + handlers_.AddObserver(handler); +} + +void SyncNotifierRegistrar::UpdateRegisteredIds( + SyncNotifierObserver* handler, + const ObjectIdSet& ids) { + DCHECK(thread_checker_.CalledOnValidThread()); + CHECK(handler); + CHECK(handlers_.HasObserver(handler)); + // Remove all existing entries for |handler|. + for (IdHandlerMap::iterator it = id_to_handler_map_.begin(); + it != id_to_handler_map_.end(); ) { + if (it->second == handler) { + IdHandlerMap::iterator erase_it = it; + ++it; + id_to_handler_map_.erase(erase_it); + } else { + ++it; + } + } + + // Now add the entries for |handler|. We keep track of the last insertion + // point so we only traverse the map once to insert all the new entries. + IdHandlerMap::iterator insert_it = id_to_handler_map_.begin(); + for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) { + insert_it = + id_to_handler_map_.insert(insert_it, std::make_pair(*it, handler)); + CHECK_EQ(handler, insert_it->second) + << "Duplicate registration: trying to register " + << ObjectIdToString(insert_it->first) << " for " + << handler << " when it's already registered for " + << insert_it->second; + } +} + +void SyncNotifierRegistrar::UnregisterHandler(SyncNotifierObserver* handler) { + DCHECK(thread_checker_.CalledOnValidThread()); + CHECK(handler); + CHECK(handlers_.HasObserver(handler)); + handlers_.RemoveObserver(handler); +} + +ObjectIdSet SyncNotifierRegistrar::GetAllRegisteredIds() const { + DCHECK(thread_checker_.CalledOnValidThread()); + ObjectIdSet registered_ids; + for (IdHandlerMap::const_iterator it = id_to_handler_map_.begin(); + it != id_to_handler_map_.end(); ++it) { + registered_ids.insert(it->first); + } + return registered_ids; +} + +void SyncNotifierRegistrar::DispatchInvalidationsToHandlers( + const ObjectIdPayloadMap& id_payloads, + IncomingNotificationSource source) { + DCHECK(thread_checker_.CalledOnValidThread()); + // If we have no handlers, there's nothing to do. + if (!handlers_.might_have_observers()) { + return; + } + + typedef std::map<SyncNotifierObserver*, ObjectIdPayloadMap> DispatchMap; + DispatchMap dispatch_map; + for (ObjectIdPayloadMap::const_iterator it = id_payloads.begin(); + it != id_payloads.end(); ++it) { + SyncNotifierObserver* const handler = ObjectIdToHandler(it->first); + // Filter out invalidations for IDs with no handler. + if (handler) + dispatch_map[handler].insert(*it); + } + + // Emit invalidations only for handlers in |handlers_|. + ObserverListBase<SyncNotifierObserver>::Iterator it(handlers_); + SyncNotifierObserver* handler = NULL; + while ((handler = it.GetNext()) != NULL) { + DispatchMap::const_iterator dispatch_it = dispatch_map.find(handler); + if (dispatch_it != dispatch_map.end()) + handler->OnIncomingNotification(dispatch_it->second, source); + } +} + +void SyncNotifierRegistrar::EmitOnNotificationsEnabled() { + DCHECK(thread_checker_.CalledOnValidThread()); + FOR_EACH_OBSERVER(SyncNotifierObserver, handlers_, OnNotificationsEnabled()); +} + +void SyncNotifierRegistrar::EmitOnNotificationsDisabled( + NotificationsDisabledReason reason) { + DCHECK(thread_checker_.CalledOnValidThread()); + FOR_EACH_OBSERVER(SyncNotifierObserver, handlers_, + OnNotificationsDisabled(reason)); +} + +void SyncNotifierRegistrar::DetachFromThreadForTest() { + DCHECK(thread_checker_.CalledOnValidThread()); + thread_checker_.DetachFromThread(); +} + +SyncNotifierObserver* SyncNotifierRegistrar::ObjectIdToHandler( + const invalidation::ObjectId& id) { + DCHECK(thread_checker_.CalledOnValidThread()); + IdHandlerMap::const_iterator it = id_to_handler_map_.find(id); + return (it == id_to_handler_map_.end()) ? NULL : it->second; +} + +} // namespace syncer |