1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/invalidation/invalidator_registrar.h"
6
7 #include <cstddef>
8 #include <iterator>
9 #include <utility>
10
11 #include "base/logging.h"
12 #include "components/invalidation/object_id_invalidation_map.h"
13
14 namespace syncer {
15
InvalidatorRegistrar()16 InvalidatorRegistrar::InvalidatorRegistrar()
17 : state_(DEFAULT_INVALIDATION_ERROR) {}
18
~InvalidatorRegistrar()19 InvalidatorRegistrar::~InvalidatorRegistrar() {
20 DCHECK(thread_checker_.CalledOnValidThread());
21 CHECK(handler_to_ids_map_.empty());
22 }
23
RegisterHandler(InvalidationHandler * handler)24 void InvalidatorRegistrar::RegisterHandler(InvalidationHandler* handler) {
25 DCHECK(thread_checker_.CalledOnValidThread());
26 CHECK(handler);
27 CHECK(!handlers_.HasObserver(handler));
28 handlers_.AddObserver(handler);
29 }
30
UpdateRegisteredIds(InvalidationHandler * handler,const ObjectIdSet & ids)31 void InvalidatorRegistrar::UpdateRegisteredIds(
32 InvalidationHandler* handler,
33 const ObjectIdSet& ids) {
34 DCHECK(thread_checker_.CalledOnValidThread());
35 CHECK(handler);
36 CHECK(handlers_.HasObserver(handler));
37
38 for (HandlerIdsMap::const_iterator it = handler_to_ids_map_.begin();
39 it != handler_to_ids_map_.end(); ++it) {
40 if (it->first == handler) {
41 continue;
42 }
43
44 std::vector<invalidation::ObjectId> intersection;
45 std::set_intersection(
46 it->second.begin(), it->second.end(),
47 ids.begin(), ids.end(),
48 std::inserter(intersection, intersection.end()),
49 ObjectIdLessThan());
50 CHECK(intersection.empty())
51 << "Duplicate registration: trying to register "
52 << ObjectIdToString(*intersection.begin()) << " for "
53 << handler << " when it's already registered for "
54 << it->first;
55 }
56
57 if (ids.empty()) {
58 handler_to_ids_map_.erase(handler);
59 } else {
60 handler_to_ids_map_[handler] = ids;
61 }
62 }
63
UnregisterHandler(InvalidationHandler * handler)64 void InvalidatorRegistrar::UnregisterHandler(InvalidationHandler* handler) {
65 DCHECK(thread_checker_.CalledOnValidThread());
66 CHECK(handler);
67 CHECK(handlers_.HasObserver(handler));
68 handlers_.RemoveObserver(handler);
69 handler_to_ids_map_.erase(handler);
70 }
71
GetRegisteredIds(InvalidationHandler * handler) const72 ObjectIdSet InvalidatorRegistrar::GetRegisteredIds(
73 InvalidationHandler* handler) const {
74 DCHECK(thread_checker_.CalledOnValidThread());
75 HandlerIdsMap::const_iterator lookup = handler_to_ids_map_.find(handler);
76 if (lookup != handler_to_ids_map_.end()) {
77 return lookup->second;
78 } else {
79 return ObjectIdSet();
80 }
81 }
82
GetAllRegisteredIds() const83 ObjectIdSet InvalidatorRegistrar::GetAllRegisteredIds() const {
84 DCHECK(thread_checker_.CalledOnValidThread());
85 ObjectIdSet registered_ids;
86 for (HandlerIdsMap::const_iterator it = handler_to_ids_map_.begin();
87 it != handler_to_ids_map_.end(); ++it) {
88 registered_ids.insert(it->second.begin(), it->second.end());
89 }
90 return registered_ids;
91 }
92
DispatchInvalidationsToHandlers(const ObjectIdInvalidationMap & invalidation_map)93 void InvalidatorRegistrar::DispatchInvalidationsToHandlers(
94 const ObjectIdInvalidationMap& invalidation_map) {
95 DCHECK(thread_checker_.CalledOnValidThread());
96 // If we have no handlers, there's nothing to do.
97 if (!handlers_.might_have_observers()) {
98 return;
99 }
100
101 for (HandlerIdsMap::iterator it = handler_to_ids_map_.begin();
102 it != handler_to_ids_map_.end(); ++it) {
103 ObjectIdInvalidationMap to_emit =
104 invalidation_map.GetSubsetWithObjectIds(it->second);
105 if (!to_emit.Empty()) {
106 it->first->OnIncomingInvalidation(to_emit);
107 }
108 }
109 }
110
UpdateInvalidatorState(InvalidatorState state)111 void InvalidatorRegistrar::UpdateInvalidatorState(InvalidatorState state) {
112 DCHECK(thread_checker_.CalledOnValidThread());
113 DVLOG(1) << "New invalidator state: " << InvalidatorStateToString(state_)
114 << " -> " << InvalidatorStateToString(state);
115 state_ = state;
116 FOR_EACH_OBSERVER(InvalidationHandler, handlers_,
117 OnInvalidatorStateChange(state));
118 }
119
GetInvalidatorState() const120 InvalidatorState InvalidatorRegistrar::GetInvalidatorState() const {
121 DCHECK(thread_checker_.CalledOnValidThread());
122 return state_;
123 }
124
125 std::map<std::string, ObjectIdSet>
GetSanitizedHandlersIdsMap()126 InvalidatorRegistrar::GetSanitizedHandlersIdsMap() {
127 DCHECK(thread_checker_.CalledOnValidThread());
128 std::map<std::string, ObjectIdSet> clean_handlers_to_ids;
129 for (HandlerIdsMap::const_iterator it = handler_to_ids_map_.begin();
130 it != handler_to_ids_map_.end();
131 ++it) {
132 clean_handlers_to_ids[it->first->GetOwnerName()] = ObjectIdSet(it->second);
133 }
134 return clean_handlers_to_ids;
135 }
136
IsHandlerRegisteredForTest(InvalidationHandler * handler) const137 bool InvalidatorRegistrar::IsHandlerRegisteredForTest(
138 InvalidationHandler* handler) const {
139 DCHECK(thread_checker_.CalledOnValidThread());
140 return handlers_.HasObserver(handler);
141 }
142
DetachFromThreadForTest()143 void InvalidatorRegistrar::DetachFromThreadForTest() {
144 DCHECK(thread_checker_.CalledOnValidThread());
145 thread_checker_.DetachFromThread();
146 }
147
148 } // namespace syncer
149