Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(789)

Side by Side Diff: components/password_manager/core/browser/affiliation_utils.cc

Issue 771173002: Added utility functions related to working with "facets". (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Introduced FacetURI. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698