Commit 2ade6a08 authored by Mugdha Lakhani's avatar Mugdha Lakhani Committed by Commit Bot

Add last_validated timestamp to GCM registration info.

Bug: 799483
Change-Id: Id180ebd58acefa8f047858101c586b940b435e70
Reviewed-on: https://chromium-review.googlesource.com/887083
Commit-Queue: Mugdha Lakhani <nator@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#533268}
parent de30ba8e
...@@ -144,6 +144,7 @@ static_library("test_support") { ...@@ -144,6 +144,7 @@ static_library("test_support") {
} }
} }
# This is part of the components_unittests BUILD target.
source_set("unit_tests") { source_set("unit_tests") {
testonly = true testonly = true
......
...@@ -889,8 +889,8 @@ void GCMClientImpl::Register( ...@@ -889,8 +889,8 @@ void GCMClientImpl::Register(
} }
if (matched) { if (matched) {
delegate_->OnRegisterFinished( delegate_->OnRegisterFinished(registration_info,
registration_info, registrations_iter->second, SUCCESS); registrations_iter->second, SUCCESS);
return; return;
} }
} }
...@@ -981,8 +981,9 @@ void GCMClientImpl::OnRegisterCompleted( ...@@ -981,8 +981,9 @@ void GCMClientImpl::OnRegisterCompleted(
// Note that the existing cached record has to be removed first because // Note that the existing cached record has to be removed first because
// otherwise the key value in registrations_ will not be updated. For GCM // otherwise the key value in registrations_ will not be updated. For GCM
// registrations, the key consists of pair of app_id and sender_ids though // registrations, the key consists of pair of app_id and sender_ids though
// only app_id is used in the comparison. // only app_id is used in the key comparison.
registrations_.erase(registration_info); registrations_.erase(registration_info);
registration_info->last_validated = clock_->Now();
registrations_[registration_info] = registration_id; registrations_[registration_info] = registration_id;
// Save it in the persistent store. // Save it in the persistent store.
......
...@@ -63,6 +63,7 @@ const uint64_t kDeviceSecurityToken2 = 2222; ...@@ -63,6 +63,7 @@ const uint64_t kDeviceSecurityToken2 = 2222;
const int64_t kSettingsCheckinInterval = 16 * 60 * 60; const int64_t kSettingsCheckinInterval = 16 * 60 * 60;
const char kProductCategoryForSubtypes[] = "com.chrome.macosx"; const char kProductCategoryForSubtypes[] = "com.chrome.macosx";
const char kExtensionAppId[] = "abcdefghijklmnopabcdefghijklmnop"; const char kExtensionAppId[] = "abcdefghijklmnopabcdefghijklmnop";
const char kRegistrationId[] = "reg_id";
const char kSubtypeAppId[] = "app_id"; const char kSubtypeAppId[] = "app_id";
const char kSender[] = "project_id"; const char kSender[] = "project_id";
const char kSender2[] = "project_id2"; const char kSender2[] = "project_id2";
...@@ -770,6 +771,26 @@ TEST_F(GCMClientImplTest, DestroyStoreWhenNotNeeded) { ...@@ -770,6 +771,26 @@ TEST_F(GCMClientImplTest, DestroyStoreWhenNotNeeded) {
EXPECT_FALSE(device_checkin_info().secret); EXPECT_FALSE(device_checkin_info().secret);
} }
TEST_F(GCMClientImplTest, SerializeAndDeserialize) {
std::vector<std::string> senders{"sender"};
auto gcm_info = std::make_unique<GCMRegistrationInfo>();
gcm_info->app_id = kExtensionAppId;
gcm_info->sender_ids = senders;
gcm_info->last_validated = clock()->Now();
std::string serialized_key = gcm_info->GetSerializedKey();
std::string serialized_value = gcm_info->GetSerializedValue(kRegistrationId);
auto gcm_info_deserialized = std::make_unique<GCMRegistrationInfo>();
std::string registration_id_deserialized;
ASSERT_TRUE(gcm_info_deserialized->Deserialize(
serialized_key, serialized_value, &registration_id_deserialized));
EXPECT_EQ(gcm_info->app_id, gcm_info_deserialized->app_id);
EXPECT_EQ(gcm_info->sender_ids, gcm_info_deserialized->sender_ids);
EXPECT_EQ(gcm_info->last_validated, gcm_info_deserialized->last_validated);
EXPECT_EQ(kRegistrationId, registration_id_deserialized);
}
TEST_F(GCMClientImplTest, RegisterApp) { TEST_F(GCMClientImplTest, RegisterApp) {
EXPECT_FALSE(ExistsRegistration(kExtensionAppId)); EXPECT_FALSE(ExistsRegistration(kExtensionAppId));
......
...@@ -6,13 +6,18 @@ ...@@ -6,13 +6,18 @@
#include <stddef.h> #include <stddef.h>
#include "base/format_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
namespace gcm { namespace gcm {
namespace { namespace {
const char kInstanceIDSerializationPrefix[] = "iid-"; const char kInstanceIDSerializationPrefix[] = "iid-";
const char kSerializedValidationTimeSeparator = '#';
const char kSerializedKeySeparator = ',';
const int kInstanceIDSerializationPrefixLength = const int kInstanceIDSerializationPrefixLength =
sizeof(kInstanceIDSerializationPrefix) / sizeof(char) - 1; sizeof(kInstanceIDSerializationPrefix) / sizeof(char) - 1;
} // namespace } // namespace
...@@ -30,8 +35,7 @@ std::unique_ptr<RegistrationInfo> RegistrationInfo::BuildFromString( ...@@ -30,8 +35,7 @@ std::unique_ptr<RegistrationInfo> RegistrationInfo::BuildFromString(
else else
registration.reset(new GCMRegistrationInfo); registration.reset(new GCMRegistrationInfo);
if (!registration->Deserialize(serialized_key, if (!registration->Deserialize(serialized_key, serialized_value,
serialized_value,
registration_id)) { registration_id)) {
registration.reset(); registration.reset();
} }
...@@ -82,7 +86,7 @@ std::string GCMRegistrationInfo::GetSerializedValue( ...@@ -82,7 +86,7 @@ std::string GCMRegistrationInfo::GetSerializedValue(
return std::string(); return std::string();
// Serialize as: // Serialize as:
// sender1,sender2,...=reg_id // sender1,sender2,...=reg_id#time_of_last_validation
std::string value; std::string value;
for (std::vector<std::string>::const_iterator iter = sender_ids.begin(); for (std::vector<std::string>::const_iterator iter = sender_ids.begin();
iter != sender_ids.end(); ++iter) { iter != sender_ids.end(); ++iter) {
...@@ -94,13 +98,13 @@ std::string GCMRegistrationInfo::GetSerializedValue( ...@@ -94,13 +98,13 @@ std::string GCMRegistrationInfo::GetSerializedValue(
value += *iter; value += *iter;
} }
value += '='; return base::StringPrintf("%s=%s%c%" PRId64, value.c_str(),
value += registration_id; registration_id.c_str(),
return value; kSerializedValidationTimeSeparator,
last_validated.since_origin().InMicroseconds());
} }
bool GCMRegistrationInfo::Deserialize( bool GCMRegistrationInfo::Deserialize(const std::string& serialized_key,
const std::string& serialized_key,
const std::string& serialized_value, const std::string& serialized_value,
std::string* registration_id) { std::string* registration_id) {
if (serialized_key.empty() || serialized_value.empty()) if (serialized_key.empty() || serialized_value.empty())
...@@ -110,12 +114,22 @@ bool GCMRegistrationInfo::Deserialize( ...@@ -110,12 +114,22 @@ bool GCMRegistrationInfo::Deserialize(
app_id = serialized_key; app_id = serialized_key;
// Sender IDs and registration ID are constructed from the serialized value. // Sender IDs and registration ID are constructed from the serialized value.
size_t pos = serialized_value.find('='); size_t pos_equals = serialized_value.find('=');
if (pos == std::string::npos) if (pos_equals == std::string::npos)
return false; return false;
// Note that it's valid for pos_hash to be std::string::npos.
std::string senders = serialized_value.substr(0, pos); size_t pos_hash = serialized_value.find(kSerializedValidationTimeSeparator);
std::string registration_id_str = serialized_value.substr(pos + 1); bool has_timestamp = (pos_hash != std::string::npos);
std::string senders = serialized_value.substr(0, pos_equals);
std::string registration_id_str, last_validated_str;
if (has_timestamp) {
registration_id_str =
serialized_value.substr(pos_equals + 1, pos_hash - pos_equals - 1);
last_validated_str = serialized_value.substr(pos_hash + 1);
} else {
registration_id_str = serialized_value.substr(pos_equals + 1);
}
sender_ids = base::SplitString( sender_ids = base::SplitString(
senders, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); senders, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
...@@ -127,6 +141,13 @@ bool GCMRegistrationInfo::Deserialize( ...@@ -127,6 +141,13 @@ bool GCMRegistrationInfo::Deserialize(
if (registration_id) if (registration_id)
*registration_id = registration_id_str; *registration_id = registration_id_str;
int64_t last_validated_ms = 0;
if (base::StringToInt64(last_validated_str, &last_validated_ms)) {
// It's okay for |last_validated| to be the default base::Time() value
// when there is no serialized timestamp value available.
last_validated =
base::Time() + base::TimeDelta::FromMicroseconds(last_validated_ms);
}
return true; return true;
} }
...@@ -166,22 +187,20 @@ std::string InstanceIDTokenInfo::GetSerializedKey() const { ...@@ -166,22 +187,20 @@ std::string InstanceIDTokenInfo::GetSerializedKey() const {
// on the combination of (app_id, authorized_entity, scope). // on the combination of (app_id, authorized_entity, scope).
// Adds a prefix to differentiate easily with GCM registration key. // Adds a prefix to differentiate easily with GCM registration key.
std::string key(kInstanceIDSerializationPrefix); return base::StringPrintf("%s%s%c%s%c%s", kInstanceIDSerializationPrefix,
key += app_id; app_id.c_str(), kSerializedKeySeparator,
key += ","; authorized_entity.c_str(), kSerializedKeySeparator,
key += authorized_entity; scope.c_str());
key += ",";
key += scope;
return key;
} }
std::string InstanceIDTokenInfo::GetSerializedValue( std::string InstanceIDTokenInfo::GetSerializedValue(
const std::string& registration_id) const { const std::string& registration_id) const {
return registration_id; int64_t last_validated_ms = last_validated.since_origin().InMicroseconds();
return registration_id + kSerializedValidationTimeSeparator +
base::Int64ToString(last_validated_ms);
} }
bool InstanceIDTokenInfo::Deserialize( bool InstanceIDTokenInfo::Deserialize(const std::string& serialized_key,
const std::string& serialized_key,
const std::string& serialized_value, const std::string& serialized_value,
std::string* registration_id) { std::string* registration_id) {
if (serialized_key.empty() || serialized_value.empty()) if (serialized_key.empty() || serialized_value.empty())
...@@ -202,9 +221,27 @@ bool InstanceIDTokenInfo::Deserialize( ...@@ -202,9 +221,27 @@ bool InstanceIDTokenInfo::Deserialize(
authorized_entity = fields[1]; authorized_entity = fields[1];
scope = fields[2]; scope = fields[2];
// Registration ID is same as the serialized value; // Get Registration ID and last_validated from serialized value
size_t pos_hash = serialized_value.find(serialized_value,
kSerializedValidationTimeSeparator);
bool has_timestamp = (pos_hash != std::string::npos);
std::string registration_id_str, last_validated_str;
if (has_timestamp) {
registration_id_str = serialized_value.substr(0, pos_hash);
last_validated_str = serialized_value.substr(pos_hash + 1);
} else {
registration_id_str = serialized_value;
}
if (registration_id) if (registration_id)
*registration_id = serialized_value; *registration_id = registration_id_str;
int64_t last_validated_ms = 0;
if (base::StringToInt64(last_validated_str, &last_validated_ms)) {
// It's okay for last_validated to be the default base::Time() value
// when there is no serialized timestamp available.
last_validated += base::TimeDelta::FromMicroseconds(last_validated_ms);
}
return true; return true;
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <vector> #include <vector>
#include "base/memory/linked_ptr.h" #include "base/memory/linked_ptr.h"
#include "base/time/time.h"
namespace gcm { namespace gcm {
...@@ -48,6 +49,7 @@ struct RegistrationInfo { ...@@ -48,6 +49,7 @@ struct RegistrationInfo {
// Every registration is associated with an application. // Every registration is associated with an application.
std::string app_id; std::string app_id;
base::Time last_validated;
}; };
// For GCM registration. // For GCM registration.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment