Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Unified Diff: google_apis/gcm/engine/gcm_store_impl.cc

Issue 215363007: [GCM] Adding basic G-services handling (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Converting service write to the store to a full replace, adding digest to checkin request, addressi… Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..c503bfbd6ba515494a1bf96056835fc1d9225d90 100644
--- a/google_apis/gcm/engine/gcm_store_impl.cc
+++ b/google_apis/gcm/engine/gcm_store_impl.cc
@@ -16,12 +16,14 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
+#include "base/time/time.h"
#include "base/tracked_objects.h"
#include "components/os_crypt/os_crypt.h"
#include "google_apis/gcm/base/mcs_message.h"
#include "google_apis/gcm/base/mcs_util.h"
#include "google_apis/gcm/protocol/mcs.pb.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
+#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
namespace gcm {
@@ -53,6 +55,16 @@ const char kOutgoingMsgKeyStart[] = "outgoing1-";
// Key guaranteed to be higher than all outgoing message keys.
// Used for limiting iteration.
const char kOutgoingMsgKeyEnd[] = "outgoing2-";
+// Lowest lexicographically ordered G service settings key.
jianli 2014/04/01 20:17:17 nit: G-service
fgorski 2014/04/01 20:47:54 Done.
+// Used for prefixing G services settings.
+const char kGServiceSettingKeyStart[] = "Gservice1-";
jianli 2014/04/01 20:17:17 nit: Make the 1st letter lower case in order to be
fgorski 2014/04/01 20:47:54 Done.
+// Key guaranteed to be higher than all G services settings keys.
+// Used for limiting iteration.
+const char kGServiceSettingKeyEnd[] = "Gservice2-";
+// Key for digest of the last G services settings update.
+const char kGServiceSettingsDigestKey[] = "gservices_digest";
+// 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;
@@ -74,6 +86,14 @@ std::string ParseOutgoingKey(const std::string& key) {
return key.substr(arraysize(kOutgoingMsgKeyStart) - 1);
}
+std::string MakeGServiceSettingKey(const std::string& setting_name) {
+ return kGServiceSettingKeyStart + setting_name;
+}
+
+std::string ParseGServiceSettingKey(const std::string& key) {
+ return key.substr(arraysize(kGServiceSettingKeyStart) - 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.
@@ -118,6 +138,11 @@ class GCMStoreImpl::Backend
void RemoveUserSerialNumber(const std::string& username,
const UpdateCallback& callback);
void SetNextSerialNumber(int64 serial_number, const UpdateCallback& callback);
+ void UpdateGServicesSettings(
jianli 2014/04/01 20:17:17 nit: SetGServicesSettings
fgorski 2014/04/01 20:47:54 Done.
+ const std::map<std::string, std::string>& new_settings,
jianli 2014/04/01 20:17:17 nit: settings
fgorski 2014/04/01 20:47:54 Done.
+ const std::string& digest,
+ const base::Time& last_checkin_time,
+ const UpdateCallback& callback);
private:
friend class base::RefCountedThreadSafe<Backend>;
@@ -127,6 +152,9 @@ class GCMStoreImpl::Backend
bool LoadRegistrations(RegistrationInfoMap* registrations);
bool LoadIncomingMessages(std::vector<std::string>* incoming_messages);
bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages);
+ bool LoadGServicesSettings(std::map<std::string, std::string>* settings,
+ std::string* digest,
+ base::Time* last_checkin_time);
const base::FilePath path_;
scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_;
@@ -171,12 +199,16 @@ 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) ||
+ !LoadGServicesSettings(&result->gservices_settings,
+ &result->gservices_digest,
+ &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);
jianli 2014/04/01 20:17:17 Do we also want to clear gservices_settings when t
fgorski 2014/04/01 20:47:54 Done.
foreground_task_runner_->PostTask(FROM_HERE,
base::Bind(callback,
base::Passed(&result)));
@@ -445,6 +477,50 @@ void GCMStoreImpl::Backend::RemoveOutgoingMessages(
AppIdToMessageCountMap()));
}
+void GCMStoreImpl::Backend::UpdateGServicesSettings(
+ const std::map<std::string, std::string>& new_settings,
+ const std::string& settings_digest,
+ const base::Time& last_checkin_time,
+ const UpdateCallback& callback) {
+ leveldb::WriteBatch write_batch;
+
+ // Remove all existing settings.
+ leveldb::ReadOptions read_options;
+ read_options.verify_checksums = true;
+ scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
+ for (iter->Seek(MakeSlice(kGServiceSettingKeyStart));
+ iter->Valid() && iter->key().ToString() < kGServiceSettingKeyEnd;
+ iter->Next()) {
+ write_batch.Delete(iter->key());
+ }
+
+ // Add the new settings.
+ for (std::map<std::string, std::string>::const_iterator iter =
+ new_settings.begin();
+ iter != new_settings.end(); ++iter) {
+ write_batch.Put(MakeSlice(MakeGServiceSettingKey(iter->first)),
+ MakeSlice(iter->second));
+ }
+
+ // Update the settings digest.
+ write_batch.Put(MakeSlice(kGServiceSettingsDigestKey),
+ MakeSlice(settings_digest));
+
+ // Update last checkin time.
+ int64 last_checkin_time_internal = last_checkin_time.ToInternalValue();
+ write_batch.Put(MakeSlice(kLastCheckinTimeKey),
+ MakeSlice(base::Int64ToString(last_checkin_time_internal)));
+
+ // Write it all in batch.
jianli 2014/04/01 20:17:17 nit: in a batch
fgorski 2014/04/01 20:47:54 Done.
+ leveldb::WriteOptions write_options;
+ write_options.sync = true;
+
+ leveldb::Status s = db_->Write(write_options, &write_batch);
+ if (!s.ok())
+ LOG(ERROR) << "LevelDB GService Settings update 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 +636,52 @@ bool GCMStoreImpl::Backend::LoadOutgoingMessages(
return true;
}
+bool GCMStoreImpl::Backend::LoadGServicesSettings(
+ std::map<std::string, std::string>* settings,
+ std::string* digest,
+ base::Time* last_checkin_time) {
+ leveldb::ReadOptions read_options;
+ read_options.verify_checksums = true;
+
+ // Load all of the GServices settings.
+ scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
+ for (iter->Seek(MakeSlice(kGServiceSettingKeyStart));
+ iter->Valid() && iter->key().ToString() < kGServiceSettingKeyEnd;
+ iter->Next()) {
+ std::string value = iter->value().ToString();
+ if (value.empty()) {
+ LOG(ERROR) << "Error reading GService Settings " << value;
+ return false;
+ }
+ std::string id = ParseGServiceSettingKey(iter->key().ToString());
+ (*settings)[id] = value;
+ DVLOG(1) << "Found G Service setting with key: " << id
+ << ", and value: " << value;
+ }
+
+ // Load the settings digest. It's ok if it is empty.
+ db_->Get(read_options, MakeSlice(kGServiceSettingsDigestKey), digest);
+
+ // Load the last checkin time.
+ std::string result;
+ leveldb::Status s = db_->Get(read_options,
+ MakeSlice(kLastCheckinTimeKey),
+ &result);
+ int64 time_internal = 0LL;
+ if (s.ok()) {
+ if (!base::StringToInt64(result, &time_internal)) {
+ LOG(ERROR) << "Failed to restore last checkin time.";
+ return false;
+ }
+ }
+
+ // 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 +856,21 @@ void GCMStoreImpl::RemoveOutgoingMessages(
callback)));
}
+void GCMStoreImpl::UpdateGServicesSettings(
+ const std::map<std::string, std::string>& new_settings,
+ const std::string& digest,
+ const base::Time& last_checkin_time,
+ const UpdateCallback& callback) {
+ blocking_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&GCMStoreImpl::Backend::UpdateGServicesSettings,
+ backend_,
+ new_settings,
+ digest,
+ last_checkin_time,
+ callback));
+}
+
void GCMStoreImpl::LoadContinuation(const LoadCallback& callback,
scoped_ptr<LoadResult> result) {
if (!result->success) {

Powered by Google App Engine
This is Rietveld 408576698