OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/services/gcm/gcm_profile_service.h" | 5 #include "chrome/browser/services/gcm/gcm_service.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <utility> |
9 #include <vector> | |
10 | 9 |
11 #include "base/base64.h" | 10 #include "base/bind.h" |
12 #include "base/files/file_path.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/location.h" | |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/path_service.h" | 14 #include "base/sequenced_task_runner.h" |
15 #include "base/prefs/pref_service.h" | |
16 #include "base/strings/string_number_conversions.h" | |
17 #include "base/threading/sequenced_worker_pool.h" | 15 #include "base/threading/sequenced_worker_pool.h" |
18 #include "chrome/browser/chrome_notification_types.h" | |
19 #include "chrome/browser/profiles/profile.h" | |
20 #include "chrome/browser/services/gcm/gcm_app_handler.h" | 16 #include "chrome/browser/services/gcm/gcm_app_handler.h" |
21 #include "chrome/browser/services/gcm/gcm_client_factory.h" | 17 #include "chrome/browser/services/gcm/gcm_client_factory.h" |
22 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" | |
23 #include "chrome/browser/signin/signin_manager_factory.h" | |
24 #include "chrome/common/chrome_constants.h" | |
25 #include "chrome/common/chrome_paths.h" | |
26 #include "chrome/common/chrome_version_info.h" | 18 #include "chrome/common/chrome_version_info.h" |
27 #include "chrome/common/pref_names.h" | |
28 #include "components/signin/core/browser/profile_oauth2_token_service.h" | |
29 #include "components/signin/core/browser/signin_manager.h" | |
30 #include "components/user_prefs/pref_registry_syncable.h" | |
31 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
32 #include "content/public/browser/notification_details.h" | 20 #include "google_apis/gaia/oauth2_token_service.h" |
33 #include "content/public/browser/notification_source.h" | |
34 #include "google_apis/gcm/protocol/android_checkin.pb.h" | 21 #include "google_apis/gcm/protocol/android_checkin.pb.h" |
35 #include "net/url_request/url_request_context_getter.h" | 22 #include "net/url_request/url_request_context_getter.h" |
36 | 23 |
37 namespace gcm { | 24 namespace gcm { |
38 | 25 |
39 namespace { | 26 namespace { |
40 | 27 |
41 checkin_proto::ChromeBuildProto_Platform GetPlatform() { | 28 checkin_proto::ChromeBuildProto_Platform GetPlatform() { |
42 #if defined(OS_WIN) | 29 #if defined(OS_WIN) |
43 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN; | 30 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 return checkin_proto::ChromeBuildProto_Channel_CHANNEL_STABLE; | 62 return checkin_proto::ChromeBuildProto_Channel_CHANNEL_STABLE; |
76 default: | 63 default: |
77 NOTREACHED(); | 64 NOTREACHED(); |
78 return checkin_proto::ChromeBuildProto_Channel_CHANNEL_UNKNOWN; | 65 return checkin_proto::ChromeBuildProto_Channel_CHANNEL_UNKNOWN; |
79 }; | 66 }; |
80 } | 67 } |
81 | 68 |
82 } // namespace | 69 } // namespace |
83 | 70 |
84 // Helper class to save tasks to run until we're ready to execute them. | 71 // Helper class to save tasks to run until we're ready to execute them. |
85 class GCMProfileService::DelayedTaskController { | 72 class GCMService::DelayedTaskController { |
86 public: | 73 public: |
87 DelayedTaskController(); | 74 DelayedTaskController(); |
88 ~DelayedTaskController(); | 75 ~DelayedTaskController(); |
89 | 76 |
90 // Adds a task that will be invoked once we're ready. | 77 // Adds a task that will be invoked once we're ready. |
91 void AddTask(base::Closure task); | 78 void AddTask(const base::Closure& task); |
92 | 79 |
93 // Sets ready status. It is ready only when check-in is completed and | 80 // Sets ready status. It is ready only when check-in is completed and |
94 // the GCMClient is fully initialized. | 81 // the GCMClient is fully initialized. |
95 void SetReady(); | 82 void SetReady(); |
96 | 83 |
97 // Returns true if it is ready to perform tasks. | 84 // Returns true if it is ready to perform tasks. |
98 bool CanRunTaskWithoutDelay() const; | 85 bool CanRunTaskWithoutDelay() const; |
99 | 86 |
100 private: | 87 private: |
101 void RunTasks(); | 88 void RunTasks(); |
102 | 89 |
103 // Flag that indicates that GCM is ready. | 90 // Flag that indicates that GCM is ready. |
104 bool ready_; | 91 bool ready_; |
105 | 92 |
106 std::vector<base::Closure> delayed_tasks_; | 93 std::vector<base::Closure> delayed_tasks_; |
94 | |
95 DISALLOW_COPY_AND_ASSIGN(DelayedTaskController); | |
107 }; | 96 }; |
108 | 97 |
109 GCMProfileService::DelayedTaskController::DelayedTaskController() | 98 GCMService::DelayedTaskController::DelayedTaskController() : ready_(false) { |
110 : ready_(false) { | |
111 } | 99 } |
112 | 100 |
113 GCMProfileService::DelayedTaskController::~DelayedTaskController() { | 101 GCMService::DelayedTaskController::~DelayedTaskController() { |
114 } | 102 } |
115 | 103 |
116 void GCMProfileService::DelayedTaskController::AddTask(base::Closure task) { | 104 void GCMService::DelayedTaskController::AddTask(const base::Closure& task) { |
117 delayed_tasks_.push_back(task); | 105 delayed_tasks_.push_back(task); |
118 } | 106 } |
119 | 107 |
120 void GCMProfileService::DelayedTaskController::SetReady() { | 108 void GCMService::DelayedTaskController::SetReady() { |
121 ready_ = true; | 109 ready_ = true; |
122 RunTasks(); | 110 RunTasks(); |
123 } | 111 } |
124 | 112 |
125 bool GCMProfileService::DelayedTaskController::CanRunTaskWithoutDelay() const { | 113 bool GCMService::DelayedTaskController::CanRunTaskWithoutDelay() const { |
126 return ready_; | 114 return ready_; |
127 } | 115 } |
128 | 116 |
129 void GCMProfileService::DelayedTaskController::RunTasks() { | 117 void GCMService::DelayedTaskController::RunTasks() { |
130 DCHECK(ready_); | 118 DCHECK(ready_); |
131 | 119 |
132 for (size_t i = 0; i < delayed_tasks_.size(); ++i) | 120 for (size_t i = 0; i < delayed_tasks_.size(); ++i) |
133 delayed_tasks_[i].Run(); | 121 delayed_tasks_[i].Run(); |
134 delayed_tasks_.clear(); | 122 delayed_tasks_.clear(); |
135 } | 123 } |
136 | 124 |
137 class GCMProfileService::IOWorker | 125 class GCMService::IOWorker : public GCMClient::Delegate { |
138 : public GCMClient::Delegate, | |
139 public base::RefCountedThreadSafe<GCMProfileService::IOWorker>{ | |
140 public: | 126 public: |
141 // Called on UI thread. | 127 // Called on UI thread. |
142 IOWorker(); | 128 IOWorker(); |
129 virtual ~IOWorker(); | |
143 | 130 |
144 // Overridden from GCMClient::Delegate: | 131 // Overridden from GCMClient::Delegate: |
145 // Called on IO thread. | 132 // Called on IO thread. |
146 virtual void OnRegisterFinished(const std::string& app_id, | 133 virtual void OnRegisterFinished(const std::string& app_id, |
147 const std::string& registration_id, | 134 const std::string& registration_id, |
148 GCMClient::Result result) OVERRIDE; | 135 GCMClient::Result result) OVERRIDE; |
149 virtual void OnUnregisterFinished(const std::string& app_id, | 136 virtual void OnUnregisterFinished(const std::string& app_id, |
150 GCMClient::Result result) OVERRIDE; | 137 GCMClient::Result result) OVERRIDE; |
151 virtual void OnSendFinished(const std::string& app_id, | 138 virtual void OnSendFinished(const std::string& app_id, |
152 const std::string& message_id, | 139 const std::string& message_id, |
153 GCMClient::Result result) OVERRIDE; | 140 GCMClient::Result result) OVERRIDE; |
154 virtual void OnMessageReceived( | 141 virtual void OnMessageReceived( |
155 const std::string& app_id, | 142 const std::string& app_id, |
156 const GCMClient::IncomingMessage& message) OVERRIDE; | 143 const GCMClient::IncomingMessage& message) OVERRIDE; |
157 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE; | 144 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE; |
158 virtual void OnMessageSendError( | 145 virtual void OnMessageSendError( |
159 const std::string& app_id, | 146 const std::string& app_id, |
160 const GCMClient::SendErrorDetails& send_error_details) OVERRIDE; | 147 const GCMClient::SendErrorDetails& send_error_details) OVERRIDE; |
161 virtual void OnGCMReady() OVERRIDE; | 148 virtual void OnGCMReady() OVERRIDE; |
162 | 149 |
163 // Called on IO thread. | 150 // Called on IO thread. |
164 void Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory, | 151 void Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory, |
165 const base::FilePath& store_path, | 152 const base::FilePath& store_path, |
166 const std::vector<std::string>& account_ids, | 153 const std::vector<std::string>& account_ids, |
167 const scoped_refptr<net::URLRequestContextGetter>& | 154 const scoped_refptr<net::URLRequestContextGetter>& |
168 url_request_context_getter); | 155 url_request_context_getter); |
169 void Reset(); | 156 void Reset(); |
170 void Load(const base::WeakPtr<GCMProfileService>& service); | 157 void Load(const base::WeakPtr<GCMService>& service); |
171 void Stop(); | 158 void Stop(); |
172 void CheckOut(); | 159 void CheckOut(); |
173 void Register(const std::string& app_id, | 160 void Register(const std::string& app_id, |
174 const std::vector<std::string>& sender_ids); | 161 const std::vector<std::string>& sender_ids); |
175 void Unregister(const std::string& app_id); | 162 void Unregister(const std::string& app_id); |
176 void Send(const std::string& app_id, | 163 void Send(const std::string& app_id, |
177 const std::string& receiver_id, | 164 const std::string& receiver_id, |
178 const GCMClient::OutgoingMessage& message); | 165 const GCMClient::OutgoingMessage& message); |
179 void RequestGCMStatistics(); | 166 void RequestGCMStatistics(); |
180 | 167 |
181 // For testing purpose. Can be called from UI thread. Use with care. | 168 // For testing purpose. Can be called from UI thread. Use with care. |
182 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); } | 169 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); } |
183 | 170 |
184 private: | 171 private: |
185 friend class base::RefCountedThreadSafe<IOWorker>; | 172 base::WeakPtr<GCMService> service_; |
186 virtual ~IOWorker(); | |
187 | |
188 base::WeakPtr<GCMProfileService> service_; | |
189 | 173 |
190 scoped_ptr<GCMClient> gcm_client_; | 174 scoped_ptr<GCMClient> gcm_client_; |
175 | |
176 DISALLOW_COPY_AND_ASSIGN(IOWorker); | |
191 }; | 177 }; |
192 | 178 |
193 GCMProfileService::IOWorker::IOWorker() { | 179 GCMService::IOWorker::IOWorker() { |
194 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 180 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
195 } | 181 } |
196 | 182 |
197 GCMProfileService::IOWorker::~IOWorker() { | 183 GCMService::IOWorker::~IOWorker() { |
184 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | |
jianli
2014/04/10 20:39:56
I do not think IOWorker can be destructed on IO th
bartfab (slow)
2014/04/11 16:58:52
Since it does work on the IO thread, it must be de
| |
198 } | 185 } |
199 | 186 |
200 void GCMProfileService::IOWorker::Initialize( | 187 void GCMService::IOWorker::Initialize( |
201 scoped_ptr<GCMClientFactory> gcm_client_factory, | 188 scoped_ptr<GCMClientFactory> gcm_client_factory, |
202 const base::FilePath& store_path, | 189 const base::FilePath& store_path, |
203 const std::vector<std::string>& account_ids, | 190 const std::vector<std::string>& account_ids, |
204 const scoped_refptr<net::URLRequestContextGetter>& | 191 const scoped_refptr<net::URLRequestContextGetter>& |
205 url_request_context_getter) { | 192 url_request_context_getter) { |
206 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 193 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
207 | 194 |
208 gcm_client_ = gcm_client_factory->BuildInstance().Pass(); | 195 gcm_client_ = gcm_client_factory->BuildInstance().Pass(); |
209 | 196 |
210 checkin_proto::ChromeBuildProto chrome_build_proto; | 197 checkin_proto::ChromeBuildProto chrome_build_proto; |
211 chrome_build_proto.set_platform(GetPlatform()); | 198 chrome_build_proto.set_platform(GetPlatform()); |
212 chrome_build_proto.set_chrome_version(GetVersion()); | 199 chrome_build_proto.set_chrome_version(GetVersion()); |
213 chrome_build_proto.set_channel(GetChannel()); | 200 chrome_build_proto.set_channel(GetChannel()); |
214 | 201 |
215 scoped_refptr<base::SequencedWorkerPool> worker_pool( | 202 scoped_refptr<base::SequencedWorkerPool> worker_pool( |
216 content::BrowserThread::GetBlockingPool()); | 203 content::BrowserThread::GetBlockingPool()); |
217 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( | 204 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( |
218 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( | 205 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( |
219 worker_pool->GetSequenceToken(), | 206 worker_pool->GetSequenceToken(), |
220 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); | 207 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); |
221 | 208 |
222 gcm_client_->Initialize(chrome_build_proto, | 209 gcm_client_->Initialize(chrome_build_proto, |
223 store_path, | 210 store_path, |
224 account_ids, | 211 account_ids, |
225 blocking_task_runner, | 212 blocking_task_runner, |
226 url_request_context_getter, | 213 url_request_context_getter, |
227 this); | 214 this); |
228 } | 215 } |
229 | 216 |
230 void GCMProfileService::IOWorker::Reset() { | 217 void GCMService::IOWorker::Reset() { |
231 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 218 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
232 | 219 |
233 // GCMClient instance must be destroyed from the same thread where it was | 220 // GCMClient instance must be destroyed from the same thread where it was |
234 // created. | 221 // created. |
235 gcm_client_.reset(); | 222 gcm_client_.reset(); |
236 } | 223 } |
237 | 224 |
238 void GCMProfileService::IOWorker::OnRegisterFinished( | 225 void GCMService::IOWorker::OnRegisterFinished( |
239 const std::string& app_id, | 226 const std::string& app_id, |
240 const std::string& registration_id, | 227 const std::string& registration_id, |
241 GCMClient::Result result) { | 228 GCMClient::Result result) { |
242 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 229 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
243 | 230 |
244 content::BrowserThread::PostTask( | 231 content::BrowserThread::PostTask(content::BrowserThread::UI, |
245 content::BrowserThread::UI, | 232 FROM_HERE, |
246 FROM_HERE, | 233 base::Bind(&GCMService::RegisterFinished, |
247 base::Bind(&GCMProfileService::RegisterFinished, | 234 service_, |
248 service_, | 235 app_id, |
249 app_id, | 236 registration_id, |
250 registration_id, | 237 result)); |
251 result)); | |
252 } | 238 } |
253 | 239 |
254 void GCMProfileService::IOWorker::OnUnregisterFinished( | 240 void GCMService::IOWorker::OnUnregisterFinished(const std::string& app_id, |
255 const std::string& app_id, | 241 GCMClient::Result result) { |
256 GCMClient::Result result) { | |
257 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 242 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
258 | 243 |
259 content::BrowserThread::PostTask( | 244 content::BrowserThread::PostTask( |
260 content::BrowserThread::UI, | 245 content::BrowserThread::UI, |
261 FROM_HERE, | 246 FROM_HERE, |
262 base::Bind( | 247 base::Bind(&GCMService::UnregisterFinished, service_, app_id, result)); |
263 &GCMProfileService::UnregisterFinished, service_, app_id, result)); | |
264 } | 248 } |
265 | 249 |
266 void GCMProfileService::IOWorker::OnSendFinished( | 250 void GCMService::IOWorker::OnSendFinished(const std::string& app_id, |
267 const std::string& app_id, | 251 const std::string& message_id, |
268 const std::string& message_id, | 252 GCMClient::Result result) { |
269 GCMClient::Result result) { | |
270 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 253 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
271 | 254 |
272 content::BrowserThread::PostTask( | 255 content::BrowserThread::PostTask(content::BrowserThread::UI, |
273 content::BrowserThread::UI, | 256 FROM_HERE, |
274 FROM_HERE, | 257 base::Bind(&GCMService::SendFinished, |
275 base::Bind(&GCMProfileService::SendFinished, | 258 service_, |
276 service_, | 259 app_id, |
277 app_id, | 260 message_id, |
278 message_id, | 261 result)); |
279 result)); | |
280 } | 262 } |
281 | 263 |
282 void GCMProfileService::IOWorker::OnMessageReceived( | 264 void GCMService::IOWorker::OnMessageReceived( |
283 const std::string& app_id, | 265 const std::string& app_id, |
284 const GCMClient::IncomingMessage& message) { | 266 const GCMClient::IncomingMessage& message) { |
285 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 267 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
286 | 268 |
287 content::BrowserThread::PostTask( | 269 content::BrowserThread::PostTask(content::BrowserThread::UI, |
288 content::BrowserThread::UI, | 270 FROM_HERE, |
289 FROM_HERE, | 271 base::Bind(&GCMService::MessageReceived, |
290 base::Bind(&GCMProfileService::MessageReceived, | 272 service_, |
291 service_, | 273 app_id, |
292 app_id, | 274 message)); |
293 message)); | |
294 } | 275 } |
295 | 276 |
296 void GCMProfileService::IOWorker::OnMessagesDeleted(const std::string& app_id) { | 277 void GCMService::IOWorker::OnMessagesDeleted(const std::string& app_id) { |
297 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 278 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
298 | 279 |
299 content::BrowserThread::PostTask( | 280 content::BrowserThread::PostTask(content::BrowserThread::UI, |
300 content::BrowserThread::UI, | 281 FROM_HERE, |
301 FROM_HERE, | 282 base::Bind(&GCMService::MessagesDeleted, |
302 base::Bind(&GCMProfileService::MessagesDeleted, | 283 service_, |
303 service_, | 284 app_id)); |
304 app_id)); | |
305 } | 285 } |
306 | 286 |
307 void GCMProfileService::IOWorker::OnMessageSendError( | 287 void GCMService::IOWorker::OnMessageSendError( |
308 const std::string& app_id, | 288 const std::string& app_id, |
309 const GCMClient::SendErrorDetails& send_error_details) { | 289 const GCMClient::SendErrorDetails& send_error_details) { |
310 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 290 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
311 | 291 |
312 content::BrowserThread::PostTask( | 292 content::BrowserThread::PostTask(content::BrowserThread::UI, |
313 content::BrowserThread::UI, | 293 FROM_HERE, |
314 FROM_HERE, | 294 base::Bind(&GCMService::MessageSendError, |
315 base::Bind(&GCMProfileService::MessageSendError, | 295 service_, |
316 service_, | 296 app_id, |
317 app_id, | 297 send_error_details)); |
318 send_error_details)); | |
319 } | 298 } |
320 | 299 |
321 void GCMProfileService::IOWorker::OnGCMReady() { | 300 void GCMService::IOWorker::OnGCMReady() { |
322 content::BrowserThread::PostTask( | 301 content::BrowserThread::PostTask(content::BrowserThread::UI, |
323 content::BrowserThread::UI, | 302 FROM_HERE, |
324 FROM_HERE, | 303 base::Bind(&GCMService::GCMClientReady, |
325 base::Bind(&GCMProfileService::GCMClientReady, | 304 service_)); |
326 service_)); | |
327 } | 305 } |
328 | 306 |
329 void GCMProfileService::IOWorker::Load( | 307 void GCMService::IOWorker::Load(const base::WeakPtr<GCMService>& service) { |
330 const base::WeakPtr<GCMProfileService>& service) { | |
331 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 308 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
332 | 309 |
333 service_ = service; | 310 service_ = service; |
334 gcm_client_->Load(); | 311 gcm_client_->Load(); |
335 } | 312 } |
336 | 313 |
337 void GCMProfileService::IOWorker::Stop() { | 314 void GCMService::IOWorker::Stop() { |
338 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 315 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
339 | 316 |
340 gcm_client_->Stop(); | 317 gcm_client_->Stop(); |
341 } | 318 } |
342 | 319 |
343 void GCMProfileService::IOWorker::CheckOut() { | 320 void GCMService::IOWorker::CheckOut() { |
344 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 321 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
345 | 322 |
346 gcm_client_->CheckOut(); | 323 gcm_client_->CheckOut(); |
347 | 324 |
348 // Note that we still need to keep GCMClient instance alive since the profile | 325 // Note that we still need to keep GCMClient instance alive since the |
349 // might be signed in again. | 326 // GCMService may check in again. |
350 } | 327 } |
351 | 328 |
352 void GCMProfileService::IOWorker::Register( | 329 void GCMService::IOWorker::Register( |
353 const std::string& app_id, | 330 const std::string& app_id, |
354 const std::vector<std::string>& sender_ids) { | 331 const std::vector<std::string>& sender_ids) { |
355 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 332 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
356 | 333 |
357 gcm_client_->Register(app_id, sender_ids); | 334 gcm_client_->Register(app_id, sender_ids); |
358 } | 335 } |
359 | 336 |
360 void GCMProfileService::IOWorker::Unregister(const std::string& app_id) { | 337 void GCMService::IOWorker::Unregister(const std::string& app_id) { |
361 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 338 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
362 | 339 |
363 gcm_client_->Unregister(app_id); | 340 gcm_client_->Unregister(app_id); |
364 } | 341 } |
365 | 342 |
366 void GCMProfileService::IOWorker::Send( | 343 void GCMService::IOWorker::Send(const std::string& app_id, |
367 const std::string& app_id, | 344 const std::string& receiver_id, |
368 const std::string& receiver_id, | 345 const GCMClient::OutgoingMessage& message) { |
369 const GCMClient::OutgoingMessage& message) { | |
370 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 346 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
371 | 347 |
372 gcm_client_->Send(app_id, receiver_id, message); | 348 gcm_client_->Send(app_id, receiver_id, message); |
373 } | 349 } |
374 | 350 |
375 void GCMProfileService::IOWorker::RequestGCMStatistics() { | 351 void GCMService::IOWorker::RequestGCMStatistics() { |
376 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 352 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
377 gcm::GCMClient::GCMStatistics stats; | 353 gcm::GCMClient::GCMStatistics stats; |
378 | 354 |
379 if (gcm_client_.get()) { | 355 if (gcm_client_.get()) { |
380 stats.gcm_client_created = true; | 356 stats.gcm_client_created = true; |
381 stats = gcm_client_->GetStatistics(); | 357 stats = gcm_client_->GetStatistics(); |
382 } | 358 } |
383 | 359 |
384 content::BrowserThread::PostTask( | 360 content::BrowserThread::PostTask( |
385 content::BrowserThread::UI, | 361 content::BrowserThread::UI, |
386 FROM_HERE, | 362 FROM_HERE, |
387 base::Bind(&GCMProfileService::RequestGCMStatisticsFinished, | 363 base::Bind(&GCMService::RequestGCMStatisticsFinished, service_, stats)); |
388 service_, | |
389 stats)); | |
390 } | 364 } |
391 | 365 |
392 std::string GCMProfileService::GetGCMEnabledStateString(GCMEnabledState state) { | 366 GCMService::GCMService( |
393 switch (state) { | 367 scoped_ptr<invalidation::InvalidationAuthProvider> auth_provider, |
394 case GCMProfileService::ALWAYS_ENABLED: | 368 const scoped_refptr<net::URLRequestContextGetter>& request_context, |
395 return "ALWAYS_ENABLED"; | 369 const base::FilePath& store_path) |
396 case GCMProfileService::ENABLED_FOR_APPS: | 370 : auth_provider_(auth_provider.Pass()), |
397 return "ENABLED_FOR_APPS"; | 371 request_context_(request_context), |
398 case GCMProfileService::ALWAYS_DISABLED: | 372 store_path_(store_path), |
399 return "ALWAYS_DISABLED"; | 373 gcm_client_ready_(false), |
400 default: | 374 weak_ptr_factory_(this) { |
401 NOTREACHED(); | |
402 return std::string(); | |
403 } | |
404 } | 375 } |
405 | 376 |
406 // static | 377 GCMService::~GCMService() { |
407 GCMProfileService::GCMEnabledState GCMProfileService::GetGCMEnabledState( | |
408 Profile* profile) { | |
409 const base::Value* gcm_enabled_value = | |
410 profile->GetPrefs()->GetUserPrefValue(prefs::kGCMChannelEnabled); | |
411 if (!gcm_enabled_value) | |
412 return ENABLED_FOR_APPS; | |
413 | |
414 bool gcm_enabled = false; | |
415 if (!gcm_enabled_value->GetAsBoolean(&gcm_enabled)) | |
416 return ENABLED_FOR_APPS; | |
417 | |
418 return gcm_enabled ? ALWAYS_ENABLED : ALWAYS_DISABLED; | |
419 } | 378 } |
420 | 379 |
421 // static | 380 void GCMService::Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory) { |
422 void GCMProfileService::RegisterProfilePrefs( | |
423 user_prefs::PrefRegistrySyncable* registry) { | |
424 // GCM support is only enabled by default for Canary/Dev/Custom builds. | |
425 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); | |
426 bool on_by_default = false; | |
427 if (channel == chrome::VersionInfo::CHANNEL_UNKNOWN || | |
428 channel == chrome::VersionInfo::CHANNEL_CANARY || | |
429 channel == chrome::VersionInfo::CHANNEL_DEV) { | |
430 on_by_default = true; | |
431 } | |
432 registry->RegisterBooleanPref( | |
433 prefs::kGCMChannelEnabled, | |
434 on_by_default, | |
435 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
436 } | |
437 | |
438 GCMProfileService::GCMProfileService(Profile* profile) | |
439 : profile_(profile), | |
440 gcm_client_ready_(false), | |
441 weak_ptr_factory_(this) { | |
442 DCHECK(!profile->IsOffTheRecord()); | |
443 } | |
444 | |
445 GCMProfileService::~GCMProfileService() { | |
446 } | |
447 | |
448 void GCMProfileService::Initialize( | |
449 scoped_ptr<GCMClientFactory> gcm_client_factory) { | |
450 registrar_.Add(this, | |
451 chrome::NOTIFICATION_PROFILE_DESTROYED, | |
452 content::Source<Profile>(profile_)); | |
453 | |
454 SigninManagerFactory::GetForProfile(profile_)->AddObserver(this); | |
455 | |
456 // Get the list of available accounts. | 381 // Get the list of available accounts. |
457 std::vector<std::string> account_ids; | 382 std::vector<std::string> account_ids; |
458 #if !defined(OS_ANDROID) | 383 #if !defined(OS_ANDROID) |
459 account_ids = | 384 account_ids = auth_provider_->GetTokenService()->GetAccounts(); |
460 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->GetAccounts(); | |
461 #endif | 385 #endif |
462 | 386 |
463 // Create and initialize the GCMClient. Note that this does not initiate the | 387 // Create and initialize the GCMClient. Note that this does not initiate the |
464 // GCM check-in. | 388 // GCM check-in. |
465 io_worker_ = new IOWorker(); | 389 DCHECK(!io_worker_); |
466 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter = | 390 io_worker_.reset(new IOWorker()); |
467 profile_->GetRequestContext(); | |
468 content::BrowserThread::PostTask( | 391 content::BrowserThread::PostTask( |
469 content::BrowserThread::IO, | 392 content::BrowserThread::IO, |
470 FROM_HERE, | 393 FROM_HERE, |
471 base::Bind(&GCMProfileService::IOWorker::Initialize, | 394 base::Bind(&GCMService::IOWorker::Initialize, |
472 io_worker_, | 395 base::Unretained(io_worker_.get()), |
473 base::Passed(&gcm_client_factory), | 396 base::Passed(&gcm_client_factory), |
474 profile_->GetPath().Append(chrome::kGCMStoreDirname), | 397 store_path_, |
475 account_ids, | 398 account_ids, |
476 url_request_context_getter)); | 399 request_context_)); |
477 | 400 |
478 // Load from the GCM store and initiate the GCM check-in if the rollout signal | 401 // Load from the GCM store and initiate the GCM check-in if the rollout signal |
479 // indicates yes. | 402 // indicates yes. |
480 if (GetGCMEnabledState(profile_) == ALWAYS_ENABLED) | 403 if (IsAlwaysEnabled()) |
481 EnsureLoaded(); | 404 EnsureLoaded(); |
405 | |
406 auth_provider_->AddObserver(this); | |
482 } | 407 } |
483 | 408 |
484 void GCMProfileService::Start() { | 409 void GCMService::Start() { |
485 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 410 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
486 | 411 |
487 EnsureLoaded(); | 412 EnsureLoaded(); |
488 } | 413 } |
489 | 414 |
490 void GCMProfileService::Stop() { | 415 void GCMService::Stop() { |
491 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 416 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
492 | 417 |
493 // No need to stop GCM service if not started yet. | 418 // No need to stop GCM service if not started yet. |
494 if (username_.empty()) | 419 if (account_id_.empty()) |
495 return; | 420 return; |
496 | 421 |
497 RemoveCachedData(); | 422 RemoveCachedData(); |
498 | 423 |
499 content::BrowserThread::PostTask( | 424 content::BrowserThread::PostTask( |
500 content::BrowserThread::IO, | 425 content::BrowserThread::IO, |
501 FROM_HERE, | 426 FROM_HERE, |
502 base::Bind(&GCMProfileService::IOWorker::Stop, io_worker_)); | 427 base::Bind(&GCMService::IOWorker::Stop, |
428 base::Unretained(io_worker_.get()))); | |
jianli
2014/04/10 20:39:56
base::Unretained should almost never be used in no
bartfab (slow)
2014/04/11 16:58:52
Used correctly, base::Unretained is both useful an
jianli
2014/04/17 00:33:18
I understand this, but it still seems to be danger
bartfab (slow)
2014/04/17 14:20:00
The way to ensure safe and predictable operation i
| |
503 } | 429 } |
504 | 430 |
505 void GCMProfileService::Shutdown() { | 431 void GCMService::Shutdown() { |
432 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
433 auth_provider_->RemoveObserver(this); | |
506 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin(); | 434 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin(); |
507 iter != app_handlers_.end(); ++iter) { | 435 iter != app_handlers_.end(); ++iter) { |
508 iter->second->ShutdownHandler(); | 436 iter->second->ShutdownHandler(); |
509 } | 437 } |
510 app_handlers_.clear(); | 438 app_handlers_.clear(); |
511 | 439 content::BrowserThread::DeleteSoon(content::BrowserThread::IO, |
512 SigninManagerFactory::GetForProfile(profile_)->RemoveObserver(this); | 440 FROM_HERE, |
441 io_worker_.release()); | |
513 } | 442 } |
514 | 443 |
515 void GCMProfileService::AddAppHandler(const std::string& app_id, | 444 void GCMService::AddAppHandler(const std::string& app_id, |
516 GCMAppHandler* handler) { | 445 GCMAppHandler* handler) { |
446 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
517 DCHECK(!app_id.empty()); | 447 DCHECK(!app_id.empty()); |
518 DCHECK(handler); | 448 DCHECK(handler); |
519 DCHECK(app_handlers_.find(app_id) == app_handlers_.end()); | 449 DCHECK(app_handlers_.find(app_id) == app_handlers_.end()); |
520 | 450 |
521 app_handlers_[app_id] = handler; | 451 app_handlers_[app_id] = handler; |
522 } | 452 } |
523 | 453 |
524 void GCMProfileService::RemoveAppHandler(const std::string& app_id) { | 454 void GCMService::RemoveAppHandler(const std::string& app_id) { |
455 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
525 DCHECK(!app_id.empty()); | 456 DCHECK(!app_id.empty()); |
526 | 457 |
527 app_handlers_.erase(app_id); | 458 app_handlers_.erase(app_id); |
528 } | 459 } |
529 | 460 |
530 void GCMProfileService::Register(const std::string& app_id, | 461 void GCMService::Register(const std::string& app_id, |
531 const std::vector<std::string>& sender_ids, | 462 const std::vector<std::string>& sender_ids, |
532 RegisterCallback callback) { | 463 RegisterCallback callback) { |
533 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 464 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
534 DCHECK(!app_id.empty() && !sender_ids.empty() && !callback.is_null()); | 465 DCHECK(!app_id.empty()); |
466 DCHECK(!sender_ids.empty()); | |
467 DCHECK(!callback.is_null()); | |
535 | 468 |
536 GCMClient::Result result = EnsureAppReady(app_id); | 469 GCMClient::Result result = EnsureAppReady(app_id); |
537 if (result != GCMClient::SUCCESS) { | 470 if (result != GCMClient::SUCCESS) { |
538 callback.Run(std::string(), result); | 471 callback.Run(std::string(), result); |
539 return; | 472 return; |
540 } | 473 } |
541 | 474 |
542 // If previous un/register operation is still in progress, bail out. | 475 // If previous un/register operation is still in progress, bail out. |
543 if (IsAsyncOperationPending(app_id)) { | 476 if (IsAsyncOperationPending(app_id)) { |
544 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); | 477 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); |
545 return; | 478 return; |
546 } | 479 } |
547 | 480 |
548 register_callbacks_[app_id] = callback; | 481 register_callbacks_[app_id] = callback; |
549 | 482 |
550 // Delay the register operation until GCMClient is ready. | 483 // Delay the register operation until GCMClient is ready. |
551 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { | 484 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { |
552 delayed_task_controller_->AddTask( | 485 delayed_task_controller_->AddTask(base::Bind(&GCMService::DoRegister, |
553 base::Bind(&GCMProfileService::DoRegister, | 486 weak_ptr_factory_.GetWeakPtr(), |
554 weak_ptr_factory_.GetWeakPtr(), | 487 app_id, |
555 app_id, | 488 sender_ids)); |
556 sender_ids)); | |
557 return; | 489 return; |
558 } | 490 } |
559 | 491 |
560 DoRegister(app_id, sender_ids); | 492 DoRegister(app_id, sender_ids); |
561 } | 493 } |
562 | 494 |
563 void GCMProfileService::DoRegister(const std::string& app_id, | 495 void GCMService::DoRegister(const std::string& app_id, |
564 const std::vector<std::string>& sender_ids) { | 496 const std::vector<std::string>& sender_ids) { |
497 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
565 std::map<std::string, RegisterCallback>::iterator callback_iter = | 498 std::map<std::string, RegisterCallback>::iterator callback_iter = |
566 register_callbacks_.find(app_id); | 499 register_callbacks_.find(app_id); |
567 if (callback_iter == register_callbacks_.end()) { | 500 if (callback_iter == register_callbacks_.end()) { |
568 // The callback could have been removed when the app is uninstalled. | 501 // The callback could have been removed when the app is uninstalled. |
569 return; | 502 return; |
570 } | 503 } |
571 | 504 |
572 // Normalize the sender IDs by making them sorted. | 505 // Normalize the sender IDs by making them sorted. |
573 std::vector<std::string> normalized_sender_ids = sender_ids; | 506 std::vector<std::string> normalized_sender_ids = sender_ids; |
574 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end()); | 507 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end()); |
575 | 508 |
576 content::BrowserThread::PostTask( | 509 content::BrowserThread::PostTask( |
577 content::BrowserThread::IO, | 510 content::BrowserThread::IO, |
578 FROM_HERE, | 511 FROM_HERE, |
579 base::Bind(&GCMProfileService::IOWorker::Register, | 512 base::Bind(&GCMService::IOWorker::Register, |
580 io_worker_, | 513 base::Unretained(io_worker_.get()), |
581 app_id, | 514 app_id, |
582 normalized_sender_ids)); | 515 normalized_sender_ids)); |
583 } | 516 } |
584 | 517 |
585 void GCMProfileService::Unregister(const std::string& app_id, | 518 void GCMService::Unregister(const std::string& app_id, |
586 UnregisterCallback callback) { | 519 UnregisterCallback callback) { |
587 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 520 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
588 DCHECK(!app_id.empty() && !callback.is_null()); | 521 DCHECK(!app_id.empty()); |
522 DCHECK(!callback.is_null()); | |
589 | 523 |
590 GCMClient::Result result = EnsureAppReady(app_id); | 524 GCMClient::Result result = EnsureAppReady(app_id); |
591 if (result != GCMClient::SUCCESS) { | 525 if (result != GCMClient::SUCCESS) { |
592 callback.Run(result); | 526 callback.Run(result); |
593 return; | 527 return; |
594 } | 528 } |
595 | 529 |
596 // If previous un/register operation is still in progress, bail out. | 530 // If previous un/register operation is still in progress, bail out. |
597 if (IsAsyncOperationPending(app_id)) { | 531 if (IsAsyncOperationPending(app_id)) { |
598 callback.Run(GCMClient::ASYNC_OPERATION_PENDING); | 532 callback.Run(GCMClient::ASYNC_OPERATION_PENDING); |
599 return; | 533 return; |
600 } | 534 } |
601 | 535 |
602 unregister_callbacks_[app_id] = callback; | 536 unregister_callbacks_[app_id] = callback; |
603 | 537 |
604 // Delay the unregister operation until GCMClient is ready. | 538 // Delay the unregister operation until GCMClient is ready. |
605 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { | 539 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { |
606 delayed_task_controller_->AddTask( | 540 delayed_task_controller_->AddTask(base::Bind(&GCMService::DoUnregister, |
607 base::Bind(&GCMProfileService::DoUnregister, | 541 weak_ptr_factory_.GetWeakPtr(), |
608 weak_ptr_factory_.GetWeakPtr(), | 542 app_id)); |
609 app_id)); | |
610 return; | 543 return; |
611 } | 544 } |
612 | 545 |
613 DoUnregister(app_id); | 546 DoUnregister(app_id); |
614 } | 547 } |
615 | 548 |
616 void GCMProfileService::DoUnregister(const std::string& app_id) { | 549 void GCMService::DoUnregister(const std::string& app_id) { |
617 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 550 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
618 | 551 |
619 // Ask the server to unregister it. There could be a small chance that the | 552 // Ask the server to unregister it. There could be a small chance that the |
620 // unregister request fails. If this occurs, it does not bring any harm since | 553 // unregister request fails. If this occurs, it does not bring any harm since |
621 // we simply reject the messages/events received from the server. | 554 // we simply reject the messages/events received from the server. |
622 content::BrowserThread::PostTask( | 555 content::BrowserThread::PostTask( |
623 content::BrowserThread::IO, | 556 content::BrowserThread::IO, |
624 FROM_HERE, | 557 FROM_HERE, |
625 base::Bind(&GCMProfileService::IOWorker::Unregister, | 558 base::Bind(&GCMService::IOWorker::Unregister, |
626 io_worker_, | 559 base::Unretained(io_worker_.get()), |
627 app_id)); | 560 app_id)); |
628 } | 561 } |
629 | 562 |
630 void GCMProfileService::Send(const std::string& app_id, | 563 void GCMService::Send(const std::string& app_id, |
631 const std::string& receiver_id, | 564 const std::string& receiver_id, |
632 const GCMClient::OutgoingMessage& message, | 565 const GCMClient::OutgoingMessage& message, |
633 SendCallback callback) { | 566 SendCallback callback) { |
634 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 567 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
635 DCHECK(!app_id.empty() && !receiver_id.empty() && !callback.is_null()); | 568 DCHECK(!app_id.empty()); |
569 DCHECK(!receiver_id.empty()); | |
570 DCHECK(!callback.is_null()); | |
636 | 571 |
637 GCMClient::Result result = EnsureAppReady(app_id); | 572 GCMClient::Result result = EnsureAppReady(app_id); |
638 if (result != GCMClient::SUCCESS) { | 573 if (result != GCMClient::SUCCESS) { |
639 callback.Run(std::string(), result); | 574 callback.Run(std::string(), result); |
640 return; | 575 return; |
641 } | 576 } |
642 | 577 |
643 // If the message with send ID is still in progress, bail out. | 578 // If the message with send ID is still in progress, bail out. |
644 std::pair<std::string, std::string> key(app_id, message.id); | 579 std::pair<std::string, std::string> key(app_id, message.id); |
645 if (send_callbacks_.find(key) != send_callbacks_.end()) { | 580 if (send_callbacks_.find(key) != send_callbacks_.end()) { |
646 callback.Run(message.id, GCMClient::INVALID_PARAMETER); | 581 callback.Run(message.id, GCMClient::INVALID_PARAMETER); |
647 return; | 582 return; |
648 } | 583 } |
649 | 584 |
650 send_callbacks_[key] = callback; | 585 send_callbacks_[key] = callback; |
651 | 586 |
652 // Delay the send operation until all GCMClient is ready. | 587 // Delay the send operation until all GCMClient is ready. |
653 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { | 588 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { |
654 delayed_task_controller_->AddTask( | 589 delayed_task_controller_->AddTask(base::Bind(&GCMService::DoSend, |
655 base::Bind(&GCMProfileService::DoSend, | 590 weak_ptr_factory_.GetWeakPtr(), |
656 weak_ptr_factory_.GetWeakPtr(), | 591 app_id, |
657 app_id, | 592 receiver_id, |
658 receiver_id, | 593 message)); |
659 message)); | |
660 return; | 594 return; |
661 } | 595 } |
662 | 596 |
663 DoSend(app_id, receiver_id, message); | 597 DoSend(app_id, receiver_id, message); |
664 } | 598 } |
665 | 599 |
666 void GCMProfileService::DoSend(const std::string& app_id, | 600 void GCMService::DoSend(const std::string& app_id, |
667 const std::string& receiver_id, | 601 const std::string& receiver_id, |
668 const GCMClient::OutgoingMessage& message) { | 602 const GCMClient::OutgoingMessage& message) { |
603 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
669 content::BrowserThread::PostTask( | 604 content::BrowserThread::PostTask( |
670 content::BrowserThread::IO, | 605 content::BrowserThread::IO, |
671 FROM_HERE, | 606 FROM_HERE, |
672 base::Bind(&GCMProfileService::IOWorker::Send, | 607 base::Bind(&GCMService::IOWorker::Send, |
673 io_worker_, | 608 base::Unretained(io_worker_.get()), |
674 app_id, | 609 app_id, |
675 receiver_id, | 610 receiver_id, |
676 message)); | 611 message)); |
677 } | 612 } |
678 | 613 |
679 GCMClient* GCMProfileService::GetGCMClientForTesting() const { | 614 GCMClient* GCMService::GetGCMClientForTesting() const { |
615 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
680 return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL; | 616 return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL; |
681 } | 617 } |
682 | 618 |
683 std::string GCMProfileService::SignedInUserName() const { | 619 bool GCMService::IsStarted() const { |
684 return username_; | 620 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
621 return !account_id_.empty(); | |
685 } | 622 } |
686 | 623 |
687 bool GCMProfileService::IsGCMClientReady() const { | 624 bool GCMService::IsGCMClientReady() const { |
625 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
688 return gcm_client_ready_; | 626 return gcm_client_ready_; |
689 } | 627 } |
690 | 628 |
691 void GCMProfileService::RequestGCMStatistics( | 629 void GCMService::RequestGCMStatistics(RequestGCMStatisticsCallback callback) { |
692 RequestGCMStatisticsCallback callback) { | |
693 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 630 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
694 DCHECK(!callback.is_null()); | 631 DCHECK(!callback.is_null()); |
695 | 632 |
696 request_gcm_statistics_callback_ = callback; | 633 request_gcm_statistics_callback_ = callback; |
697 content::BrowserThread::PostTask( | 634 content::BrowserThread::PostTask( |
698 content::BrowserThread::IO, | 635 content::BrowserThread::IO, |
699 FROM_HERE, | 636 FROM_HERE, |
700 base::Bind(&GCMProfileService::IOWorker::RequestGCMStatistics, | 637 base::Bind(&GCMService::IOWorker::RequestGCMStatistics, |
701 io_worker_)); | 638 base::Unretained(io_worker_.get()))); |
702 } | 639 } |
703 | 640 |
704 void GCMProfileService::Observe(int type, | 641 void GCMService::OnInvalidationAuthLogin() { |
705 const content::NotificationSource& source, | 642 if (IsAlwaysEnabled()) |
706 const content::NotificationDetails& details) { | |
707 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
708 | |
709 switch (type) { | |
710 case chrome::NOTIFICATION_PROFILE_DESTROYED: | |
711 ResetGCMClient(); | |
712 break; | |
713 default: | |
714 NOTREACHED(); | |
715 } | |
716 } | |
717 | |
718 void GCMProfileService::GoogleSigninSucceeded(const std::string& username, | |
719 const std::string& password) { | |
720 if (GetGCMEnabledState(profile_) == ALWAYS_ENABLED) | |
721 EnsureLoaded(); | 643 EnsureLoaded(); |
722 } | 644 } |
723 | 645 |
724 void GCMProfileService::GoogleSignedOut(const std::string& username) { | 646 void GCMService::OnInvalidationAuthLogout() { |
725 CheckOut(); | 647 CheckOut(); |
726 } | 648 } |
727 | 649 |
728 void GCMProfileService::EnsureLoaded() { | 650 void GCMService::ResetGCMClient() { |
729 SigninManagerBase* manager = SigninManagerFactory::GetForProfile(profile_); | 651 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
730 if (!manager) | 652 content::BrowserThread::PostTask( |
731 return; | 653 content::BrowserThread::IO, |
732 std::string username = manager->GetAuthenticatedUsername(); | 654 FROM_HERE, |
733 if (username.empty()) | 655 base::Bind(&GCMService::IOWorker::Reset, |
656 base::Unretained(io_worker_.get()))); | |
657 } | |
658 | |
659 void GCMService::EnsureLoaded() { | |
660 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
661 std::string account_id = auth_provider_->GetAccountId(); | |
662 if (account_id.empty()) | |
734 return; | 663 return; |
735 | 664 |
736 // CheckIn could be called more than once when: | 665 // CheckIn could be called more than once when: |
737 // 1) The password changes. | 666 // 1) The password changes. |
738 // 2) Register/send function calls it to ensure CheckIn is done. | 667 // 2) Register/send function calls it to ensure CheckIn is done. |
739 if (username_ == username) | 668 if (account_id_ == account_id) |
740 return; | 669 return; |
741 username_ = username; | 670 account_id_ = account_id; |
742 | 671 |
743 DCHECK(!delayed_task_controller_); | 672 DCHECK(!delayed_task_controller_); |
744 delayed_task_controller_.reset(new DelayedTaskController); | 673 delayed_task_controller_.reset(new DelayedTaskController); |
745 | 674 |
746 // This will load the data from the gcm store and trigger the check-in if | 675 // This will load the data from the gcm store and trigger the check-in if |
747 // the persisted check-in info is not found. | 676 // the persisted check-in info is not found. |
748 // Note that we need to pass weak pointer again since the existing weak | 677 // Note that we need to pass weak pointer again since the existing weak |
749 // pointer in IOWorker might have been invalidated when check-out occurs. | 678 // pointer in IOWorker might have been invalidated when check-out occurs. |
750 content::BrowserThread::PostTask( | 679 content::BrowserThread::PostTask( |
751 content::BrowserThread::IO, | 680 content::BrowserThread::IO, |
752 FROM_HERE, | 681 FROM_HERE, |
753 base::Bind(&GCMProfileService::IOWorker::Load, | 682 base::Bind(&GCMService::IOWorker::Load, |
754 io_worker_, | 683 base::Unretained(io_worker_.get()), |
755 weak_ptr_factory_.GetWeakPtr())); | 684 weak_ptr_factory_.GetWeakPtr())); |
756 } | 685 } |
757 | 686 |
758 void GCMProfileService::RemoveCachedData() { | 687 void GCMService::RemoveCachedData() { |
688 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
759 // Remove all the queued tasks since they no longer make sense after | 689 // Remove all the queued tasks since they no longer make sense after |
760 // GCM service is stopped. | 690 // GCM service is stopped. |
761 weak_ptr_factory_.InvalidateWeakPtrs(); | 691 weak_ptr_factory_.InvalidateWeakPtrs(); |
762 | 692 |
763 username_.clear(); | 693 account_id_.clear(); |
764 gcm_client_ready_ = false; | 694 gcm_client_ready_ = false; |
765 delayed_task_controller_.reset(); | 695 delayed_task_controller_.reset(); |
766 register_callbacks_.clear(); | 696 register_callbacks_.clear(); |
767 send_callbacks_.clear(); | 697 send_callbacks_.clear(); |
768 } | 698 } |
769 | 699 |
770 void GCMProfileService::CheckOut() { | 700 void GCMService::CheckOut() { |
771 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 701 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
772 | 702 |
773 // We still proceed with the check-out logic even if the check-in is not | 703 // We still proceed with the check-out logic even if the check-in is not |
774 // initiated in the current session. This will make sure that all the | 704 // initiated in the current session. This will make sure that all the |
775 // persisted data written previously will get purged. | 705 // persisted data written previously will get purged. |
776 | 706 |
777 RemoveCachedData(); | 707 RemoveCachedData(); |
778 | 708 |
779 content::BrowserThread::PostTask( | 709 content::BrowserThread::PostTask( |
780 content::BrowserThread::IO, | 710 content::BrowserThread::IO, |
781 FROM_HERE, | 711 FROM_HERE, |
782 base::Bind(&GCMProfileService::IOWorker::CheckOut, io_worker_)); | 712 base::Bind(&GCMService::IOWorker::CheckOut, |
713 base::Unretained(io_worker_.get()))); | |
783 } | 714 } |
784 | 715 |
785 void GCMProfileService::ResetGCMClient() { | 716 GCMClient::Result GCMService::EnsureAppReady(const std::string& app_id) { |
786 content::BrowserThread::PostTask( | 717 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
787 content::BrowserThread::IO, | |
788 FROM_HERE, | |
789 base::Bind(&GCMProfileService::IOWorker::Reset, io_worker_)); | |
790 } | |
791 | |
792 GCMClient::Result GCMProfileService::EnsureAppReady(const std::string& app_id) { | |
793 // Ensure that check-in has been done. | 718 // Ensure that check-in has been done. |
794 EnsureLoaded(); | 719 EnsureLoaded(); |
795 | 720 |
796 // If the profile was not signed in, bail out. | 721 // If the service was not started, bail out. |
797 if (username_.empty()) | 722 if (account_id_.empty()) |
798 return GCMClient::NOT_SIGNED_IN; | 723 return GCMClient::NOT_SIGNED_IN; |
799 | 724 |
800 return GCMClient::SUCCESS; | 725 return GCMClient::SUCCESS; |
801 } | 726 } |
802 | 727 |
803 bool GCMProfileService::IsAsyncOperationPending( | 728 bool GCMService::IsAsyncOperationPending(const std::string& app_id) const { |
804 const std::string& app_id) const { | 729 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
805 return register_callbacks_.find(app_id) != register_callbacks_.end() || | 730 return register_callbacks_.find(app_id) != register_callbacks_.end() || |
806 unregister_callbacks_.find(app_id) != unregister_callbacks_.end(); | 731 unregister_callbacks_.find(app_id) != unregister_callbacks_.end(); |
807 } | 732 } |
808 | 733 |
809 void GCMProfileService::RegisterFinished(const std::string& app_id, | 734 void GCMService::RegisterFinished(const std::string& app_id, |
810 const std::string& registration_id, | 735 const std::string& registration_id, |
811 GCMClient::Result result) { | 736 GCMClient::Result result) { |
812 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 737 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
813 | 738 |
814 std::map<std::string, RegisterCallback>::iterator callback_iter = | 739 std::map<std::string, RegisterCallback>::iterator callback_iter = |
815 register_callbacks_.find(app_id); | 740 register_callbacks_.find(app_id); |
816 if (callback_iter == register_callbacks_.end()) { | 741 if (callback_iter == register_callbacks_.end()) { |
817 // The callback could have been removed when the app is uninstalled. | 742 // The callback could have been removed when the app is uninstalled. |
818 return; | 743 return; |
819 } | 744 } |
820 | 745 |
821 RegisterCallback callback = callback_iter->second; | 746 RegisterCallback callback = callback_iter->second; |
822 register_callbacks_.erase(callback_iter); | 747 register_callbacks_.erase(callback_iter); |
823 callback.Run(registration_id, result); | 748 callback.Run(registration_id, result); |
824 } | 749 } |
825 | 750 |
826 void GCMProfileService::UnregisterFinished(const std::string& app_id, | 751 void GCMService::UnregisterFinished(const std::string& app_id, |
827 GCMClient::Result result) { | 752 GCMClient::Result result) { |
828 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 753 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
829 | 754 |
830 std::map<std::string, UnregisterCallback>::iterator callback_iter = | 755 std::map<std::string, UnregisterCallback>::iterator callback_iter = |
831 unregister_callbacks_.find(app_id); | 756 unregister_callbacks_.find(app_id); |
832 if (callback_iter == unregister_callbacks_.end()) | 757 if (callback_iter == unregister_callbacks_.end()) |
833 return; | 758 return; |
834 | 759 |
835 UnregisterCallback callback = callback_iter->second; | 760 UnregisterCallback callback = callback_iter->second; |
836 unregister_callbacks_.erase(callback_iter); | 761 unregister_callbacks_.erase(callback_iter); |
837 callback.Run(result); | 762 callback.Run(result); |
838 } | 763 } |
839 | 764 |
840 void GCMProfileService::SendFinished(const std::string& app_id, | 765 void GCMService::SendFinished(const std::string& app_id, |
841 const std::string& message_id, | 766 const std::string& message_id, |
842 GCMClient::Result result) { | 767 GCMClient::Result result) { |
843 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 768 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
844 | 769 |
845 std::map<std::pair<std::string, std::string>, SendCallback>::iterator | 770 std::map<std::pair<std::string, std::string>, SendCallback>::iterator |
846 callback_iter = send_callbacks_.find( | 771 callback_iter = send_callbacks_.find( |
847 std::pair<std::string, std::string>(app_id, message_id)); | 772 std::pair<std::string, std::string>(app_id, message_id)); |
848 if (callback_iter == send_callbacks_.end()) { | 773 if (callback_iter == send_callbacks_.end()) { |
849 // The callback could have been removed when the app is uninstalled. | 774 // The callback could have been removed when the app is uninstalled. |
850 return; | 775 return; |
851 } | 776 } |
852 | 777 |
853 SendCallback callback = callback_iter->second; | 778 SendCallback callback = callback_iter->second; |
854 send_callbacks_.erase(callback_iter); | 779 send_callbacks_.erase(callback_iter); |
855 callback.Run(message_id, result); | 780 callback.Run(message_id, result); |
856 } | 781 } |
857 | 782 |
858 void GCMProfileService::MessageReceived(const std::string& app_id, | 783 void GCMService::MessageReceived(const std::string& app_id, |
859 GCMClient::IncomingMessage message) { | 784 GCMClient::IncomingMessage message) { |
860 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 785 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
861 | 786 |
862 // Drop the event if signed out. | 787 // Drop the event if signed out. |
863 if (username_.empty()) | 788 if (account_id_.empty()) |
864 return; | 789 return; |
865 | 790 |
866 GetAppHandler(app_id)->OnMessage(app_id, message); | 791 GetAppHandler(app_id)->OnMessage(app_id, message); |
867 } | 792 } |
868 | 793 |
869 void GCMProfileService::MessagesDeleted(const std::string& app_id) { | 794 void GCMService::MessagesDeleted(const std::string& app_id) { |
870 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 795 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
871 | 796 |
872 // Drop the event if signed out. | 797 // Drop the event if signed out. |
873 if (username_.empty()) | 798 if (account_id_.empty()) |
874 return; | 799 return; |
875 | 800 |
876 GetAppHandler(app_id)->OnMessagesDeleted(app_id); | 801 GetAppHandler(app_id)->OnMessagesDeleted(app_id); |
877 } | 802 } |
878 | 803 |
879 void GCMProfileService::MessageSendError( | 804 void GCMService::MessageSendError( |
880 const std::string& app_id, | 805 const std::string& app_id, |
881 const GCMClient::SendErrorDetails& send_error_details) { | 806 const GCMClient::SendErrorDetails& send_error_details) { |
882 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 807 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
883 | 808 |
884 // Drop the event if signed out. | 809 // Drop the event if signed out. |
885 if (username_.empty()) | 810 if (account_id_.empty()) |
886 return; | 811 return; |
887 | 812 |
888 GetAppHandler(app_id)->OnSendError(app_id, send_error_details); | 813 GetAppHandler(app_id)->OnSendError(app_id, send_error_details); |
889 } | 814 } |
890 | 815 |
891 void GCMProfileService::GCMClientReady() { | 816 void GCMService::GCMClientReady() { |
892 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 817 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
893 | 818 |
894 if (gcm_client_ready_) | 819 if (gcm_client_ready_) |
895 return; | 820 return; |
896 gcm_client_ready_ = true; | 821 gcm_client_ready_ = true; |
897 | 822 |
898 delayed_task_controller_->SetReady(); | 823 delayed_task_controller_->SetReady(); |
899 } | 824 } |
900 | 825 |
901 GCMAppHandler* GCMProfileService::GetAppHandler(const std::string& app_id) { | 826 GCMAppHandler* GCMService::GetAppHandler(const std::string& app_id) { |
827 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
828 | |
902 std::map<std::string, GCMAppHandler*>::const_iterator iter = | 829 std::map<std::string, GCMAppHandler*>::const_iterator iter = |
903 app_handlers_.find(app_id); | 830 app_handlers_.find(app_id); |
904 return iter == app_handlers_.end() ? &default_app_handler_ : iter->second; | 831 return iter == app_handlers_.end() ? &default_app_handler_ : iter->second; |
905 } | 832 } |
906 | 833 |
907 void GCMProfileService::RequestGCMStatisticsFinished( | 834 void GCMService::RequestGCMStatisticsFinished( |
908 GCMClient::GCMStatistics stats) { | 835 GCMClient::GCMStatistics stats) { |
909 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 836 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
910 | 837 |
911 request_gcm_statistics_callback_.Run(stats); | 838 request_gcm_statistics_callback_.Run(stats); |
912 } | 839 } |
913 | 840 |
914 } // namespace gcm | 841 } // namespace gcm |
OLD | NEW |