178 lines
5.9 KiB
C++
178 lines
5.9 KiB
C++
// Copyright 2020 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "net/base/schemeful_site.h"
|
|
|
|
#include "base/check.h"
|
|
#include "base/metrics/histogram_macros.h"
|
|
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
|
|
#include "net/base/url_util.h"
|
|
#include "url/gurl.h"
|
|
#include "url/url_canon.h"
|
|
#include "url/url_constants.h"
|
|
|
|
namespace net {
|
|
|
|
// Return a tuple containing:
|
|
// * a new origin using the registerable domain of `origin` if possible and
|
|
// a port of 0; otherwise, the passed-in origin.
|
|
// * a bool indicating whether `origin` had a non-null registerable domain.
|
|
// (False if `origin` was opaque.)
|
|
//
|
|
// Follows steps specified in
|
|
// https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site
|
|
SchemefulSite::ObtainASiteResult SchemefulSite::ObtainASite(
|
|
const url::Origin& origin) {
|
|
// 1. If origin is an opaque origin, then return origin.
|
|
if (origin.opaque())
|
|
return {origin, false /* used_registerable_domain */};
|
|
|
|
std::string registerable_domain;
|
|
|
|
// Non-normative step.
|
|
// We only lookup the registerable domain for schemes with network hosts, this
|
|
// is non-normative. Other schemes for non-opaque origins do not
|
|
// meaningfully have a registerable domain for their host, so they are
|
|
// skipped.
|
|
if (IsStandardSchemeWithNetworkHost(origin.scheme())) {
|
|
registerable_domain = GetDomainAndRegistry(
|
|
origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
|
|
}
|
|
|
|
// If origin's host's registrable domain is null, then return (origin's
|
|
// scheme, origin's host).
|
|
//
|
|
// `GetDomainAndRegistry()` returns an empty string for IP literals and
|
|
// effective TLDs.
|
|
//
|
|
// Note that `registerable_domain` could still end up empty, since the
|
|
// `origin` might have a scheme that permits empty hostnames, such as "file".
|
|
bool used_registerable_domain = !registerable_domain.empty();
|
|
if (!used_registerable_domain)
|
|
registerable_domain = origin.host();
|
|
|
|
int port = url::DefaultPortForScheme(origin.scheme().c_str(),
|
|
origin.scheme().length());
|
|
|
|
// Provide a default port of 0 for non-standard schemes.
|
|
if (port == url::PORT_UNSPECIFIED)
|
|
port = 0;
|
|
|
|
return {url::Origin::CreateFromNormalizedTuple(origin.scheme(),
|
|
registerable_domain, port),
|
|
used_registerable_domain};
|
|
}
|
|
|
|
SchemefulSite::SchemefulSite(ObtainASiteResult result)
|
|
: site_as_origin_(std::move(result.origin)) {}
|
|
|
|
SchemefulSite::SchemefulSite(const url::Origin& origin)
|
|
: SchemefulSite(ObtainASite(origin)) {}
|
|
|
|
SchemefulSite::SchemefulSite(const GURL& url)
|
|
: SchemefulSite(url::Origin::Create(url)) {}
|
|
|
|
SchemefulSite::SchemefulSite(const SchemefulSite& other) = default;
|
|
SchemefulSite::SchemefulSite(SchemefulSite&& other) noexcept = default;
|
|
|
|
SchemefulSite& SchemefulSite::operator=(const SchemefulSite& other) = default;
|
|
SchemefulSite& SchemefulSite::operator=(SchemefulSite&& other) noexcept =
|
|
default;
|
|
|
|
// static
|
|
bool SchemefulSite::FromWire(const url::Origin& site_as_origin,
|
|
SchemefulSite* out) {
|
|
// The origin passed into this constructor may not match the
|
|
// `site_as_origin_` used as the internal representation of the schemeful
|
|
// site. However, a valid SchemefulSite's internal origin should result in a
|
|
// match if used to construct another SchemefulSite. Thus, if there is a
|
|
// mismatch here, we must indicate a failure.
|
|
SchemefulSite candidate(site_as_origin);
|
|
if (candidate.site_as_origin_ != site_as_origin)
|
|
return false;
|
|
|
|
*out = std::move(candidate);
|
|
return true;
|
|
}
|
|
|
|
absl::optional<SchemefulSite> SchemefulSite::CreateIfHasRegisterableDomain(
|
|
const url::Origin& origin) {
|
|
ObtainASiteResult result = ObtainASite(origin);
|
|
if (!result.used_registerable_domain)
|
|
return absl::nullopt;
|
|
return SchemefulSite(std::move(result));
|
|
}
|
|
|
|
void SchemefulSite::ConvertWebSocketToHttp() {
|
|
if (site_as_origin_.scheme() == url::kWsScheme ||
|
|
site_as_origin_.scheme() == url::kWssScheme) {
|
|
site_as_origin_ = url::Origin::Create(
|
|
ChangeWebSocketSchemeToHttpScheme(site_as_origin_.GetURL()));
|
|
}
|
|
}
|
|
|
|
// static
|
|
SchemefulSite SchemefulSite::Deserialize(const std::string& value) {
|
|
return SchemefulSite(GURL(value));
|
|
}
|
|
|
|
std::string SchemefulSite::Serialize() const {
|
|
return site_as_origin_.Serialize();
|
|
}
|
|
|
|
std::string SchemefulSite::SerializeFileSiteWithHost() const {
|
|
DCHECK_EQ(url::kFileScheme, site_as_origin_.scheme());
|
|
return site_as_origin_.GetTupleOrPrecursorTupleIfOpaque().Serialize();
|
|
}
|
|
|
|
std::string SchemefulSite::GetDebugString() const {
|
|
return site_as_origin_.GetDebugString();
|
|
}
|
|
|
|
GURL SchemefulSite::GetURL() const {
|
|
return site_as_origin_.GetURL();
|
|
}
|
|
|
|
const url::Origin& SchemefulSite::GetInternalOriginForTesting() const {
|
|
return site_as_origin_;
|
|
}
|
|
|
|
bool SchemefulSite::operator==(const SchemefulSite& other) const {
|
|
return site_as_origin_ == other.site_as_origin_;
|
|
}
|
|
|
|
bool SchemefulSite::operator!=(const SchemefulSite& other) const {
|
|
return !(*this == other);
|
|
}
|
|
|
|
// Allows SchemefulSite to be used as a key in STL containers (for example, a
|
|
// std::set or std::map).
|
|
bool SchemefulSite::operator<(const SchemefulSite& other) const {
|
|
return site_as_origin_ < other.site_as_origin_;
|
|
}
|
|
|
|
// static
|
|
absl::optional<SchemefulSite> SchemefulSite::DeserializeWithNonce(
|
|
const std::string& value) {
|
|
absl::optional<url::Origin> result = url::Origin::Deserialize(value);
|
|
if (!result)
|
|
return absl::nullopt;
|
|
return SchemefulSite(result.value());
|
|
}
|
|
|
|
absl::optional<std::string> SchemefulSite::SerializeWithNonce() {
|
|
return site_as_origin_.SerializeWithNonceAndInitIfNeeded();
|
|
}
|
|
|
|
bool SchemefulSite::SchemelesslyEqual(const SchemefulSite& other) const {
|
|
return site_as_origin_.host() == other.site_as_origin_.host();
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& os, const SchemefulSite& ss) {
|
|
os << ss.Serialize();
|
|
return os;
|
|
}
|
|
|
|
} // namespace net
|