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.
5 #include "components/invalidation/non_blocking_invalidator.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/profiler/scoped_tracker.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/threading/thread.h"
16 #include "components/invalidation/gcm_network_channel_delegate.h"
17 #include "components/invalidation/invalidation_handler.h"
18 #include "components/invalidation/invalidation_notifier.h"
19 #include "components/invalidation/object_id_invalidation_map.h"
20 #include "components/invalidation/sync_system_resources.h"
21 #include "jingle/notifier/listener/push_client.h"
25 struct NonBlockingInvalidator::InitializeOptions
{
27 NetworkChannelCreator network_channel_creator
,
28 const std::string
& invalidator_client_id
,
29 const UnackedInvalidationsMap
& saved_invalidations
,
30 const std::string
& invalidation_bootstrap_data
,
31 const base::WeakPtr
<InvalidationStateTracker
>& invalidation_state_tracker
,
32 const scoped_refptr
<base::SingleThreadTaskRunner
>&
33 invalidation_state_tracker_task_runner
,
34 const std::string
& client_info
,
35 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter
)
36 : network_channel_creator(network_channel_creator
),
37 invalidator_client_id(invalidator_client_id
),
38 saved_invalidations(saved_invalidations
),
39 invalidation_bootstrap_data(invalidation_bootstrap_data
),
40 invalidation_state_tracker(invalidation_state_tracker
),
41 invalidation_state_tracker_task_runner(
42 invalidation_state_tracker_task_runner
),
43 client_info(client_info
),
44 request_context_getter(request_context_getter
) {}
46 NetworkChannelCreator network_channel_creator
;
47 std::string invalidator_client_id
;
48 UnackedInvalidationsMap saved_invalidations
;
49 std::string invalidation_bootstrap_data
;
50 base::WeakPtr
<InvalidationStateTracker
> invalidation_state_tracker
;
51 scoped_refptr
<base::SingleThreadTaskRunner
>
52 invalidation_state_tracker_task_runner
;
53 std::string client_info
;
54 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter
;
58 // This class provides a wrapper for a logging class in order to receive
59 // callbacks across threads, without having to worry about owner threads.
62 explicit CallbackProxy(
63 base::Callback
<void(const base::DictionaryValue
&)> callback
);
66 void Run(const base::DictionaryValue
& value
);
69 static void DoRun(base::Callback
<void(const base::DictionaryValue
&)> callback
,
70 scoped_ptr
<base::DictionaryValue
> value
);
72 base::Callback
<void(const base::DictionaryValue
&)> callback_
;
73 scoped_refptr
<base::SingleThreadTaskRunner
> running_thread_
;
75 DISALLOW_COPY_AND_ASSIGN(CallbackProxy
);
78 CallbackProxy::CallbackProxy(
79 base::Callback
<void(const base::DictionaryValue
&)> callback
)
80 : callback_(callback
),
81 running_thread_(base::ThreadTaskRunnerHandle::Get()) {}
83 CallbackProxy::~CallbackProxy() {}
85 void CallbackProxy::DoRun(
86 base::Callback
<void(const base::DictionaryValue
&)> callback
,
87 scoped_ptr
<base::DictionaryValue
> value
) {
91 void CallbackProxy::Run(const base::DictionaryValue
& value
) {
92 scoped_ptr
<base::DictionaryValue
> copied(value
.DeepCopy());
93 running_thread_
->PostTask(
95 base::Bind(&CallbackProxy::DoRun
, callback_
, base::Passed(&copied
)));
99 class NonBlockingInvalidator::Core
100 : public base::RefCountedThreadSafe
<NonBlockingInvalidator::Core
>,
101 // InvalidationHandler to observe the InvalidationNotifier we create.
102 public InvalidationHandler
{
104 // Called on parent thread. |delegate_observer| should be initialized.
105 Core(const base::WeakPtr
<NonBlockingInvalidator
>& delegate_observer
,
106 const scoped_refptr
<base::SingleThreadTaskRunner
>&
107 delegate_observer_task_runner
);
109 // Helpers called on I/O thread.
111 const NonBlockingInvalidator::InitializeOptions
& initialize_options
);
113 void UpdateRegisteredIds(const ObjectIdSet
& ids
);
114 void UpdateCredentials(const std::string
& email
, const std::string
& token
);
115 void RequestDetailedStatus(
116 base::Callback
<void(const base::DictionaryValue
&)> callback
) const;
118 // InvalidationHandler implementation (all called on I/O thread by
119 // InvalidationNotifier).
120 void OnInvalidatorStateChange(InvalidatorState reason
) override
;
121 void OnIncomingInvalidation(
122 const ObjectIdInvalidationMap
& invalidation_map
) override
;
123 std::string
GetOwnerName() const override
;
127 base::RefCountedThreadSafe
<NonBlockingInvalidator::Core
>;
128 // Called on parent or I/O thread.
131 // The variables below should be used only on the I/O thread.
132 const base::WeakPtr
<NonBlockingInvalidator
> delegate_observer_
;
133 scoped_refptr
<base::SingleThreadTaskRunner
> delegate_observer_task_runner_
;
134 scoped_ptr
<InvalidationNotifier
> invalidation_notifier_
;
135 scoped_refptr
<base::SingleThreadTaskRunner
> network_task_runner_
;
137 DISALLOW_COPY_AND_ASSIGN(Core
);
140 NonBlockingInvalidator::Core::Core(
141 const base::WeakPtr
<NonBlockingInvalidator
>& delegate_observer
,
142 const scoped_refptr
<base::SingleThreadTaskRunner
>&
143 delegate_observer_task_runner
)
144 : delegate_observer_(delegate_observer
),
145 delegate_observer_task_runner_(delegate_observer_task_runner
) {
146 DCHECK(delegate_observer_
);
147 DCHECK(delegate_observer_task_runner_
.get());
150 NonBlockingInvalidator::Core::~Core() {
153 void NonBlockingInvalidator::Core::Initialize(
154 const NonBlockingInvalidator::InitializeOptions
& initialize_options
) {
155 DCHECK(initialize_options
.request_context_getter
.get());
156 network_task_runner_
=
157 initialize_options
.request_context_getter
->GetNetworkTaskRunner();
158 DCHECK(network_task_runner_
->BelongsToCurrentThread());
159 scoped_ptr
<SyncNetworkChannel
> network_channel
=
160 initialize_options
.network_channel_creator
.Run();
161 invalidation_notifier_
.reset(new InvalidationNotifier(
162 network_channel
.Pass(),
163 initialize_options
.invalidator_client_id
,
164 initialize_options
.saved_invalidations
,
165 initialize_options
.invalidation_bootstrap_data
,
166 initialize_options
.invalidation_state_tracker
,
167 initialize_options
.invalidation_state_tracker_task_runner
,
168 initialize_options
.client_info
));
169 invalidation_notifier_
->RegisterHandler(this);
172 void NonBlockingInvalidator::Core::Teardown() {
173 DCHECK(network_task_runner_
->BelongsToCurrentThread());
174 invalidation_notifier_
->UnregisterHandler(this);
175 invalidation_notifier_
.reset();
176 network_task_runner_
= NULL
;
179 void NonBlockingInvalidator::Core::UpdateRegisteredIds(const ObjectIdSet
& ids
) {
180 DCHECK(network_task_runner_
->BelongsToCurrentThread());
181 invalidation_notifier_
->UpdateRegisteredIds(this, ids
);
184 void NonBlockingInvalidator::Core::UpdateCredentials(const std::string
& email
,
185 const std::string
& token
) {
186 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
187 tracked_objects::ScopedTracker
tracking_profile(
188 FROM_HERE_WITH_EXPLICIT_FUNCTION(
189 "477117 NonBlockingInvalidator::Core::UpdateCredentials"));
190 DCHECK(network_task_runner_
->BelongsToCurrentThread());
191 invalidation_notifier_
->UpdateCredentials(email
, token
);
194 void NonBlockingInvalidator::Core::RequestDetailedStatus(
195 base::Callback
<void(const base::DictionaryValue
&)> callback
) const {
196 DCHECK(network_task_runner_
->BelongsToCurrentThread());
197 invalidation_notifier_
->RequestDetailedStatus(callback
);
200 void NonBlockingInvalidator::Core::OnInvalidatorStateChange(
201 InvalidatorState reason
) {
202 DCHECK(network_task_runner_
->BelongsToCurrentThread());
203 delegate_observer_task_runner_
->PostTask(
205 base::Bind(&NonBlockingInvalidator::OnInvalidatorStateChange
,
210 void NonBlockingInvalidator::Core::OnIncomingInvalidation(
211 const ObjectIdInvalidationMap
& invalidation_map
) {
212 DCHECK(network_task_runner_
->BelongsToCurrentThread());
213 delegate_observer_task_runner_
->PostTask(
215 base::Bind(&NonBlockingInvalidator::OnIncomingInvalidation
,
220 std::string
NonBlockingInvalidator::Core::GetOwnerName() const {
224 NonBlockingInvalidator::NonBlockingInvalidator(
225 NetworkChannelCreator network_channel_creator
,
226 const std::string
& invalidator_client_id
,
227 const UnackedInvalidationsMap
& saved_invalidations
,
228 const std::string
& invalidation_bootstrap_data
,
229 InvalidationStateTracker
* invalidation_state_tracker
,
230 const std::string
& client_info
,
231 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
)
232 : invalidation_state_tracker_(invalidation_state_tracker
),
233 parent_task_runner_(base::ThreadTaskRunnerHandle::Get()),
234 network_task_runner_(request_context_getter
->GetNetworkTaskRunner()),
235 weak_ptr_factory_(this) {
236 base::WeakPtr
<NonBlockingInvalidator
> weak_ptr_this
=
237 weak_ptr_factory_
.GetWeakPtr();
238 weak_ptr_this
.get(); // Bind to this thread.
240 core_
= new Core(weak_ptr_this
,
241 base::MessageLoopProxy::current());
243 InitializeOptions
initialize_options(network_channel_creator
,
244 invalidator_client_id
,
246 invalidation_bootstrap_data
,
248 base::MessageLoopProxy::current(),
250 request_context_getter
);
252 if (!network_task_runner_
->PostTask(
255 &NonBlockingInvalidator::Core::Initialize
,
257 initialize_options
))) {
262 NonBlockingInvalidator::~NonBlockingInvalidator() {
263 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
264 if (!network_task_runner_
->PostTask(
266 base::Bind(&NonBlockingInvalidator::Core::Teardown
,
268 DVLOG(1) << "Network thread stopped before invalidator is destroyed.";
272 void NonBlockingInvalidator::RegisterHandler(InvalidationHandler
* handler
) {
273 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
274 registrar_
.RegisterHandler(handler
);
277 bool NonBlockingInvalidator::UpdateRegisteredIds(InvalidationHandler
* handler
,
278 const ObjectIdSet
& ids
) {
279 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
280 if (!registrar_
.UpdateRegisteredIds(handler
, ids
))
282 if (!network_task_runner_
->PostTask(
285 &NonBlockingInvalidator::Core::UpdateRegisteredIds
,
287 registrar_
.GetAllRegisteredIds()))) {
293 void NonBlockingInvalidator::UnregisterHandler(InvalidationHandler
* handler
) {
294 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
295 registrar_
.UnregisterHandler(handler
);
298 InvalidatorState
NonBlockingInvalidator::GetInvalidatorState() const {
299 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
300 return registrar_
.GetInvalidatorState();
303 void NonBlockingInvalidator::UpdateCredentials(const std::string
& email
,
304 const std::string
& token
) {
305 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
306 if (!network_task_runner_
->PostTask(
308 base::Bind(&NonBlockingInvalidator::Core::UpdateCredentials
,
309 core_
.get(), email
, token
))) {
314 void NonBlockingInvalidator::RequestDetailedStatus(
315 base::Callback
<void(const base::DictionaryValue
&)> callback
) const {
316 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
317 base::Callback
<void(const base::DictionaryValue
&)> proxy_callback
=
318 base::Bind(&CallbackProxy::Run
, base::Owned(new CallbackProxy(callback
)));
319 if (!network_task_runner_
->PostTask(
321 base::Bind(&NonBlockingInvalidator::Core::RequestDetailedStatus
,
328 NetworkChannelCreator
329 NonBlockingInvalidator::MakePushClientChannelCreator(
330 const notifier::NotifierOptions
& notifier_options
) {
331 return base::Bind(SyncNetworkChannel::CreatePushClientChannel
,
335 NetworkChannelCreator
NonBlockingInvalidator::MakeGCMNetworkChannelCreator(
336 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter
,
337 scoped_ptr
<GCMNetworkChannelDelegate
> delegate
) {
338 return base::Bind(&SyncNetworkChannel::CreateGCMNetworkChannel
,
339 request_context_getter
,
340 base::Passed(&delegate
));
343 void NonBlockingInvalidator::ClearAndSetNewClientId(const std::string
& data
) {
344 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
345 invalidation_state_tracker_
->ClearAndSetNewClientId(data
);
348 std::string
NonBlockingInvalidator::GetInvalidatorClientId() const {
349 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
350 return invalidation_state_tracker_
->GetInvalidatorClientId();
353 void NonBlockingInvalidator::SetBootstrapData(const std::string
& data
) {
354 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
355 invalidation_state_tracker_
->SetBootstrapData(data
);
358 std::string
NonBlockingInvalidator::GetBootstrapData() const {
359 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
360 return invalidation_state_tracker_
->GetBootstrapData();
363 void NonBlockingInvalidator::SetSavedInvalidations(
364 const UnackedInvalidationsMap
& states
) {
365 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
366 invalidation_state_tracker_
->SetSavedInvalidations(states
);
369 UnackedInvalidationsMap
NonBlockingInvalidator::GetSavedInvalidations() const {
370 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
371 return invalidation_state_tracker_
->GetSavedInvalidations();
374 void NonBlockingInvalidator::Clear() {
375 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
376 invalidation_state_tracker_
->Clear();
379 void NonBlockingInvalidator::OnInvalidatorStateChange(InvalidatorState state
) {
380 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
381 registrar_
.UpdateInvalidatorState(state
);
384 void NonBlockingInvalidator::OnIncomingInvalidation(
385 const ObjectIdInvalidationMap
& invalidation_map
) {
386 DCHECK(parent_task_runner_
->BelongsToCurrentThread());
387 registrar_
.DispatchInvalidationsToHandlers(invalidation_map
);
390 std::string
NonBlockingInvalidator::GetOwnerName() const { return "Sync"; }
392 } // namespace syncer