| 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/file_util.h" | 10 #include "base/file_util.h" |
| 11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/message_loop/message_loop_proxy.h" | 13 #include "base/message_loop/message_loop_proxy.h" |
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/sequenced_task_runner.h" | 15 #include "base/sequenced_task_runner.h" |
| 16 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/strings/string_piece.h" | 18 #include "base/strings/string_piece.h" |
| 19 #include "base/strings/string_tokenizer.h" |
| 19 #include "base/time/time.h" | 20 #include "base/time/time.h" |
| 20 #include "base/tracked_objects.h" | 21 #include "base/tracked_objects.h" |
| 21 #include "google_apis/gcm/base/encryptor.h" | 22 #include "google_apis/gcm/base/encryptor.h" |
| 22 #include "google_apis/gcm/base/mcs_message.h" | 23 #include "google_apis/gcm/base/mcs_message.h" |
| 23 #include "google_apis/gcm/base/mcs_util.h" | 24 #include "google_apis/gcm/base/mcs_util.h" |
| 24 #include "google_apis/gcm/protocol/mcs.pb.h" | 25 #include "google_apis/gcm/protocol/mcs.pb.h" |
| 25 #include "third_party/leveldatabase/src/include/leveldb/db.h" | 26 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
| 26 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" | 27 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
| 27 | 28 |
| 28 namespace gcm { | 29 namespace gcm { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 56 // Used for limiting iteration. | 57 // Used for limiting iteration. |
| 57 const char kOutgoingMsgKeyEnd[] = "outgoing2-"; | 58 const char kOutgoingMsgKeyEnd[] = "outgoing2-"; |
| 58 // Lowest lexicographically ordered G-service settings key. | 59 // Lowest lexicographically ordered G-service settings key. |
| 59 // Used for prefixing G-services settings. | 60 // Used for prefixing G-services settings. |
| 60 const char kGServiceSettingKeyStart[] = "gservice1-"; | 61 const char kGServiceSettingKeyStart[] = "gservice1-"; |
| 61 // Key guaranteed to be higher than all G-services settings keys. | 62 // Key guaranteed to be higher than all G-services settings keys. |
| 62 // Used for limiting iteration. | 63 // Used for limiting iteration. |
| 63 const char kGServiceSettingKeyEnd[] = "gservice2-"; | 64 const char kGServiceSettingKeyEnd[] = "gservice2-"; |
| 64 // Key for digest of the last G-services settings update. | 65 // Key for digest of the last G-services settings update. |
| 65 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. |
| 68 const char kLastCheckinAccountsKey[] = "last_checkin_accounts_count"; |
| 66 // 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). |
| 67 const char kLastCheckinTimeKey[] = "last_checkin_time"; | 70 const char kLastCheckinTimeKey[] = "last_checkin_time"; |
| 68 | 71 |
| 69 std::string MakeRegistrationKey(const std::string& app_id) { | 72 std::string MakeRegistrationKey(const std::string& app_id) { |
| 70 return kRegistrationKeyStart + app_id; | 73 return kRegistrationKeyStart + app_id; |
| 71 } | 74 } |
| 72 | 75 |
| 73 std::string ParseRegistrationKey(const std::string& key) { | 76 std::string ParseRegistrationKey(const std::string& key) { |
| 74 return key.substr(arraysize(kRegistrationKeyStart) - 1); | 77 return key.substr(arraysize(kRegistrationKeyStart) - 1); |
| 75 } | 78 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 const UpdateCallback& callback); | 134 const UpdateCallback& callback); |
| 132 void RemoveOutgoingMessages( | 135 void RemoveOutgoingMessages( |
| 133 const PersistentIdList& persistent_ids, | 136 const PersistentIdList& persistent_ids, |
| 134 const base::Callback<void(bool, const AppIdToMessageCountMap&)> | 137 const base::Callback<void(bool, const AppIdToMessageCountMap&)> |
| 135 callback); | 138 callback); |
| 136 void AddUserSerialNumber(const std::string& username, | 139 void AddUserSerialNumber(const std::string& username, |
| 137 int64 serial_number, | 140 int64 serial_number, |
| 138 const UpdateCallback& callback); | 141 const UpdateCallback& callback); |
| 139 void RemoveUserSerialNumber(const std::string& username, | 142 void RemoveUserSerialNumber(const std::string& username, |
| 140 const UpdateCallback& callback); | 143 const UpdateCallback& callback); |
| 141 void SetLastCheckinTime(const base::Time& last_checkin_time, | 144 void SetLastCheckinInfo(const base::Time& time, |
| 145 const std::set<std::string>& accounts, |
| 142 const UpdateCallback& callback); | 146 const UpdateCallback& callback); |
| 143 void SetGServicesSettings( | 147 void SetGServicesSettings( |
| 144 const std::map<std::string, std::string>& settings, | 148 const std::map<std::string, std::string>& settings, |
| 145 const std::string& digest, | 149 const std::string& digest, |
| 146 const UpdateCallback& callback); | 150 const UpdateCallback& callback); |
| 147 | 151 |
| 148 private: | 152 private: |
| 149 friend class base::RefCountedThreadSafe<Backend>; | 153 friend class base::RefCountedThreadSafe<Backend>; |
| 150 ~Backend(); | 154 ~Backend(); |
| 151 | 155 |
| 152 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); | 156 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); |
| 153 bool LoadRegistrations(RegistrationInfoMap* registrations); | 157 bool LoadRegistrations(RegistrationInfoMap* registrations); |
| 154 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); | 158 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); |
| 155 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); | 159 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); |
| 156 bool LoadLastCheckinTime(base::Time* last_checkin_time); | 160 bool LoadLastCheckinInfo(base::Time* last_checkin_time, |
| 161 std::set<std::string>* accounts); |
| 157 bool LoadGServicesSettings(std::map<std::string, std::string>* settings, | 162 bool LoadGServicesSettings(std::map<std::string, std::string>* settings, |
| 158 std::string* digest); | 163 std::string* digest); |
| 159 | 164 |
| 160 const base::FilePath path_; | 165 const base::FilePath path_; |
| 161 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; | 166 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; |
| 162 scoped_ptr<Encryptor> encryptor_; | 167 scoped_ptr<Encryptor> encryptor_; |
| 163 | 168 |
| 164 scoped_ptr<leveldb::DB> db_; | 169 scoped_ptr<leveldb::DB> db_; |
| 165 }; | 170 }; |
| 166 | 171 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 base::Passed(&result))); | 204 base::Passed(&result))); |
| 200 return; | 205 return; |
| 201 } | 206 } |
| 202 db_.reset(db); | 207 db_.reset(db); |
| 203 | 208 |
| 204 if (!LoadDeviceCredentials(&result->device_android_id, | 209 if (!LoadDeviceCredentials(&result->device_android_id, |
| 205 &result->device_security_token) || | 210 &result->device_security_token) || |
| 206 !LoadRegistrations(&result->registrations) || | 211 !LoadRegistrations(&result->registrations) || |
| 207 !LoadIncomingMessages(&result->incoming_messages) || | 212 !LoadIncomingMessages(&result->incoming_messages) || |
| 208 !LoadOutgoingMessages(&result->outgoing_messages) || | 213 !LoadOutgoingMessages(&result->outgoing_messages) || |
| 209 !LoadLastCheckinTime(&result->last_checkin_time) || | 214 !LoadLastCheckinInfo(&result->last_checkin_time, |
| 215 &result->last_checkin_accounts) || |
| 210 !LoadGServicesSettings(&result->gservices_settings, | 216 !LoadGServicesSettings(&result->gservices_settings, |
| 211 &result->gservices_digest)) { | 217 &result->gservices_digest)) { |
| 212 result->device_android_id = 0; | 218 result->device_android_id = 0; |
| 213 result->device_security_token = 0; | 219 result->device_security_token = 0; |
| 214 result->registrations.clear(); | 220 result->registrations.clear(); |
| 215 result->incoming_messages.clear(); | 221 result->incoming_messages.clear(); |
| 216 result->outgoing_messages.clear(); | 222 result->outgoing_messages.clear(); |
| 217 result->gservices_settings.clear(); | 223 result->gservices_settings.clear(); |
| 218 result->gservices_digest.clear(); | 224 result->gservices_digest.clear(); |
| 219 result->last_checkin_time = base::Time::FromInternalValue(0LL); | 225 result->last_checkin_time = base::Time::FromInternalValue(0LL); |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 removed_message_counts)); | 484 removed_message_counts)); |
| 479 return; | 485 return; |
| 480 } | 486 } |
| 481 LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); | 487 LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); |
| 482 foreground_task_runner_->PostTask(FROM_HERE, | 488 foreground_task_runner_->PostTask(FROM_HERE, |
| 483 base::Bind(callback, | 489 base::Bind(callback, |
| 484 false, | 490 false, |
| 485 AppIdToMessageCountMap())); | 491 AppIdToMessageCountMap())); |
| 486 } | 492 } |
| 487 | 493 |
| 488 void GCMStoreImpl::Backend::SetLastCheckinTime( | 494 void GCMStoreImpl::Backend::SetLastCheckinInfo( |
| 489 const base::Time& last_checkin_time, | 495 const base::Time& time, |
| 496 const std::set<std::string>& accounts, |
| 490 const UpdateCallback& callback) { | 497 const UpdateCallback& callback) { |
| 498 leveldb::WriteBatch write_batch; |
| 499 |
| 500 int64 last_checkin_time_internal = time.ToInternalValue(); |
| 501 write_batch.Put(MakeSlice(kLastCheckinTimeKey), |
| 502 MakeSlice(base::Int64ToString(last_checkin_time_internal))); |
| 503 |
| 504 std::string serialized_accounts; |
| 505 for (std::set<std::string>::iterator iter = accounts.begin(); |
| 506 iter != accounts.end(); |
| 507 ++iter) { |
| 508 serialized_accounts += *iter; |
| 509 serialized_accounts += ","; |
| 510 } |
| 511 if (!serialized_accounts.empty()) |
| 512 serialized_accounts.erase(serialized_accounts.length() - 1); |
| 513 |
| 514 write_batch.Put(MakeSlice(kLastCheckinAccountsKey), |
| 515 MakeSlice(serialized_accounts)); |
| 516 |
| 491 leveldb::WriteOptions write_options; | 517 leveldb::WriteOptions write_options; |
| 492 write_options.sync = true; | 518 write_options.sync = true; |
| 493 | 519 const leveldb::Status s = db_->Write(write_options, &write_batch); |
| 494 int64 last_checkin_time_internal = last_checkin_time.ToInternalValue(); | |
| 495 const leveldb::Status s = | |
| 496 db_->Put(write_options, | |
| 497 MakeSlice(kLastCheckinTimeKey), | |
| 498 MakeSlice(base::Int64ToString(last_checkin_time_internal))); | |
| 499 | 520 |
| 500 if (!s.ok()) | 521 if (!s.ok()) |
| 501 LOG(ERROR) << "LevelDB set last checkin time failed: " << s.ToString(); | 522 LOG(ERROR) << "LevelDB set last checkin info failed: " << s.ToString(); |
| 502 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); | 523 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); |
| 503 } | 524 } |
| 504 | 525 |
| 505 void GCMStoreImpl::Backend::SetGServicesSettings( | 526 void GCMStoreImpl::Backend::SetGServicesSettings( |
| 506 const std::map<std::string, std::string>& settings, | 527 const std::map<std::string, std::string>& settings, |
| 507 const std::string& settings_digest, | 528 const std::string& settings_digest, |
| 508 const UpdateCallback& callback) { | 529 const UpdateCallback& callback) { |
| 509 leveldb::WriteBatch write_batch; | 530 leveldb::WriteBatch write_batch; |
| 510 | 531 |
| 511 // Remove all existing settings. | 532 // Remove all existing settings. |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 return false; | 669 return false; |
| 649 } | 670 } |
| 650 DVLOG(1) << "Found outgoing message with id " << id << " of type " | 671 DVLOG(1) << "Found outgoing message with id " << id << " of type " |
| 651 << base::IntToString(tag); | 672 << base::IntToString(tag); |
| 652 (*outgoing_messages)[id] = make_linked_ptr(message.release()); | 673 (*outgoing_messages)[id] = make_linked_ptr(message.release()); |
| 653 } | 674 } |
| 654 | 675 |
| 655 return true; | 676 return true; |
| 656 } | 677 } |
| 657 | 678 |
| 658 bool GCMStoreImpl::Backend::LoadLastCheckinTime( | 679 bool GCMStoreImpl::Backend::LoadLastCheckinInfo( |
| 659 base::Time* last_checkin_time) { | 680 base::Time* last_checkin_time, |
| 681 std::set<std::string>* accounts) { |
| 660 leveldb::ReadOptions read_options; | 682 leveldb::ReadOptions read_options; |
| 661 read_options.verify_checksums = true; | 683 read_options.verify_checksums = true; |
| 662 | 684 |
| 663 std::string result; | 685 std::string result; |
| 664 leveldb::Status s = db_->Get(read_options, | 686 leveldb::Status s = db_->Get(read_options, |
| 665 MakeSlice(kLastCheckinTimeKey), | 687 MakeSlice(kLastCheckinTimeKey), |
| 666 &result); | 688 &result); |
| 667 int64 time_internal = 0LL; | 689 int64 time_internal = 0LL; |
| 668 if (s.ok() && !base::StringToInt64(result, &time_internal)) | 690 if (s.ok() && !base::StringToInt64(result, &time_internal)) |
| 669 LOG(ERROR) << "Failed to restore last checkin time. Using default = 0."; | 691 LOG(ERROR) << "Failed to restore last checkin time. Using default = 0."; |
| 670 | 692 |
| 671 // In case we cannot read last checkin time, we default it to 0, as we don't | 693 // In case we cannot read last checkin time, we default it to 0, as we don't |
| 672 // want that situation to cause the whole load to fail. | 694 // want that situation to cause the whole load to fail. |
| 673 *last_checkin_time = base::Time::FromInternalValue(time_internal); | 695 *last_checkin_time = base::Time::FromInternalValue(time_internal); |
| 674 | 696 |
| 697 accounts->clear(); |
| 698 s = db_->Get(read_options, MakeSlice(kLastCheckinAccountsKey), &result); |
| 699 if (!s.ok()) |
| 700 DVLOG(1) << "No accounts where stored during last run."; |
| 701 |
| 702 base::StringTokenizer t(result, ","); |
| 703 while (t.GetNext()) |
| 704 accounts->insert(t.token()); |
| 705 |
| 675 return true; | 706 return true; |
| 676 } | 707 } |
| 677 | 708 |
| 678 bool GCMStoreImpl::Backend::LoadGServicesSettings( | 709 bool GCMStoreImpl::Backend::LoadGServicesSettings( |
| 679 std::map<std::string, std::string>* settings, | 710 std::map<std::string, std::string>* settings, |
| 680 std::string* digest) { | 711 std::string* digest) { |
| 681 leveldb::ReadOptions read_options; | 712 leveldb::ReadOptions read_options; |
| 682 read_options.verify_checksums = true; | 713 read_options.verify_checksums = true; |
| 683 | 714 |
| 684 // Load all of the GServices settings. | 715 // Load all of the GServices settings. |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 blocking_task_runner_->PostTask( | 901 blocking_task_runner_->PostTask( |
| 871 FROM_HERE, | 902 FROM_HERE, |
| 872 base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, | 903 base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, |
| 873 backend_, | 904 backend_, |
| 874 persistent_ids, | 905 persistent_ids, |
| 875 base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, | 906 base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, |
| 876 weak_ptr_factory_.GetWeakPtr(), | 907 weak_ptr_factory_.GetWeakPtr(), |
| 877 callback))); | 908 callback))); |
| 878 } | 909 } |
| 879 | 910 |
| 880 void GCMStoreImpl::SetLastCheckinTime(const base::Time& last_checkin_time, | 911 void GCMStoreImpl::SetLastCheckinInfo(const base::Time& time, |
| 912 const std::set<std::string>& accounts, |
| 881 const UpdateCallback& callback) { | 913 const UpdateCallback& callback) { |
| 882 blocking_task_runner_->PostTask( | 914 blocking_task_runner_->PostTask( |
| 883 FROM_HERE, | 915 FROM_HERE, |
| 884 base::Bind(&GCMStoreImpl::Backend::SetLastCheckinTime, | 916 base::Bind(&GCMStoreImpl::Backend::SetLastCheckinInfo, |
| 885 backend_, | 917 backend_, |
| 886 last_checkin_time, | 918 time, |
| 919 accounts, |
| 887 callback)); | 920 callback)); |
| 888 } | 921 } |
| 889 | 922 |
| 890 void GCMStoreImpl::SetGServicesSettings( | 923 void GCMStoreImpl::SetGServicesSettings( |
| 891 const std::map<std::string, std::string>& settings, | 924 const std::map<std::string, std::string>& settings, |
| 892 const std::string& digest, | 925 const std::string& digest, |
| 893 const UpdateCallback& callback) { | 926 const UpdateCallback& callback) { |
| 894 blocking_task_runner_->PostTask( | 927 blocking_task_runner_->PostTask( |
| 895 FROM_HERE, | 928 FROM_HERE, |
| 896 base::Bind(&GCMStoreImpl::Backend::SetGServicesSettings, | 929 base::Bind(&GCMStoreImpl::Backend::SetGServicesSettings, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 947 removed_message_counts.begin(); | 980 removed_message_counts.begin(); |
| 948 iter != removed_message_counts.end(); ++iter) { | 981 iter != removed_message_counts.end(); ++iter) { |
| 949 DCHECK_NE(app_message_counts_.count(iter->first), 0U); | 982 DCHECK_NE(app_message_counts_.count(iter->first), 0U); |
| 950 app_message_counts_[iter->first] -= iter->second; | 983 app_message_counts_[iter->first] -= iter->second; |
| 951 DCHECK_GE(app_message_counts_[iter->first], 0); | 984 DCHECK_GE(app_message_counts_[iter->first], 0); |
| 952 } | 985 } |
| 953 callback.Run(true); | 986 callback.Run(true); |
| 954 } | 987 } |
| 955 | 988 |
| 956 } // namespace gcm | 989 } // namespace gcm |
| OLD | NEW |