| Index: google_apis/gcm/engine/gcm_store_impl.cc
|
| diff --git a/google_apis/gcm/engine/gcm_store_impl.cc b/google_apis/gcm/engine/gcm_store_impl.cc
|
| index 7f272870d808cffb0c2134867fa4b9be205b6bef..3a74127c4b9607a52bc76da8848e2c372096ea24 100644
|
| --- a/google_apis/gcm/engine/gcm_store_impl.cc
|
| +++ b/google_apis/gcm/engine/gcm_store_impl.cc
|
| @@ -53,6 +53,8 @@ const char kOutgoingMsgKeyStart[] = "outgoing1-";
|
| // Key guaranteed to be higher than all outgoing message keys.
|
| // Used for limiting iteration.
|
| const char kOutgoingMsgKeyEnd[] = "outgoing2-";
|
| +// Key used to timestamp last checkin (marked with G services settings update).
|
| +const char kLastCheckinTimeKey[] = "last_checkin_time";
|
|
|
| std::string MakeRegistrationKey(const std::string& app_id) {
|
| return kRegistrationKeyStart + app_id;
|
| @@ -117,7 +119,8 @@ class GCMStoreImpl::Backend
|
| const UpdateCallback& callback);
|
| void RemoveUserSerialNumber(const std::string& username,
|
| const UpdateCallback& callback);
|
| - void SetNextSerialNumber(int64 serial_number, const UpdateCallback& callback);
|
| + void SetLastCheckinTime(const base::Time& last_checkin_time,
|
| + const UpdateCallback& callback);
|
|
|
| private:
|
| friend class base::RefCountedThreadSafe<Backend>;
|
| @@ -127,6 +130,7 @@ class GCMStoreImpl::Backend
|
| bool LoadRegistrations(RegistrationInfoMap* registrations);
|
| bool LoadIncomingMessages(std::vector<std::string>* incoming_messages);
|
| bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages);
|
| + bool LoadLastCheckinTime(base::Time* last_checkin_time);
|
|
|
| const base::FilePath path_;
|
| scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_;
|
| @@ -171,12 +175,14 @@ void GCMStoreImpl::Backend::Load(const LoadCallback& callback) {
|
| &result->device_security_token) ||
|
| !LoadRegistrations(&result->registrations) ||
|
| !LoadIncomingMessages(&result->incoming_messages) ||
|
| - !LoadOutgoingMessages(&result->outgoing_messages)) {
|
| + !LoadOutgoingMessages(&result->outgoing_messages) ||
|
| + !LoadLastCheckinTime(&result->last_checkin_time)) {
|
| result->device_android_id = 0;
|
| result->device_security_token = 0;
|
| result->registrations.clear();
|
| result->incoming_messages.clear();
|
| result->outgoing_messages.clear();
|
| + result->last_checkin_time = base::Time::FromInternalValue(0LL);
|
| foreground_task_runner_->PostTask(FROM_HERE,
|
| base::Bind(callback,
|
| base::Passed(&result)));
|
| @@ -445,6 +451,24 @@ void GCMStoreImpl::Backend::RemoveOutgoingMessages(
|
| AppIdToMessageCountMap()));
|
| }
|
|
|
| +void GCMStoreImpl::Backend::SetLastCheckinTime(
|
| + const base::Time& last_checkin_time,
|
| + const UpdateCallback& callback) {
|
| + leveldb::WriteOptions write_options;
|
| + write_options.sync = true;
|
| +
|
| + int64 last_checkin_time_internal = last_checkin_time.ToInternalValue();
|
| + const leveldb::Status s =
|
| + db_->Put(write_options,
|
| + MakeSlice(kLastCheckinTimeKey),
|
| + MakeSlice(base::Int64ToString(last_checkin_time_internal)));
|
| +
|
| + if (!s.ok())
|
| + LOG(ERROR) << "LevelDB set last checkin time failed: " << s.ToString();
|
| +
|
| + foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok()));
|
| +}
|
| +
|
| bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id,
|
| uint64* security_token) {
|
| leveldb::ReadOptions read_options;
|
| @@ -560,6 +584,26 @@ bool GCMStoreImpl::Backend::LoadOutgoingMessages(
|
| return true;
|
| }
|
|
|
| +bool GCMStoreImpl::Backend::LoadLastCheckinTime(
|
| + base::Time* last_checkin_time) {
|
| + leveldb::ReadOptions read_options;
|
| + read_options.verify_checksums = true;
|
| +
|
| + std::string result;
|
| + leveldb::Status s = db_->Get(read_options,
|
| + MakeSlice(kLastCheckinTimeKey),
|
| + &result);
|
| + int64 time_internal = 0LL;
|
| + if (s.ok() && !base::StringToInt64(result, &time_internal))
|
| + LOG(ERROR) << "Failed to restore last checkin time. Using default = 0.";
|
| +
|
| + // In case we cannot read last checkin time, we default it to 0, as we don't
|
| + // want that situation to cause the whole load to fail.
|
| + *last_checkin_time = base::Time::FromInternalValue(time_internal);
|
| +
|
| + return true;
|
| +}
|
| +
|
| GCMStoreImpl::GCMStoreImpl(
|
| bool use_mock_keychain,
|
| const base::FilePath& path,
|
| @@ -734,6 +778,16 @@ void GCMStoreImpl::RemoveOutgoingMessages(
|
| callback)));
|
| }
|
|
|
| +void GCMStoreImpl::SetLastCheckinTime(const base::Time& last_checkin_time,
|
| + const UpdateCallback& callback) {
|
| + blocking_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GCMStoreImpl::Backend::SetLastCheckinTime,
|
| + backend_,
|
| + last_checkin_time,
|
| + callback));
|
| +}
|
| +
|
| void GCMStoreImpl::LoadContinuation(const LoadCallback& callback,
|
| scoped_ptr<LoadResult> result) {
|
| if (!result->success) {
|
|
|