OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/push_messaging/push_messaging_app_identifier.h" | 5 #include "chrome/browser/push_messaging/push_messaging_app_identifier.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include "base/guid.h" | 9 #include "base/guid.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "base/strings/string_split.h" | 12 #include "base/strings/string_split.h" |
13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
15 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
16 #include "chrome/common/pref_names.h" | 16 #include "chrome/common/pref_names.h" |
17 #include "components/pref_registry/pref_registry_syncable.h" | 17 #include "components/pref_registry/pref_registry_syncable.h" |
18 #include "components/prefs/pref_service.h" | 18 #include "components/prefs/pref_service.h" |
19 #include "components/prefs/scoped_user_pref_update.h" | 19 #include "components/prefs/scoped_user_pref_update.h" |
20 | 20 |
21 const char kPushMessagingAppIdentifierPrefix[] = "wp:"; | 21 const char kPushMessagingAppIdentifierPrefix[] = "wp:"; |
| 22 const char kInstanceIDGuidSuffix[] = "-V2"; |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 // sizeof is strlen + 1 since it's null-terminated. | 26 // sizeof is strlen + 1 since it's null-terminated. |
26 const size_t kPrefixLength = sizeof(kPushMessagingAppIdentifierPrefix) - 1; | 27 const size_t kPrefixLength = sizeof(kPushMessagingAppIdentifierPrefix) - 1; |
| 28 const size_t kGuidSuffixLength = sizeof(kInstanceIDGuidSuffix) - 1; |
27 | 29 |
28 const char kSeparator = '#'; // Ok as only the origin of the url is used. | 30 const char kSeparator = '#'; // Ok as only the origin of the url is used. |
29 const size_t kGuidLength = 36; // "%08X-%04X-%04X-%04X-%012llX" | 31 const size_t kGuidLength = 36; // "%08X-%04X-%04X-%04X-%012llX" |
30 | 32 |
31 std::string MakePrefValue(const GURL& origin, | 33 std::string MakePrefValue(const GURL& origin, |
32 int64_t service_worker_registration_id) { | 34 int64_t service_worker_registration_id) { |
33 return origin.spec() + kSeparator + | 35 return origin.spec() + kSeparator + |
34 base::Int64ToString(service_worker_registration_id); | 36 base::Int64ToString(service_worker_registration_id); |
35 } | 37 } |
36 | 38 |
(...skipping 19 matching lines...) Expand all Loading... |
56 void PushMessagingAppIdentifier::RegisterProfilePrefs( | 58 void PushMessagingAppIdentifier::RegisterProfilePrefs( |
57 user_prefs::PrefRegistrySyncable* registry) { | 59 user_prefs::PrefRegistrySyncable* registry) { |
58 // TODO(johnme): If push becomes enabled in incognito, be careful that this | 60 // TODO(johnme): If push becomes enabled in incognito, be careful that this |
59 // pref is read from the right profile, as prefs defined in a regular profile | 61 // pref is read from the right profile, as prefs defined in a regular profile |
60 // are visible in the corresponding incognito profile unless overridden. | 62 // are visible in the corresponding incognito profile unless overridden. |
61 // TODO(johnme): Make sure this pref doesn't get out of sync after crashes. | 63 // TODO(johnme): Make sure this pref doesn't get out of sync after crashes. |
62 registry->RegisterDictionaryPref(prefs::kPushMessagingAppIdentifierMap); | 64 registry->RegisterDictionaryPref(prefs::kPushMessagingAppIdentifierMap); |
63 } | 65 } |
64 | 66 |
65 // static | 67 // static |
| 68 bool PushMessagingAppIdentifier::UseInstanceID(const std::string& app_id) { |
| 69 return base::EndsWith(app_id, kInstanceIDGuidSuffix, |
| 70 base::CompareCase::SENSITIVE); |
| 71 } |
| 72 |
| 73 // static |
66 PushMessagingAppIdentifier PushMessagingAppIdentifier::Generate( | 74 PushMessagingAppIdentifier PushMessagingAppIdentifier::Generate( |
67 const GURL& origin, | 75 const GURL& origin, |
68 int64_t service_worker_registration_id) { | 76 int64_t service_worker_registration_id) { |
69 // Use uppercase GUID for consistency with GUIDs Push has already sent to GCM. | 77 // Use uppercase GUID for consistency with GUIDs Push has already sent to GCM. |
70 // Also allows detecting case mangling; see code commented "crbug.com/461867". | 78 // Also allows detecting case mangling; see code commented "crbug.com/461867". |
71 std::string guid = base::ToUpperASCII(base::GenerateGUID()); | 79 std::string guid = base::ToUpperASCII(base::GenerateGUID()); |
| 80 // All new push subscriptions are Instance ID tokens. |
| 81 guid.replace(guid.size() - kGuidSuffixLength, kGuidSuffixLength, |
| 82 kInstanceIDGuidSuffix); |
72 CHECK(!guid.empty()); | 83 CHECK(!guid.empty()); |
73 std::string app_id = | 84 std::string app_id = |
74 kPushMessagingAppIdentifierPrefix + origin.spec() + kSeparator + guid; | 85 kPushMessagingAppIdentifierPrefix + origin.spec() + kSeparator + guid; |
75 | 86 |
76 PushMessagingAppIdentifier app_identifier(app_id, origin, | 87 PushMessagingAppIdentifier app_identifier(app_id, origin, |
77 service_worker_registration_id); | 88 service_worker_registration_id); |
78 app_identifier.DCheckValid(); | 89 app_identifier.DCheckValid(); |
79 return app_identifier; | 90 return app_identifier; |
80 } | 91 } |
81 | 92 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 void PushMessagingAppIdentifier::DeleteFromPrefs(Profile* profile) const { | 200 void PushMessagingAppIdentifier::DeleteFromPrefs(Profile* profile) const { |
190 DCheckValid(); | 201 DCheckValid(); |
191 | 202 |
192 DictionaryPrefUpdate update(profile->GetPrefs(), | 203 DictionaryPrefUpdate update(profile->GetPrefs(), |
193 prefs::kPushMessagingAppIdentifierMap); | 204 prefs::kPushMessagingAppIdentifierMap); |
194 base::DictionaryValue* map = update.Get(); | 205 base::DictionaryValue* map = update.Get(); |
195 map->RemoveWithoutPathExpansion(app_id_, nullptr /* out_value */); | 206 map->RemoveWithoutPathExpansion(app_id_, nullptr /* out_value */); |
196 } | 207 } |
197 | 208 |
198 void PushMessagingAppIdentifier::DCheckValid() const { | 209 void PushMessagingAppIdentifier::DCheckValid() const { |
| 210 #if DCHECK_IS_ON() |
199 DCHECK_GE(service_worker_registration_id_, 0); | 211 DCHECK_GE(service_worker_registration_id_, 0); |
200 | 212 |
201 DCHECK(origin_.is_valid()); | 213 DCHECK(origin_.is_valid()); |
202 DCHECK_EQ(origin_.GetOrigin(), origin_); | 214 DCHECK_EQ(origin_.GetOrigin(), origin_); |
203 | 215 |
204 // "wp:" | 216 // "wp:" |
205 DCHECK_EQ(kPushMessagingAppIdentifierPrefix, | 217 DCHECK_EQ(kPushMessagingAppIdentifierPrefix, |
206 app_id_.substr(0, kPrefixLength)); | 218 app_id_.substr(0, kPrefixLength)); |
| 219 |
207 // Optional (origin.spec() + '#') | 220 // Optional (origin.spec() + '#') |
208 if (app_id_.size() != kPrefixLength + kGuidLength) { | 221 if (app_id_.size() != kPrefixLength + kGuidLength) { |
209 const size_t suffix_length = 1 /* kSeparator */ + kGuidLength; | 222 const size_t suffix_length = 1 /* kSeparator */ + kGuidLength; |
210 DCHECK(app_id_.size() > kPrefixLength + suffix_length); | 223 DCHECK_GT(app_id_.size(), kPrefixLength + suffix_length); |
211 DCHECK_EQ(origin_, GURL(app_id_.substr( | 224 DCHECK_EQ(origin_, GURL(app_id_.substr( |
212 kPrefixLength, | 225 kPrefixLength, |
213 app_id_.size() - kPrefixLength - suffix_length))); | 226 app_id_.size() - kPrefixLength - suffix_length))); |
214 DCHECK_EQ(std::string(1, kSeparator), | 227 DCHECK_EQ(std::string(1, kSeparator), |
215 app_id_.substr(app_id_.size() - suffix_length, 1)); | 228 app_id_.substr(app_id_.size() - suffix_length, 1)); |
216 } | 229 } |
217 // GUID | 230 |
218 DCHECK(base::IsValidGUID(app_id_.substr(app_id_.size() - kGuidLength))); | 231 // GUID. In order to distinguish them, an app_id created for an InstanceID |
| 232 // based subscription has the last few characters of the GUID overwritten with |
| 233 // kInstanceIDGuidSuffix (which contains non-hex characters invalid in GUIDs). |
| 234 std::string guid = app_id_.substr(app_id_.size() - kGuidLength); |
| 235 if (UseInstanceID(app_id_)) { |
| 236 DCHECK(!base::IsValidGUID(guid)); |
| 237 |
| 238 // Replace suffix with valid hex so we can validate the rest of the string. |
| 239 guid = guid.replace(guid.size() - kGuidSuffixLength, kGuidSuffixLength, |
| 240 kGuidSuffixLength, 'C'); |
| 241 } |
| 242 DCHECK(base::IsValidGUID(guid)); |
| 243 #endif // DCHECK_IS_ON() |
219 } | 244 } |
OLD | NEW |