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

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

Powered by Google App Engine
This is Rietveld 408576698