Commit ef0225f0 authored by Lily Chen's avatar Lily Chen Committed by Commit Bot

Add mojo serialization code for net::SchemefulSite

SchemefulSite was added in https://crrev.com/c/2458466.

This adds an equivalent mojo struct and StructTraits for SchemefulSite.

Change-Id: Iec7f4b99df90a00eccdf240dcdf345fb7255d852
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2514464
Commit-Queue: Lily Chen <chlily@chromium.org>
Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Reviewed-by: default avatarJohn Delaney <johnidel@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#823758}
parent a602d1ac
...@@ -45,11 +45,12 @@ url::Origin SwitchToRegistrableDomainAndRemovePort(const url::Origin& origin) { ...@@ -45,11 +45,12 @@ url::Origin SwitchToRegistrableDomainAndRemovePort(const url::Origin& origin) {
// //
// `GetDomainAndRegistry()` returns an empty string for IP literals and // `GetDomainAndRegistry()` returns an empty string for IP literals and
// effective TLDs. // 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".
if (registerable_domain.empty()) if (registerable_domain.empty())
registerable_domain = origin.host(); registerable_domain = origin.host();
DCHECK(!registerable_domain.empty());
int port = url::DefaultPortForScheme(origin.scheme().c_str(), int port = url::DefaultPortForScheme(origin.scheme().c_str(),
origin.scheme().length()); origin.scheme().length());
...@@ -57,8 +58,6 @@ url::Origin SwitchToRegistrableDomainAndRemovePort(const url::Origin& origin) { ...@@ -57,8 +58,6 @@ url::Origin SwitchToRegistrableDomainAndRemovePort(const url::Origin& origin) {
if (port == url::PORT_UNSPECIFIED) if (port == url::PORT_UNSPECIFIED)
port = 0; port = 0;
// We tack on a port of 0, as a port is not included in the result of running
// the above algorithm.
return url::Origin::CreateFromNormalizedTuple(origin.scheme(), return url::Origin::CreateFromNormalizedTuple(origin.scheme(),
registerable_domain, port); registerable_domain, port);
} }
...@@ -66,10 +65,10 @@ url::Origin SwitchToRegistrableDomainAndRemovePort(const url::Origin& origin) { ...@@ -66,10 +65,10 @@ url::Origin SwitchToRegistrableDomainAndRemovePort(const url::Origin& origin) {
} // namespace } // namespace
SchemefulSite::SchemefulSite(const url::Origin& origin) SchemefulSite::SchemefulSite(const url::Origin& origin)
: origin_(SwitchToRegistrableDomainAndRemovePort(origin)) {} : site_as_origin_(SwitchToRegistrableDomainAndRemovePort(origin)) {}
SchemefulSite::SchemefulSite(const GURL& url) SchemefulSite::SchemefulSite(const GURL& url)
: origin_( : site_as_origin_(
SwitchToRegistrableDomainAndRemovePort(url::Origin::Create(url))) {} SwitchToRegistrableDomainAndRemovePort(url::Origin::Create(url))) {}
SchemefulSite::SchemefulSite(const SchemefulSite& other) = default; SchemefulSite::SchemefulSite(const SchemefulSite& other) = default;
...@@ -84,19 +83,19 @@ SchemefulSite SchemefulSite::Deserialize(const std::string& value) { ...@@ -84,19 +83,19 @@ SchemefulSite SchemefulSite::Deserialize(const std::string& value) {
} }
std::string SchemefulSite::Serialize() const { std::string SchemefulSite::Serialize() const {
return origin_.Serialize(); return site_as_origin_.Serialize();
} }
std::string SchemefulSite::GetDebugString() const { std::string SchemefulSite::GetDebugString() const {
return origin_.GetDebugString(); return site_as_origin_.GetDebugString();
} }
const url::Origin& SchemefulSite::GetInternalOriginForTesting() const { const url::Origin& SchemefulSite::GetInternalOriginForTesting() const {
return origin_; return site_as_origin_;
} }
bool SchemefulSite::operator==(const SchemefulSite& other) const { bool SchemefulSite::operator==(const SchemefulSite& other) const {
return origin_ == other.origin_; return site_as_origin_ == other.site_as_origin_;
} }
bool SchemefulSite::operator!=(const SchemefulSite& other) const { bool SchemefulSite::operator!=(const SchemefulSite& other) const {
...@@ -106,7 +105,7 @@ bool SchemefulSite::operator!=(const SchemefulSite& other) const { ...@@ -106,7 +105,7 @@ bool SchemefulSite::operator!=(const SchemefulSite& other) const {
// Allows SchemefulSite to be used as a key in STL containers (for example, a // Allows SchemefulSite to be used as a key in STL containers (for example, a
// std::set or std::map). // std::set or std::map).
bool SchemefulSite::operator<(const SchemefulSite& other) const { bool SchemefulSite::operator<(const SchemefulSite& other) const {
return origin_ < other.origin_; return site_as_origin_ < other.site_as_origin_;
} }
// static // static
...@@ -119,7 +118,7 @@ base::Optional<SchemefulSite> SchemefulSite::DeserializeWithNonce( ...@@ -119,7 +118,7 @@ base::Optional<SchemefulSite> SchemefulSite::DeserializeWithNonce(
} }
base::Optional<std::string> SchemefulSite::SerializeWithNonce() { base::Optional<std::string> SchemefulSite::SerializeWithNonce() {
return origin_.SerializeWithNonceAndInitIfNeeded(); return site_as_origin_.SerializeWithNonceAndInitIfNeeded();
} }
} // namespace net } // namespace net
...@@ -14,6 +14,17 @@ ...@@ -14,6 +14,17 @@
class GURL; class GURL;
namespace network {
namespace mojom {
class SchemefulSiteDataView;
} // namespace mojom
} // namespace network
namespace mojo {
template <typename DataViewType, typename T>
struct StructTraits;
} // namespace mojo
namespace net { namespace net {
// Class which represents a scheme and etld+1 for an origin, as specified by // Class which represents a scheme and etld+1 for an origin, as specified by
...@@ -21,6 +32,10 @@ namespace net { ...@@ -21,6 +32,10 @@ namespace net {
class NET_EXPORT SchemefulSite { class NET_EXPORT SchemefulSite {
public: public:
SchemefulSite() = default; SchemefulSite() = default;
// The passed `origin` may not match the resulting internal representation in
// certain circumstances. See the comment, below, on the `site_as_origin_`
// member.
explicit SchemefulSite(const url::Origin& origin); explicit SchemefulSite(const url::Origin& origin);
// Using the origin constructor is preferred as this is less efficient. // Using the origin constructor is preferred as this is less efficient.
...@@ -38,17 +53,17 @@ class NET_EXPORT SchemefulSite { ...@@ -38,17 +53,17 @@ class NET_EXPORT SchemefulSite {
// Returns an opaque `SchemefulSite` if the value was invalid in any way. // Returns an opaque `SchemefulSite` if the value was invalid in any way.
static SchemefulSite Deserialize(const std::string& value); static SchemefulSite Deserialize(const std::string& value);
// Returns a serialized version of `origin_`. If the underlying origin is // Returns a serialized version of `site_as_origin_`. If the underlying origin
// invalid, returns an empty string. If serialization of opaque origins with // is invalid, returns an empty string. If serialization of opaque origins
// their associated nonce is necessary, see `SerializeWithNonce()`. // with their associated nonce is necessary, see `SerializeWithNonce()`.
std::string Serialize() const; std::string Serialize() const;
std::string GetDebugString() const; std::string GetDebugString() const;
bool opaque() const { return origin_.opaque(); } bool opaque() const { return site_as_origin_.opaque(); }
// Testing only function which allows tests to access the underlying `origin_` // Testing only function which allows tests to access the underlying
// in order to verify behavior. // `site_as_origin_` in order to verify behavior.
const url::Origin& GetInternalOriginForTesting() const; const url::Origin& GetInternalOriginForTesting() const;
bool operator==(const SchemefulSite& other) const; bool operator==(const SchemefulSite& other) const;
...@@ -58,6 +73,10 @@ class NET_EXPORT SchemefulSite { ...@@ -58,6 +73,10 @@ class NET_EXPORT SchemefulSite {
bool operator<(const SchemefulSite& other) const; bool operator<(const SchemefulSite& other) const;
private: private:
// Mojo serialization code needs to access internal origin.
friend struct mojo::StructTraits<network::mojom::SchemefulSiteDataView,
SchemefulSite>;
FRIEND_TEST_ALL_PREFIXES(SchemefulSiteTest, OpaqueSerialization); FRIEND_TEST_ALL_PREFIXES(SchemefulSiteTest, OpaqueSerialization);
// Deserializes a string obtained from `SerializeWithNonce()` to a // Deserializes a string obtained from `SerializeWithNonce()` to a
...@@ -65,14 +84,25 @@ class NET_EXPORT SchemefulSite { ...@@ -65,14 +84,25 @@ class NET_EXPORT SchemefulSite {
static base::Optional<SchemefulSite> DeserializeWithNonce( static base::Optional<SchemefulSite> DeserializeWithNonce(
const std::string& value); const std::string& value);
// Returns a serialized version of `origin_`. For an opaque `origin_`, this // Returns a serialized version of `site_as_origin_`. For an opaque
// serializes with the nonce. See `url::origin::SerializeWithNonce()` for // `site_as_origin_`, this serializes with the nonce. See
// usage information. // `url::origin::SerializeWithNonce()` for usage information.
base::Optional<std::string> SerializeWithNonce(); base::Optional<std::string> SerializeWithNonce();
// Origin which stores the result of running the steps documented at // Origin which stores the result of running the steps documented at
// https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site. // https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site.
url::Origin origin_; // This is not an arbitrary origin. It must either be an opaque origin, or a
// scheme + eTLD+1 + default port.
//
// The `origin` passed into the SchemefulSite(const url::Origin&) constructor
// might not match this internal representation used by this class to track
// the scheme and eTLD+1 representing a schemeful site. This may be the case
// if, e.g., the passed `origin` has an eTLD+1 that is not equal to its
// hostname, or if the port number is not the default port for its scheme.
//
// In general, this `site_as_origin_` used for the internal representation
// should NOT be used directly by SchemefulSite consumers.
url::Origin site_as_origin_;
}; };
} // namespace net } // namespace net
......
...@@ -141,6 +141,14 @@ TEST(SchemefulSiteTest, OpaqueOrigins) { ...@@ -141,6 +141,14 @@ TEST(SchemefulSiteTest, OpaqueOrigins) {
EXPECT_NE(SchemefulSite(opaque_origin_a), SchemefulSite(opaque_origin_b)); EXPECT_NE(SchemefulSite(opaque_origin_a), SchemefulSite(opaque_origin_b));
} }
TEST(SchemefulSiteTest, FileOriginWithoutHostname) {
SchemefulSite site1(url::Origin::Create(GURL("file:///")));
SchemefulSite site2(url::Origin::Create(GURL("file:///path/")));
EXPECT_EQ(site1, site2);
EXPECT_TRUE(site1.GetInternalOriginForTesting().host().empty());
}
TEST(SchemefulSiteTest, SerializationConsistent) { TEST(SchemefulSiteTest, SerializationConsistent) {
url::ScopedSchemeRegistryForTests scoped_registry; url::ScopedSchemeRegistryForTests scoped_registry;
url::AddStandardScheme("chrome", url::SCHEME_WITH_HOST); url::AddStandardScheme("chrome", url::SCHEME_WITH_HOST);
......
...@@ -249,6 +249,8 @@ component("cpp_base") { ...@@ -249,6 +249,8 @@ component("cpp_base") {
"resource_request.h", "resource_request.h",
"resource_request_body.cc", "resource_request_body.cc",
"resource_request_body.h", "resource_request_body.h",
"schemeful_site_mojom_traits.cc",
"schemeful_site_mojom_traits.h",
"trust_token_parameterization.h", "trust_token_parameterization.h",
"url_loader_completion_status.cc", "url_loader_completion_status.cc",
"url_loader_completion_status.h", "url_loader_completion_status.h",
...@@ -325,6 +327,7 @@ source_set("tests") { ...@@ -325,6 +327,7 @@ source_set("tests") {
"optional_trust_token_params_unittest.cc", "optional_trust_token_params_unittest.cc",
"origin_isolation_parser_unittest.cc", "origin_isolation_parser_unittest.cc",
"proxy_config_mojom_traits_unittest.cc", "proxy_config_mojom_traits_unittest.cc",
"schemeful_site_mojom_traits_unittest.cc",
"simple_url_loader_unittest.cc", "simple_url_loader_unittest.cc",
"site_for_cookies_mojom_traits_unittest.cc", "site_for_cookies_mojom_traits_unittest.cc",
"source_stream_to_data_pipe_unittest.cc", "source_stream_to_data_pipe_unittest.cc",
......
// Copyright 2020 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 "services/network/public/cpp/schemeful_site_mojom_traits.h"
#include "url/origin.h"
namespace mojo {
bool StructTraits<network::mojom::SchemefulSiteDataView, net::SchemefulSite>::
Read(network::mojom::SchemefulSiteDataView data, net::SchemefulSite* out) {
url::Origin site_as_origin;
if (!data.ReadSiteAsOrigin(&site_as_origin))
return false;
// 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.
net::SchemefulSite ss(site_as_origin);
bool success = site_as_origin == ss.site_as_origin_;
if (success)
*out = std::move(ss);
return success;
}
} // namespace mojo
// Copyright 2020 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.
#ifndef SERVICES_NETWORK_PUBLIC_CPP_SCHEMEFUL_SITE_MOJOM_TRAITS_H_
#define SERVICES_NETWORK_PUBLIC_CPP_SCHEMEFUL_SITE_MOJOM_TRAITS_H_
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "net/base/schemeful_site.h"
#include "services/network/public/mojom/schemeful_site.mojom-shared.h"
#include "url/mojom/origin_mojom_traits.h"
namespace url {
class Origin;
} // namespace url
namespace mojo {
template <>
struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
StructTraits<network::mojom::SchemefulSiteDataView, net::SchemefulSite> {
static const url::Origin& site_as_origin(const net::SchemefulSite& input) {
return input.site_as_origin_;
}
static bool Read(network::mojom::SchemefulSiteDataView data,
net::SchemefulSite* out);
};
} // namespace mojo
#endif // SERVICES_NETWORK_PUBLIC_CPP_SCHEMEFUL_SITE_MOJOM_TRAITS_H_
// Copyright 2020 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 "services/network/public/cpp/schemeful_site_mojom_traits.h"
#include "base/stl_util.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "services/network/public/mojom/schemeful_site.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
#include "url/url_util.h"
namespace network {
namespace {
TEST(SchemefulSiteMojomTraitsTest, SerializeAndDeserialize) {
url::ScopedSchemeRegistryForTests scoped_registry;
url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST);
std::vector<net::SchemefulSite> keys = {
net::SchemefulSite(),
net::SchemefulSite(url::Origin()),
net::SchemefulSite(url::Origin::Create(GURL("http://a.test"))),
net::SchemefulSite(url::Origin::Create(GURL("https://a.test"))),
net::SchemefulSite(url::Origin::Create(GURL("https://subdomain.a.test"))),
net::SchemefulSite(url::Origin::Create(GURL("https://127.0.0.1"))),
net::SchemefulSite(url::Origin::Create(GURL("https://127.0.0.1:5000"))),
net::SchemefulSite(url::Origin::Create(GURL("https://a.test:1337"))),
net::SchemefulSite(url::Origin::Create(GURL("file:///"))),
net::SchemefulSite(url::Origin::Create(GURL("file:///path"))),
net::SchemefulSite(url::Origin::Create(GURL("file://foo.test/path"))),
net::SchemefulSite(
url::Origin::Create(GURL("chrome-extension://abcdefghi"))),
net::SchemefulSite(url::Origin::Create(GURL("data:text/plain,foo")))};
for (auto original : keys) {
net::SchemefulSite copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SchemefulSite>(
&original, &copied));
EXPECT_EQ(original, copied);
}
}
TEST(SchemefulSiteMojomTraitsTest, DeserializeFailure) {
mojom::SchemefulSitePtr schemeful_site = mojom::SchemefulSite::New();
// This origin could never be the internal `site_as_origin_` of a cromulent
// SchemefulSite, so should fail deserialization.
schemeful_site->site_as_origin =
url::Origin::Create(GURL("https://not.a.registrable.domain.test:1337"));
std::vector<uint8_t> serialized =
mojom::SchemefulSite::Serialize(&schemeful_site);
net::SchemefulSite deserialized;
EXPECT_FALSE(mojom::SchemefulSite::Deserialize(serialized, &deserialized));
}
} // namespace
} // namespace network
...@@ -471,6 +471,7 @@ mojom("mojom") { ...@@ -471,6 +471,7 @@ mojom("mojom") {
"proxy_resolving_socket.mojom", "proxy_resolving_socket.mojom",
"quic_transport.mojom", "quic_transport.mojom",
"referrer_policy.mojom", "referrer_policy.mojom",
"schemeful_site.mojom",
"source_location.mojom", "source_location.mojom",
"ssl_config.mojom", "ssl_config.mojom",
"supports_loading_mode.mojom", "supports_loading_mode.mojom",
...@@ -855,6 +856,17 @@ mojom("mojom") { ...@@ -855,6 +856,17 @@ mojom("mojom") {
"//net", "//net",
] ]
}, },
{
types = [
{
mojom = "network.mojom.SchemefulSite"
cpp = "::net::SchemefulSite"
},
]
traits_headers =
[ "//services/network/public/cpp/schemeful_site_mojom_traits.h" ]
traits_public_deps = [ "//net" ]
},
] ]
cpp_typemaps += shared_cpp_typemaps cpp_typemaps += shared_cpp_typemaps
......
// Copyright 2020 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.
module network.mojom;
import "url/mojom/origin.mojom";
// Class which represents a scheme and eTLD+1 for an origin.
// Mapped to net::SchemefulSite.
struct SchemefulSite {
// Underlying origin of the schemeful site. This is not an arbitrary origin.
// It must either be an opaque origin, or a scheme + eTLD+1 + default port.
url.mojom.Origin site_as_origin;
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment