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_split.h"
8 #include "base/strings/string_util.h"
13 const char kInsanceIDSerializationPrefix
[] = "iid-";
14 const int kInsanceIDSerializationPrefixLength
=
15 sizeof(kInsanceIDSerializationPrefix
) / sizeof(char) - 1;
19 scoped_ptr
<RegistrationInfo
> RegistrationInfo::BuildFromString(
20 const std::string
& serialzied_key
,
21 const std::string
& serialzied_value
,
22 std::string
* registration_id
) {
23 scoped_ptr
<RegistrationInfo
> registration
;
25 if (base::StartsWithASCII(serialzied_key
, kInsanceIDSerializationPrefix
,
27 registration
.reset(new InstanceIDTokenInfo
);
29 registration
.reset(new GCMRegistrationInfo
);
31 if (!registration
->Deserialize(serialzied_key
,
36 return registration
.Pass();
39 RegistrationInfo::RegistrationInfo() {
42 RegistrationInfo::~RegistrationInfo() {
46 const GCMRegistrationInfo
* GCMRegistrationInfo::FromRegistrationInfo(
47 const RegistrationInfo
* registration_info
) {
48 if (!registration_info
|| registration_info
->GetType() != GCM_REGISTRATION
)
50 return static_cast<const GCMRegistrationInfo
*>(registration_info
);
54 GCMRegistrationInfo
* GCMRegistrationInfo::FromRegistrationInfo(
55 RegistrationInfo
* registration_info
) {
56 if (!registration_info
|| registration_info
->GetType() != GCM_REGISTRATION
)
58 return static_cast<GCMRegistrationInfo
*>(registration_info
);
61 GCMRegistrationInfo::GCMRegistrationInfo() {
64 GCMRegistrationInfo::~GCMRegistrationInfo() {
67 RegistrationInfo::RegistrationType
GCMRegistrationInfo::GetType() const {
68 return GCM_REGISTRATION
;
71 std::string
GCMRegistrationInfo::GetSerializedKey() const {
72 // Multiple registrations are not supported for legacy GCM. So the key is
73 // purely based on the application id.
77 std::string
GCMRegistrationInfo::GetSerializedValue(
78 const std::string
& registration_id
) const {
79 if (sender_ids
.empty() || registration_id
.empty())
83 // sender1,sender2,...=reg_id
85 for (std::vector
<std::string
>::const_iterator iter
= sender_ids
.begin();
86 iter
!= sender_ids
.end(); ++iter
) {
87 DCHECK(!iter
->empty() &&
88 iter
->find(',') == std::string::npos
&&
89 iter
->find('=') == std::string::npos
);
96 value
+= registration_id
;
100 bool GCMRegistrationInfo::Deserialize(
101 const std::string
& serialzied_key
,
102 const std::string
& serialzied_value
,
103 std::string
* registration_id
) {
104 if (serialzied_key
.empty() || serialzied_value
.empty())
107 // Application ID is same as the serialized key.
108 app_id
= serialzied_key
;
110 // Sender IDs and registration ID are constructed from the serialized value.
111 size_t pos
= serialzied_value
.find('=');
112 if (pos
== std::string::npos
)
115 std::string senders
= serialzied_value
.substr(0, pos
);
116 std::string registration_id_str
= serialzied_value
.substr(pos
+ 1);
118 sender_ids
= base::SplitString(
119 senders
, ",", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
120 if (sender_ids
.empty() || registration_id_str
.empty()) {
122 registration_id_str
.clear();
127 *registration_id
= registration_id_str
;
133 const InstanceIDTokenInfo
* InstanceIDTokenInfo::FromRegistrationInfo(
134 const RegistrationInfo
* registration_info
) {
135 if (!registration_info
|| registration_info
->GetType() != INSTANCE_ID_TOKEN
)
137 return static_cast<const InstanceIDTokenInfo
*>(registration_info
);
141 InstanceIDTokenInfo
* InstanceIDTokenInfo::FromRegistrationInfo(
142 RegistrationInfo
* registration_info
) {
143 if (!registration_info
|| registration_info
->GetType() != INSTANCE_ID_TOKEN
)
145 return static_cast<InstanceIDTokenInfo
*>(registration_info
);
148 InstanceIDTokenInfo::InstanceIDTokenInfo() {
151 InstanceIDTokenInfo::~InstanceIDTokenInfo() {
154 RegistrationInfo::RegistrationType
InstanceIDTokenInfo::GetType() const {
155 return INSTANCE_ID_TOKEN
;
158 std::string
InstanceIDTokenInfo::GetSerializedKey() const {
159 DCHECK(authorized_entity
.find(',') == std::string::npos
&&
160 scope
.find(',') == std::string::npos
);
162 // Multiple registrations are supported for Instance ID. So the key is based
163 // on the combination of (app_id, authorized_entity, scope).
165 // Adds a prefix to differentiate easily with GCM registration key.
166 std::string
key(kInsanceIDSerializationPrefix
);
169 key
+= authorized_entity
;
175 std::string
InstanceIDTokenInfo::GetSerializedValue(
176 const std::string
& registration_id
) const {
177 return registration_id
;
180 bool InstanceIDTokenInfo::Deserialize(
181 const std::string
& serialized_key
,
182 const std::string
& serialized_value
,
183 std::string
* registration_id
) {
184 if (serialized_key
.empty() || serialized_value
.empty())
187 if (!base::StartsWithASCII(serialized_key
, kInsanceIDSerializationPrefix
,
191 std::vector
<std::string
> fields
= base::SplitString(
192 serialized_key
.substr(kInsanceIDSerializationPrefixLength
),
193 ",", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
194 if (fields
.size() != 3 || fields
[0].empty() ||
195 fields
[1].empty() || fields
[2].empty()) {
199 authorized_entity
= fields
[1];
202 // Registration ID is same as the serialized value;
204 *registration_id
= serialized_value
;
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
)
219 if (a
->app_id
> b
->app_id
)
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.
231 return iid_b
!= NULL
;
233 // iid_a && !iid_b => false.
237 // Otherwise, compare with authorized_entity and scope.
238 if (iid_a
->authorized_entity
< iid_b
->authorized_entity
)
240 if (iid_a
->authorized_entity
> iid_b
->authorized_entity
)
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
;
250 make_linked_ptr
<RegistrationInfo
>(gcm_registration
.release())) > 0;