• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "chrome/browser/sync/notifier/non_blocking_invalidation_notifier.h"
6 
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop.h"
10 #include "base/observer_list_threadsafe.h"
11 #include "base/threading/thread.h"
12 #include "chrome/browser/sync/notifier/invalidation_notifier.h"
13 #include "chrome/browser/sync/notifier/sync_notifier_observer.h"
14 
15 namespace sync_notifier {
16 
17 class NonBlockingInvalidationNotifier::Core
18     : public base::RefCountedThreadSafe<NonBlockingInvalidationNotifier::Core>,
19       public SyncNotifierObserver {
20  public:
21   // Called on parent thread.
22   Core();
23 
24   // Called on parent thread.
25   void AddObserver(SyncNotifierObserver* observer);
26   void RemoveObserver(SyncNotifierObserver* observer);
27 
28   // Helpers called on I/O thread.
29   void Initialize(const notifier::NotifierOptions& notifier_options,
30                   const std::string& client_info);
31   void Teardown();
32   void SetState(const std::string& state);
33   void UpdateCredentials(const std::string& email, const std::string& token);
34   void UpdateEnabledTypes(const syncable::ModelTypeSet& types);
35   void SendNotification();
36 
37   // SyncNotifierObserver implementation (all called on I/O thread).
38   virtual void OnIncomingNotification(
39       const syncable::ModelTypePayloadMap& type_payloads);
40   virtual void OnNotificationStateChange(bool notifications_enabled);
41   virtual void StoreState(const std::string& state);
42 
43  private:
44   friend class
45       base::RefCountedThreadSafe<NonBlockingInvalidationNotifier::Core>;
46   // Called on parent or I/O thread.
47   ~Core();
48 
49   scoped_ptr<InvalidationNotifier> invalidation_notifier_;
50   scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
51   scoped_refptr<ObserverListThreadSafe<SyncNotifierObserver> > observers_;
52   DISALLOW_COPY_AND_ASSIGN(Core);
53 };
54 
Core()55 NonBlockingInvalidationNotifier::Core::Core()
56     : observers_(new ObserverListThreadSafe<SyncNotifierObserver>()) {
57 }
58 
~Core()59 NonBlockingInvalidationNotifier::Core::~Core() {
60 }
61 
Initialize(const notifier::NotifierOptions & notifier_options,const std::string & client_info)62 void NonBlockingInvalidationNotifier::Core::Initialize(
63     const notifier::NotifierOptions& notifier_options,
64     const std::string& client_info) {
65   DCHECK(notifier_options.request_context_getter);
66   DCHECK_EQ(notifier::NOTIFICATION_SERVER,
67             notifier_options.notification_method);
68   io_message_loop_proxy_ = notifier_options.request_context_getter->
69       GetIOMessageLoopProxy();
70   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
71   invalidation_notifier_.reset(
72       new InvalidationNotifier(notifier_options, client_info));
73   invalidation_notifier_->AddObserver(this);
74 }
75 
76 
Teardown()77 void NonBlockingInvalidationNotifier::Core::Teardown() {
78   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
79   invalidation_notifier_->RemoveObserver(this);
80   invalidation_notifier_.reset();
81   io_message_loop_proxy_ = NULL;
82 }
83 
AddObserver(SyncNotifierObserver * observer)84 void NonBlockingInvalidationNotifier::Core::AddObserver(
85     SyncNotifierObserver* observer) {
86   observers_->AddObserver(observer);
87 }
88 
RemoveObserver(SyncNotifierObserver * observer)89 void NonBlockingInvalidationNotifier::Core::RemoveObserver(
90     SyncNotifierObserver* observer) {
91   observers_->RemoveObserver(observer);
92 }
93 
SetState(const std::string & state)94 void NonBlockingInvalidationNotifier::Core::SetState(
95     const std::string& state) {
96   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
97   invalidation_notifier_->SetState(state);
98 }
99 
UpdateCredentials(const std::string & email,const std::string & token)100 void NonBlockingInvalidationNotifier::Core::UpdateCredentials(
101     const std::string& email, const std::string& token) {
102   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
103   invalidation_notifier_->UpdateCredentials(email, token);
104 }
105 
UpdateEnabledTypes(const syncable::ModelTypeSet & types)106 void NonBlockingInvalidationNotifier::Core::UpdateEnabledTypes(
107     const syncable::ModelTypeSet& types) {
108   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
109   invalidation_notifier_->UpdateEnabledTypes(types);
110 }
111 
OnIncomingNotification(const syncable::ModelTypePayloadMap & type_payloads)112 void NonBlockingInvalidationNotifier::Core::OnIncomingNotification(
113         const syncable::ModelTypePayloadMap& type_payloads) {
114   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
115   observers_->Notify(&SyncNotifierObserver::OnIncomingNotification,
116                      type_payloads);
117 }
118 
OnNotificationStateChange(bool notifications_enabled)119 void NonBlockingInvalidationNotifier::Core::OnNotificationStateChange(
120         bool notifications_enabled) {
121   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
122   observers_->Notify(&SyncNotifierObserver::OnNotificationStateChange,
123                      notifications_enabled);
124 }
125 
StoreState(const std::string & state)126 void NonBlockingInvalidationNotifier::Core::StoreState(
127     const std::string& state) {
128   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
129   observers_->Notify(&SyncNotifierObserver::StoreState, state);
130 }
131 
NonBlockingInvalidationNotifier(const notifier::NotifierOptions & notifier_options,const std::string & client_info)132 NonBlockingInvalidationNotifier::NonBlockingInvalidationNotifier(
133     const notifier::NotifierOptions& notifier_options,
134     const std::string& client_info)
135         : core_(new Core),
136           construction_message_loop_proxy_(
137               base::MessageLoopProxy::CreateForCurrentThread()),
138           io_message_loop_proxy_(notifier_options.request_context_getter->
139               GetIOMessageLoopProxy()) {
140   io_message_loop_proxy_->PostTask(
141       FROM_HERE,
142       NewRunnableMethod(
143           core_.get(),
144           &NonBlockingInvalidationNotifier::Core::Initialize,
145           notifier_options, client_info));
146 }
147 
~NonBlockingInvalidationNotifier()148 NonBlockingInvalidationNotifier::~NonBlockingInvalidationNotifier() {
149   DCHECK(construction_message_loop_proxy_->BelongsToCurrentThread());
150   io_message_loop_proxy_->PostTask(
151       FROM_HERE,
152       NewRunnableMethod(
153           core_.get(),
154           &NonBlockingInvalidationNotifier::Core::Teardown));
155 }
156 
AddObserver(SyncNotifierObserver * observer)157 void NonBlockingInvalidationNotifier::AddObserver(
158     SyncNotifierObserver* observer) {
159   CheckOrSetValidThread();
160   core_->AddObserver(observer);
161 }
162 
RemoveObserver(SyncNotifierObserver * observer)163 void NonBlockingInvalidationNotifier::RemoveObserver(
164     SyncNotifierObserver* observer) {
165   CheckOrSetValidThread();
166   core_->RemoveObserver(observer);
167 }
168 
SetState(const std::string & state)169 void NonBlockingInvalidationNotifier::SetState(const std::string& state) {
170   CheckOrSetValidThread();
171   io_message_loop_proxy_->PostTask(
172       FROM_HERE,
173       NewRunnableMethod(
174           core_.get(),
175           &NonBlockingInvalidationNotifier::Core::SetState,
176           state));
177 }
178 
UpdateCredentials(const std::string & email,const std::string & token)179 void NonBlockingInvalidationNotifier::UpdateCredentials(
180     const std::string& email, const std::string& token) {
181   CheckOrSetValidThread();
182   io_message_loop_proxy_->PostTask(
183       FROM_HERE,
184       NewRunnableMethod(
185           core_.get(),
186           &NonBlockingInvalidationNotifier::Core::UpdateCredentials,
187           email, token));
188 }
189 
UpdateEnabledTypes(const syncable::ModelTypeSet & types)190 void NonBlockingInvalidationNotifier::UpdateEnabledTypes(
191     const syncable::ModelTypeSet& types) {
192   CheckOrSetValidThread();
193   io_message_loop_proxy_->PostTask(
194       FROM_HERE,
195       NewRunnableMethod(
196           core_.get(),
197           &NonBlockingInvalidationNotifier::Core::UpdateEnabledTypes,
198           types));
199 }
200 
SendNotification()201 void NonBlockingInvalidationNotifier::SendNotification() {
202   CheckOrSetValidThread();
203   // InvalidationClient doesn't implement SendNotification(), so no
204   // need to forward on the call.
205 }
206 
CheckOrSetValidThread()207 void NonBlockingInvalidationNotifier::CheckOrSetValidThread() {
208   if (method_message_loop_proxy_) {
209     DCHECK(method_message_loop_proxy_->BelongsToCurrentThread());
210   } else {
211     method_message_loop_proxy_ =
212         base::MessageLoopProxy::CreateForCurrentThread();
213   }
214 }
215 
216 }  // namespace sync_notifier
217