Chromium Code Reviews| 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 4105e68518b6cd89dbce19c1c122554d82e9b367..a54cf34d3b82a76de3fb19cd569f4b4494fd50f0 100644 |
| --- a/google_apis/gcm/engine/gcm_store_impl.cc |
| +++ b/google_apis/gcm/engine/gcm_store_impl.cc |
| @@ -48,6 +48,7 @@ enum LoadStatus { |
| LOADING_ACCOUNT_MAPPING_FAILED, |
| LOADING_LAST_TOKEN_TIME_FAILED, |
| LOADING_HEARTBEAT_INTERVALS_FAILED, |
| + LOADING_INSTANCE_ID_DATA_FAILED, |
| // NOTE: always keep this entry at the end. Add new status types only |
| // immediately above this line. Make sure to update the corresponding |
| @@ -107,6 +108,12 @@ const char kHeartbeatKeyStart[] = "heartbeat1-"; |
| const char kHeartbeatKeyEnd[] = "heartbeat2-"; |
| // Key used for last token fetch time. |
| const char kLastTokenFetchTimeKey[] = "last_token_fetch_time"; |
| +// Lowest lexicographically ordered app ids. |
| +// Used for prefixing app id. |
| +const char kInstanceIDKeyStart[] = "iid1-"; |
| +// Key guaranteed to be higher than all app ids. |
| +// Used for limiting iteration. |
| +const char kInstanceIDKeyEnd[] = "iid2-"; |
| std::string MakeRegistrationKey(const std::string& app_id) { |
| return kRegistrationKeyStart + app_id; |
| @@ -152,6 +159,14 @@ std::string ParseHeartbeatKey(const std::string& key) { |
| return key.substr(arraysize(kHeartbeatKeyStart) - 1); |
| } |
| +std::string MakeInstanceIDKey(const std::string& app_id) { |
| + return kInstanceIDKeyStart + app_id; |
| +} |
| + |
| +std::string ParseInstanceIDKey(const std::string& key) { |
| + return key.substr(arraysize(kInstanceIDKeyStart) - 1); |
| +} |
| + |
| // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore |
| // outlive the slice. |
| // For example: MakeSlice(MakeOutgoingKey(x)) is invalid. |
| @@ -214,6 +229,11 @@ class GCMStoreImpl::Backend |
| const UpdateCallback& callback); |
| void RemoveHeartbeatInterval(const std::string& scope, |
| const UpdateCallback& callback); |
| + void AddInstanceIDData(const std::string& app_id, |
| + const std::string& instance_id_data, |
| + const UpdateCallback& callback); |
| + void RemoveInstanceIDData(const std::string& app_id, |
| + const UpdateCallback& callback); |
| void SetValue(const std::string& key, |
| const std::string& value, |
| const UpdateCallback& callback); |
| @@ -234,6 +254,7 @@ class GCMStoreImpl::Backend |
| bool LoadAccountMappingInfo(AccountMappings* account_mappings); |
| bool LoadLastTokenFetchTime(base::Time* last_token_fetch_time); |
| bool LoadHeartbeatIntervals(std::map<std::string, int>* heartbeat_intervals); |
| + bool LoadInstanceIDData(std::map<std::string, std::string>* instance_id_data); |
| const base::FilePath path_; |
| scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; |
| @@ -297,6 +318,8 @@ LoadStatus GCMStoreImpl::Backend::OpenStoreAndLoadData(LoadResult* result) { |
| return LOADING_LAST_TOKEN_TIME_FAILED; |
| if (!LoadHeartbeatIntervals(&result->heartbeat_intervals)) |
| return LOADING_HEARTBEAT_INTERVALS_FAILED; |
| + if (!LoadInstanceIDData(&result->instance_id_data)) |
| + return LOADING_INSTANCE_ID_DATA_FAILED; |
| return LOADING_SUCCEEDED; |
| } |
| @@ -607,6 +630,28 @@ void GCMStoreImpl::Backend::SetLastCheckinInfo( |
| foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); |
| } |
| +void GCMStoreImpl::AddInstanceIDData(const std::string& app_id, |
| + const std::string& instance_id_data, |
| + const UpdateCallback& callback) { |
| + blocking_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&GCMStoreImpl::Backend::AddInstanceIDData, |
| + backend_, |
| + app_id, |
| + instance_id_data, |
| + callback)); |
| +} |
| + |
| +void GCMStoreImpl::RemoveInstanceIDData(const std::string& app_id, |
| + const UpdateCallback& callback) { |
| + blocking_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&GCMStoreImpl::Backend::RemoveInstanceIDData, |
| + backend_, |
| + app_id, |
| + callback)); |
| +} |
| + |
| void GCMStoreImpl::Backend::SetGServicesSettings( |
| const std::map<std::string, std::string>& settings, |
| const std::string& settings_digest, |
| @@ -757,6 +802,53 @@ void GCMStoreImpl::Backend::RemoveHeartbeatInterval( |
| foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); |
| } |
| +void GCMStoreImpl::Backend::AddInstanceIDData( |
| + const std::string& app_id, |
| + const std::string& instance_id_data, |
| + const UpdateCallback& callback) { |
| + DVLOG(1) << "Adding Instance ID data."; |
| + if (!db_.get()) { |
| + LOG(ERROR) << "GCMStore db doesn't exist."; |
| + foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| + return; |
| + } |
| + |
| + leveldb::WriteOptions write_options; |
| + write_options.sync = true; |
| + |
| + std::string key = MakeInstanceIDKey(app_id); |
| + const leveldb::Status status = db_->Put(write_options, |
| + MakeSlice(key), |
| + MakeSlice(instance_id_data)); |
| + 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.
|
| + foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
| + return; |
| + } |
| + LOG(ERROR) << "LevelDB put failed: " << status.ToString(); |
| + foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| +} |
| + |
| +void GCMStoreImpl::Backend::RemoveInstanceIDData( |
| + const std::string& app_id, |
| + const UpdateCallback& callback) { |
| + if (!db_.get()) { |
| + LOG(ERROR) << "GCMStore db doesn't exist."; |
| + foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| + return; |
| + } |
| + leveldb::WriteOptions write_options; |
| + write_options.sync = true; |
| + |
| + leveldb::Status status = |
| + db_->Delete(write_options, MakeSlice(MakeInstanceIDKey(app_id))); |
| + if (status.ok()) { |
| + foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
| + return; |
| + } |
| + LOG(ERROR) << "LevelDB remove failed: " << status.ToString(); |
| + foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| +} |
| + |
| void GCMStoreImpl::Backend::SetValue(const std::string& key, |
| const std::string& value, |
| const UpdateCallback& callback) { |
| @@ -1022,6 +1114,28 @@ bool GCMStoreImpl::Backend::LoadHeartbeatIntervals( |
| return true; |
| } |
| +bool GCMStoreImpl::Backend::LoadInstanceIDData( |
| + std::map<std::string, std::string>* instance_id_data) { |
| + leveldb::ReadOptions read_options; |
| + read_options.verify_checksums = true; |
| + |
| + scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); |
| + for (iter->Seek(MakeSlice(kInstanceIDKeyStart)); |
| + iter->Valid() && iter->key().ToString() < kInstanceIDKeyEnd; |
| + iter->Next()) { |
| + leveldb::Slice s = iter->value(); |
| + if (s.size() <= 1) { |
| + LOG(ERROR) << "Error reading IID data with key " << s.ToString(); |
| + return false; |
| + } |
| + std::string app_id = ParseInstanceIDKey(iter->key().ToString()); |
| + DVLOG(1) << "Found IID data with app id " << app_id; |
| + (*instance_id_data)[app_id] = s.ToString(); |
| + } |
| + |
| + return true; |
| +} |
| + |
| GCMStoreImpl::GCMStoreImpl( |
| const base::FilePath& path, |
| scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, |