summaryrefslogtreecommitdiffstats
path: root/google_apis
diff options
context:
space:
mode:
authorfgorski@chromium.org <fgorski@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-17 07:35:58 +0000
committerfgorski@chromium.org <fgorski@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-17 07:35:58 +0000
commit7df5ef237e07608b08c11216fbdf91f9ae27f779 (patch)
treefb94f2256a9f04e30c59830958f503aa695e8573 /google_apis
parent44594085abf90e33fbf7136c4c978176cc22f37a (diff)
downloadchromium_src-7df5ef237e07608b08c11216fbdf91f9ae27f779.zip
chromium_src-7df5ef237e07608b08c11216fbdf91f9ae27f779.tar.gz
chromium_src-7df5ef237e07608b08c11216fbdf91f9ae27f779.tar.bz2
Adding a step to the check-in process that ensures the correct account information is present before device
check-in happen, in order to maintain a relationship between signed in accounts and the device. Behavior of the check-in is not symmetric: * Adding an account converges slowly - newly added account will be associated to device with next periodic check, to avoid checking in too often. * Removing account triggers check-in immediately to ensure users privacy. BUG=374969 Review URL: https://codereview.chromium.org/378643002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283693 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'google_apis')
-rw-r--r--google_apis/gcm/engine/checkin_request.cc12
-rw-r--r--google_apis/gcm/engine/checkin_request.h3
-rw-r--r--google_apis/gcm/engine/checkin_request_unittest.cc18
-rw-r--r--google_apis/gcm/engine/gcm_store.h5
-rw-r--r--google_apis/gcm/engine/gcm_store_impl.cc67
-rw-r--r--google_apis/gcm/engine/gcm_store_impl.h3
-rw-r--r--google_apis/gcm/engine/gcm_store_impl_unittest.cc9
-rw-r--r--google_apis/gcm/tools/mcs_probe.cc7
8 files changed, 96 insertions, 28 deletions
diff --git a/google_apis/gcm/engine/checkin_request.cc b/google_apis/gcm/engine/checkin_request.cc
index a555847..8ba65ad 100644
--- a/google_apis/gcm/engine/checkin_request.cc
+++ b/google_apis/gcm/engine/checkin_request.cc
@@ -80,10 +80,12 @@ void RecordCheckinStatusAndReportUMA(CheckinRequestStatus status,
CheckinRequest::RequestInfo::RequestInfo(
uint64 android_id,
uint64 security_token,
+ const std::map<std::string, std::string>& account_tokens,
const std::string& settings_digest,
const checkin_proto::ChromeBuildProto& chrome_build_proto)
: android_id(android_id),
security_token(security_token),
+ account_tokens(account_tokens),
settings_digest(settings_digest),
chrome_build_proto(chrome_build_proto) {
}
@@ -127,6 +129,16 @@ void CheckinRequest::Start() {
checkin->set_type(checkin_proto::DEVICE_CHROME_BROWSER);
#endif
+ // Pack a map of email -> token mappings into a repeated field, where odd
+ // entries are email addresses, while even ones are respective OAuth2 tokens.
+ for (std::map<std::string, std::string>::const_iterator iter =
+ request_info_.account_tokens.begin();
+ iter != request_info_.account_tokens.end();
+ ++iter) {
+ request.add_account_cookie(iter->first);
+ request.add_account_cookie(iter->second);
+ }
+
std::string upload_data;
CHECK(request.SerializeToString(&upload_data));
diff --git a/google_apis/gcm/engine/checkin_request.h b/google_apis/gcm/engine/checkin_request.h
index ae4a7d4..c48f3c9 100644
--- a/google_apis/gcm/engine/checkin_request.h
+++ b/google_apis/gcm/engine/checkin_request.h
@@ -41,6 +41,7 @@ class GCM_EXPORT CheckinRequest : public net::URLFetcherDelegate {
struct GCM_EXPORT RequestInfo {
RequestInfo(uint64 android_id,
uint64 security_token,
+ const std::map<std::string, std::string>& account_tokens,
const std::string& settings_digest,
const checkin_proto::ChromeBuildProto& chrome_build_proto);
~RequestInfo();
@@ -49,6 +50,8 @@ class GCM_EXPORT CheckinRequest : public net::URLFetcherDelegate {
uint64 android_id;
// Security token of the device.
uint64 security_token;
+ // Map of account OAuth2 tokens keyed by emails.
+ std::map<std::string, std::string> account_tokens;
// Digest of GServices settings on the device.
std::string settings_digest;
// Information of the Chrome build of this device.
diff --git a/google_apis/gcm/engine/checkin_request_unittest.cc b/google_apis/gcm/engine/checkin_request_unittest.cc
index 12e9a60..6f1c630 100644
--- a/google_apis/gcm/engine/checkin_request_unittest.cc
+++ b/google_apis/gcm/engine/checkin_request_unittest.cc
@@ -53,6 +53,8 @@ const char kCheckinURL[] = "http://foo.bar/checkin";
const char kChromeVersion[] = "Version String";
const uint64 kSecurityToken = 77;
const char kSettingsDigest[] = "settings_digest";
+const char kEmailAddress[] = "test_user@gmail.com";
+const char kTokenValue[] = "token_value";
class CheckinRequestTest : public testing::Test {
public:
@@ -122,11 +124,14 @@ void CheckinRequestTest::CreateRequest(uint64 android_id,
checkin_proto::ChromeBuildProto::CHANNEL_CANARY);
chrome_build_proto_.set_chrome_version(kChromeVersion);
- CheckinRequest::RequestInfo request_info(
- android_id,
- security_token,
- kSettingsDigest,
- chrome_build_proto_);
+ std::map<std::string, std::string> account_tokens;
+ account_tokens[kEmailAddress] = kTokenValue;
+
+ CheckinRequest::RequestInfo request_info(android_id,
+ security_token,
+ account_tokens,
+ kSettingsDigest,
+ chrome_build_proto_);
// Then create a request with that protobuf and specified android_id,
// security_token.
request_.reset(new CheckinRequest(
@@ -199,6 +204,9 @@ TEST_F(CheckinRequestTest, FetcherDataAndURL) {
request_proto.checkin().chrome_build().chrome_version());
EXPECT_EQ(chrome_build_proto_.channel(),
request_proto.checkin().chrome_build().channel());
+ EXPECT_EQ(2, request_proto.account_cookie_size());
+ EXPECT_EQ(kEmailAddress, request_proto.account_cookie(0));
+ EXPECT_EQ(kTokenValue, request_proto.account_cookie(1));
#if defined(CHROME_OS)
EXPECT_EQ(checkin_proto::DEVICE_CHROME_OS, request_proto.checkin().type());
diff --git a/google_apis/gcm/engine/gcm_store.h b/google_apis/gcm/engine/gcm_store.h
index 8b9891d0..ca02850 100644
--- a/google_apis/gcm/engine/gcm_store.h
+++ b/google_apis/gcm/engine/gcm_store.h
@@ -6,6 +6,7 @@
#define GOOGLE_APIS_GCM_ENGINE_GCM_STORE_H_
#include <map>
+#include <set>
#include <string>
#include <vector>
@@ -46,6 +47,7 @@ class GCM_EXPORT GCMStore {
std::map<std::string, std::string> gservices_settings;
std::string gservices_digest;
base::Time last_checkin_time;
+ std::set<std::string> last_checkin_accounts;
};
typedef std::vector<std::string> PersistentIdList;
@@ -101,7 +103,8 @@ class GCM_EXPORT GCMStore {
const UpdateCallback& callback) = 0;
// Sets last device's checkin time.
- virtual void SetLastCheckinTime(const base::Time& last_checkin_time,
+ virtual void SetLastCheckinInfo(const base::Time& time,
+ const std::set<std::string>& accounts,
const UpdateCallback& callback) = 0;
// G-service settings handling.
diff --git a/google_apis/gcm/engine/gcm_store_impl.cc b/google_apis/gcm/engine/gcm_store_impl.cc
index e27e82e..df35925 100644
--- a/google_apis/gcm/engine/gcm_store_impl.cc
+++ b/google_apis/gcm/engine/gcm_store_impl.cc
@@ -16,6 +16,7 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
+#include "base/strings/string_tokenizer.h"
#include "base/time/time.h"
#include "base/tracked_objects.h"
#include "google_apis/gcm/base/encryptor.h"
@@ -63,6 +64,8 @@ const char kGServiceSettingKeyStart[] = "gservice1-";
const char kGServiceSettingKeyEnd[] = "gservice2-";
// Key for digest of the last G-services settings update.
const char kGServiceSettingsDigestKey[] = "gservices_digest";
+// Key used to indicate how many accounts were last checked in with this device.
+const char kLastCheckinAccountsKey[] = "last_checkin_accounts_count";
// Key used to timestamp last checkin (marked with G services settings update).
const char kLastCheckinTimeKey[] = "last_checkin_time";
@@ -138,7 +141,8 @@ class GCMStoreImpl::Backend
const UpdateCallback& callback);
void RemoveUserSerialNumber(const std::string& username,
const UpdateCallback& callback);
- void SetLastCheckinTime(const base::Time& last_checkin_time,
+ void SetLastCheckinInfo(const base::Time& time,
+ const std::set<std::string>& accounts,
const UpdateCallback& callback);
void SetGServicesSettings(
const std::map<std::string, std::string>& settings,
@@ -153,7 +157,8 @@ 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);
+ bool LoadLastCheckinInfo(base::Time* last_checkin_time,
+ std::set<std::string>* accounts);
bool LoadGServicesSettings(std::map<std::string, std::string>* settings,
std::string* digest);
@@ -206,7 +211,8 @@ void GCMStoreImpl::Backend::Load(const LoadCallback& callback) {
!LoadRegistrations(&result->registrations) ||
!LoadIncomingMessages(&result->incoming_messages) ||
!LoadOutgoingMessages(&result->outgoing_messages) ||
- !LoadLastCheckinTime(&result->last_checkin_time) ||
+ !LoadLastCheckinInfo(&result->last_checkin_time,
+ &result->last_checkin_accounts) ||
!LoadGServicesSettings(&result->gservices_settings,
&result->gservices_digest)) {
result->device_android_id = 0;
@@ -485,20 +491,35 @@ void GCMStoreImpl::Backend::RemoveOutgoingMessages(
AppIdToMessageCountMap()));
}
-void GCMStoreImpl::Backend::SetLastCheckinTime(
- const base::Time& last_checkin_time,
+void GCMStoreImpl::Backend::SetLastCheckinInfo(
+ const base::Time& time,
+ const std::set<std::string>& accounts,
const UpdateCallback& callback) {
+ leveldb::WriteBatch write_batch;
+
+ int64 last_checkin_time_internal = time.ToInternalValue();
+ write_batch.Put(MakeSlice(kLastCheckinTimeKey),
+ MakeSlice(base::Int64ToString(last_checkin_time_internal)));
+
+ std::string serialized_accounts;
+ for (std::set<std::string>::iterator iter = accounts.begin();
+ iter != accounts.end();
+ ++iter) {
+ serialized_accounts += *iter;
+ serialized_accounts += ",";
+ }
+ if (!serialized_accounts.empty())
+ serialized_accounts.erase(serialized_accounts.length() - 1);
+
+ write_batch.Put(MakeSlice(kLastCheckinAccountsKey),
+ MakeSlice(serialized_accounts));
+
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)));
+ const leveldb::Status s = db_->Write(write_options, &write_batch);
if (!s.ok())
- LOG(ERROR) << "LevelDB set last checkin time failed: " << s.ToString();
+ LOG(ERROR) << "LevelDB set last checkin info failed: " << s.ToString();
foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok()));
}
@@ -655,8 +676,9 @@ bool GCMStoreImpl::Backend::LoadOutgoingMessages(
return true;
}
-bool GCMStoreImpl::Backend::LoadLastCheckinTime(
- base::Time* last_checkin_time) {
+bool GCMStoreImpl::Backend::LoadLastCheckinInfo(
+ base::Time* last_checkin_time,
+ std::set<std::string>* accounts) {
leveldb::ReadOptions read_options;
read_options.verify_checksums = true;
@@ -672,6 +694,15 @@ bool GCMStoreImpl::Backend::LoadLastCheckinTime(
// want that situation to cause the whole load to fail.
*last_checkin_time = base::Time::FromInternalValue(time_internal);
+ accounts->clear();
+ s = db_->Get(read_options, MakeSlice(kLastCheckinAccountsKey), &result);
+ if (!s.ok())
+ DVLOG(1) << "No accounts where stored during last run.";
+
+ base::StringTokenizer t(result, ",");
+ while (t.GetNext())
+ accounts->insert(t.token());
+
return true;
}
@@ -877,13 +908,15 @@ void GCMStoreImpl::RemoveOutgoingMessages(
callback)));
}
-void GCMStoreImpl::SetLastCheckinTime(const base::Time& last_checkin_time,
+void GCMStoreImpl::SetLastCheckinInfo(const base::Time& time,
+ const std::set<std::string>& accounts,
const UpdateCallback& callback) {
blocking_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&GCMStoreImpl::Backend::SetLastCheckinTime,
+ base::Bind(&GCMStoreImpl::Backend::SetLastCheckinInfo,
backend_,
- last_checkin_time,
+ time,
+ accounts,
callback));
}
diff --git a/google_apis/gcm/engine/gcm_store_impl.h b/google_apis/gcm/engine/gcm_store_impl.h
index f49509a..30ce411 100644
--- a/google_apis/gcm/engine/gcm_store_impl.h
+++ b/google_apis/gcm/engine/gcm_store_impl.h
@@ -77,7 +77,8 @@ class GCM_EXPORT GCMStoreImpl : public GCMStore {
const UpdateCallback& callback) OVERRIDE;
// Sets last device's checkin time.
- virtual void SetLastCheckinTime(const base::Time& last_checkin_time,
+ virtual void SetLastCheckinInfo(const base::Time& time,
+ const std::set<std::string>& accounts,
const UpdateCallback& callback) OVERRIDE;
// G-service settings handling.
diff --git a/google_apis/gcm/engine/gcm_store_impl_unittest.cc b/google_apis/gcm/engine/gcm_store_impl_unittest.cc
index 7b9c893..ad4b024 100644
--- a/google_apis/gcm/engine/gcm_store_impl_unittest.cc
+++ b/google_apis/gcm/engine/gcm_store_impl_unittest.cc
@@ -142,7 +142,7 @@ TEST_F(GCMStoreImplTest, DeviceCredentials) {
ASSERT_EQ(kDeviceToken, load_result->device_security_token);
}
-TEST_F(GCMStoreImplTest, LastCheckinTime) {
+TEST_F(GCMStoreImplTest, LastCheckinInfo) {
scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
scoped_ptr<GCMStore::LoadResult> load_result;
gcm_store->Load(base::Bind(
@@ -150,9 +150,13 @@ TEST_F(GCMStoreImplTest, LastCheckinTime) {
PumpLoop();
base::Time last_checkin_time = base::Time::Now();
+ std::set<std::string> accounts;
+ accounts.insert("test_user1@gmail.com");
+ accounts.insert("test_user2@gmail.com");
- gcm_store->SetLastCheckinTime(
+ gcm_store->SetLastCheckinInfo(
last_checkin_time,
+ accounts,
base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
PumpLoop();
@@ -161,6 +165,7 @@ TEST_F(GCMStoreImplTest, LastCheckinTime) {
&GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
PumpLoop();
ASSERT_EQ(last_checkin_time, load_result->last_checkin_time);
+ ASSERT_EQ(accounts, load_result->last_checkin_accounts);
}
TEST_F(GCMStoreImplTest, GServicesSettings_ProtocolV2) {
diff --git a/google_apis/gcm/tools/mcs_probe.cc b/google_apis/gcm/tools/mcs_probe.cc
index 1bb0bc1..9e090fd 100644
--- a/google_apis/gcm/tools/mcs_probe.cc
+++ b/google_apis/gcm/tools/mcs_probe.cc
@@ -431,8 +431,11 @@ void MCSProbe::CheckIn() {
checkin_proto::ChromeBuildProto::CHANNEL_CANARY);
chrome_build_proto.set_chrome_version(kChromeVersion);
- CheckinRequest::RequestInfo request_info(
- 0, 0, std::string(), chrome_build_proto);
+ CheckinRequest::RequestInfo request_info(0,
+ 0,
+ std::map<std::string, std::string>(),
+ std::string(),
+ chrome_build_proto);
checkin_request_.reset(new CheckinRequest(
GServicesSettings::DefaultCheckinURL(),