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") {
}
}
# This is part of the components_unittests BUILD target.
source_set("unit_tests") {
testonly = true
......
......@@ -889,8 +889,8 @@ void GCMClientImpl::Register(
}
if (matched) {
delegate_->OnRegisterFinished(
registration_info, registrations_iter->second, SUCCESS);
delegate_->OnRegisterFinished(registration_info,
registrations_iter->second, SUCCESS);
return;
}
}
......@@ -981,8 +981,9 @@ void GCMClientImpl::OnRegisterCompleted(
// Note that the existing cached record has to be removed first because
// 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
// only app_id is used in the comparison.
// only app_id is used in the key comparison.
registrations_.erase(registration_info);
registration_info->last_validated = clock_->Now();
registrations_[registration_info] = registration_id;
// Save it in the persistent store.
......
......@@ -63,6 +63,7 @@ const uint64_t kDeviceSecurityToken2 = 2222;
const int64_t kSettingsCheckinInterval = 16 * 60 * 60;
const char kProductCategoryForSubtypes[] = "com.chrome.macosx";
const char kExtensionAppId[] = "abcdefghijklmnopabcdefghijklmnop";
const char kRegistrationId[] = "reg_id";
const char kSubtypeAppId[] = "app_id";
const char kSender[] = "project_id";
const char kSender2[] = "project_id2";
......@@ -770,6 +771,26 @@ TEST_F(GCMClientImplTest, DestroyStoreWhenNotNeeded) {
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) {
EXPECT_FALSE(ExistsRegistration(kExtensionAppId));
......
......@@ -6,13 +6,18 @@
#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_util.h"
#include "base/strings/stringprintf.h"
namespace gcm {
namespace {
const char kInstanceIDSerializationPrefix[] = "iid-";
const char kSerializedValidationTimeSeparator = '#';
const char kSerializedKeySeparator = ',';
const int kInstanceIDSerializationPrefixLength =
sizeof(kInstanceIDSerializationPrefix) / sizeof(char) - 1;
} // namespace
......@@ -30,8 +35,7 @@ std::unique_ptr<RegistrationInfo> RegistrationInfo::BuildFromString(
else
registration.reset(new GCMRegistrationInfo);
if (!registration->Deserialize(serialized_key,
serialized_value,
if (!registration->Deserialize(serialized_key, serialized_value,
registration_id)) {
registration.reset();
}
......@@ -82,7 +86,7 @@ std::string GCMRegistrationInfo::GetSerializedValue(
return std::string();
// Serialize as:
// sender1,sender2,...=reg_id
// sender1,sender2,...=reg_id#time_of_last_validation
std::string value;
for (std::vector<std::string>::const_iterator iter = sender_ids.begin();
iter != sender_ids.end(); ++iter) {
......@@ -94,15 +98,15 @@ std::string GCMRegistrationInfo::GetSerializedValue(
value += *iter;
}
value += '=';
value += registration_id;
return value;
return base::StringPrintf("%s=%s%c%" PRId64, value.c_str(),
registration_id.c_str(),
kSerializedValidationTimeSeparator,
last_validated.since_origin().InMicroseconds());
}
bool GCMRegistrationInfo::Deserialize(
const std::string& serialized_key,
const std::string& serialized_value,
std::string* registration_id) {
bool GCMRegistrationInfo::Deserialize(const std::string& serialized_key,
const std::string& serialized_value,
std::string* registration_id) {
if (serialized_key.empty() || serialized_value.empty())
return false;
......@@ -110,12 +114,22 @@ bool GCMRegistrationInfo::Deserialize(
app_id = serialized_key;
// Sender IDs and registration ID are constructed from the serialized value.
size_t pos = serialized_value.find('=');
if (pos == std::string::npos)
size_t pos_equals = serialized_value.find('=');
if (pos_equals == std::string::npos)
return false;
std::string senders = serialized_value.substr(0, pos);
std::string registration_id_str = serialized_value.substr(pos + 1);
// Note that it's valid for pos_hash to be std::string::npos.
size_t pos_hash = serialized_value.find(kSerializedValidationTimeSeparator);
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(
senders, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
......@@ -127,6 +141,13 @@ bool GCMRegistrationInfo::Deserialize(
if (registration_id)
*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;
}
......@@ -166,24 +187,22 @@ std::string InstanceIDTokenInfo::GetSerializedKey() const {
// on the combination of (app_id, authorized_entity, scope).
// Adds a prefix to differentiate easily with GCM registration key.
std::string key(kInstanceIDSerializationPrefix);
key += app_id;
key += ",";
key += authorized_entity;
key += ",";
key += scope;
return key;
return base::StringPrintf("%s%s%c%s%c%s", kInstanceIDSerializationPrefix,
app_id.c_str(), kSerializedKeySeparator,
authorized_entity.c_str(), kSerializedKeySeparator,
scope.c_str());
}
std::string InstanceIDTokenInfo::GetSerializedValue(
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(
const std::string& serialized_key,
const std::string& serialized_value,
std::string* registration_id) {
bool InstanceIDTokenInfo::Deserialize(const std::string& serialized_key,
const std::string& serialized_value,
std::string* registration_id) {
if (serialized_key.empty() || serialized_value.empty())
return false;
......@@ -202,9 +221,27 @@ bool InstanceIDTokenInfo::Deserialize(
authorized_entity = fields[1];
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)
*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;
}
......@@ -251,7 +288,7 @@ bool ExistsGCMRegistrationInMap(const RegistrationInfoMap& map,
new GCMRegistrationInfo);
gcm_registration->app_id = app_id;
return map.count(
make_linked_ptr<RegistrationInfo>(gcm_registration.release())) > 0;
make_linked_ptr<RegistrationInfo>(gcm_registration.release())) > 0;
}
} // namespace gcm
......@@ -11,6 +11,7 @@
#include <vector>
#include "base/memory/linked_ptr.h"
#include "base/time/time.h"
namespace gcm {
......@@ -48,6 +49,7 @@ struct RegistrationInfo {
// Every registration is associated with an application.
std::string app_id;
base::Time last_validated;
};
// 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