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/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 const char kIncomingMsgKeyStart[] = "incoming1-"; | 46 const char kIncomingMsgKeyStart[] = "incoming1-"; |
| 47 // Key guaranteed to be higher than all incoming message keys. | 47 // Key guaranteed to be higher than all incoming message keys. |
| 48 // Used for limiting iteration. | 48 // Used for limiting iteration. |
| 49 const char kIncomingMsgKeyEnd[] = "incoming2-"; | 49 const char kIncomingMsgKeyEnd[] = "incoming2-"; |
| 50 // Lowest lexicographically ordered outgoing message key. | 50 // Lowest lexicographically ordered outgoing message key. |
| 51 // Used for prefixing outgoing messages. | 51 // Used for prefixing outgoing messages. |
| 52 const char kOutgoingMsgKeyStart[] = "outgoing1-"; | 52 const char kOutgoingMsgKeyStart[] = "outgoing1-"; |
| 53 // Key guaranteed to be higher than all outgoing message keys. | 53 // Key guaranteed to be higher than all outgoing message keys. |
| 54 // Used for limiting iteration. | 54 // Used for limiting iteration. |
| 55 const char kOutgoingMsgKeyEnd[] = "outgoing2-"; | 55 const char kOutgoingMsgKeyEnd[] = "outgoing2-"; |
| 56 // Key used to timestamp last checkin (marked with G services settings update). | |
| 57 const char kLastCheckinTimeKey[] = "last_checkin_time"; | |
| 56 | 58 |
| 57 std::string MakeRegistrationKey(const std::string& app_id) { | 59 std::string MakeRegistrationKey(const std::string& app_id) { |
| 58 return kRegistrationKeyStart + app_id; | 60 return kRegistrationKeyStart + app_id; |
| 59 } | 61 } |
| 60 | 62 |
| 61 std::string ParseRegistrationKey(const std::string& key) { | 63 std::string ParseRegistrationKey(const std::string& key) { |
| 62 return key.substr(arraysize(kRegistrationKeyStart) - 1); | 64 return key.substr(arraysize(kRegistrationKeyStart) - 1); |
| 63 } | 65 } |
| 64 | 66 |
| 65 std::string MakeIncomingKey(const std::string& persistent_id) { | 67 std::string MakeIncomingKey(const std::string& persistent_id) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 110 const UpdateCallback& callback); | 112 const UpdateCallback& callback); |
| 111 void RemoveOutgoingMessages( | 113 void RemoveOutgoingMessages( |
| 112 const PersistentIdList& persistent_ids, | 114 const PersistentIdList& persistent_ids, |
| 113 const base::Callback<void(bool, const AppIdToMessageCountMap&)> | 115 const base::Callback<void(bool, const AppIdToMessageCountMap&)> |
| 114 callback); | 116 callback); |
| 115 void AddUserSerialNumber(const std::string& username, | 117 void AddUserSerialNumber(const std::string& username, |
| 116 int64 serial_number, | 118 int64 serial_number, |
| 117 const UpdateCallback& callback); | 119 const UpdateCallback& callback); |
| 118 void RemoveUserSerialNumber(const std::string& username, | 120 void RemoveUserSerialNumber(const std::string& username, |
| 119 const UpdateCallback& callback); | 121 const UpdateCallback& callback); |
| 120 void SetNextSerialNumber(int64 serial_number, const UpdateCallback& callback); | 122 void SetLastCheckinTime(const base::Time& last_checkin_time, |
| 123 const UpdateCallback& callback); | |
| 121 | 124 |
| 122 private: | 125 private: |
| 123 friend class base::RefCountedThreadSafe<Backend>; | 126 friend class base::RefCountedThreadSafe<Backend>; |
| 124 ~Backend(); | 127 ~Backend(); |
| 125 | 128 |
| 126 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); | 129 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); |
| 127 bool LoadRegistrations(RegistrationInfoMap* registrations); | 130 bool LoadRegistrations(RegistrationInfoMap* registrations); |
| 128 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); | 131 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); |
| 129 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); | 132 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); |
| 133 bool LoadLastCheckinTime(base::Time* last_checkin_time); | |
| 130 | 134 |
| 131 const base::FilePath path_; | 135 const base::FilePath path_; |
| 132 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; | 136 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; |
| 133 | 137 |
| 134 scoped_ptr<leveldb::DB> db_; | 138 scoped_ptr<leveldb::DB> db_; |
| 135 }; | 139 }; |
| 136 | 140 |
| 137 GCMStoreImpl::Backend::Backend( | 141 GCMStoreImpl::Backend::Backend( |
| 138 const base::FilePath& path, | 142 const base::FilePath& path, |
| 139 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner) | 143 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner) |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 164 base::Bind(callback, | 168 base::Bind(callback, |
| 165 base::Passed(&result))); | 169 base::Passed(&result))); |
| 166 return; | 170 return; |
| 167 } | 171 } |
| 168 db_.reset(db); | 172 db_.reset(db); |
| 169 | 173 |
| 170 if (!LoadDeviceCredentials(&result->device_android_id, | 174 if (!LoadDeviceCredentials(&result->device_android_id, |
| 171 &result->device_security_token) || | 175 &result->device_security_token) || |
| 172 !LoadRegistrations(&result->registrations) || | 176 !LoadRegistrations(&result->registrations) || |
| 173 !LoadIncomingMessages(&result->incoming_messages) || | 177 !LoadIncomingMessages(&result->incoming_messages) || |
| 174 !LoadOutgoingMessages(&result->outgoing_messages)) { | 178 !LoadOutgoingMessages(&result->outgoing_messages) || |
| 179 !LoadLastCheckinTime(&result->last_checkin_time)) { | |
| 175 result->device_android_id = 0; | 180 result->device_android_id = 0; |
| 176 result->device_security_token = 0; | 181 result->device_security_token = 0; |
| 177 result->registrations.clear(); | 182 result->registrations.clear(); |
| 178 result->incoming_messages.clear(); | 183 result->incoming_messages.clear(); |
| 179 result->outgoing_messages.clear(); | 184 result->outgoing_messages.clear(); |
| 185 result->last_checkin_time = base::Time::FromInternalValue(0LL); | |
| 180 foreground_task_runner_->PostTask(FROM_HERE, | 186 foreground_task_runner_->PostTask(FROM_HERE, |
| 181 base::Bind(callback, | 187 base::Bind(callback, |
| 182 base::Passed(&result))); | 188 base::Passed(&result))); |
| 183 return; | 189 return; |
| 184 } | 190 } |
| 185 | 191 |
| 186 // Only record histograms if GCM had already been set up for this device. | 192 // Only record histograms if GCM had already been set up for this device. |
| 187 if (result->device_android_id != 0 && result->device_security_token != 0) { | 193 if (result->device_android_id != 0 && result->device_security_token != 0) { |
| 188 int64 file_size = 0; | 194 int64 file_size = 0; |
| 189 if (base::GetFileSize(path_, &file_size)) { | 195 if (base::GetFileSize(path_, &file_size)) { |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 removed_message_counts)); | 444 removed_message_counts)); |
| 439 return; | 445 return; |
| 440 } | 446 } |
| 441 LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); | 447 LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); |
| 442 foreground_task_runner_->PostTask(FROM_HERE, | 448 foreground_task_runner_->PostTask(FROM_HERE, |
| 443 base::Bind(callback, | 449 base::Bind(callback, |
| 444 false, | 450 false, |
| 445 AppIdToMessageCountMap())); | 451 AppIdToMessageCountMap())); |
| 446 } | 452 } |
| 447 | 453 |
| 454 void GCMStoreImpl::Backend::SetLastCheckinTime( | |
| 455 const base::Time& last_checkin_time, | |
| 456 const UpdateCallback& callback) { | |
| 457 leveldb::WriteOptions write_options; | |
| 458 write_options.sync = true; | |
| 459 | |
| 460 int64 last_checkin_time_internal = last_checkin_time.ToInternalValue(); | |
| 461 const leveldb::Status s = | |
| 462 db_->Put(write_options, | |
| 463 MakeSlice(kLastCheckinTimeKey), | |
| 464 MakeSlice(base::Int64ToString(last_checkin_time_internal))); | |
| 465 | |
| 466 if (!s.ok()) | |
| 467 LOG(ERROR) << "LevelDB set last checkin time failed: " << s.ToString(); | |
| 468 | |
| 469 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); | |
| 470 } | |
| 471 | |
| 472 | |
|
Nicolas Zea
2014/04/02 21:53:55
nit: remove extra newline
fgorski
2014/04/02 22:37:21
Done.
| |
| 448 bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, | 473 bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, |
| 449 uint64* security_token) { | 474 uint64* security_token) { |
| 450 leveldb::ReadOptions read_options; | 475 leveldb::ReadOptions read_options; |
| 451 read_options.verify_checksums = true; | 476 read_options.verify_checksums = true; |
| 452 | 477 |
| 453 std::string result; | 478 std::string result; |
| 454 leveldb::Status s = db_->Get(read_options, MakeSlice(kDeviceAIDKey), &result); | 479 leveldb::Status s = db_->Get(read_options, MakeSlice(kDeviceAIDKey), &result); |
| 455 if (s.ok()) { | 480 if (s.ok()) { |
| 456 if (!base::StringToUint64(result, android_id)) { | 481 if (!base::StringToUint64(result, android_id)) { |
| 457 LOG(ERROR) << "Failed to restore device id."; | 482 LOG(ERROR) << "Failed to restore device id."; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 553 return false; | 578 return false; |
| 554 } | 579 } |
| 555 DVLOG(1) << "Found outgoing message with id " << id << " of type " | 580 DVLOG(1) << "Found outgoing message with id " << id << " of type " |
| 556 << base::IntToString(tag); | 581 << base::IntToString(tag); |
| 557 (*outgoing_messages)[id] = make_linked_ptr(message.release()); | 582 (*outgoing_messages)[id] = make_linked_ptr(message.release()); |
| 558 } | 583 } |
| 559 | 584 |
| 560 return true; | 585 return true; |
| 561 } | 586 } |
| 562 | 587 |
| 588 bool GCMStoreImpl::Backend::LoadLastCheckinTime( | |
| 589 base::Time* last_checkin_time) { | |
| 590 leveldb::ReadOptions read_options; | |
| 591 read_options.verify_checksums = true; | |
| 592 | |
| 593 std::string result; | |
| 594 leveldb::Status s = db_->Get(read_options, | |
| 595 MakeSlice(kLastCheckinTimeKey), | |
| 596 &result); | |
| 597 int64 time_internal = 0LL; | |
| 598 if (s.ok() && !base::StringToInt64(result, &time_internal)) | |
| 599 LOG(ERROR) << "Failed to restore last checkin time. Using default = 0."; | |
| 600 | |
| 601 // In case we cannot read last checkin time, we default it to 0, as we don't | |
| 602 // want that situation to cause the whole load to fail. | |
| 603 *last_checkin_time = base::Time::FromInternalValue(time_internal); | |
| 604 | |
| 605 return true; | |
| 606 } | |
| 607 | |
| 563 GCMStoreImpl::GCMStoreImpl( | 608 GCMStoreImpl::GCMStoreImpl( |
| 564 bool use_mock_keychain, | 609 bool use_mock_keychain, |
| 565 const base::FilePath& path, | 610 const base::FilePath& path, |
| 566 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) | 611 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) |
| 567 : backend_(new Backend(path, base::MessageLoopProxy::current())), | 612 : backend_(new Backend(path, base::MessageLoopProxy::current())), |
| 568 blocking_task_runner_(blocking_task_runner), | 613 blocking_task_runner_(blocking_task_runner), |
| 569 weak_ptr_factory_(this) { | 614 weak_ptr_factory_(this) { |
| 570 // On OSX, prevent the Keychain permissions popup during unit tests. | 615 // On OSX, prevent the Keychain permissions popup during unit tests. |
| 571 #if defined(OS_MACOSX) | 616 #if defined(OS_MACOSX) |
| 572 OSCrypt::UseMockKeychain(use_mock_keychain); | 617 OSCrypt::UseMockKeychain(use_mock_keychain); |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 727 blocking_task_runner_->PostTask( | 772 blocking_task_runner_->PostTask( |
| 728 FROM_HERE, | 773 FROM_HERE, |
| 729 base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, | 774 base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, |
| 730 backend_, | 775 backend_, |
| 731 persistent_ids, | 776 persistent_ids, |
| 732 base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, | 777 base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, |
| 733 weak_ptr_factory_.GetWeakPtr(), | 778 weak_ptr_factory_.GetWeakPtr(), |
| 734 callback))); | 779 callback))); |
| 735 } | 780 } |
| 736 | 781 |
| 782 void GCMStoreImpl::SetLastCheckinTime(const base::Time& last_checkin_time, | |
| 783 const UpdateCallback& callback) { | |
| 784 blocking_task_runner_->PostTask( | |
| 785 FROM_HERE, | |
| 786 base::Bind(&GCMStoreImpl::Backend::SetLastCheckinTime, | |
| 787 backend_, | |
| 788 last_checkin_time, | |
| 789 callback)); | |
| 790 } | |
| 791 | |
| 737 void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, | 792 void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, |
| 738 scoped_ptr<LoadResult> result) { | 793 scoped_ptr<LoadResult> result) { |
| 739 if (!result->success) { | 794 if (!result->success) { |
| 740 callback.Run(result.Pass()); | 795 callback.Run(result.Pass()); |
| 741 return; | 796 return; |
| 742 } | 797 } |
| 743 int num_throttled_apps = 0; | 798 int num_throttled_apps = 0; |
| 744 for (OutgoingMessageMap::const_iterator | 799 for (OutgoingMessageMap::const_iterator |
| 745 iter = result->outgoing_messages.begin(); | 800 iter = result->outgoing_messages.begin(); |
| 746 iter != result->outgoing_messages.end(); ++iter) { | 801 iter != result->outgoing_messages.end(); ++iter) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 781 removed_message_counts.begin(); | 836 removed_message_counts.begin(); |
| 782 iter != removed_message_counts.end(); ++iter) { | 837 iter != removed_message_counts.end(); ++iter) { |
| 783 DCHECK_NE(app_message_counts_.count(iter->first), 0U); | 838 DCHECK_NE(app_message_counts_.count(iter->first), 0U); |
| 784 app_message_counts_[iter->first] -= iter->second; | 839 app_message_counts_[iter->first] -= iter->second; |
| 785 DCHECK_GE(app_message_counts_[iter->first], 0); | 840 DCHECK_GE(app_message_counts_[iter->first], 0); |
| 786 } | 841 } |
| 787 callback.Run(true); | 842 callback.Run(true); |
| 788 } | 843 } |
| 789 | 844 |
| 790 } // namespace gcm | 845 } // namespace gcm |
| OLD | NEW |