Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "components/password_manager/core/browser/affiliation_utils.h" | |
| 6 | |
| 7 #include "base/base64.h" | |
| 8 #include "base/strings/string_piece.h" | |
| 9 #include "base/strings/string_util.h" | |
| 10 #include "url/gurl.h" | |
| 11 #include "url/third_party/mozilla/url_parse.h" | |
| 12 | |
| 13 namespace password_manager { | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 // The scheme used for identifying Android applications. | |
| 18 const char kAndroidAppScheme[] = "android"; | |
| 19 | |
| 20 base::StringPiece ExtractComponent(const std::string& uri, | |
| 21 const url::Component& component) { | |
| 22 if (!component.is_valid()) | |
| 23 return base::StringPiece(); | |
| 24 return base::StringPiece(uri.c_str() + component.begin, component.len); | |
| 25 } | |
| 26 | |
| 27 base::StringPiece ExtractScheme(const std::string& uri) { | |
| 28 url::Component scheme_component; | |
| 29 if (url::ExtractScheme(uri.c_str(), uri.size(), &scheme_component)) | |
| 30 return ExtractComponent(uri, scheme_component); | |
| 31 return base::StringPiece(); | |
| 32 } | |
| 33 | |
| 34 // Computes the canonicalized form of |uri| into |canonical_uri|, and returns | |
| 35 // whether or not the result is a valid facet URI. Even if the result is not | |
| 36 // valid, |canonical_uri| will contain something reasonable. | |
| 37 bool CanonicalizeFacetURI(const std::string& uri, std::string* canonical_uri) { | |
| 38 DCHECK(canonical_uri); | |
| 39 canonical_uri->clear(); | |
| 40 canonical_uri->reserve(uri.size() + 32); | |
| 41 | |
| 42 url::Parsed original_parsed; | |
| 43 url::ParseStandardURL(uri.c_str(), uri.size(), &original_parsed); | |
| 44 url::Parsed canonical_parsed; | |
| 45 url::StdStringCanonOutput canonical_output(canonical_uri); | |
| 46 if (!url::CanonicalizeStandardURL(uri.c_str(), uri.size(), original_parsed, | |
| 47 NULL, &canonical_output, | |
| 48 &canonical_parsed)) { | |
| 49 return false; | |
| 50 } | |
| 51 canonical_output.Complete(); | |
| 52 | |
| 53 // Note that in the canonical form, the scheme will be in lower case already. | |
| 54 if (ExtractComponent(*canonical_uri, canonical_parsed.scheme) == | |
| 55 url::kHttpsScheme) { | |
| 56 // Web facet URI, should be of the form: https://<host>[:<port>]/ | |
| 57 return !canonical_parsed.username.is_valid() && | |
| 58 !canonical_parsed.password.is_valid() && | |
| 59 canonical_parsed.host.is_nonempty() && | |
| 60 ExtractComponent(*canonical_uri, canonical_parsed.path) == "/" && | |
| 61 !canonical_parsed.query.is_valid() && | |
| 62 !canonical_parsed.ref.is_valid(); | |
| 63 } else if (ExtractComponent(*canonical_uri, canonical_parsed.scheme) == | |
| 64 kAndroidAppScheme) { | |
| 65 // Android facet URI, should be form: android://<cert_hash>@<package_name>/, | |
| 66 // where <cert_hash> is base64-encoded but uses '-' and '_' as the 62nd and | |
| 67 // 63rd value, respectively, and the '=' padding character is URL-encoded. | |
| 68 base::StringPiece hash_component( | |
| 69 ExtractComponent(*canonical_uri, canonical_parsed.username)); | |
| 70 std::string base64_encoded_hash(hash_component.as_string()); | |
| 71 base::ReplaceChars(base64_encoded_hash, "-", "+", &base64_encoded_hash); | |
| 72 base::ReplaceChars(base64_encoded_hash, "_", "/", &base64_encoded_hash); | |
| 73 ReplaceSubstringsAfterOffset(&base64_encoded_hash, 0, "%3D", "="); | |
| 74 std::string unused_decoded_hash; | |
| 75 return canonical_parsed.username.is_nonempty() && | |
| 76 base::Base64Decode(base64_encoded_hash, &unused_decoded_hash) && | |
|
Mike West
2014/12/03 22:58:35
Hrm. It surprises me a little bit that we don't su
engedy
2014/12/08 20:53:16
I could not find any support for this in the commo
| |
| 77 !canonical_parsed.password.is_valid() && | |
| 78 canonical_parsed.host.is_nonempty() && | |
| 79 ExtractComponent(*canonical_uri, canonical_parsed.path) == "/" && | |
| 80 !canonical_parsed.query.is_valid() && | |
| 81 !canonical_parsed.ref.is_valid(); | |
|
Mike West
2014/12/03 22:58:35
Most of this is shared with the case above. Pretty
engedy
2014/12/08 20:53:16
Unfortunately, I have realized that we cannot cano
| |
| 82 } | |
| 83 return false; | |
| 84 } | |
| 85 | |
| 86 } // namespace | |
| 87 | |
| 88 FacetURI::FacetURI() : is_valid_(false) { | |
| 89 } | |
| 90 | |
| 91 // static | |
| 92 FacetURI FacetURI::FromPotentiallyInvalidURI(const std::string& uri) { | |
| 93 std::string canonical_uri; | |
| 94 return FacetURI(canonical_uri, CanonicalizeFacetURI(uri, &canonical_uri)); | |
| 95 } | |
| 96 | |
| 97 // static | |
| 98 FacetURI FacetURI::FromCanonicalFacetURI(const std::string& uri) { | |
| 99 return FacetURI(uri, true); | |
| 100 } | |
| 101 | |
| 102 bool FacetURI::IsValidWebFacetURI() const { | |
| 103 return is_valid_ && ExtractScheme(canonical_uri_) == url::kHttpsScheme; | |
| 104 } | |
| 105 | |
| 106 bool FacetURI::IsValidAndroidFacetURI() const { | |
| 107 return is_valid_ && ExtractScheme(canonical_uri_) == kAndroidAppScheme; | |
| 108 } | |
| 109 | |
| 110 FacetURI::FacetURI(const std::string& canonical_facet_uri, bool is_valid) | |
| 111 : is_valid_(is_valid), canonical_uri_(canonical_facet_uri) { | |
| 112 } | |
| 113 | |
| 114 bool AreEquivalenceClassesEqual(const AffiliatedFacets& a, | |
| 115 const AffiliatedFacets& b) { | |
| 116 if (a.size() != b.size()) | |
| 117 return false; | |
| 118 | |
| 119 std::vector<FacetURI> a_sorted(a.begin(), a.end()); | |
| 120 std::vector<FacetURI> b_sorted(b.begin(), b.end()); | |
| 121 std::sort(a_sorted.begin(), a_sorted.end()); | |
| 122 std::sort(b_sorted.begin(), b_sorted.end()); | |
| 123 return std::equal(a_sorted.begin(), a_sorted.end(), b_sorted.begin()); | |
| 124 } | |
| 125 | |
| 126 } // namespace password_manager | |
| OLD | NEW |