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

Side by Side Diff: google_apis/gcm/engine/gcm_store_impl.cc

Issue 429073002: [GCM] Persistence of account mappings. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixing the gn build Created 6 years, 4 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 2014 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 "google_apis/gcm/engine/gcm_store_impl.h" 5 #include "google_apis/gcm/engine/gcm_store_impl.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 const char kGServiceSettingKeyStart[] = "gservice1-"; 61 const char kGServiceSettingKeyStart[] = "gservice1-";
62 // Key guaranteed to be higher than all G-services settings keys. 62 // Key guaranteed to be higher than all G-services settings keys.
63 // Used for limiting iteration. 63 // Used for limiting iteration.
64 const char kGServiceSettingKeyEnd[] = "gservice2-"; 64 const char kGServiceSettingKeyEnd[] = "gservice2-";
65 // Key for digest of the last G-services settings update. 65 // Key for digest of the last G-services settings update.
66 const char kGServiceSettingsDigestKey[] = "gservices_digest"; 66 const char kGServiceSettingsDigestKey[] = "gservices_digest";
67 // Key used to indicate how many accounts were last checked in with this device. 67 // Key used to indicate how many accounts were last checked in with this device.
68 const char kLastCheckinAccountsKey[] = "last_checkin_accounts_count"; 68 const char kLastCheckinAccountsKey[] = "last_checkin_accounts_count";
69 // Key used to timestamp last checkin (marked with G services settings update). 69 // Key used to timestamp last checkin (marked with G services settings update).
70 const char kLastCheckinTimeKey[] = "last_checkin_time"; 70 const char kLastCheckinTimeKey[] = "last_checkin_time";
71 // Lowest lexicographically ordered account key.
72 // Used for prefixing account information.
73 const char kAccountKeyStart[] = "account1-";
74 // Key guaranteed to be higher than all account keys.
75 // Used for limiting iteration.
76 const char kAccountKeyEnd[] = "account2-";
71 77
72 std::string MakeRegistrationKey(const std::string& app_id) { 78 std::string MakeRegistrationKey(const std::string& app_id) {
73 return kRegistrationKeyStart + app_id; 79 return kRegistrationKeyStart + app_id;
74 } 80 }
75 81
76 std::string ParseRegistrationKey(const std::string& key) { 82 std::string ParseRegistrationKey(const std::string& key) {
77 return key.substr(arraysize(kRegistrationKeyStart) - 1); 83 return key.substr(arraysize(kRegistrationKeyStart) - 1);
78 } 84 }
79 85
80 std::string MakeIncomingKey(const std::string& persistent_id) { 86 std::string MakeIncomingKey(const std::string& persistent_id) {
81 return kIncomingMsgKeyStart + persistent_id; 87 return kIncomingMsgKeyStart + persistent_id;
82 } 88 }
83 89
84 std::string MakeOutgoingKey(const std::string& persistent_id) { 90 std::string MakeOutgoingKey(const std::string& persistent_id) {
85 return kOutgoingMsgKeyStart + persistent_id; 91 return kOutgoingMsgKeyStart + persistent_id;
86 } 92 }
87 93
88 std::string ParseOutgoingKey(const std::string& key) { 94 std::string ParseOutgoingKey(const std::string& key) {
89 return key.substr(arraysize(kOutgoingMsgKeyStart) - 1); 95 return key.substr(arraysize(kOutgoingMsgKeyStart) - 1);
90 } 96 }
91 97
92 std::string MakeGServiceSettingKey(const std::string& setting_name) { 98 std::string MakeGServiceSettingKey(const std::string& setting_name) {
93 return kGServiceSettingKeyStart + setting_name; 99 return kGServiceSettingKeyStart + setting_name;
94 } 100 }
95 101
96 std::string ParseGServiceSettingKey(const std::string& key) { 102 std::string ParseGServiceSettingKey(const std::string& key) {
97 return key.substr(arraysize(kGServiceSettingKeyStart) - 1); 103 return key.substr(arraysize(kGServiceSettingKeyStart) - 1);
98 } 104 }
99 105
106 std::string MakeAccountKey(const std::string& account_id) {
107 return kAccountKeyStart + account_id;
108 }
109
110 std::string ParseAccountKey(const std::string& key) {
111 return key.substr(arraysize(kAccountKeyStart) - 1);
112 }
113
100 // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore 114 // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore
101 // outlive the slice. 115 // outlive the slice.
102 // For example: MakeSlice(MakeOutgoingKey(x)) is invalid. 116 // For example: MakeSlice(MakeOutgoingKey(x)) is invalid.
103 leveldb::Slice MakeSlice(const base::StringPiece& s) { 117 leveldb::Slice MakeSlice(const base::StringPiece& s) {
104 return leveldb::Slice(s.begin(), s.size()); 118 return leveldb::Slice(s.begin(), s.size());
105 } 119 }
106 120
107 } // namespace 121 } // namespace
108 122
109 class GCMStoreImpl::Backend 123 class GCMStoreImpl::Backend
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 const UpdateCallback& callback); 155 const UpdateCallback& callback);
142 void RemoveUserSerialNumber(const std::string& username, 156 void RemoveUserSerialNumber(const std::string& username,
143 const UpdateCallback& callback); 157 const UpdateCallback& callback);
144 void SetLastCheckinInfo(const base::Time& time, 158 void SetLastCheckinInfo(const base::Time& time,
145 const std::set<std::string>& accounts, 159 const std::set<std::string>& accounts,
146 const UpdateCallback& callback); 160 const UpdateCallback& callback);
147 void SetGServicesSettings( 161 void SetGServicesSettings(
148 const std::map<std::string, std::string>& settings, 162 const std::map<std::string, std::string>& settings,
149 const std::string& digest, 163 const std::string& digest,
150 const UpdateCallback& callback); 164 const UpdateCallback& callback);
165 void AddAccountMapping(const AccountInfo& account_info,
166 const UpdateCallback& callback);
167 void RemoveAccountMapping(const std::string& account_id,
168 const UpdateCallback& callback);
151 169
152 private: 170 private:
153 friend class base::RefCountedThreadSafe<Backend>; 171 friend class base::RefCountedThreadSafe<Backend>;
154 ~Backend(); 172 ~Backend();
155 173
156 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); 174 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token);
157 bool LoadRegistrations(RegistrationInfoMap* registrations); 175 bool LoadRegistrations(RegistrationInfoMap* registrations);
158 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); 176 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages);
159 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); 177 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages);
160 bool LoadLastCheckinInfo(base::Time* last_checkin_time, 178 bool LoadLastCheckinInfo(base::Time* last_checkin_time,
161 std::set<std::string>* accounts); 179 std::set<std::string>* accounts);
162 bool LoadGServicesSettings(std::map<std::string, std::string>* settings, 180 bool LoadGServicesSettings(std::map<std::string, std::string>* settings,
163 std::string* digest); 181 std::string* digest);
182 bool LoadAccountMappingInfo(AccountInfoMap* account_infos);
164 183
165 const base::FilePath path_; 184 const base::FilePath path_;
166 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; 185 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_;
167 scoped_ptr<Encryptor> encryptor_; 186 scoped_ptr<Encryptor> encryptor_;
168 187
169 scoped_ptr<leveldb::DB> db_; 188 scoped_ptr<leveldb::DB> db_;
170 }; 189 };
171 190
172 GCMStoreImpl::Backend::Backend( 191 GCMStoreImpl::Backend::Backend(
173 const base::FilePath& path, 192 const base::FilePath& path,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 db_.reset(db); 226 db_.reset(db);
208 227
209 if (!LoadDeviceCredentials(&result->device_android_id, 228 if (!LoadDeviceCredentials(&result->device_android_id,
210 &result->device_security_token) || 229 &result->device_security_token) ||
211 !LoadRegistrations(&result->registrations) || 230 !LoadRegistrations(&result->registrations) ||
212 !LoadIncomingMessages(&result->incoming_messages) || 231 !LoadIncomingMessages(&result->incoming_messages) ||
213 !LoadOutgoingMessages(&result->outgoing_messages) || 232 !LoadOutgoingMessages(&result->outgoing_messages) ||
214 !LoadLastCheckinInfo(&result->last_checkin_time, 233 !LoadLastCheckinInfo(&result->last_checkin_time,
215 &result->last_checkin_accounts) || 234 &result->last_checkin_accounts) ||
216 !LoadGServicesSettings(&result->gservices_settings, 235 !LoadGServicesSettings(&result->gservices_settings,
217 &result->gservices_digest)) { 236 &result->gservices_digest) ||
218 result->device_android_id = 0; 237 !LoadAccountMappingInfo(&result->account_infos)) {
219 result->device_security_token = 0; 238 result->Reset();
220 result->registrations.clear();
221 result->incoming_messages.clear();
222 result->outgoing_messages.clear();
223 result->gservices_settings.clear();
224 result->gservices_digest.clear();
225 result->last_checkin_time = base::Time::FromInternalValue(0LL);
226 foreground_task_runner_->PostTask(FROM_HERE, 239 foreground_task_runner_->PostTask(FROM_HERE,
227 base::Bind(callback, 240 base::Bind(callback,
228 base::Passed(&result))); 241 base::Passed(&result)));
229 return; 242 return;
230 } 243 }
231 244
232 // Only record histograms if GCM had already been set up for this device. 245 // Only record histograms if GCM had already been set up for this device.
233 if (result->device_android_id != 0 && result->device_security_token != 0) { 246 if (result->device_android_id != 0 && result->device_security_token != 0) {
234 int64 file_size = 0; 247 int64 file_size = 0;
235 if (base::GetFileSize(path_, &file_size)) { 248 if (base::GetFileSize(path_, &file_size)) {
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 // Write it all in a batch. 567 // Write it all in a batch.
555 leveldb::WriteOptions write_options; 568 leveldb::WriteOptions write_options;
556 write_options.sync = true; 569 write_options.sync = true;
557 570
558 leveldb::Status s = db_->Write(write_options, &write_batch); 571 leveldb::Status s = db_->Write(write_options, &write_batch);
559 if (!s.ok()) 572 if (!s.ok())
560 LOG(ERROR) << "LevelDB GService Settings update failed: " << s.ToString(); 573 LOG(ERROR) << "LevelDB GService Settings update failed: " << s.ToString();
561 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); 574 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok()));
562 } 575 }
563 576
577 void GCMStoreImpl::Backend::AddAccountMapping(const AccountInfo& account_info,
578 const UpdateCallback& callback) {
579 DVLOG(1) << "Saving account info for account with email: "
580 << account_info.email;
581 if (!db_.get()) {
582 LOG(ERROR) << "GCMStore db doesn't exist.";
583 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
584 return;
585 }
586
587 leveldb::WriteOptions write_options;
588 write_options.sync = true;
589
590 std::string data = account_info.SerializeAsString();
591 std::string key = MakeAccountKey(account_info.account_id);
592 const leveldb::Status s =
593 db_->Put(write_options, MakeSlice(key), MakeSlice(data));
594 if (!s.ok())
595 LOG(ERROR) << "LevelDB adding account mapping failed: " << s.ToString();
596 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok()));
597 }
598
599 void GCMStoreImpl::Backend::RemoveAccountMapping(
600 const std::string& account_id,
601 const UpdateCallback& callback) {
602 if (!db_.get()) {
603 LOG(ERROR) << "GCMStore db doesn't exist.";
604 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
605 return;
606 }
607
608 leveldb::WriteOptions write_options;
609 write_options.sync = true;
610
611 leveldb::Status s =
612 db_->Delete(write_options, MakeSlice(MakeAccountKey(account_id)));
613
614 if (!s.ok())
615 LOG(ERROR) << "LevelDB removal of account mapping failed: " << s.ToString();
616 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok()));
617 }
618
564 bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, 619 bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id,
565 uint64* security_token) { 620 uint64* security_token) {
566 leveldb::ReadOptions read_options; 621 leveldb::ReadOptions read_options;
567 read_options.verify_checksums = true; 622 read_options.verify_checksums = true;
568 623
569 std::string result; 624 std::string result;
570 leveldb::Status s = db_->Get(read_options, MakeSlice(kDeviceAIDKey), &result); 625 leveldb::Status s = db_->Get(read_options, MakeSlice(kDeviceAIDKey), &result);
571 if (s.ok()) { 626 if (s.ok()) {
572 if (!base::StringToUint64(result, android_id)) { 627 if (!base::StringToUint64(result, android_id)) {
573 LOG(ERROR) << "Failed to restore device id."; 628 LOG(ERROR) << "Failed to restore device id.";
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 DVLOG(1) << "Found G Service setting with key: " << id 782 DVLOG(1) << "Found G Service setting with key: " << id
728 << ", and value: " << value; 783 << ", and value: " << value;
729 } 784 }
730 785
731 // Load the settings digest. It's ok if it is empty. 786 // Load the settings digest. It's ok if it is empty.
732 db_->Get(read_options, MakeSlice(kGServiceSettingsDigestKey), digest); 787 db_->Get(read_options, MakeSlice(kGServiceSettingsDigestKey), digest);
733 788
734 return true; 789 return true;
735 } 790 }
736 791
792 bool GCMStoreImpl::Backend::LoadAccountMappingInfo(
793 AccountInfoMap* account_infos) {
794 leveldb::ReadOptions read_options;
795 read_options.verify_checksums = true;
796
797 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
798 for (iter->Seek(MakeSlice(kAccountKeyStart));
799 iter->Valid() && iter->key().ToString() < kAccountKeyEnd;
800 iter->Next()) {
801 AccountInfo account_info;
802 account_info.account_id = ParseAccountKey(iter->key().ToString());
803 if (!account_info.ParseFromString(iter->value().ToString())) {
804 DVLOG(1) << "Failed to parse account info with ID: "
805 << account_info.account_id;
806 return false;
807 }
808 DVLOG(1) << "Found account mapping with ID: " << account_info.account_id;
809 (*account_infos)[account_info.account_id] = account_info;
810 }
811
812 return true;
813 }
814
737 GCMStoreImpl::GCMStoreImpl( 815 GCMStoreImpl::GCMStoreImpl(
738 const base::FilePath& path, 816 const base::FilePath& path,
739 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, 817 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
740 scoped_ptr<Encryptor> encryptor) 818 scoped_ptr<Encryptor> encryptor)
741 : backend_(new Backend(path, 819 : backend_(new Backend(path,
742 base::MessageLoopProxy::current(), 820 base::MessageLoopProxy::current(),
743 encryptor.Pass())), 821 encryptor.Pass())),
744 blocking_task_runner_(blocking_task_runner), 822 blocking_task_runner_(blocking_task_runner),
745 weak_ptr_factory_(this) { 823 weak_ptr_factory_(this) {
746 } 824 }
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 const UpdateCallback& callback) { 1004 const UpdateCallback& callback) {
927 blocking_task_runner_->PostTask( 1005 blocking_task_runner_->PostTask(
928 FROM_HERE, 1006 FROM_HERE,
929 base::Bind(&GCMStoreImpl::Backend::SetGServicesSettings, 1007 base::Bind(&GCMStoreImpl::Backend::SetGServicesSettings,
930 backend_, 1008 backend_,
931 settings, 1009 settings,
932 digest, 1010 digest,
933 callback)); 1011 callback));
934 } 1012 }
935 1013
1014 void GCMStoreImpl::AddAccountMapping(const AccountInfo& account_info,
1015 const UpdateCallback& callback) {
1016 blocking_task_runner_->PostTask(
1017 FROM_HERE,
1018 base::Bind(&GCMStoreImpl::Backend::AddAccountMapping,
1019 backend_,
1020 account_info,
1021 callback));
1022 }
1023
1024 void GCMStoreImpl::RemoveAccountMapping(const std::string& account_id,
1025 const UpdateCallback& callback) {
1026 blocking_task_runner_->PostTask(
1027 FROM_HERE,
1028 base::Bind(&GCMStoreImpl::Backend::RemoveAccountMapping,
1029 backend_,
1030 account_id,
1031 callback));
1032 }
1033
936 void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, 1034 void GCMStoreImpl::LoadContinuation(const LoadCallback& callback,
937 scoped_ptr<LoadResult> result) { 1035 scoped_ptr<LoadResult> result) {
938 if (!result->success) { 1036 if (!result->success) {
939 callback.Run(result.Pass()); 1037 callback.Run(result.Pass());
940 return; 1038 return;
941 } 1039 }
942 int num_throttled_apps = 0; 1040 int num_throttled_apps = 0;
943 for (OutgoingMessageMap::const_iterator 1041 for (OutgoingMessageMap::const_iterator
944 iter = result->outgoing_messages.begin(); 1042 iter = result->outgoing_messages.begin();
945 iter != result->outgoing_messages.end(); ++iter) { 1043 iter != result->outgoing_messages.end(); ++iter) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 removed_message_counts.begin(); 1078 removed_message_counts.begin();
981 iter != removed_message_counts.end(); ++iter) { 1079 iter != removed_message_counts.end(); ++iter) {
982 DCHECK_NE(app_message_counts_.count(iter->first), 0U); 1080 DCHECK_NE(app_message_counts_.count(iter->first), 0U);
983 app_message_counts_[iter->first] -= iter->second; 1081 app_message_counts_[iter->first] -= iter->second;
984 DCHECK_GE(app_message_counts_[iter->first], 0); 1082 DCHECK_GE(app_message_counts_[iter->first], 0);
985 } 1083 }
986 callback.Run(true); 1084 callback.Run(true);
987 } 1085 }
988 1086
989 } // namespace gcm 1087 } // namespace gcm
OLDNEW
« no previous file with comments | « google_apis/gcm/engine/gcm_store_impl.h ('k') | google_apis/gcm/engine/gcm_store_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698