1 // Copyright (c) 2012 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 "sync/notifier/non_blocking_invalidator.h"
6
7 #include <cstddef>
8
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/threading/thread.h"
15 #include "jingle/notifier/listener/push_client.h"
16 #include "sync/notifier/invalidation_notifier.h"
17 #include "sync/notifier/object_id_invalidation_map.h"
18
19 namespace syncer {
20
21 class NonBlockingInvalidator::Core
22 : public base::RefCountedThreadSafe<NonBlockingInvalidator::Core>,
23 // InvalidationHandler to observe the InvalidationNotifier we create.
24 public InvalidationHandler {
25 public:
26 // Called on parent thread. |delegate_observer| should be
27 // initialized.
28 explicit Core(
29 const WeakHandle<InvalidationHandler>& delegate_observer);
30
31 // Helpers called on I/O thread.
32 void Initialize(
33 const notifier::NotifierOptions& notifier_options,
34 const std::string& invalidator_client_id,
35 const UnackedInvalidationsMap& saved_invalidations,
36 const std::string& invalidation_bootstrap_data,
37 const WeakHandle<InvalidationStateTracker>& invalidation_state_tracker,
38 const std::string& client_info);
39 void Teardown();
40 void UpdateRegisteredIds(const ObjectIdSet& ids);
41 void UpdateCredentials(const std::string& email, const std::string& token);
42
43 // InvalidationHandler implementation (all called on I/O thread by
44 // InvalidationNotifier).
45 virtual void OnInvalidatorStateChange(InvalidatorState reason) OVERRIDE;
46 virtual void OnIncomingInvalidation(
47 const ObjectIdInvalidationMap& invalidation_map) OVERRIDE;
48
49 private:
50 friend class
51 base::RefCountedThreadSafe<NonBlockingInvalidator::Core>;
52 // Called on parent or I/O thread.
53 virtual ~Core();
54
55 // The variables below should be used only on the I/O thread.
56 const WeakHandle<InvalidationHandler> delegate_observer_;
57 scoped_ptr<InvalidationNotifier> invalidation_notifier_;
58 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
59
60 DISALLOW_COPY_AND_ASSIGN(Core);
61 };
62
Core(const WeakHandle<InvalidationHandler> & delegate_observer)63 NonBlockingInvalidator::Core::Core(
64 const WeakHandle<InvalidationHandler>& delegate_observer)
65 : delegate_observer_(delegate_observer) {
66 DCHECK(delegate_observer_.IsInitialized());
67 }
68
~Core()69 NonBlockingInvalidator::Core::~Core() {
70 }
71
Initialize(const notifier::NotifierOptions & notifier_options,const std::string & invalidator_client_id,const UnackedInvalidationsMap & saved_invalidations,const std::string & invalidation_bootstrap_data,const WeakHandle<InvalidationStateTracker> & invalidation_state_tracker,const std::string & client_info)72 void NonBlockingInvalidator::Core::Initialize(
73 const notifier::NotifierOptions& notifier_options,
74 const std::string& invalidator_client_id,
75 const UnackedInvalidationsMap& saved_invalidations,
76 const std::string& invalidation_bootstrap_data,
77 const WeakHandle<InvalidationStateTracker>& invalidation_state_tracker,
78 const std::string& client_info) {
79 DCHECK(notifier_options.request_context_getter.get());
80 DCHECK_EQ(notifier::NOTIFICATION_SERVER,
81 notifier_options.notification_method);
82 network_task_runner_ = notifier_options.request_context_getter->
83 GetNetworkTaskRunner();
84 DCHECK(network_task_runner_->BelongsToCurrentThread());
85 invalidation_notifier_.reset(
86 new InvalidationNotifier(
87 notifier::PushClient::CreateDefaultOnIOThread(notifier_options),
88 invalidator_client_id,
89 saved_invalidations,
90 invalidation_bootstrap_data,
91 invalidation_state_tracker,
92 client_info));
93 invalidation_notifier_->RegisterHandler(this);
94 }
95
Teardown()96 void NonBlockingInvalidator::Core::Teardown() {
97 DCHECK(network_task_runner_->BelongsToCurrentThread());
98 invalidation_notifier_->UnregisterHandler(this);
99 invalidation_notifier_.reset();
100 network_task_runner_ = NULL;
101 }
102
UpdateRegisteredIds(const ObjectIdSet & ids)103 void NonBlockingInvalidator::Core::UpdateRegisteredIds(const ObjectIdSet& ids) {
104 DCHECK(network_task_runner_->BelongsToCurrentThread());
105 invalidation_notifier_->UpdateRegisteredIds(this, ids);
106 }
107
UpdateCredentials(const std::string & email,const std::string & token)108 void NonBlockingInvalidator::Core::UpdateCredentials(const std::string& email,
109 const std::string& token) {
110 DCHECK(network_task_runner_->BelongsToCurrentThread());
111 invalidation_notifier_->UpdateCredentials(email, token);
112 }
113
OnInvalidatorStateChange(InvalidatorState reason)114 void NonBlockingInvalidator::Core::OnInvalidatorStateChange(
115 InvalidatorState reason) {
116 DCHECK(network_task_runner_->BelongsToCurrentThread());
117 delegate_observer_.Call(
118 FROM_HERE, &InvalidationHandler::OnInvalidatorStateChange, reason);
119 }
120
OnIncomingInvalidation(const ObjectIdInvalidationMap & invalidation_map)121 void NonBlockingInvalidator::Core::OnIncomingInvalidation(
122 const ObjectIdInvalidationMap& invalidation_map) {
123 DCHECK(network_task_runner_->BelongsToCurrentThread());
124 delegate_observer_.Call(FROM_HERE,
125 &InvalidationHandler::OnIncomingInvalidation,
126 invalidation_map);
127 }
128
NonBlockingInvalidator(const notifier::NotifierOptions & notifier_options,const std::string & invalidator_client_id,const UnackedInvalidationsMap & saved_invalidations,const std::string & invalidation_bootstrap_data,const WeakHandle<InvalidationStateTracker> & invalidation_state_tracker,const std::string & client_info)129 NonBlockingInvalidator::NonBlockingInvalidator(
130 const notifier::NotifierOptions& notifier_options,
131 const std::string& invalidator_client_id,
132 const UnackedInvalidationsMap& saved_invalidations,
133 const std::string& invalidation_bootstrap_data,
134 const WeakHandle<InvalidationStateTracker>&
135 invalidation_state_tracker,
136 const std::string& client_info)
137 : parent_task_runner_(base::ThreadTaskRunnerHandle::Get()),
138 network_task_runner_(
139 notifier_options.request_context_getter->GetNetworkTaskRunner()),
140 weak_ptr_factory_(this) {
141 core_ = new Core(MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()));
142
143 if (!network_task_runner_->PostTask(
144 FROM_HERE,
145 base::Bind(
146 &NonBlockingInvalidator::Core::Initialize,
147 core_.get(),
148 notifier_options,
149 invalidator_client_id,
150 saved_invalidations,
151 invalidation_bootstrap_data,
152 invalidation_state_tracker,
153 client_info))) {
154 NOTREACHED();
155 }
156 }
157
~NonBlockingInvalidator()158 NonBlockingInvalidator::~NonBlockingInvalidator() {
159 DCHECK(parent_task_runner_->BelongsToCurrentThread());
160 if (!network_task_runner_->PostTask(
161 FROM_HERE,
162 base::Bind(&NonBlockingInvalidator::Core::Teardown,
163 core_.get()))) {
164 DVLOG(1) << "Network thread stopped before invalidator is destroyed.";
165 }
166 }
167
RegisterHandler(InvalidationHandler * handler)168 void NonBlockingInvalidator::RegisterHandler(InvalidationHandler* handler) {
169 DCHECK(parent_task_runner_->BelongsToCurrentThread());
170 registrar_.RegisterHandler(handler);
171 }
172
UpdateRegisteredIds(InvalidationHandler * handler,const ObjectIdSet & ids)173 void NonBlockingInvalidator::UpdateRegisteredIds(InvalidationHandler* handler,
174 const ObjectIdSet& ids) {
175 DCHECK(parent_task_runner_->BelongsToCurrentThread());
176 registrar_.UpdateRegisteredIds(handler, ids);
177 if (!network_task_runner_->PostTask(
178 FROM_HERE,
179 base::Bind(
180 &NonBlockingInvalidator::Core::UpdateRegisteredIds,
181 core_.get(),
182 registrar_.GetAllRegisteredIds()))) {
183 NOTREACHED();
184 }
185 }
186
UnregisterHandler(InvalidationHandler * handler)187 void NonBlockingInvalidator::UnregisterHandler(InvalidationHandler* handler) {
188 DCHECK(parent_task_runner_->BelongsToCurrentThread());
189 registrar_.UnregisterHandler(handler);
190 }
191
GetInvalidatorState() const192 InvalidatorState NonBlockingInvalidator::GetInvalidatorState() const {
193 DCHECK(parent_task_runner_->BelongsToCurrentThread());
194 return registrar_.GetInvalidatorState();
195 }
196
UpdateCredentials(const std::string & email,const std::string & token)197 void NonBlockingInvalidator::UpdateCredentials(const std::string& email,
198 const std::string& token) {
199 DCHECK(parent_task_runner_->BelongsToCurrentThread());
200 if (!network_task_runner_->PostTask(
201 FROM_HERE,
202 base::Bind(&NonBlockingInvalidator::Core::UpdateCredentials,
203 core_.get(), email, token))) {
204 NOTREACHED();
205 }
206 }
207
OnInvalidatorStateChange(InvalidatorState state)208 void NonBlockingInvalidator::OnInvalidatorStateChange(InvalidatorState state) {
209 DCHECK(parent_task_runner_->BelongsToCurrentThread());
210 registrar_.UpdateInvalidatorState(state);
211 }
212
OnIncomingInvalidation(const ObjectIdInvalidationMap & invalidation_map)213 void NonBlockingInvalidator::OnIncomingInvalidation(
214 const ObjectIdInvalidationMap& invalidation_map) {
215 DCHECK(parent_task_runner_->BelongsToCurrentThread());
216 registrar_.DispatchInvalidationsToHandlers(invalidation_map);
217 }
218
219 } // namespace syncer
220