Fix a couple problems related to getting and deleting Instance ID
[chromium-blink-merge.git] / components / gcm_driver / registration_info.cc
blob5bae2fd49c2325107b96efeac816cd397da21409
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/gcm_driver/registration_info.h"
7 #include "base/strings/string_util.h"
9 namespace gcm {
11 namespace {
12 const char kInsanceIDSerializationPrefix[] = "iid-";
13 const int kInsanceIDSerializationPrefixLength =
14 sizeof(kInsanceIDSerializationPrefix) / sizeof(char) - 1;
15 } // namespace
17 // static
18 scoped_ptr<RegistrationInfo> RegistrationInfo::BuildFromString(
19 const std::string& serialzied_key,
20 const std::string& serialzied_value,
21 std::string* registration_id) {
22 scoped_ptr<RegistrationInfo> registration;
24 if (base::StartsWithASCII(serialzied_key, kInsanceIDSerializationPrefix,
25 true))
26 registration.reset(new InstanceIDTokenInfo);
27 else
28 registration.reset(new GCMRegistrationInfo);
30 if (!registration->Deserialize(serialzied_key,
31 serialzied_value,
32 registration_id)) {
33 registration.reset();
35 return registration.Pass();
38 RegistrationInfo::RegistrationInfo() {
41 RegistrationInfo::~RegistrationInfo() {
44 // static
45 const GCMRegistrationInfo* GCMRegistrationInfo::FromRegistrationInfo(
46 const RegistrationInfo* registration_info) {
47 if (!registration_info || registration_info->GetType() != GCM_REGISTRATION)
48 return NULL;
49 return static_cast<const GCMRegistrationInfo*>(registration_info);
52 // static
53 GCMRegistrationInfo* GCMRegistrationInfo::FromRegistrationInfo(
54 RegistrationInfo* registration_info) {
55 if (!registration_info || registration_info->GetType() != GCM_REGISTRATION)
56 return NULL;
57 return static_cast<GCMRegistrationInfo*>(registration_info);
60 GCMRegistrationInfo::GCMRegistrationInfo() {
63 GCMRegistrationInfo::~GCMRegistrationInfo() {
66 RegistrationInfo::RegistrationType GCMRegistrationInfo::GetType() const {
67 return GCM_REGISTRATION;
70 std::string GCMRegistrationInfo::GetSerializedKey() const {
71 // Multiple registrations are not supported for legacy GCM. So the key is
72 // purely based on the application id.
73 return app_id;
76 std::string GCMRegistrationInfo::GetSerializedValue(
77 const std::string& registration_id) const {
78 if (sender_ids.empty() || registration_id.empty())
79 return std::string();
81 // Serialize as:
82 // sender1,sender2,...=reg_id
83 std::string value;
84 for (std::vector<std::string>::const_iterator iter = sender_ids.begin();
85 iter != sender_ids.end(); ++iter) {
86 DCHECK(!iter->empty() &&
87 iter->find(',') == std::string::npos &&
88 iter->find('=') == std::string::npos);
89 if (!value.empty())
90 value += ",";
91 value += *iter;
94 value += '=';
95 value += registration_id;
96 return value;
99 bool GCMRegistrationInfo::Deserialize(
100 const std::string& serialzied_key,
101 const std::string& serialzied_value,
102 std::string* registration_id) {
103 if (serialzied_key.empty() || serialzied_value.empty())
104 return false;
106 // Application ID is same as the serialized key.
107 app_id = serialzied_key;
109 // Sender IDs and registration ID are constructed from the serialized value.
110 size_t pos = serialzied_value.find('=');
111 if (pos == std::string::npos)
112 return false;
114 std::string senders = serialzied_value.substr(0, pos);
115 std::string registration_id_str = serialzied_value.substr(pos + 1);
117 Tokenize(senders, ",", &sender_ids);
119 if (sender_ids.empty() || registration_id_str.empty()) {
120 sender_ids.clear();
121 registration_id_str.clear();
122 return false;
125 if (registration_id)
126 *registration_id = registration_id_str;
128 return true;
131 // static
132 const InstanceIDTokenInfo* InstanceIDTokenInfo::FromRegistrationInfo(
133 const RegistrationInfo* registration_info) {
134 if (!registration_info || registration_info->GetType() != INSTANCE_ID_TOKEN)
135 return NULL;
136 return static_cast<const InstanceIDTokenInfo*>(registration_info);
139 // static
140 InstanceIDTokenInfo* InstanceIDTokenInfo::FromRegistrationInfo(
141 RegistrationInfo* registration_info) {
142 if (!registration_info || registration_info->GetType() != INSTANCE_ID_TOKEN)
143 return NULL;
144 return static_cast<InstanceIDTokenInfo*>(registration_info);
147 InstanceIDTokenInfo::InstanceIDTokenInfo() {
150 InstanceIDTokenInfo::~InstanceIDTokenInfo() {
153 RegistrationInfo::RegistrationType InstanceIDTokenInfo::GetType() const {
154 return INSTANCE_ID_TOKEN;
157 std::string InstanceIDTokenInfo::GetSerializedKey() const {
158 DCHECK(authorized_entity.find(',') == std::string::npos &&
159 scope.find(',') == std::string::npos);
161 // Multiple registrations are supported for Instance ID. So the key is based
162 // on the combination of (app_id, authorized_entity, scope).
164 // Adds a prefix to differentiate easily with GCM registration key.
165 std::string key(kInsanceIDSerializationPrefix);
166 key += app_id;
167 key += ",";
168 key += authorized_entity;
169 key += ",";
170 key += scope;
171 return key;
174 std::string InstanceIDTokenInfo::GetSerializedValue(
175 const std::string& registration_id) const {
176 return registration_id;
179 bool InstanceIDTokenInfo::Deserialize(
180 const std::string& serialized_key,
181 const std::string& serialized_value,
182 std::string* registration_id) {
183 if (serialized_key.empty() || serialized_value.empty())
184 return false;
186 if (!base::StartsWithASCII(serialized_key, kInsanceIDSerializationPrefix,
187 true))
188 return false;
190 std::vector<std::string> fields;
191 Tokenize(serialized_key.substr(kInsanceIDSerializationPrefixLength),
192 ",",
193 &fields);
194 if (fields.size() != 3 || fields[0].empty() ||
195 fields[1].empty() || fields[2].empty()) {
196 return false;
198 app_id = fields[0];
199 authorized_entity = fields[1];
200 scope = fields[2];
202 // Registration ID is same as the serialized value;
203 if (registration_id)
204 *registration_id = serialized_value;
206 return true;
209 bool RegistrationInfoComparer::operator()(
210 const linked_ptr<RegistrationInfo>& a,
211 const linked_ptr<RegistrationInfo>& b) const {
212 DCHECK(a.get() && b.get());
214 // For GCMRegistrationInfo, the comparison is based on app_id only.
215 // For InstanceIDTokenInfo, the comparison is bsaed on
216 // <app_id, authorized_entity, scope>.
217 if (a->app_id < b->app_id)
218 return true;
219 if (a->app_id > b->app_id)
220 return false;
222 InstanceIDTokenInfo* iid_a =
223 InstanceIDTokenInfo::FromRegistrationInfo(a.get());
224 InstanceIDTokenInfo* iid_b =
225 InstanceIDTokenInfo::FromRegistrationInfo(b.get());
227 // !iid_a && !iid_b => false.
228 // !iid_a && iid_b => true.
229 // This makes GCM record is sorted before InstanceID record.
230 if (!iid_a)
231 return iid_b != NULL;
233 // iid_a && !iid_b => false.
234 if (!iid_b)
235 return false;
237 // Otherwise, compare with authorized_entity and scope.
238 if (iid_a->authorized_entity < iid_b->authorized_entity)
239 return true;
240 if (iid_a->authorized_entity > iid_b->authorized_entity)
241 return false;
242 return iid_a->scope < iid_b->scope;
245 bool ExistsGCMRegistrationInMap(const RegistrationInfoMap& map,
246 const std::string& app_id) {
247 scoped_ptr<GCMRegistrationInfo> gcm_registration(new GCMRegistrationInfo);
248 gcm_registration->app_id = app_id;
249 return map.count(
250 make_linked_ptr<RegistrationInfo>(gcm_registration.release())) > 0;
253 } // namespace gcm