Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1188)

Side by Side Diff: chrome/browser/services/gcm/gcm_driver.cc

Issue 290013011: Move all remaining files to gcm_driver component (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/services/gcm/gcm_driver.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/threading/sequenced_worker_pool.h"
16 #include "chrome/common/chrome_version_info.h"
17 #include "components/gcm_driver/gcm_app_handler.h"
18 #include "components/gcm_driver/gcm_client_factory.h"
19 #include "components/gcm_driver/system_encryptor.h"
20 #include "google_apis/gaia/oauth2_token_service.h"
21 #include "net/url_request/url_request_context_getter.h"
22
23 namespace gcm {
24
25 // Helper class to save tasks to run until we're ready to execute them.
26 class GCMDriver::DelayedTaskController {
27 public:
28 DelayedTaskController();
29 ~DelayedTaskController();
30
31 // Adds a task that will be invoked once we're ready.
32 void AddTask(const base::Closure& task);
33
34 // Sets ready status. It is ready only when check-in is completed and
35 // the GCMClient is fully initialized.
36 void SetReady();
37
38 // Returns true if it is ready to perform tasks.
39 bool CanRunTaskWithoutDelay() const;
40
41 private:
42 void RunTasks();
43
44 // Flag that indicates that GCM is ready.
45 bool ready_;
46
47 std::vector<base::Closure> delayed_tasks_;
48
49 DISALLOW_COPY_AND_ASSIGN(DelayedTaskController);
50 };
51
52 GCMDriver::DelayedTaskController::DelayedTaskController() : ready_(false) {
53 }
54
55 GCMDriver::DelayedTaskController::~DelayedTaskController() {
56 }
57
58 void GCMDriver::DelayedTaskController::AddTask(const base::Closure& task) {
59 delayed_tasks_.push_back(task);
60 }
61
62 void GCMDriver::DelayedTaskController::SetReady() {
63 ready_ = true;
64 RunTasks();
65 }
66
67 bool GCMDriver::DelayedTaskController::CanRunTaskWithoutDelay() const {
68 return ready_;
69 }
70
71 void GCMDriver::DelayedTaskController::RunTasks() {
72 DCHECK(ready_);
73
74 for (size_t i = 0; i < delayed_tasks_.size(); ++i)
75 delayed_tasks_[i].Run();
76 delayed_tasks_.clear();
77 }
78
79 class GCMDriver::IOWorker : public GCMClient::Delegate {
80 public:
81 // Called on UI thread.
82 IOWorker(const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
83 const scoped_refptr<base::SequencedTaskRunner>& io_thread);
84 virtual ~IOWorker();
85
86 // Overridden from GCMClient::Delegate:
87 // Called on IO thread.
88 virtual void OnRegisterFinished(const std::string& app_id,
89 const std::string& registration_id,
90 GCMClient::Result result) OVERRIDE;
91 virtual void OnUnregisterFinished(const std::string& app_id,
92 GCMClient::Result result) OVERRIDE;
93 virtual void OnSendFinished(const std::string& app_id,
94 const std::string& message_id,
95 GCMClient::Result result) OVERRIDE;
96 virtual void OnMessageReceived(
97 const std::string& app_id,
98 const GCMClient::IncomingMessage& message) OVERRIDE;
99 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
100 virtual void OnMessageSendError(
101 const std::string& app_id,
102 const GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
103 virtual void OnGCMReady() OVERRIDE;
104 virtual void OnActivityRecorded() OVERRIDE;
105
106 // Called on IO thread.
107 void Initialize(
108 scoped_ptr<GCMClientFactory> gcm_client_factory,
109 const GCMClient::ChromeBuildInfo& chrome_build_info,
110 const base::FilePath& store_path,
111 const std::vector<std::string>& account_ids,
112 const scoped_refptr<net::URLRequestContextGetter>& request_context,
113 const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
114 void Start(const base::WeakPtr<GCMDriver>& service);
115 void Stop();
116 void CheckOut();
117 void Register(const std::string& app_id,
118 const std::vector<std::string>& sender_ids);
119 void Unregister(const std::string& app_id);
120 void Send(const std::string& app_id,
121 const std::string& receiver_id,
122 const GCMClient::OutgoingMessage& message);
123 void GetGCMStatistics(bool clear_logs);
124 void SetGCMRecording(bool recording);
125
126 // For testing purpose. Can be called from UI thread. Use with care.
127 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); }
128
129 private:
130 scoped_refptr<base::SequencedTaskRunner> ui_thread_;
131 scoped_refptr<base::SequencedTaskRunner> io_thread_;
132
133 base::WeakPtr<GCMDriver> service_;
134
135 scoped_ptr<GCMClient> gcm_client_;
136
137 DISALLOW_COPY_AND_ASSIGN(IOWorker);
138 };
139
140 GCMDriver::IOWorker::IOWorker(
141 const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
142 const scoped_refptr<base::SequencedTaskRunner>& io_thread)
143 : ui_thread_(ui_thread),
144 io_thread_(io_thread) {
145 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
146 }
147
148 GCMDriver::IOWorker::~IOWorker() {
149 DCHECK(io_thread_->RunsTasksOnCurrentThread());
150 }
151
152 void GCMDriver::IOWorker::Initialize(
153 scoped_ptr<GCMClientFactory> gcm_client_factory,
154 const GCMClient::ChromeBuildInfo& chrome_build_info,
155 const base::FilePath& store_path,
156 const std::vector<std::string>& account_ids,
157 const scoped_refptr<net::URLRequestContextGetter>& request_context,
158 const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
159 DCHECK(io_thread_->RunsTasksOnCurrentThread());
160
161 gcm_client_ = gcm_client_factory->BuildInstance();
162
163 gcm_client_->Initialize(chrome_build_info,
164 store_path,
165 account_ids,
166 blocking_task_runner,
167 request_context,
168 make_scoped_ptr<Encryptor>(new SystemEncryptor),
169 this);
170 }
171
172 void GCMDriver::IOWorker::OnRegisterFinished(
173 const std::string& app_id,
174 const std::string& registration_id,
175 GCMClient::Result result) {
176 DCHECK(io_thread_->RunsTasksOnCurrentThread());
177
178 ui_thread_->PostTask(
179 FROM_HERE,
180 base::Bind(&GCMDriver::RegisterFinished, service_, app_id,
181 registration_id, result));
182 }
183
184 void GCMDriver::IOWorker::OnUnregisterFinished(const std::string& app_id,
185 GCMClient::Result result) {
186 DCHECK(io_thread_->RunsTasksOnCurrentThread());
187
188 ui_thread_->PostTask(
189 FROM_HERE,
190 base::Bind(&GCMDriver::UnregisterFinished, service_, app_id, result));
191 }
192
193 void GCMDriver::IOWorker::OnSendFinished(const std::string& app_id,
194 const std::string& message_id,
195 GCMClient::Result result) {
196 DCHECK(io_thread_->RunsTasksOnCurrentThread());
197
198 ui_thread_->PostTask(
199 FROM_HERE,
200 base::Bind(&GCMDriver::SendFinished, service_, app_id, message_id,
201 result));
202 }
203
204 void GCMDriver::IOWorker::OnMessageReceived(
205 const std::string& app_id,
206 const GCMClient::IncomingMessage& message) {
207 DCHECK(io_thread_->RunsTasksOnCurrentThread());
208
209 ui_thread_->PostTask(
210 FROM_HERE,
211 base::Bind(&GCMDriver::MessageReceived, service_, app_id, message));
212 }
213
214 void GCMDriver::IOWorker::OnMessagesDeleted(const std::string& app_id) {
215 DCHECK(io_thread_->RunsTasksOnCurrentThread());
216
217 ui_thread_->PostTask(
218 FROM_HERE,
219 base::Bind(&GCMDriver::MessagesDeleted, service_, app_id));
220 }
221
222 void GCMDriver::IOWorker::OnMessageSendError(
223 const std::string& app_id,
224 const GCMClient::SendErrorDetails& send_error_details) {
225 DCHECK(io_thread_->RunsTasksOnCurrentThread());
226
227 ui_thread_->PostTask(
228 FROM_HERE,
229 base::Bind(&GCMDriver::MessageSendError, service_, app_id,
230 send_error_details));
231 }
232
233 void GCMDriver::IOWorker::OnGCMReady() {
234 ui_thread_->PostTask(
235 FROM_HERE,
236 base::Bind(&GCMDriver::GCMClientReady, service_));
237 }
238
239 void GCMDriver::IOWorker::OnActivityRecorded() {
240 DCHECK(io_thread_->RunsTasksOnCurrentThread());
241 // When an activity is recorded, get all the stats and refresh the UI of
242 // gcm-internals page.
243 GetGCMStatistics(false);
244 }
245
246 void GCMDriver::IOWorker::Start(const base::WeakPtr<GCMDriver>& service) {
247 DCHECK(io_thread_->RunsTasksOnCurrentThread());
248
249 service_ = service;
250 gcm_client_->Start();
251 }
252
253 void GCMDriver::IOWorker::Stop() {
254 DCHECK(io_thread_->RunsTasksOnCurrentThread());
255
256 gcm_client_->Stop();
257 }
258
259 void GCMDriver::IOWorker::CheckOut() {
260 DCHECK(io_thread_->RunsTasksOnCurrentThread());
261
262 gcm_client_->CheckOut();
263
264 // Note that we still need to keep GCMClient instance alive since the
265 // GCMDriver may check in again.
266 }
267
268 void GCMDriver::IOWorker::Register(
269 const std::string& app_id,
270 const std::vector<std::string>& sender_ids) {
271 DCHECK(io_thread_->RunsTasksOnCurrentThread());
272
273 gcm_client_->Register(app_id, sender_ids);
274 }
275
276 void GCMDriver::IOWorker::Unregister(const std::string& app_id) {
277 DCHECK(io_thread_->RunsTasksOnCurrentThread());
278
279 gcm_client_->Unregister(app_id);
280 }
281
282 void GCMDriver::IOWorker::Send(const std::string& app_id,
283 const std::string& receiver_id,
284 const GCMClient::OutgoingMessage& message) {
285 DCHECK(io_thread_->RunsTasksOnCurrentThread());
286
287 gcm_client_->Send(app_id, receiver_id, message);
288 }
289
290 void GCMDriver::IOWorker::GetGCMStatistics(bool clear_logs) {
291 DCHECK(io_thread_->RunsTasksOnCurrentThread());
292 gcm::GCMClient::GCMStatistics stats;
293
294 if (gcm_client_.get()) {
295 if (clear_logs)
296 gcm_client_->ClearActivityLogs();
297 stats = gcm_client_->GetStatistics();
298 }
299
300 ui_thread_->PostTask(
301 FROM_HERE,
302 base::Bind(&GCMDriver::GetGCMStatisticsFinished, service_, stats));
303 }
304
305 void GCMDriver::IOWorker::SetGCMRecording(bool recording) {
306 DCHECK(io_thread_->RunsTasksOnCurrentThread());
307 gcm::GCMClient::GCMStatistics stats;
308
309 if (gcm_client_.get()) {
310 gcm_client_->SetRecording(recording);
311 stats = gcm_client_->GetStatistics();
312 stats.gcm_client_created = true;
313 }
314
315 ui_thread_->PostTask(
316 FROM_HERE,
317 base::Bind(&GCMDriver::GetGCMStatisticsFinished, service_, stats));
318 }
319
320 GCMDriver::GCMDriver(
321 scoped_ptr<GCMClientFactory> gcm_client_factory,
322 scoped_ptr<IdentityProvider> identity_provider,
323 const GCMClient::ChromeBuildInfo& chrome_build_info,
324 const base::FilePath& store_path,
325 const scoped_refptr<net::URLRequestContextGetter>& request_context,
326 const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
327 const scoped_refptr<base::SequencedTaskRunner>& io_thread,
328 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner)
329 : gcm_enabled_(true),
330 gcm_client_ready_(false),
331 identity_provider_(identity_provider.Pass()),
332 ui_thread_(ui_thread),
333 io_thread_(io_thread),
334 weak_ptr_factory_(this) {
335 // Get the list of available accounts.
336 std::vector<std::string> account_ids;
337 #if !defined(OS_ANDROID)
338 account_ids = identity_provider_->GetTokenService()->GetAccounts();
339 #endif
340
341 // Create and initialize the GCMClient. Note that this does not initiate the
342 // GCM check-in.
343 io_worker_.reset(new IOWorker(ui_thread, io_thread));
344 io_thread_->PostTask(
345 FROM_HERE,
346 base::Bind(&GCMDriver::IOWorker::Initialize,
347 base::Unretained(io_worker_.get()),
348 base::Passed(&gcm_client_factory),
349 chrome_build_info,
350 store_path,
351 account_ids,
352 request_context,
353 blocking_task_runner));
354
355 identity_provider_->AddObserver(this);
356 }
357
358 GCMDriver::GCMDriver()
359 : gcm_enabled_(true),
360 gcm_client_ready_(false),
361 weak_ptr_factory_(this) {
362 }
363
364 GCMDriver::~GCMDriver() {
365 }
366
367 void GCMDriver::Enable() {
368 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
369
370 if (gcm_enabled_)
371 return;
372 gcm_enabled_ = true;
373
374 EnsureStarted();
375 }
376
377 void GCMDriver::Disable() {
378 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
379
380 if (!gcm_enabled_)
381 return;
382 gcm_enabled_ = false;
383
384 Stop();
385 }
386
387 void GCMDriver::Stop() {
388 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
389
390 // No need to stop GCM service if not started yet.
391 if (account_id_.empty())
392 return;
393
394 RemoveCachedData();
395
396 io_thread_->PostTask(
397 FROM_HERE,
398 base::Bind(&GCMDriver::IOWorker::Stop,
399 base::Unretained(io_worker_.get())));
400 }
401
402 void GCMDriver::Shutdown() {
403 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
404 identity_provider_->RemoveObserver(this);
405 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin();
406 iter != app_handlers_.end(); ++iter) {
407 iter->second->ShutdownHandler();
408 }
409 app_handlers_.clear();
410 io_thread_->DeleteSoon(FROM_HERE, io_worker_.release());
411 }
412
413 void GCMDriver::AddAppHandler(const std::string& app_id,
414 GCMAppHandler* handler) {
415 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
416 DCHECK(!app_id.empty());
417 DCHECK(handler);
418 DCHECK(app_handlers_.find(app_id) == app_handlers_.end());
419
420 app_handlers_[app_id] = handler;
421
422 // Ensures that the GCM service is started when there is an interest.
423 EnsureStarted();
424 }
425
426 void GCMDriver::RemoveAppHandler(const std::string& app_id) {
427 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
428 DCHECK(!app_id.empty());
429
430 app_handlers_.erase(app_id);
431
432 // Stops the GCM service when no app intends to consume it.
433 if (app_handlers_.empty())
434 Stop();
435 }
436
437 void GCMDriver::Register(const std::string& app_id,
438 const std::vector<std::string>& sender_ids,
439 const RegisterCallback& callback) {
440 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
441 DCHECK(!app_id.empty());
442 DCHECK(!sender_ids.empty());
443 DCHECK(!callback.is_null());
444
445 GCMClient::Result result = EnsureStarted();
446 if (result != GCMClient::SUCCESS) {
447 callback.Run(std::string(), result);
448 return;
449 }
450
451 // If previous un/register operation is still in progress, bail out.
452 if (IsAsyncOperationPending(app_id)) {
453 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
454 return;
455 }
456
457 register_callbacks_[app_id] = callback;
458
459 // Delay the register operation until GCMClient is ready.
460 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
461 delayed_task_controller_->AddTask(base::Bind(&GCMDriver::DoRegister,
462 weak_ptr_factory_.GetWeakPtr(),
463 app_id,
464 sender_ids));
465 return;
466 }
467
468 DoRegister(app_id, sender_ids);
469 }
470
471 void GCMDriver::DoRegister(const std::string& app_id,
472 const std::vector<std::string>& sender_ids) {
473 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
474 std::map<std::string, RegisterCallback>::iterator callback_iter =
475 register_callbacks_.find(app_id);
476 if (callback_iter == register_callbacks_.end()) {
477 // The callback could have been removed when the app is uninstalled.
478 return;
479 }
480
481 // Normalize the sender IDs by making them sorted.
482 std::vector<std::string> normalized_sender_ids = sender_ids;
483 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
484
485 io_thread_->PostTask(
486 FROM_HERE,
487 base::Bind(&GCMDriver::IOWorker::Register,
488 base::Unretained(io_worker_.get()),
489 app_id,
490 normalized_sender_ids));
491 }
492
493 void GCMDriver::Unregister(const std::string& app_id,
494 const UnregisterCallback& callback) {
495 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
496 DCHECK(!app_id.empty());
497 DCHECK(!callback.is_null());
498
499 GCMClient::Result result = EnsureStarted();
500 if (result != GCMClient::SUCCESS) {
501 callback.Run(result);
502 return;
503 }
504
505 // If previous un/register operation is still in progress, bail out.
506 if (IsAsyncOperationPending(app_id)) {
507 callback.Run(GCMClient::ASYNC_OPERATION_PENDING);
508 return;
509 }
510
511 unregister_callbacks_[app_id] = callback;
512
513 // Delay the unregister operation until GCMClient is ready.
514 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
515 delayed_task_controller_->AddTask(base::Bind(&GCMDriver::DoUnregister,
516 weak_ptr_factory_.GetWeakPtr(),
517 app_id));
518 return;
519 }
520
521 DoUnregister(app_id);
522 }
523
524 void GCMDriver::DoUnregister(const std::string& app_id) {
525 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
526
527 // Ask the server to unregister it. There could be a small chance that the
528 // unregister request fails. If this occurs, it does not bring any harm since
529 // we simply reject the messages/events received from the server.
530 io_thread_->PostTask(
531 FROM_HERE,
532 base::Bind(&GCMDriver::IOWorker::Unregister,
533 base::Unretained(io_worker_.get()),
534 app_id));
535 }
536
537 void GCMDriver::Send(const std::string& app_id,
538 const std::string& receiver_id,
539 const GCMClient::OutgoingMessage& message,
540 const SendCallback& callback) {
541 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
542 DCHECK(!app_id.empty());
543 DCHECK(!receiver_id.empty());
544 DCHECK(!callback.is_null());
545
546 GCMClient::Result result = EnsureStarted();
547 if (result != GCMClient::SUCCESS) {
548 callback.Run(std::string(), result);
549 return;
550 }
551
552 // If the message with send ID is still in progress, bail out.
553 std::pair<std::string, std::string> key(app_id, message.id);
554 if (send_callbacks_.find(key) != send_callbacks_.end()) {
555 callback.Run(message.id, GCMClient::INVALID_PARAMETER);
556 return;
557 }
558
559 send_callbacks_[key] = callback;
560
561 // Delay the send operation until all GCMClient is ready.
562 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
563 delayed_task_controller_->AddTask(base::Bind(&GCMDriver::DoSend,
564 weak_ptr_factory_.GetWeakPtr(),
565 app_id,
566 receiver_id,
567 message));
568 return;
569 }
570
571 DoSend(app_id, receiver_id, message);
572 }
573
574 void GCMDriver::DoSend(const std::string& app_id,
575 const std::string& receiver_id,
576 const GCMClient::OutgoingMessage& message) {
577 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
578 io_thread_->PostTask(
579 FROM_HERE,
580 base::Bind(&GCMDriver::IOWorker::Send,
581 base::Unretained(io_worker_.get()),
582 app_id,
583 receiver_id,
584 message));
585 }
586
587 GCMClient* GCMDriver::GetGCMClientForTesting() const {
588 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
589 return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL;
590 }
591
592 bool GCMDriver::IsStarted() const {
593 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
594 return !account_id_.empty();
595 }
596
597 bool GCMDriver::IsGCMClientReady() const {
598 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
599 return gcm_client_ready_;
600 }
601
602 void GCMDriver::GetGCMStatistics(const GetGCMStatisticsCallback& callback,
603 bool clear_logs) {
604 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
605 DCHECK(!callback.is_null());
606
607 request_gcm_statistics_callback_ = callback;
608 io_thread_->PostTask(
609 FROM_HERE,
610 base::Bind(&GCMDriver::IOWorker::GetGCMStatistics,
611 base::Unretained(io_worker_.get()),
612 clear_logs));
613 }
614
615 void GCMDriver::SetGCMRecording(const GetGCMStatisticsCallback& callback,
616 bool recording) {
617 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
618
619 request_gcm_statistics_callback_ = callback;
620 io_thread_->PostTask(
621 FROM_HERE,
622 base::Bind(&GCMDriver::IOWorker::SetGCMRecording,
623 base::Unretained(io_worker_.get()),
624 recording));
625 }
626
627 void GCMDriver::OnActiveAccountLogin() {
628 EnsureStarted();
629 }
630
631 void GCMDriver::OnActiveAccountLogout() {
632 CheckOut();
633 }
634
635 GCMClient::Result GCMDriver::EnsureStarted() {
636 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
637
638 if (!gcm_enabled_)
639 return GCMClient::GCM_DISABLED;
640
641 // Have any app requested the service?
642 if (app_handlers_.empty())
643 return GCMClient::UNKNOWN_ERROR;
644
645 // Is the user signed in?
646 const std::string account_id = identity_provider_->GetActiveAccountId();
647 if (account_id.empty())
648 return GCMClient::NOT_SIGNED_IN;
649
650 // CheckIn could be called more than once when:
651 // 1) The password changes.
652 // 2) Register/send function calls it to ensure CheckIn is done.
653 if (account_id_ == account_id)
654 return GCMClient::SUCCESS;
655 account_id_ = account_id;
656
657 DCHECK(!delayed_task_controller_);
658 delayed_task_controller_.reset(new DelayedTaskController);
659
660 // Note that we need to pass weak pointer again since the existing weak
661 // pointer in IOWorker might have been invalidated when check-out occurs.
662 io_thread_->PostTask(
663 FROM_HERE,
664 base::Bind(&GCMDriver::IOWorker::Start,
665 base::Unretained(io_worker_.get()),
666 weak_ptr_factory_.GetWeakPtr()));
667
668 return GCMClient::SUCCESS;
669 }
670
671 void GCMDriver::RemoveCachedData() {
672 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
673 // Remove all the queued tasks since they no longer make sense after
674 // GCM service is stopped.
675 weak_ptr_factory_.InvalidateWeakPtrs();
676
677 account_id_.clear();
678 gcm_client_ready_ = false;
679 delayed_task_controller_.reset();
680 register_callbacks_.clear();
681 send_callbacks_.clear();
682 }
683
684 void GCMDriver::CheckOut() {
685 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
686
687 // We still proceed with the check-out logic even if the check-in is not
688 // initiated in the current session. This will make sure that all the
689 // persisted data written previously will get purged.
690
691 RemoveCachedData();
692
693 io_thread_->PostTask(
694 FROM_HERE,
695 base::Bind(&GCMDriver::IOWorker::CheckOut,
696 base::Unretained(io_worker_.get())));
697 }
698
699 bool GCMDriver::IsAsyncOperationPending(const std::string& app_id) const {
700 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
701 return register_callbacks_.find(app_id) != register_callbacks_.end() ||
702 unregister_callbacks_.find(app_id) != unregister_callbacks_.end();
703 }
704
705 void GCMDriver::RegisterFinished(const std::string& app_id,
706 const std::string& registration_id,
707 GCMClient::Result result) {
708 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
709
710 std::map<std::string, RegisterCallback>::iterator callback_iter =
711 register_callbacks_.find(app_id);
712 if (callback_iter == register_callbacks_.end()) {
713 // The callback could have been removed when the app is uninstalled.
714 return;
715 }
716
717 RegisterCallback callback = callback_iter->second;
718 register_callbacks_.erase(callback_iter);
719 callback.Run(registration_id, result);
720 }
721
722 void GCMDriver::UnregisterFinished(const std::string& app_id,
723 GCMClient::Result result) {
724 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
725
726 std::map<std::string, UnregisterCallback>::iterator callback_iter =
727 unregister_callbacks_.find(app_id);
728 if (callback_iter == unregister_callbacks_.end())
729 return;
730
731 UnregisterCallback callback = callback_iter->second;
732 unregister_callbacks_.erase(callback_iter);
733 callback.Run(result);
734 }
735
736 void GCMDriver::SendFinished(const std::string& app_id,
737 const std::string& message_id,
738 GCMClient::Result result) {
739 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
740
741 std::map<std::pair<std::string, std::string>, SendCallback>::iterator
742 callback_iter = send_callbacks_.find(
743 std::pair<std::string, std::string>(app_id, message_id));
744 if (callback_iter == send_callbacks_.end()) {
745 // The callback could have been removed when the app is uninstalled.
746 return;
747 }
748
749 SendCallback callback = callback_iter->second;
750 send_callbacks_.erase(callback_iter);
751 callback.Run(message_id, result);
752 }
753
754 void GCMDriver::MessageReceived(const std::string& app_id,
755 GCMClient::IncomingMessage message) {
756 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
757
758 // Drop the event if signed out.
759 if (account_id_.empty())
760 return;
761
762 GetAppHandler(app_id)->OnMessage(app_id, message);
763 }
764
765 void GCMDriver::MessagesDeleted(const std::string& app_id) {
766 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
767
768 // Drop the event if signed out.
769 if (account_id_.empty())
770 return;
771
772 GetAppHandler(app_id)->OnMessagesDeleted(app_id);
773 }
774
775 void GCMDriver::MessageSendError(
776 const std::string& app_id,
777 const GCMClient::SendErrorDetails& send_error_details) {
778 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
779
780 // Drop the event if signed out.
781 if (account_id_.empty())
782 return;
783
784 GetAppHandler(app_id)->OnSendError(app_id, send_error_details);
785 }
786
787 void GCMDriver::GCMClientReady() {
788 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
789
790 if (gcm_client_ready_)
791 return;
792 gcm_client_ready_ = true;
793
794 delayed_task_controller_->SetReady();
795 }
796
797 GCMAppHandler* GCMDriver::GetAppHandler(const std::string& app_id) {
798 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
799
800 std::map<std::string, GCMAppHandler*>::const_iterator iter =
801 app_handlers_.find(app_id);
802 return iter == app_handlers_.end() ? &default_app_handler_ : iter->second;
803 }
804
805 void GCMDriver::GetGCMStatisticsFinished(GCMClient::GCMStatistics stats) {
806 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
807
808 // Normally request_gcm_statistics_callback_ would not be null.
809 if (!request_gcm_statistics_callback_.is_null())
810 request_gcm_statistics_callback_.Run(stats);
811 else
812 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL.";
813 }
814
815 std::string GCMDriver::SignedInUserName() const {
816 if (IsStarted())
817 return identity_provider_->GetActiveUsername();
818 return std::string();
819 }
820
821 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698