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 63 NonBlockingInvalidator::Core::Core( 64 const WeakHandle<InvalidationHandler>& delegate_observer) 65 : delegate_observer_(delegate_observer) { 66 DCHECK(delegate_observer_.IsInitialized()); 67 } 68 69 NonBlockingInvalidator::Core::~Core() { 70 } 71 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 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 103 void NonBlockingInvalidator::Core::UpdateRegisteredIds(const ObjectIdSet& ids) { 104 DCHECK(network_task_runner_->BelongsToCurrentThread()); 105 invalidation_notifier_->UpdateRegisteredIds(this, ids); 106 } 107 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 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 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 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 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 168 void NonBlockingInvalidator::RegisterHandler(InvalidationHandler* handler) { 169 DCHECK(parent_task_runner_->BelongsToCurrentThread()); 170 registrar_.RegisterHandler(handler); 171 } 172 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 187 void NonBlockingInvalidator::UnregisterHandler(InvalidationHandler* handler) { 188 DCHECK(parent_task_runner_->BelongsToCurrentThread()); 189 registrar_.UnregisterHandler(handler); 190 } 191 192 InvalidatorState NonBlockingInvalidator::GetInvalidatorState() const { 193 DCHECK(parent_task_runner_->BelongsToCurrentThread()); 194 return registrar_.GetInvalidatorState(); 195 } 196 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 208 void NonBlockingInvalidator::OnInvalidatorStateChange(InvalidatorState state) { 209 DCHECK(parent_task_runner_->BelongsToCurrentThread()); 210 registrar_.UpdateInvalidatorState(state); 211 } 212 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