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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: components/password_manager/core/browser/affiliation_utils.cc
diff --git a/components/password_manager/core/browser/affiliation_utils.cc b/components/password_manager/core/browser/affiliation_utils.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e906ee4c62a7e3924b4f249fc033a2408c8de6a9
--- /dev/null
+++ b/components/password_manager/core/browser/affiliation_utils.cc
@@ -0,0 +1,126 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/affiliation_utils.h"
+
+#include "base/base64.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "url/gurl.h"
+#include "url/third_party/mozilla/url_parse.h"
+
+namespace password_manager {
+
+namespace {
+
+// The scheme used for identifying Android applications.
+const char kAndroidAppScheme[] = "android";
+
+base::StringPiece ExtractComponent(const std::string& uri,
+ const url::Component& component) {
+ if (!component.is_valid())
+ return base::StringPiece();
+ return base::StringPiece(uri.c_str() + component.begin, component.len);
+}
+
+base::StringPiece ExtractScheme(const std::string& uri) {
+ url::Component scheme_component;
+ if (url::ExtractScheme(uri.c_str(), uri.size(), &scheme_component))
+ return ExtractComponent(uri, scheme_component);
+ return base::StringPiece();
+}
+
+// Computes the canonicalized form of |uri| into |canonical_uri|, and returns
+// whether or not the result is a valid facet URI. Even if the result is not
+// valid, |canonical_uri| will contain something reasonable.
+bool CanonicalizeFacetURI(const std::string& uri, std::string* canonical_uri) {
+ DCHECK(canonical_uri);
+ canonical_uri->clear();
+ canonical_uri->reserve(uri.size() + 32);
+
+ url::Parsed original_parsed;
+ url::ParseStandardURL(uri.c_str(), uri.size(), &original_parsed);
+ url::Parsed canonical_parsed;
+ url::StdStringCanonOutput canonical_output(canonical_uri);
+ if (!url::CanonicalizeStandardURL(uri.c_str(), uri.size(), original_parsed,
+ NULL, &canonical_output,
+ &canonical_parsed)) {
+ return false;
+ }
+ canonical_output.Complete();
+
+ // Note that in the canonical form, the scheme will be in lower case already.
+ if (ExtractComponent(*canonical_uri, canonical_parsed.scheme) ==
+ url::kHttpsScheme) {
+ // Web facet URI, should be of the form: https://<host>[:<port>]/
+ return !canonical_parsed.username.is_valid() &&
+ !canonical_parsed.password.is_valid() &&
+ canonical_parsed.host.is_nonempty() &&
+ ExtractComponent(*canonical_uri, canonical_parsed.path) == "/" &&
+ !canonical_parsed.query.is_valid() &&
+ !canonical_parsed.ref.is_valid();
+ } else if (ExtractComponent(*canonical_uri, canonical_parsed.scheme) ==
+ kAndroidAppScheme) {
+ // Android facet URI, should be form: android://<cert_hash>@<package_name>/,
+ // where <cert_hash> is base64-encoded but uses '-' and '_' as the 62nd and
+ // 63rd value, respectively, and the '=' padding character is URL-encoded.
+ base::StringPiece hash_component(
+ ExtractComponent(*canonical_uri, canonical_parsed.username));
+ std::string base64_encoded_hash(hash_component.as_string());
+ base::ReplaceChars(base64_encoded_hash, "-", "+", &base64_encoded_hash);
+ base::ReplaceChars(base64_encoded_hash, "_", "/", &base64_encoded_hash);
+ ReplaceSubstringsAfterOffset(&base64_encoded_hash, 0, "%3D", "=");
+ std::string unused_decoded_hash;
+ return canonical_parsed.username.is_nonempty() &&
+ 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
+ !canonical_parsed.password.is_valid() &&
+ canonical_parsed.host.is_nonempty() &&
+ ExtractComponent(*canonical_uri, canonical_parsed.path) == "/" &&
+ !canonical_parsed.query.is_valid() &&
+ !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
+ }
+ return false;
+}
+
+} // namespace
+
+FacetURI::FacetURI() : is_valid_(false) {
+}
+
+// static
+FacetURI FacetURI::FromPotentiallyInvalidURI(const std::string& uri) {
+ std::string canonical_uri;
+ return FacetURI(canonical_uri, CanonicalizeFacetURI(uri, &canonical_uri));
+}
+
+// static
+FacetURI FacetURI::FromCanonicalFacetURI(const std::string& uri) {
+ return FacetURI(uri, true);
+}
+
+bool FacetURI::IsValidWebFacetURI() const {
+ return is_valid_ && ExtractScheme(canonical_uri_) == url::kHttpsScheme;
+}
+
+bool FacetURI::IsValidAndroidFacetURI() const {
+ return is_valid_ && ExtractScheme(canonical_uri_) == kAndroidAppScheme;
+}
+
+FacetURI::FacetURI(const std::string& canonical_facet_uri, bool is_valid)
+ : is_valid_(is_valid), canonical_uri_(canonical_facet_uri) {
+}
+
+bool AreEquivalenceClassesEqual(const AffiliatedFacets& a,
+ const AffiliatedFacets& b) {
+ if (a.size() != b.size())
+ return false;
+
+ std::vector<FacetURI> a_sorted(a.begin(), a.end());
+ std::vector<FacetURI> b_sorted(b.begin(), b.end());
+ std::sort(a_sorted.begin(), a_sorted.end());
+ std::sort(b_sorted.begin(), b_sorted.end());
+ return std::equal(a_sorted.begin(), a_sorted.end(), b_sorted.begin());
+}
+
+} // namespace password_manager

Powered by Google App Engine
This is Rietveld 408576698