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

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

Issue 183923006: [GCM] API update to allow only a single sender in registration (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Updates based on CR. Changing how the senders/reg_ids are stored to avoid upgrade to multiple sedne… Created 6 years, 9 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
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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_profile_service.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/base64.h" 10 #include "base/base64.h"
(...skipping 28 matching lines...) Expand all
39 #include "google_apis/gcm/protocol/android_checkin.pb.h" 39 #include "google_apis/gcm/protocol/android_checkin.pb.h"
40 #include "net/url_request/url_request_context_getter.h" 40 #include "net/url_request/url_request_context_getter.h"
41 41
42 using extensions::Extension; 42 using extensions::Extension;
43 43
44 namespace gcm { 44 namespace gcm {
45 45
46 namespace { 46 namespace {
47 47
48 const char kRegistrationKey[] = "gcm.registration"; 48 const char kRegistrationKey[] = "gcm.registration";
49 const char kSendersKey[] = "senders";
50 const char kRegistrationIDKey[] = "reg_id";
51 49
52 checkin_proto::ChromeBuildProto_Platform GetPlatform() { 50 checkin_proto::ChromeBuildProto_Platform GetPlatform() {
53 #if defined(OS_WIN) 51 #if defined(OS_WIN)
54 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN; 52 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN;
55 #elif defined(OS_MACOSX) 53 #elif defined(OS_MACOSX)
56 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_MAC; 54 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_MAC;
57 #elif defined(OS_CHROMEOS) 55 #elif defined(OS_CHROMEOS)
58 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_CROS; 56 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_CROS;
59 #elif defined(OS_LINUX) 57 #elif defined(OS_LINUX)
60 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_LINUX; 58 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_LINUX;
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 // Called on IO thread. 258 // Called on IO thread.
261 void Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory, 259 void Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory,
262 const base::FilePath& store_path, 260 const base::FilePath& store_path,
263 const std::vector<std::string>& account_ids, 261 const std::vector<std::string>& account_ids,
264 const scoped_refptr<net::URLRequestContextGetter>& 262 const scoped_refptr<net::URLRequestContextGetter>&
265 url_request_context_getter); 263 url_request_context_getter);
266 void Reset(); 264 void Reset();
267 void Load(const base::WeakPtr<GCMProfileService>& service); 265 void Load(const base::WeakPtr<GCMProfileService>& service);
268 void CheckOut(); 266 void CheckOut();
269 void Register(const std::string& app_id, 267 void Register(const std::string& app_id,
270 const std::vector<std::string>& sender_ids, 268 const std::string& sender_id,
271 const std::string& cert); 269 const std::string& cert);
272 void Unregister(const std::string& app_id); 270 void Unregister(const std::string& app_id);
273 void Send(const std::string& app_id, 271 void Send(const std::string& app_id,
274 const std::string& receiver_id, 272 const std::string& receiver_id,
275 const GCMClient::OutgoingMessage& message); 273 const GCMClient::OutgoingMessage& message);
276 274
277 // For testing purpose. Can be called from UI thread. Use with care. 275 // For testing purpose. Can be called from UI thread. Use with care.
278 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); } 276 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); }
279 277
280 private: 278 private:
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 428 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
431 429
432 gcm_client_->CheckOut(); 430 gcm_client_->CheckOut();
433 431
434 // Note that we still need to keep GCMClient instance alive since the profile 432 // Note that we still need to keep GCMClient instance alive since the profile
435 // might be signed in again. 433 // might be signed in again.
436 } 434 }
437 435
438 void GCMProfileService::IOWorker::Register( 436 void GCMProfileService::IOWorker::Register(
439 const std::string& app_id, 437 const std::string& app_id,
440 const std::vector<std::string>& sender_ids, 438 const std::string& sender_id,
441 const std::string& cert) { 439 const std::string& cert) {
442 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 440 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
443 441
444 gcm_client_->Register(app_id, cert, sender_ids); 442 gcm_client_->Register(app_id, cert, sender_id);
445 } 443 }
446 444
447 void GCMProfileService::IOWorker::Unregister(const std::string& app_id) { 445 void GCMProfileService::IOWorker::Unregister(const std::string& app_id) {
448 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 446 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
449 447
450 gcm_client_->Unregister(app_id); 448 gcm_client_->Unregister(app_id);
451 } 449 }
452 450
453 void GCMProfileService::IOWorker::Send( 451 void GCMProfileService::IOWorker::Send(
454 const std::string& app_id, 452 const std::string& app_id,
455 const std::string& receiver_id, 453 const std::string& receiver_id,
456 const GCMClient::OutgoingMessage& message) { 454 const GCMClient::OutgoingMessage& message) {
457 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 455 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
458 456
459 gcm_client_->Send(app_id, receiver_id, message); 457 gcm_client_->Send(app_id, receiver_id, message);
460 } 458 }
461 459
462 GCMProfileService::RegistrationInfo::RegistrationInfo() { 460 GCMProfileService::RegistrationInfo::RegistrationInfo() {
463 } 461 }
464 462
465 GCMProfileService::RegistrationInfo::~RegistrationInfo() { 463 GCMProfileService::RegistrationInfo::~RegistrationInfo() {
466 } 464 }
467 465
468 bool GCMProfileService::RegistrationInfo::IsValid() const { 466 bool GCMProfileService::RegistrationInfo::IsValid() const {
469 return !sender_ids.empty() && !registration_id.empty(); 467 return !sender_id.empty() && !registration_id.empty();
470 } 468 }
471 469
472 // static 470 // static
473 GCMProfileService::GCMEnabledState GCMProfileService::GetGCMEnabledState( 471 GCMProfileService::GCMEnabledState GCMProfileService::GetGCMEnabledState(
474 Profile* profile) { 472 Profile* profile) {
475 const base::Value* gcm_enabled_value = 473 const base::Value* gcm_enabled_value =
476 profile->GetPrefs()->GetUserPrefValue(prefs::kGCMChannelEnabled); 474 profile->GetPrefs()->GetUserPrefValue(prefs::kGCMChannelEnabled);
477 if (!gcm_enabled_value) 475 if (!gcm_enabled_value)
478 return ENABLED_FOR_APPS; 476 return ENABLED_FOR_APPS;
479 477
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 account_ids, 551 account_ids,
554 url_request_context_getter)); 552 url_request_context_getter));
555 553
556 // Load from the GCM store and initiate the GCM check-in if the rollout signal 554 // Load from the GCM store and initiate the GCM check-in if the rollout signal
557 // indicates yes. 555 // indicates yes.
558 if (GetGCMEnabledState(profile_) == ALWAYS_ENABLED) 556 if (GetGCMEnabledState(profile_) == ALWAYS_ENABLED)
559 EnsureLoaded(); 557 EnsureLoaded();
560 } 558 }
561 559
562 void GCMProfileService::Register(const std::string& app_id, 560 void GCMProfileService::Register(const std::string& app_id,
563 const std::vector<std::string>& sender_ids, 561 const std::string& sender_id,
564 const std::string& cert, 562 const std::string& cert,
565 RegisterCallback callback) { 563 RegisterCallback callback) {
566 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 564 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
567 DCHECK(!app_id.empty() && !sender_ids.empty() && !callback.is_null()); 565 DCHECK(!app_id.empty() && !sender_id.empty() && !callback.is_null());
568 566
569 // Ensure that check-in has been done. 567 // Ensure that check-in has been done.
570 EnsureLoaded(); 568 EnsureLoaded();
571 569
572 // If the profile was not signed in, bail out. 570 // If the profile was not signed in, bail out.
573 if (username_.empty()) { 571 if (username_.empty()) {
574 callback.Run(std::string(), GCMClient::NOT_SIGNED_IN); 572 callback.Run(std::string(), GCMClient::NOT_SIGNED_IN);
575 return; 573 return;
576 } 574 }
577 575
578 // If previous register operation is still in progress, bail out. 576 // If previous register operation is still in progress, bail out.
579 if (register_callbacks_.find(app_id) != register_callbacks_.end()) { 577 if (register_callbacks_.find(app_id) != register_callbacks_.end()) {
580 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); 578 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
581 return; 579 return;
582 } 580 }
583 581
584 register_callbacks_[app_id] = callback; 582 register_callbacks_[app_id] = callback;
585 583
586 EnsureAppReady(app_id); 584 EnsureAppReady(app_id);
587 585
588 // Delay the register operation until GCMClient is ready. 586 // Delay the register operation until GCMClient is ready.
589 if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) { 587 if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) {
590 delayed_task_controller_->AddTask( 588 delayed_task_controller_->AddTask(
591 app_id, 589 app_id,
592 base::Bind(&GCMProfileService::DoRegister, 590 base::Bind(&GCMProfileService::DoRegister,
593 weak_ptr_factory_.GetWeakPtr(), 591 weak_ptr_factory_.GetWeakPtr(),
594 app_id, 592 app_id,
595 sender_ids, 593 sender_id,
596 cert)); 594 cert));
597 return; 595 return;
598 } 596 }
599 597
600 DoRegister(app_id, sender_ids, cert); 598 DoRegister(app_id, sender_id, cert);
601 } 599 }
602 600
603 void GCMProfileService::DoRegister(const std::string& app_id, 601 void GCMProfileService::DoRegister(const std::string& app_id,
604 const std::vector<std::string>& sender_ids, 602 const std::string& sender_id,
605 const std::string& cert) { 603 const std::string& cert) {
606 std::map<std::string, RegisterCallback>::iterator callback_iter = 604 std::map<std::string, RegisterCallback>::iterator callback_iter =
607 register_callbacks_.find(app_id); 605 register_callbacks_.find(app_id);
608 if (callback_iter == register_callbacks_.end()) { 606 if (callback_iter == register_callbacks_.end()) {
609 // The callback could have been removed when the app is uninstalled. 607 // The callback could have been removed when the app is uninstalled.
610 return; 608 return;
611 } 609 }
612 610
613 // Normalize the sender IDs by making them sorted.
614 std::vector<std::string> normalized_sender_ids = sender_ids;
615 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
616
617 // If the same sender ids is provided, return the cached registration ID 611 // If the same sender ids is provided, return the cached registration ID
618 // directly. 612 // directly.
619 RegistrationInfoMap::const_iterator registration_info_iter = 613 RegistrationInfoMap::const_iterator registration_info_iter =
620 registration_info_map_.find(app_id); 614 registration_info_map_.find(app_id);
621 if (registration_info_iter != registration_info_map_.end() && 615 if (registration_info_iter != registration_info_map_.end() &&
622 registration_info_iter->second.sender_ids == normalized_sender_ids) { 616 registration_info_iter->second.sender_id == sender_id) {
623 RegisterCallback callback = callback_iter->second; 617 RegisterCallback callback = callback_iter->second;
624 register_callbacks_.erase(callback_iter); 618 register_callbacks_.erase(callback_iter);
625 callback.Run(registration_info_iter->second.registration_id, 619 callback.Run(registration_info_iter->second.registration_id,
626 GCMClient::SUCCESS); 620 GCMClient::SUCCESS);
627 return; 621 return;
628 } 622 }
629 623
630 // Cache the sender IDs. The registration ID will be filled when the 624 // Cache the sender IDs. The registration ID will be filled when the
631 // registration completes. 625 // registration completes.
632 RegistrationInfo registration_info; 626 RegistrationInfo registration_info;
633 registration_info.sender_ids = normalized_sender_ids; 627 registration_info.sender_id = sender_id;
634 registration_info_map_[app_id] = registration_info; 628 registration_info_map_[app_id] = registration_info;
635 629
636 // Save the IDs of all registered apps such that we know what to remove from 630 // Save the IDs of all registered apps such that we know what to remove from
637 // the the app's state store when the profile is signed out. 631 // the the app's state store when the profile is signed out.
638 WriteRegisteredAppIDs(); 632 WriteRegisteredAppIDs();
639 633
640 content::BrowserThread::PostTask( 634 content::BrowserThread::PostTask(
641 content::BrowserThread::IO, 635 content::BrowserThread::IO,
642 FROM_HERE, 636 FROM_HERE,
643 base::Bind(&GCMProfileService::IOWorker::Register, 637 base::Bind(&GCMProfileService::IOWorker::Register,
644 io_worker_, 638 io_worker_,
645 app_id, 639 app_id,
646 normalized_sender_ids, 640 sender_id,
647 cert)); 641 cert));
648 } 642 }
649 643
650 void GCMProfileService::Send(const std::string& app_id, 644 void GCMProfileService::Send(const std::string& app_id,
651 const std::string& receiver_id, 645 const std::string& receiver_id,
652 const GCMClient::OutgoingMessage& message, 646 const GCMClient::OutgoingMessage& message,
653 SendCallback callback) { 647 SendCallback callback) {
654 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 648 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
655 DCHECK(!app_id.empty() && !receiver_id.empty() && !callback.is_null()); 649 DCHECK(!app_id.empty() && !receiver_id.empty() && !callback.is_null());
656 650
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 983
990 void GCMProfileService::WriteRegistrationInfo(const std::string& app_id) { 984 void GCMProfileService::WriteRegistrationInfo(const std::string& app_id) {
991 extensions::StateStore* storage = 985 extensions::StateStore* storage =
992 extensions::ExtensionSystem::Get(profile_)->state_store(); 986 extensions::ExtensionSystem::Get(profile_)->state_store();
993 DCHECK(storage); 987 DCHECK(storage);
994 988
995 RegistrationInfoMap::const_iterator registration_info_iter = 989 RegistrationInfoMap::const_iterator registration_info_iter =
996 registration_info_map_.find(app_id); 990 registration_info_map_.find(app_id);
997 if (registration_info_iter == registration_info_map_.end()) 991 if (registration_info_iter == registration_info_map_.end())
998 return; 992 return;
993
999 const RegistrationInfo& registration_info = registration_info_iter->second; 994 const RegistrationInfo& registration_info = registration_info_iter->second;
1000
1001 scoped_ptr<base::ListValue> senders_list(new base::ListValue());
1002 for (std::vector<std::string>::const_iterator senders_iter =
1003 registration_info.sender_ids.begin();
1004 senders_iter != registration_info.sender_ids.end();
1005 ++senders_iter) {
1006 senders_list->AppendString(*senders_iter);
1007 }
1008
1009 scoped_ptr<base::DictionaryValue> registration_info_dict( 995 scoped_ptr<base::DictionaryValue> registration_info_dict(
1010 new base::DictionaryValue()); 996 new base::DictionaryValue());
1011 registration_info_dict->Set(kSendersKey, senders_list.release()); 997 registration_info_dict->SetString(registration_info.sender_id,
1012 registration_info_dict->SetString(kRegistrationIDKey,
1013 registration_info.registration_id); 998 registration_info.registration_id);
1014 999
1015 storage->SetExtensionValue( 1000 storage->SetExtensionValue(
1016 app_id, kRegistrationKey, registration_info_dict.PassAs<base::Value>()); 1001 app_id, kRegistrationKey, registration_info_dict.PassAs<base::Value>());
1017 } 1002 }
1018 1003
1019 void GCMProfileService::ReadRegistrationInfo(const std::string& app_id) { 1004 void GCMProfileService::ReadRegistrationInfo(const std::string& app_id) {
1020 delayed_task_controller_->AddApp(app_id); 1005 delayed_task_controller_->AddApp(app_id);
1021 1006
1022 extensions::StateStore* storage = 1007 extensions::StateStore* storage =
(...skipping 24 matching lines...) Expand all
1047 delayed_task_controller_->SetAppReady(app_id); 1032 delayed_task_controller_->SetAppReady(app_id);
1048 } 1033 }
1049 1034
1050 bool GCMProfileService::ParsePersistedRegistrationInfo( 1035 bool GCMProfileService::ParsePersistedRegistrationInfo(
1051 scoped_ptr<base::Value> value, 1036 scoped_ptr<base::Value> value,
1052 RegistrationInfo* registration_info) { 1037 RegistrationInfo* registration_info) {
1053 base::DictionaryValue* dict = NULL; 1038 base::DictionaryValue* dict = NULL;
1054 if (!value.get() || !value->GetAsDictionary(&dict)) 1039 if (!value.get() || !value->GetAsDictionary(&dict))
1055 return false; 1040 return false;
1056 1041
1057 if (!dict->GetString(kRegistrationIDKey, &registration_info->registration_id)) 1042 // TODO(fgorski): Remove a DCHECK when more than a single sender is allowed.
1058 return false; 1043 DCHECK_LE(dict->size(), 1UL);
1059 1044
1060 const base::ListValue* senders_list = NULL; 1045 for (base::DictionaryValue::Iterator iter(*dict);
1061 if (!dict->GetList(kSendersKey, &senders_list) || !senders_list->GetSize()) 1046 !iter.IsAtEnd();
1062 return false; 1047 iter.Advance()) {
1063 for (size_t i = 0; i < senders_list->GetSize(); ++i) { 1048 registration_info->sender_id = iter.key();
1064 std::string sender; 1049 if (iter.value().GetAsString(&registration_info->registration_id))
1065 if (!senders_list->GetString(i, &sender)) 1050 return true;
1066 return false;
1067 registration_info->sender_ids.push_back(sender);
1068 } 1051 }
1069 1052
1070 return true; 1053 // TODO(fgorski): Switch the return statements when multiple sendres are
jianli 2014/03/04 01:13:53 Probably you only need to add one TODO comment at
1054 // allowed.
1055 return false;
1071 } 1056 }
1072 1057
1073 // static 1058 // static
1074 const char* GCMProfileService::GetPersistentRegisterKeyForTesting() { 1059 const char* GCMProfileService::GetPersistentRegisterKeyForTesting() {
1075 return kRegistrationKey; 1060 return kRegistrationKey;
1076 } 1061 }
1077 1062
1078 } // namespace gcm 1063 } // namespace gcm
OLDNEW
« no previous file with comments | « chrome/browser/services/gcm/gcm_profile_service.h ('k') | chrome/browser/services/gcm/gcm_profile_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698