Home | History | Annotate | Download | only in notifier
      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