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

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

Issue 1126233004: Persist Instance ID data to GCM store. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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
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/files/file_path.h" 10 #include "base/files/file_path.h"
(...skipping 30 matching lines...) Expand all
41 OPENING_STORE_FAILED, 41 OPENING_STORE_FAILED,
42 LOADING_DEVICE_CREDENTIALS_FAILED, 42 LOADING_DEVICE_CREDENTIALS_FAILED,
43 LOADING_REGISTRATION_FAILED, 43 LOADING_REGISTRATION_FAILED,
44 LOADING_INCOMING_MESSAGES_FAILED, 44 LOADING_INCOMING_MESSAGES_FAILED,
45 LOADING_OUTGOING_MESSAGES_FAILED, 45 LOADING_OUTGOING_MESSAGES_FAILED,
46 LOADING_LAST_CHECKIN_INFO_FAILED, 46 LOADING_LAST_CHECKIN_INFO_FAILED,
47 LOADING_GSERVICE_SETTINGS_FAILED, 47 LOADING_GSERVICE_SETTINGS_FAILED,
48 LOADING_ACCOUNT_MAPPING_FAILED, 48 LOADING_ACCOUNT_MAPPING_FAILED,
49 LOADING_LAST_TOKEN_TIME_FAILED, 49 LOADING_LAST_TOKEN_TIME_FAILED,
50 LOADING_HEARTBEAT_INTERVALS_FAILED, 50 LOADING_HEARTBEAT_INTERVALS_FAILED,
51 LOADING_INSTANCE_ID_DATA_FAILED,
51 52
52 // NOTE: always keep this entry at the end. Add new status types only 53 // NOTE: always keep this entry at the end. Add new status types only
53 // immediately above this line. Make sure to update the corresponding 54 // immediately above this line. Make sure to update the corresponding
54 // histogram enum accordingly. 55 // histogram enum accordingly.
55 LOAD_STATUS_COUNT 56 LOAD_STATUS_COUNT
56 }; 57 };
57 58
58 // Limit to the number of outstanding messages per app. 59 // Limit to the number of outstanding messages per app.
59 const int kMessagesPerAppLimit = 20; 60 const int kMessagesPerAppLimit = 20;
60 61
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 // Used for limiting iteration. 101 // Used for limiting iteration.
101 const char kAccountKeyEnd[] = "account2-"; 102 const char kAccountKeyEnd[] = "account2-";
102 // Lowest lexicographically ordered heartbeat key. 103 // Lowest lexicographically ordered heartbeat key.
103 // Used for prefixing account information. 104 // Used for prefixing account information.
104 const char kHeartbeatKeyStart[] = "heartbeat1-"; 105 const char kHeartbeatKeyStart[] = "heartbeat1-";
105 // Key guaranteed to be higher than all heartbeat keys. 106 // Key guaranteed to be higher than all heartbeat keys.
106 // Used for limiting iteration. 107 // Used for limiting iteration.
107 const char kHeartbeatKeyEnd[] = "heartbeat2-"; 108 const char kHeartbeatKeyEnd[] = "heartbeat2-";
108 // Key used for last token fetch time. 109 // Key used for last token fetch time.
109 const char kLastTokenFetchTimeKey[] = "last_token_fetch_time"; 110 const char kLastTokenFetchTimeKey[] = "last_token_fetch_time";
111 // Lowest lexicographically ordered app ids.
112 // Used for prefixing app id.
113 const char kInstanceIDKeyStart[] = "iid1-";
114 // Key guaranteed to be higher than all app ids.
115 // Used for limiting iteration.
116 const char kInstanceIDKeyEnd[] = "iid2-";
110 117
111 std::string MakeRegistrationKey(const std::string& app_id) { 118 std::string MakeRegistrationKey(const std::string& app_id) {
112 return kRegistrationKeyStart + app_id; 119 return kRegistrationKeyStart + app_id;
113 } 120 }
114 121
115 std::string ParseRegistrationKey(const std::string& key) { 122 std::string ParseRegistrationKey(const std::string& key) {
116 return key.substr(arraysize(kRegistrationKeyStart) - 1); 123 return key.substr(arraysize(kRegistrationKeyStart) - 1);
117 } 124 }
118 125
119 std::string MakeIncomingKey(const std::string& persistent_id) { 126 std::string MakeIncomingKey(const std::string& persistent_id) {
(...skipping 25 matching lines...) Expand all
145 } 152 }
146 153
147 std::string MakeHeartbeatKey(const std::string& scope) { 154 std::string MakeHeartbeatKey(const std::string& scope) {
148 return kHeartbeatKeyStart + scope; 155 return kHeartbeatKeyStart + scope;
149 } 156 }
150 157
151 std::string ParseHeartbeatKey(const std::string& key) { 158 std::string ParseHeartbeatKey(const std::string& key) {
152 return key.substr(arraysize(kHeartbeatKeyStart) - 1); 159 return key.substr(arraysize(kHeartbeatKeyStart) - 1);
153 } 160 }
154 161
162 std::string MakeInstanceIDKey(const std::string& app_id) {
163 return kInstanceIDKeyStart + app_id;
164 }
165
166 std::string ParseInstanceIDKey(const std::string& key) {
167 return key.substr(arraysize(kInstanceIDKeyStart) - 1);
168 }
169
155 // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore 170 // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore
156 // outlive the slice. 171 // outlive the slice.
157 // For example: MakeSlice(MakeOutgoingKey(x)) is invalid. 172 // For example: MakeSlice(MakeOutgoingKey(x)) is invalid.
158 leveldb::Slice MakeSlice(const base::StringPiece& s) { 173 leveldb::Slice MakeSlice(const base::StringPiece& s) {
159 return leveldb::Slice(s.begin(), s.size()); 174 return leveldb::Slice(s.begin(), s.size());
160 } 175 }
161 176
162 } // namespace 177 } // namespace
163 178
164 class GCMStoreImpl::Backend 179 class GCMStoreImpl::Backend
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 const UpdateCallback& callback); 222 const UpdateCallback& callback);
208 void RemoveAccountMapping(const std::string& account_id, 223 void RemoveAccountMapping(const std::string& account_id,
209 const UpdateCallback& callback); 224 const UpdateCallback& callback);
210 void SetLastTokenFetchTime(const base::Time& time, 225 void SetLastTokenFetchTime(const base::Time& time,
211 const UpdateCallback& callback); 226 const UpdateCallback& callback);
212 void AddHeartbeatInterval(const std::string& scope, 227 void AddHeartbeatInterval(const std::string& scope,
213 int interval_ms, 228 int interval_ms,
214 const UpdateCallback& callback); 229 const UpdateCallback& callback);
215 void RemoveHeartbeatInterval(const std::string& scope, 230 void RemoveHeartbeatInterval(const std::string& scope,
216 const UpdateCallback& callback); 231 const UpdateCallback& callback);
232 void AddInstanceIDData(const std::string& app_id,
233 const std::string& instance_id_data,
234 const UpdateCallback& callback);
235 void RemoveInstanceIDData(const std::string& app_id,
236 const UpdateCallback& callback);
217 void SetValue(const std::string& key, 237 void SetValue(const std::string& key,
218 const std::string& value, 238 const std::string& value,
219 const UpdateCallback& callback); 239 const UpdateCallback& callback);
220 240
221 private: 241 private:
222 friend class base::RefCountedThreadSafe<Backend>; 242 friend class base::RefCountedThreadSafe<Backend>;
223 ~Backend(); 243 ~Backend();
224 244
225 LoadStatus OpenStoreAndLoadData(LoadResult* result); 245 LoadStatus OpenStoreAndLoadData(LoadResult* result);
226 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); 246 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token);
227 bool LoadRegistrations(RegistrationInfoMap* registrations); 247 bool LoadRegistrations(RegistrationInfoMap* registrations);
228 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); 248 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages);
229 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); 249 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages);
230 bool LoadLastCheckinInfo(base::Time* last_checkin_time, 250 bool LoadLastCheckinInfo(base::Time* last_checkin_time,
231 std::set<std::string>* accounts); 251 std::set<std::string>* accounts);
232 bool LoadGServicesSettings(std::map<std::string, std::string>* settings, 252 bool LoadGServicesSettings(std::map<std::string, std::string>* settings,
233 std::string* digest); 253 std::string* digest);
234 bool LoadAccountMappingInfo(AccountMappings* account_mappings); 254 bool LoadAccountMappingInfo(AccountMappings* account_mappings);
235 bool LoadLastTokenFetchTime(base::Time* last_token_fetch_time); 255 bool LoadLastTokenFetchTime(base::Time* last_token_fetch_time);
236 bool LoadHeartbeatIntervals(std::map<std::string, int>* heartbeat_intervals); 256 bool LoadHeartbeatIntervals(std::map<std::string, int>* heartbeat_intervals);
257 bool LoadInstanceIDData(std::map<std::string, std::string>* instance_id_data);
237 258
238 const base::FilePath path_; 259 const base::FilePath path_;
239 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; 260 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_;
240 scoped_ptr<Encryptor> encryptor_; 261 scoped_ptr<Encryptor> encryptor_;
241 262
242 scoped_ptr<leveldb::DB> db_; 263 scoped_ptr<leveldb::DB> db_;
243 }; 264 };
244 265
245 GCMStoreImpl::Backend::Backend( 266 GCMStoreImpl::Backend::Backend(
246 const base::FilePath& path, 267 const base::FilePath& path,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 if (!LoadGServicesSettings(&result->gservices_settings, 311 if (!LoadGServicesSettings(&result->gservices_settings,
291 &result->gservices_digest)) { 312 &result->gservices_digest)) {
292 return load_status = LOADING_GSERVICE_SETTINGS_FAILED; 313 return load_status = LOADING_GSERVICE_SETTINGS_FAILED;
293 } 314 }
294 if (!LoadAccountMappingInfo(&result->account_mappings)) 315 if (!LoadAccountMappingInfo(&result->account_mappings))
295 return LOADING_ACCOUNT_MAPPING_FAILED; 316 return LOADING_ACCOUNT_MAPPING_FAILED;
296 if (!LoadLastTokenFetchTime(&result->last_token_fetch_time)) 317 if (!LoadLastTokenFetchTime(&result->last_token_fetch_time))
297 return LOADING_LAST_TOKEN_TIME_FAILED; 318 return LOADING_LAST_TOKEN_TIME_FAILED;
298 if (!LoadHeartbeatIntervals(&result->heartbeat_intervals)) 319 if (!LoadHeartbeatIntervals(&result->heartbeat_intervals))
299 return LOADING_HEARTBEAT_INTERVALS_FAILED; 320 return LOADING_HEARTBEAT_INTERVALS_FAILED;
321 if (!LoadInstanceIDData(&result->instance_id_data))
322 return LOADING_INSTANCE_ID_DATA_FAILED;
300 323
301 return LOADING_SUCCEEDED; 324 return LOADING_SUCCEEDED;
302 } 325 }
303 326
304 void GCMStoreImpl::Backend::Load(const LoadCallback& callback) { 327 void GCMStoreImpl::Backend::Load(const LoadCallback& callback) {
305 scoped_ptr<LoadResult> result(new LoadResult()); 328 scoped_ptr<LoadResult> result(new LoadResult());
306 LoadStatus load_status = OpenStoreAndLoadData(result.get()); 329 LoadStatus load_status = OpenStoreAndLoadData(result.get());
307 UMA_HISTOGRAM_ENUMERATION("GCM.LoadStatus", load_status, LOAD_STATUS_COUNT); 330 UMA_HISTOGRAM_ENUMERATION("GCM.LoadStatus", load_status, LOAD_STATUS_COUNT);
308 if (load_status != LOADING_SUCCEEDED) { 331 if (load_status != LOADING_SUCCEEDED) {
309 result->Reset(); 332 result->Reset();
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 623
601 leveldb::WriteOptions write_options; 624 leveldb::WriteOptions write_options;
602 write_options.sync = true; 625 write_options.sync = true;
603 const leveldb::Status s = db_->Write(write_options, &write_batch); 626 const leveldb::Status s = db_->Write(write_options, &write_batch);
604 627
605 if (!s.ok()) 628 if (!s.ok())
606 LOG(ERROR) << "LevelDB set last checkin info failed: " << s.ToString(); 629 LOG(ERROR) << "LevelDB set last checkin info failed: " << s.ToString();
607 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); 630 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok()));
608 } 631 }
609 632
633 void GCMStoreImpl::AddInstanceIDData(const std::string& app_id,
634 const std::string& instance_id_data,
635 const UpdateCallback& callback) {
636 blocking_task_runner_->PostTask(
637 FROM_HERE,
638 base::Bind(&GCMStoreImpl::Backend::AddInstanceIDData,
639 backend_,
640 app_id,
641 instance_id_data,
642 callback));
643 }
644
645 void GCMStoreImpl::RemoveInstanceIDData(const std::string& app_id,
646 const UpdateCallback& callback) {
647 blocking_task_runner_->PostTask(
648 FROM_HERE,
649 base::Bind(&GCMStoreImpl::Backend::RemoveInstanceIDData,
650 backend_,
651 app_id,
652 callback));
653 }
654
610 void GCMStoreImpl::Backend::SetGServicesSettings( 655 void GCMStoreImpl::Backend::SetGServicesSettings(
611 const std::map<std::string, std::string>& settings, 656 const std::map<std::string, std::string>& settings,
612 const std::string& settings_digest, 657 const std::string& settings_digest,
613 const UpdateCallback& callback) { 658 const UpdateCallback& callback) {
614 leveldb::WriteBatch write_batch; 659 leveldb::WriteBatch write_batch;
615 660
616 // Remove all existing settings. 661 // Remove all existing settings.
617 leveldb::ReadOptions read_options; 662 leveldb::ReadOptions read_options;
618 read_options.verify_checksums = true; 663 read_options.verify_checksums = true;
619 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 664 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 leveldb::Status s = 795 leveldb::Status s =
751 db_->Delete(write_options, MakeSlice(MakeHeartbeatKey(scope))); 796 db_->Delete(write_options, MakeSlice(MakeHeartbeatKey(scope)));
752 797
753 if (!s.ok()) { 798 if (!s.ok()) {
754 LOG(ERROR) << "LevelDB removal of heartbeat interval failed: " 799 LOG(ERROR) << "LevelDB removal of heartbeat interval failed: "
755 << s.ToString(); 800 << s.ToString();
756 } 801 }
757 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); 802 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok()));
758 } 803 }
759 804
805 void GCMStoreImpl::Backend::AddInstanceIDData(
806 const std::string& app_id,
807 const std::string& instance_id_data,
808 const UpdateCallback& callback) {
809 DVLOG(1) << "Adding Instance ID data.";
810 if (!db_.get()) {
811 LOG(ERROR) << "GCMStore db doesn't exist.";
812 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
813 return;
814 }
815
816 leveldb::WriteOptions write_options;
817 write_options.sync = true;
818
819 std::string key = MakeInstanceIDKey(app_id);
820 const leveldb::Status status = db_->Put(write_options,
821 MakeSlice(key),
822 MakeSlice(instance_id_data));
823 if (status.ok()) {
fgorski 2015/05/08 17:12:33 nit: see method above for a cleaner completion if
jianli 2015/05/08 20:56:01 Done.
824 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
825 return;
826 }
827 LOG(ERROR) << "LevelDB put failed: " << status.ToString();
828 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
829 }
830
831 void GCMStoreImpl::Backend::RemoveInstanceIDData(
832 const std::string& app_id,
833 const UpdateCallback& callback) {
834 if (!db_.get()) {
835 LOG(ERROR) << "GCMStore db doesn't exist.";
836 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
837 return;
838 }
839 leveldb::WriteOptions write_options;
840 write_options.sync = true;
841
842 leveldb::Status status =
843 db_->Delete(write_options, MakeSlice(MakeInstanceIDKey(app_id)));
844 if (status.ok()) {
845 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
846 return;
847 }
848 LOG(ERROR) << "LevelDB remove failed: " << status.ToString();
849 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
850 }
851
760 void GCMStoreImpl::Backend::SetValue(const std::string& key, 852 void GCMStoreImpl::Backend::SetValue(const std::string& key,
761 const std::string& value, 853 const std::string& value,
762 const UpdateCallback& callback) { 854 const UpdateCallback& callback) {
763 DVLOG(1) << "Injecting a value to GCM Store for testing. Key: " 855 DVLOG(1) << "Injecting a value to GCM Store for testing. Key: "
764 << key << ", Value: " << value; 856 << key << ", Value: " << value;
765 if (!db_.get()) { 857 if (!db_.get()) {
766 LOG(ERROR) << "GCMStore db doesn't exist."; 858 LOG(ERROR) << "GCMStore db doesn't exist.";
767 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 859 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
768 return; 860 return;
769 } 861 }
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 return false; 1107 return false;
1016 } 1108 }
1017 DVLOG(1) << "Found heartbeat interval with scope: " << scope 1109 DVLOG(1) << "Found heartbeat interval with scope: " << scope
1018 << " interval: " << interval_ms << "ms."; 1110 << " interval: " << interval_ms << "ms.";
1019 (*heartbeat_intervals)[scope] = interval_ms; 1111 (*heartbeat_intervals)[scope] = interval_ms;
1020 } 1112 }
1021 1113
1022 return true; 1114 return true;
1023 } 1115 }
1024 1116
1117 bool GCMStoreImpl::Backend::LoadInstanceIDData(
1118 std::map<std::string, std::string>* instance_id_data) {
1119 leveldb::ReadOptions read_options;
1120 read_options.verify_checksums = true;
1121
1122 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
1123 for (iter->Seek(MakeSlice(kInstanceIDKeyStart));
1124 iter->Valid() && iter->key().ToString() < kInstanceIDKeyEnd;
1125 iter->Next()) {
1126 leveldb::Slice s = iter->value();
1127 if (s.size() <= 1) {
1128 LOG(ERROR) << "Error reading IID data with key " << s.ToString();
1129 return false;
1130 }
1131 std::string app_id = ParseInstanceIDKey(iter->key().ToString());
1132 DVLOG(1) << "Found IID data with app id " << app_id;
1133 (*instance_id_data)[app_id] = s.ToString();
1134 }
1135
1136 return true;
1137 }
1138
1025 GCMStoreImpl::GCMStoreImpl( 1139 GCMStoreImpl::GCMStoreImpl(
1026 const base::FilePath& path, 1140 const base::FilePath& path,
1027 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, 1141 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
1028 scoped_ptr<Encryptor> encryptor) 1142 scoped_ptr<Encryptor> encryptor)
1029 : backend_(new Backend(path, 1143 : backend_(new Backend(path,
1030 base::MessageLoopProxy::current(), 1144 base::MessageLoopProxy::current(),
1031 encryptor.Pass())), 1145 encryptor.Pass())),
1032 blocking_task_runner_(blocking_task_runner), 1146 blocking_task_runner_(blocking_task_runner),
1033 weak_ptr_factory_(this) { 1147 weak_ptr_factory_(this) {
1034 } 1148 }
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
1337 removed_message_counts.begin(); 1451 removed_message_counts.begin();
1338 iter != removed_message_counts.end(); ++iter) { 1452 iter != removed_message_counts.end(); ++iter) {
1339 DCHECK_NE(app_message_counts_.count(iter->first), 0U); 1453 DCHECK_NE(app_message_counts_.count(iter->first), 0U);
1340 app_message_counts_[iter->first] -= iter->second; 1454 app_message_counts_[iter->first] -= iter->second;
1341 DCHECK_GE(app_message_counts_[iter->first], 0); 1455 DCHECK_GE(app_message_counts_[iter->first], 0);
1342 } 1456 }
1343 callback.Run(true); 1457 callback.Run(true);
1344 } 1458 }
1345 1459
1346 } // namespace gcm 1460 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698