Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 29 matching lines...) Expand all Loading... | |
| 40 RELOADING_OPEN_STORE, | 40 RELOADING_OPEN_STORE, |
| 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 | 51 |
| 51 // NOTE: always keep this entry at the end. Add new status types only | 52 // NOTE: always keep this entry at the end. Add new status types only |
| 52 // immediately above this line. Make sure to update the corresponding | 53 // immediately above this line. Make sure to update the corresponding |
| 53 // histogram enum accordingly. | 54 // histogram enum accordingly. |
| 54 LOAD_STATUS_COUNT | 55 LOAD_STATUS_COUNT |
| 55 }; | 56 }; |
| 56 | 57 |
| 57 // Limit to the number of outstanding messages per app. | 58 // Limit to the number of outstanding messages per app. |
| 58 const int kMessagesPerAppLimit = 20; | 59 const int kMessagesPerAppLimit = 20; |
| 59 | 60 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 // Key used to indicate how many accounts were last checked in with this device. | 92 // Key used to indicate how many accounts were last checked in with this device. |
| 92 const char kLastCheckinAccountsKey[] = "last_checkin_accounts_count"; | 93 const char kLastCheckinAccountsKey[] = "last_checkin_accounts_count"; |
| 93 // Key used to timestamp last checkin (marked with G services settings update). | 94 // Key used to timestamp last checkin (marked with G services settings update). |
| 94 const char kLastCheckinTimeKey[] = "last_checkin_time"; | 95 const char kLastCheckinTimeKey[] = "last_checkin_time"; |
| 95 // Lowest lexicographically ordered account key. | 96 // Lowest lexicographically ordered account key. |
| 96 // Used for prefixing account information. | 97 // Used for prefixing account information. |
| 97 const char kAccountKeyStart[] = "account1-"; | 98 const char kAccountKeyStart[] = "account1-"; |
| 98 // Key guaranteed to be higher than all account keys. | 99 // Key guaranteed to be higher than all account keys. |
| 99 // Used for limiting iteration. | 100 // Used for limiting iteration. |
| 100 const char kAccountKeyEnd[] = "account2-"; | 101 const char kAccountKeyEnd[] = "account2-"; |
| 102 // Lowest lexicographically ordered heartbeat key. | |
| 103 // Used for prefixing account information. | |
| 104 const char kHeartbeatKeyStart[] = "heartbeat1-"; | |
| 105 // Key guaranteed to be higher than all heartbeat keys. | |
| 106 // Used for limiting iteration. | |
| 107 const char kHeartbeatKeyEnd[] = "heartbeat2-"; | |
| 101 // Key used for last token fetch time. | 108 // Key used for last token fetch time. |
| 102 const char kLastTokenFetchTimeKey[] = "last_token_fetch_time"; | 109 const char kLastTokenFetchTimeKey[] = "last_token_fetch_time"; |
| 103 | 110 |
| 104 std::string MakeRegistrationKey(const std::string& app_id) { | 111 std::string MakeRegistrationKey(const std::string& app_id) { |
| 105 return kRegistrationKeyStart + app_id; | 112 return kRegistrationKeyStart + app_id; |
| 106 } | 113 } |
| 107 | 114 |
| 108 std::string ParseRegistrationKey(const std::string& key) { | 115 std::string ParseRegistrationKey(const std::string& key) { |
| 109 return key.substr(arraysize(kRegistrationKeyStart) - 1); | 116 return key.substr(arraysize(kRegistrationKeyStart) - 1); |
| 110 } | 117 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 130 } | 137 } |
| 131 | 138 |
| 132 std::string MakeAccountKey(const std::string& account_id) { | 139 std::string MakeAccountKey(const std::string& account_id) { |
| 133 return kAccountKeyStart + account_id; | 140 return kAccountKeyStart + account_id; |
| 134 } | 141 } |
| 135 | 142 |
| 136 std::string ParseAccountKey(const std::string& key) { | 143 std::string ParseAccountKey(const std::string& key) { |
| 137 return key.substr(arraysize(kAccountKeyStart) - 1); | 144 return key.substr(arraysize(kAccountKeyStart) - 1); |
| 138 } | 145 } |
| 139 | 146 |
| 147 std::string MakeHeartbeatKey(const std::string& scope) { | |
|
Nicolas Zea
2015/05/04 17:45:28
remind me, what is the scope derived from?
fgorski
2015/05/04 18:14:54
It is simply a token uniquely identifying componen
| |
| 148 return kHeartbeatKeyStart + scope; | |
| 149 } | |
| 150 | |
| 151 std::string ParseHeartbeatKey(const std::string& key) { | |
| 152 return key.substr(arraysize(kHeartbeatKeyStart) - 1); | |
| 153 } | |
| 154 | |
| 140 // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore | 155 // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore |
| 141 // outlive the slice. | 156 // outlive the slice. |
| 142 // For example: MakeSlice(MakeOutgoingKey(x)) is invalid. | 157 // For example: MakeSlice(MakeOutgoingKey(x)) is invalid. |
| 143 leveldb::Slice MakeSlice(const base::StringPiece& s) { | 158 leveldb::Slice MakeSlice(const base::StringPiece& s) { |
| 144 return leveldb::Slice(s.begin(), s.size()); | 159 return leveldb::Slice(s.begin(), s.size()); |
| 145 } | 160 } |
| 146 | 161 |
| 147 } // namespace | 162 } // namespace |
| 148 | 163 |
| 149 class GCMStoreImpl::Backend | 164 class GCMStoreImpl::Backend |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 void SetGServicesSettings( | 202 void SetGServicesSettings( |
| 188 const std::map<std::string, std::string>& settings, | 203 const std::map<std::string, std::string>& settings, |
| 189 const std::string& digest, | 204 const std::string& digest, |
| 190 const UpdateCallback& callback); | 205 const UpdateCallback& callback); |
| 191 void AddAccountMapping(const AccountMapping& account_mapping, | 206 void AddAccountMapping(const AccountMapping& account_mapping, |
| 192 const UpdateCallback& callback); | 207 const UpdateCallback& callback); |
| 193 void RemoveAccountMapping(const std::string& account_id, | 208 void RemoveAccountMapping(const std::string& account_id, |
| 194 const UpdateCallback& callback); | 209 const UpdateCallback& callback); |
| 195 void SetLastTokenFetchTime(const base::Time& time, | 210 void SetLastTokenFetchTime(const base::Time& time, |
| 196 const UpdateCallback& callback); | 211 const UpdateCallback& callback); |
| 212 void AddHeartbeatInterval(const std::string& scope, | |
| 213 int interval_ms, | |
| 214 const UpdateCallback& callback); | |
| 215 void RemoveHeartbeatInterval(const std::string& scope, | |
| 216 const UpdateCallback& callback); | |
| 197 void SetValue(const std::string& key, | 217 void SetValue(const std::string& key, |
| 198 const std::string& value, | 218 const std::string& value, |
| 199 const UpdateCallback& callback); | 219 const UpdateCallback& callback); |
| 200 | 220 |
| 201 private: | 221 private: |
| 202 friend class base::RefCountedThreadSafe<Backend>; | 222 friend class base::RefCountedThreadSafe<Backend>; |
| 203 ~Backend(); | 223 ~Backend(); |
| 204 | 224 |
| 205 LoadStatus OpenStoreAndLoadData(LoadResult* result); | 225 LoadStatus OpenStoreAndLoadData(LoadResult* result); |
| 206 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); | 226 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); |
| 207 bool LoadRegistrations(RegistrationInfoMap* registrations); | 227 bool LoadRegistrations(RegistrationInfoMap* registrations); |
| 208 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); | 228 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); |
| 209 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); | 229 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); |
| 210 bool LoadLastCheckinInfo(base::Time* last_checkin_time, | 230 bool LoadLastCheckinInfo(base::Time* last_checkin_time, |
| 211 std::set<std::string>* accounts); | 231 std::set<std::string>* accounts); |
| 212 bool LoadGServicesSettings(std::map<std::string, std::string>* settings, | 232 bool LoadGServicesSettings(std::map<std::string, std::string>* settings, |
| 213 std::string* digest); | 233 std::string* digest); |
| 214 bool LoadAccountMappingInfo(AccountMappings* account_mappings); | 234 bool LoadAccountMappingInfo(AccountMappings* account_mappings); |
| 215 bool LoadLastTokenFetchTime(base::Time* last_token_fetch_time); | 235 bool LoadLastTokenFetchTime(base::Time* last_token_fetch_time); |
| 236 bool LoadHeartbeatIntervals(std::map<std::string, int>* heartbeat_intervals); | |
| 216 | 237 |
| 217 const base::FilePath path_; | 238 const base::FilePath path_; |
| 218 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; | 239 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; |
| 219 scoped_ptr<Encryptor> encryptor_; | 240 scoped_ptr<Encryptor> encryptor_; |
| 220 | 241 |
| 221 scoped_ptr<leveldb::DB> db_; | 242 scoped_ptr<leveldb::DB> db_; |
| 222 }; | 243 }; |
| 223 | 244 |
| 224 GCMStoreImpl::Backend::Backend( | 245 GCMStoreImpl::Backend::Backend( |
| 225 const base::FilePath& path, | 246 const base::FilePath& path, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 &result->last_checkin_accounts)) { | 287 &result->last_checkin_accounts)) { |
| 267 return LOADING_LAST_CHECKIN_INFO_FAILED; | 288 return LOADING_LAST_CHECKIN_INFO_FAILED; |
| 268 } | 289 } |
| 269 if (!LoadGServicesSettings(&result->gservices_settings, | 290 if (!LoadGServicesSettings(&result->gservices_settings, |
| 270 &result->gservices_digest)) { | 291 &result->gservices_digest)) { |
| 271 return load_status = LOADING_GSERVICE_SETTINGS_FAILED; | 292 return load_status = LOADING_GSERVICE_SETTINGS_FAILED; |
| 272 } | 293 } |
| 273 if (!LoadAccountMappingInfo(&result->account_mappings)) | 294 if (!LoadAccountMappingInfo(&result->account_mappings)) |
| 274 return LOADING_ACCOUNT_MAPPING_FAILED; | 295 return LOADING_ACCOUNT_MAPPING_FAILED; |
| 275 if (!LoadLastTokenFetchTime(&result->last_token_fetch_time)) | 296 if (!LoadLastTokenFetchTime(&result->last_token_fetch_time)) |
| 276 return LOADING_LAST_TOKEN_TIME_FAILED; | 297 return LOADING_LAST_TOKEN_TIME_FAILED; |
| 298 if (!LoadHeartbeatIntervals(&result->heartbeat_intervals)) | |
| 299 return LOADING_HEARTBEAT_INTERVALS_FAILED; | |
| 277 | 300 |
| 278 return LOADING_SUCCEEDED; | 301 return LOADING_SUCCEEDED; |
| 279 } | 302 } |
| 280 | 303 |
| 281 void GCMStoreImpl::Backend::Load(const LoadCallback& callback) { | 304 void GCMStoreImpl::Backend::Load(const LoadCallback& callback) { |
| 282 scoped_ptr<LoadResult> result(new LoadResult()); | 305 scoped_ptr<LoadResult> result(new LoadResult()); |
| 283 LoadStatus load_status = OpenStoreAndLoadData(result.get()); | 306 LoadStatus load_status = OpenStoreAndLoadData(result.get()); |
| 284 UMA_HISTOGRAM_ENUMERATION("GCM.LoadStatus", load_status, LOAD_STATUS_COUNT); | 307 UMA_HISTOGRAM_ENUMERATION("GCM.LoadStatus", load_status, LOAD_STATUS_COUNT); |
| 285 if (load_status != LOADING_SUCCEEDED) { | 308 if (load_status != LOADING_SUCCEEDED) { |
| 286 result->Reset(); | 309 result->Reset(); |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 681 const leveldb::Status s = | 704 const leveldb::Status s = |
| 682 db_->Put(write_options, | 705 db_->Put(write_options, |
| 683 MakeSlice(kLastTokenFetchTimeKey), | 706 MakeSlice(kLastTokenFetchTimeKey), |
| 684 MakeSlice(base::Int64ToString(time.ToInternalValue()))); | 707 MakeSlice(base::Int64ToString(time.ToInternalValue()))); |
| 685 | 708 |
| 686 if (!s.ok()) | 709 if (!s.ok()) |
| 687 LOG(ERROR) << "LevelDB setting last token fetching time: " << s.ToString(); | 710 LOG(ERROR) << "LevelDB setting last token fetching time: " << s.ToString(); |
| 688 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); | 711 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); |
| 689 } | 712 } |
| 690 | 713 |
| 714 void GCMStoreImpl::Backend::AddHeartbeatInterval( | |
| 715 const std::string& scope, | |
| 716 int interval_ms, | |
| 717 const UpdateCallback& callback) { | |
| 718 DVLOG(1) << "Saving a heartbeat interval: scope: " << scope | |
| 719 << " interval: " << interval_ms << "ms."; | |
| 720 if (!db_.get()) { | |
| 721 LOG(ERROR) << "GCMStore db doesn't exist."; | |
| 722 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | |
| 723 return; | |
| 724 } | |
| 725 | |
| 726 leveldb::WriteOptions write_options; | |
| 727 write_options.sync = true; | |
| 728 | |
| 729 std::string data = base::IntToString(interval_ms); | |
| 730 std::string key = MakeHeartbeatKey(scope); | |
| 731 const leveldb::Status s = | |
| 732 db_->Put(write_options, MakeSlice(key), MakeSlice(data)); | |
| 733 if (!s.ok()) | |
| 734 LOG(ERROR) << "LevelDB adding heartbeat interval failed: " << s.ToString(); | |
| 735 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); | |
| 736 } | |
| 737 | |
| 738 void GCMStoreImpl::Backend::RemoveHeartbeatInterval( | |
| 739 const std::string& scope, | |
| 740 const UpdateCallback& callback) { | |
| 741 if (!db_.get()) { | |
| 742 LOG(ERROR) << "GCMStore db doesn't exist."; | |
| 743 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | |
| 744 return; | |
| 745 } | |
| 746 | |
| 747 leveldb::WriteOptions write_options; | |
| 748 write_options.sync = true; | |
| 749 | |
| 750 leveldb::Status s = | |
| 751 db_->Delete(write_options, MakeSlice(MakeHeartbeatKey(scope))); | |
| 752 | |
| 753 if (!s.ok()) { | |
| 754 LOG(ERROR) << "LevelDB removal of heartbeat interval failed: " | |
| 755 << s.ToString(); | |
| 756 } | |
| 757 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); | |
| 758 } | |
| 759 | |
| 691 void GCMStoreImpl::Backend::SetValue(const std::string& key, | 760 void GCMStoreImpl::Backend::SetValue(const std::string& key, |
| 692 const std::string& value, | 761 const std::string& value, |
| 693 const UpdateCallback& callback) { | 762 const UpdateCallback& callback) { |
| 694 DVLOG(1) << "Injecting a value to GCM Store for testing. Key: " | 763 DVLOG(1) << "Injecting a value to GCM Store for testing. Key: " |
| 695 << key << ", Value: " << value; | 764 << key << ", Value: " << value; |
| 696 if (!db_.get()) { | 765 if (!db_.get()) { |
| 697 LOG(ERROR) << "GCMStore db doesn't exist."; | 766 LOG(ERROR) << "GCMStore db doesn't exist."; |
| 698 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 767 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 699 return; | 768 return; |
| 700 } | 769 } |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 922 "Failed to restore last token fetching time. Using default = 0."; | 991 "Failed to restore last token fetching time. Using default = 0."; |
| 923 time_internal = 0LL; | 992 time_internal = 0LL; |
| 924 } | 993 } |
| 925 | 994 |
| 926 // In case we cannot read last token fetching time, we default it to 0. | 995 // In case we cannot read last token fetching time, we default it to 0. |
| 927 *last_token_fetch_time = base::Time::FromInternalValue(time_internal); | 996 *last_token_fetch_time = base::Time::FromInternalValue(time_internal); |
| 928 | 997 |
| 929 return true; | 998 return true; |
| 930 } | 999 } |
| 931 | 1000 |
| 1001 bool GCMStoreImpl::Backend::LoadHeartbeatIntervals( | |
| 1002 std::map<std::string, int>* heartbeat_intervals) { | |
| 1003 leveldb::ReadOptions read_options; | |
| 1004 read_options.verify_checksums = true; | |
| 1005 | |
| 1006 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); | |
| 1007 for (iter->Seek(MakeSlice(kHeartbeatKeyStart)); | |
| 1008 iter->Valid() && iter->key().ToString() < kHeartbeatKeyEnd; | |
| 1009 iter->Next()) { | |
| 1010 std::string scope = ParseHeartbeatKey(iter->key().ToString()); | |
| 1011 int interval_ms; | |
| 1012 if (!base::StringToInt(iter->value().ToString(), &interval_ms)) { | |
| 1013 DVLOG(1) << "Failed to parse heartbeat interval info with scope: " | |
| 1014 << scope; | |
| 1015 return false; | |
| 1016 } | |
| 1017 DVLOG(1) << "Found heartbeat interval with scope: " << scope | |
| 1018 << " interval: " << interval_ms << "ms."; | |
| 1019 (*heartbeat_intervals)[scope] = interval_ms; | |
| 1020 } | |
| 1021 | |
| 1022 return true; | |
| 1023 } | |
| 1024 | |
| 932 GCMStoreImpl::GCMStoreImpl( | 1025 GCMStoreImpl::GCMStoreImpl( |
| 933 const base::FilePath& path, | 1026 const base::FilePath& path, |
| 934 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, | 1027 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, |
| 935 scoped_ptr<Encryptor> encryptor) | 1028 scoped_ptr<Encryptor> encryptor) |
| 936 : backend_(new Backend(path, | 1029 : backend_(new Backend(path, |
| 937 base::MessageLoopProxy::current(), | 1030 base::MessageLoopProxy::current(), |
| 938 encryptor.Pass())), | 1031 encryptor.Pass())), |
| 939 blocking_task_runner_(blocking_task_runner), | 1032 blocking_task_runner_(blocking_task_runner), |
| 940 weak_ptr_factory_(this) { | 1033 weak_ptr_factory_(this) { |
| 941 } | 1034 } |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1152 void GCMStoreImpl::SetLastTokenFetchTime(const base::Time& time, | 1245 void GCMStoreImpl::SetLastTokenFetchTime(const base::Time& time, |
| 1153 const UpdateCallback& callback) { | 1246 const UpdateCallback& callback) { |
| 1154 blocking_task_runner_->PostTask( | 1247 blocking_task_runner_->PostTask( |
| 1155 FROM_HERE, | 1248 FROM_HERE, |
| 1156 base::Bind(&GCMStoreImpl::Backend::SetLastTokenFetchTime, | 1249 base::Bind(&GCMStoreImpl::Backend::SetLastTokenFetchTime, |
| 1157 backend_, | 1250 backend_, |
| 1158 time, | 1251 time, |
| 1159 callback)); | 1252 callback)); |
| 1160 } | 1253 } |
| 1161 | 1254 |
| 1255 void GCMStoreImpl::AddHeartbeatInterval(const std::string& scope, | |
| 1256 int interval_ms, | |
| 1257 const UpdateCallback& callback) { | |
| 1258 blocking_task_runner_->PostTask( | |
| 1259 FROM_HERE, | |
| 1260 base::Bind(&GCMStoreImpl::Backend::AddHeartbeatInterval, | |
| 1261 backend_, | |
| 1262 scope, | |
| 1263 interval_ms, | |
| 1264 callback)); | |
| 1265 } | |
| 1266 | |
| 1267 void GCMStoreImpl::RemoveHeartbeatInterval(const std::string& scope, | |
| 1268 const UpdateCallback& callback) { | |
| 1269 blocking_task_runner_->PostTask( | |
| 1270 FROM_HERE, | |
| 1271 base::Bind(&GCMStoreImpl::Backend::RemoveHeartbeatInterval, | |
| 1272 backend_, | |
| 1273 scope, | |
| 1274 callback)); | |
| 1275 } | |
| 1276 | |
| 1162 void GCMStoreImpl::SetValueForTesting(const std::string& key, | 1277 void GCMStoreImpl::SetValueForTesting(const std::string& key, |
| 1163 const std::string& value, | 1278 const std::string& value, |
| 1164 const UpdateCallback& callback) { | 1279 const UpdateCallback& callback) { |
| 1165 blocking_task_runner_->PostTask( | 1280 blocking_task_runner_->PostTask( |
| 1166 FROM_HERE, | 1281 FROM_HERE, |
| 1167 base::Bind(&GCMStoreImpl::Backend::SetValue, | 1282 base::Bind(&GCMStoreImpl::Backend::SetValue, |
| 1168 backend_, | 1283 backend_, |
| 1169 key, | 1284 key, |
| 1170 value, | 1285 value, |
| 1171 callback)); | 1286 callback)); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1222 removed_message_counts.begin(); | 1337 removed_message_counts.begin(); |
| 1223 iter != removed_message_counts.end(); ++iter) { | 1338 iter != removed_message_counts.end(); ++iter) { |
| 1224 DCHECK_NE(app_message_counts_.count(iter->first), 0U); | 1339 DCHECK_NE(app_message_counts_.count(iter->first), 0U); |
| 1225 app_message_counts_[iter->first] -= iter->second; | 1340 app_message_counts_[iter->first] -= iter->second; |
| 1226 DCHECK_GE(app_message_counts_[iter->first], 0); | 1341 DCHECK_GE(app_message_counts_[iter->first], 0); |
| 1227 } | 1342 } |
| 1228 callback.Run(true); | 1343 callback.Run(true); |
| 1229 } | 1344 } |
| 1230 | 1345 |
| 1231 } // namespace gcm | 1346 } // namespace gcm |
| OLD | NEW |