Commit 631e39db authored by Victor Costan's avatar Victor Costan Committed by Commit Bot

Introduce blink::WebCanonicalCookie

Add a blink analogue for net::CanonicalCookie. This is initially
used by the CookieStore. Once the RestrictedCookieManager is ready,
Document cookie/setCookie can be changed to it directly instead of
a parallel pipeline to the browser with redundant security checks.
A mojo type mapping is introduced. net::CanonicalCookie is not used
directly due to std::string vs. WTF::String uncertainty, but we may
revisit this in the future.

Bug: 729800
Change-Id: I1492379bee98d44f13470e32da794616b905260b
Reviewed-on: https://chromium-review.googlesource.com/1062599
Commit-Queue: Victor Costan <pwnall@chromium.org>
Reviewed-by: default avatarMarijn Kruisselbrink <mek@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#566588}
parent 648b432e
...@@ -212,6 +212,7 @@ source_set("blink_headers") { ...@@ -212,6 +212,7 @@ source_set("blink_headers") {
"platform/web_browser_controls_state.h", "platform/web_browser_controls_state.h",
"platform/web_cache.h", "platform/web_cache.h",
"platform/web_callbacks.h", "platform/web_callbacks.h",
"platform/web_canonical_cookie.h",
"platform/web_canvas.h", "platform/web_canvas.h",
"platform/web_canvas_capture_handler.h", "platform/web_canvas_capture_handler.h",
"platform/web_client_hints_type.h", "platform/web_client_hints_type.h",
......
...@@ -30,6 +30,7 @@ include_rules = [ ...@@ -30,6 +30,7 @@ include_rules = [
"+services/network/public/mojom/cors.mojom-shared.h", "+services/network/public/mojom/cors.mojom-shared.h",
"+services/network/public/mojom/fetch_api.mojom-shared.h", "+services/network/public/mojom/fetch_api.mojom-shared.h",
"+services/network/public/mojom/request_context_frame_type.mojom-shared.h", "+services/network/public/mojom/request_context_frame_type.mojom-shared.h",
"+services/network/public/mojom/restricted_cookie_manager.mojom-shared.h",
"+services/service_manager/public/mojom", "+services/service_manager/public/mojom",
"+third_party/blink/public/platform", "+third_party/blink/public/platform",
......
// Copyright 2018 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 THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CANONICAL_COOKIE_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CANONICAL_COOKIE_H_
#include "base/optional.h"
#include "base/time/time.h"
#include "services/network/public/mojom/restricted_cookie_manager.mojom-shared.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
// This class is a blink analogue for net::CanonicalCookie.
// TODO(jsbell): Once all prospective clients are migrated to blink, move this
// to renderer/platform as blink::CanonicalCookie.
class BLINK_PLATFORM_EXPORT WebCanonicalCookie {
public:
// Default/copy constructor needed for use with Vector.
WebCanonicalCookie();
WebCanonicalCookie(const WebCanonicalCookie& other);
~WebCanonicalCookie();
WebCanonicalCookie& operator=(const WebCanonicalCookie& other);
const WebString& Name() const { return name_; }
const WebString& Value() const { return value_; }
const WebString& Domain() const { return domain_; }
const WebString& Path() const { return path_; }
base::Time CreationDate() const { return creation_; }
base::Time ExpiryDate() const { return expiration_; }
base::Time LastAccessDate() const { return last_access_; }
bool IsSecure() const { return is_secure_; }
bool IsHttpOnly() const { return is_http_only_; }
network::mojom::CookieSameSite SameSite() const { return same_site_; }
network::mojom::CookiePriority Priority() const { return priority_; }
// If the result is not canonical, nullopt will be returned.
static base::Optional<WebCanonicalCookie> Create(
WebString name,
WebString value,
WebString domain,
WebString path,
base::Time creation,
base::Time expiration,
base::Time last_access,
bool is_secure,
bool is_http_only,
network::mojom::CookieSameSite same_site,
network::mojom::CookiePriority priority);
// Parsing, for the document.cookie API.
// If the result is not canonical, nullopt will be returned.
static base::Optional<WebCanonicalCookie> Create(const WebURL& url,
const WebString& cookie_line,
base::Time creation_time);
// Serializing, for the document.cookie API.
static String BuildCookieLine(const Vector<WebCanonicalCookie>& cookies);
static constexpr const network::mojom::CookieSameSite kDefaultSameSiteMode =
network::mojom::CookieSameSite::NO_RESTRICTION;
static constexpr const network::mojom::CookiePriority kDefaultPriority =
network::mojom::CookiePriority::MEDIUM;
private:
// Prefer static Create methods, which ensure that the returned cookie is
// canonical.
WebCanonicalCookie(WebString name,
WebString value,
WebString domain,
WebString path,
base::Time creation,
base::Time expiration,
base::Time last_access,
bool is_secure,
bool is_http_only,
network::mojom::CookieSameSite same_site,
network::mojom::CookiePriority priority);
WebString name_;
WebString value_;
WebString domain_;
WebString path_;
base::Time creation_;
base::Time expiration_;
base::Time last_access_;
bool is_secure_ = false;
bool is_http_only_ = false;
network::mojom::CookieSameSite same_site_ = kDefaultSameSiteMode;
network::mojom::CookiePriority priority_ = kDefaultPriority;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CANONICAL_COOKIE_H_
...@@ -71,117 +71,108 @@ network::mojom::blink::CookieManagerGetOptionsPtr ToBackendOptions( ...@@ -71,117 +71,108 @@ network::mojom::blink::CookieManagerGetOptionsPtr ToBackendOptions(
return backend_options; return backend_options;
} }
// Returns null if and only if an exception is thrown. // Returns no value if and only if an exception is thrown.
network::mojom::blink::CanonicalCookiePtr ToCanonicalCookie( base::Optional<WebCanonicalCookie> ToWebCanonicalCookie(
const KURL& cookie_url, const KURL& cookie_url,
const String& name, // Value of the "name" positional argument. const String& name_arg, // Value of the "name" positional argument.
const String& value, // Value of the "value" positional argument. const String& value_arg, // Value of the "value" positional argument.
bool for_deletion, // True for CookieStore.delete, false for set. bool for_deletion, // True for CookieStore.delete, false for set.
const CookieStoreSetOptions& options, const CookieStoreSetOptions& options,
ExceptionState& exception_state) { ExceptionState& exception_state) {
auto canonical_cookie = network::mojom::blink::CanonicalCookie::New(); String name;
if (name_arg.IsNull()) {
if (name.IsNull()) {
if (!options.hasName()) { if (!options.hasName()) {
exception_state.ThrowTypeError("Unspecified cookie name"); exception_state.ThrowTypeError("Unspecified cookie name");
return nullptr; return base::nullopt;
} }
canonical_cookie->name = options.name(); name = options.name();
} else { } else {
if (options.hasName()) { if (options.hasName()) {
exception_state.ThrowTypeError( exception_state.ThrowTypeError(
"Cookie name specified both as an argument and as an option"); "Cookie name specified both as an argument and as an option");
return nullptr; return base::nullopt;
} }
canonical_cookie->name = name; name = name_arg;
} }
String value;
base::Time expiry;
if (for_deletion) { if (for_deletion) {
DCHECK(value.IsNull()); DCHECK(value_arg.IsNull());
if (options.hasValue()) { if (options.hasValue()) {
exception_state.ThrowTypeError( exception_state.ThrowTypeError(
"Cookie value is meaningless when deleting"); "Cookie value is meaningless when deleting");
return nullptr; return base::nullopt;
} }
canonical_cookie->value = g_empty_string; value = g_empty_string;
if (options.hasExpires()) { if (options.hasExpires()) {
exception_state.ThrowTypeError( exception_state.ThrowTypeError(
"Cookie expiration time is meaningless when deleting"); "Cookie expiration time is meaningless when deleting");
return nullptr; return base::nullopt;
} }
canonical_cookie->expiry = WTF::Time::Min(); expiry = WTF::Time::Min();
} else { } else {
if (value.IsNull()) { if (value_arg.IsNull()) {
if (!options.hasValue()) { if (!options.hasValue()) {
exception_state.ThrowTypeError("Unspecified cookie value"); exception_state.ThrowTypeError("Unspecified cookie value");
return nullptr; return base::nullopt;
} }
canonical_cookie->value = options.value(); value = options.value();
} else { } else {
if (options.hasValue()) { if (options.hasValue()) {
exception_state.ThrowTypeError( exception_state.ThrowTypeError(
"Cookie value specified both as an argument and as an option"); "Cookie value specified both as an argument and as an option");
return nullptr; return base::nullopt;
} }
canonical_cookie->value = value; value = value_arg;
} }
if (canonical_cookie->name.IsEmpty() && if (name.IsEmpty() && value.Contains('=')) {
canonical_cookie->value.Contains('=')) {
exception_state.ThrowTypeError( exception_state.ThrowTypeError(
"Cookie value cannot contain '=' if the name is empty."); "Cookie value cannot contain '=' if the name is empty.");
return nullptr; return base::nullopt;
} }
if (options.hasExpires()) { if (options.hasExpires()) {
canonical_cookie->expiry = WTF::Time::FromJavaTime(options.expires()); expiry = WTF::Time::FromJavaTime(options.expires());
} else { } else {
// Session cookie. expiry = WTF::Time();
canonical_cookie->expiry = WTF::Time();
} }
} }
String domain;
if (options.hasDomain()) { if (options.hasDomain()) {
// TODO(crbug.com/729800): Checks and exception throwing. // TODO(crbug.com/729800): Checks and exception throwing.
canonical_cookie->domain = options.domain(); domain = options.domain();
} else { } else {
// TODO(crbug.com/729800): Correct value? // TODO(crbug.com/729800): Correct value?
canonical_cookie->domain = cookie_url.Host(); domain = cookie_url.Host();
} }
if (options.hasPath()) { const String path = options.hasPath() ? options.path() : String("/");
canonical_cookie->path = options.path();
} else {
canonical_cookie->path = String("/");
}
bool is_secure_origin = SecurityOrigin::IsSecure(cookie_url); const bool is_secure_origin = SecurityOrigin::IsSecure(cookie_url);
if (options.hasSecure()) { const bool secure = options.hasSecure() ? options.secure() : is_secure_origin;
canonical_cookie->secure = options.secure();
} else {
canonical_cookie->secure = is_secure_origin;
}
if (name.StartsWith("__Secure-") || name.StartsWith("__Host-")) { if (name.StartsWith("__Secure-") || name.StartsWith("__Host-")) {
if (!canonical_cookie->secure) { if (!secure) {
exception_state.ThrowTypeError( exception_state.ThrowTypeError(
"__Secure- and __Host- cookies must be secure"); "__Secure- and __Host- cookies must be secure");
return nullptr; return base::nullopt;
} }
if (!is_secure_origin) { if (!is_secure_origin) {
exception_state.ThrowTypeError( exception_state.ThrowTypeError(
"__Secure- and __Host- cookies must be written from secure origin"); "__Secure- and __Host- cookies must be written from secure origin");
return nullptr; return base::nullopt;
} }
} }
canonical_cookie->httponly = options.httpOnly(); return WebCanonicalCookie::Create(
name, value, domain, path, WTF::Time() /*creation*/, expiry,
// The backend does not trust these fields. WTF::Time() /*last_access*/, secure, options.httpOnly(),
canonical_cookie->creation = WTF::Time(); WebCanonicalCookie::kDefaultSameSiteMode,
canonical_cookie->last_access = WTF::Time(); WebCanonicalCookie::kDefaultPriority);
return canonical_cookie;
} }
// Returns null if and only if an exception is thrown. // Returns null if and only if an exception is thrown.
...@@ -223,12 +214,12 @@ blink::mojom::blink::CookieChangeSubscriptionPtr ToBackendSubscription( ...@@ -223,12 +214,12 @@ blink::mojom::blink::CookieChangeSubscriptionPtr ToBackendSubscription(
} }
void ToCookieListItem( void ToCookieListItem(
const network::mojom::blink::CanonicalCookiePtr& canonical_cookie, const WebCanonicalCookie& canonical_cookie,
bool is_deleted, // True for the information from a cookie deletion event. bool is_deleted, // True for the information from a cookie deletion event.
CookieListItem& cookie) { CookieListItem& cookie) {
cookie.setName(canonical_cookie->name); cookie.setName(canonical_cookie.Name());
if (!is_deleted) if (!is_deleted)
cookie.setValue(canonical_cookie->value); cookie.setValue(canonical_cookie.Value());
} }
void ToCookieChangeSubscription( void ToCookieChangeSubscription(
...@@ -371,8 +362,10 @@ ScriptPromise CookieStore::subscribeToChanges( ...@@ -371,8 +362,10 @@ ScriptPromise CookieStore::subscribeToChanges(
blink::mojom::blink::CookieChangeSubscriptionPtr backend_subscription = blink::mojom::blink::CookieChangeSubscriptionPtr backend_subscription =
ToBackendSubscription(default_cookie_url_, subscription, ToBackendSubscription(default_cookie_url_, subscription,
exception_state); exception_state);
if (backend_subscription.is_null()) if (backend_subscription.is_null()) {
return ScriptPromise(); // ToBackendSubscription has thrown an exception. DCHECK(exception_state.HadException());
return ScriptPromise();
}
backend_subscriptions.emplace_back(std::move(backend_subscription)); backend_subscriptions.emplace_back(std::move(backend_subscription));
} }
...@@ -443,7 +436,7 @@ void CookieStore::RemoveAllEventListeners() { ...@@ -443,7 +436,7 @@ void CookieStore::RemoveAllEventListeners() {
} }
void CookieStore::OnCookieChange( void CookieStore::OnCookieChange(
network::mojom::blink::CanonicalCookiePtr backend_cookie, const WebCanonicalCookie& backend_cookie,
network::mojom::blink::CookieChangeCause change_cause) { network::mojom::blink::CookieChangeCause change_cause) {
HeapVector<CookieListItem> changed, deleted; HeapVector<CookieListItem> changed, deleted;
...@@ -516,8 +509,10 @@ ScriptPromise CookieStore::DoRead( ...@@ -516,8 +509,10 @@ ScriptPromise CookieStore::DoRead(
ExceptionState& exception_state) { ExceptionState& exception_state) {
network::mojom::blink::CookieManagerGetOptionsPtr backend_options = network::mojom::blink::CookieManagerGetOptionsPtr backend_options =
ToBackendOptions(name, options, exception_state); ToBackendOptions(name, options, exception_state);
if (backend_options.is_null()) if (backend_options.is_null()) {
return ScriptPromise(); // ToBackendOptions has thrown an exception. DCHECK(exception_state.HadException());
return ScriptPromise();
}
if (!backend_) { if (!backend_) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
...@@ -536,7 +531,7 @@ ScriptPromise CookieStore::DoRead( ...@@ -536,7 +531,7 @@ ScriptPromise CookieStore::DoRead(
// static // static
void CookieStore::GetAllForUrlToGetAllResult( void CookieStore::GetAllForUrlToGetAllResult(
ScriptPromiseResolver* resolver, ScriptPromiseResolver* resolver,
Vector<network::mojom::blink::CanonicalCookiePtr> backend_cookies) { const Vector<WebCanonicalCookie>& backend_cookies) {
ScriptState* script_state = resolver->GetScriptState(); ScriptState* script_state = resolver->GetScriptState();
if (!script_state->ContextIsValid()) if (!script_state->ContextIsValid())
return; return;
...@@ -554,7 +549,7 @@ void CookieStore::GetAllForUrlToGetAllResult( ...@@ -554,7 +549,7 @@ void CookieStore::GetAllForUrlToGetAllResult(
// static // static
void CookieStore::GetAllForUrlToGetResult( void CookieStore::GetAllForUrlToGetResult(
ScriptPromiseResolver* resolver, ScriptPromiseResolver* resolver,
Vector<network::mojom::blink::CanonicalCookiePtr> backend_cookies) { const Vector<WebCanonicalCookie>& backend_cookies) {
ScriptState* script_state = resolver->GetScriptState(); ScriptState* script_state = resolver->GetScriptState();
if (!script_state->ContextIsValid()) if (!script_state->ContextIsValid())
return; return;
...@@ -573,7 +568,7 @@ void CookieStore::GetAllForUrlToGetResult( ...@@ -573,7 +568,7 @@ void CookieStore::GetAllForUrlToGetResult(
// static // static
void CookieStore::GetAllForUrlToHasResult( void CookieStore::GetAllForUrlToHasResult(
ScriptPromiseResolver* resolver, ScriptPromiseResolver* resolver,
Vector<network::mojom::blink::CanonicalCookiePtr> backend_cookies) { const Vector<WebCanonicalCookie>& backend_cookies) {
ScriptState* script_state = resolver->GetScriptState(); ScriptState* script_state = resolver->GetScriptState();
if (!script_state->ContextIsValid()) if (!script_state->ContextIsValid())
return; return;
...@@ -587,11 +582,12 @@ ScriptPromise CookieStore::DoWrite(ScriptState* script_state, ...@@ -587,11 +582,12 @@ ScriptPromise CookieStore::DoWrite(ScriptState* script_state,
const CookieStoreSetOptions& options, const CookieStoreSetOptions& options,
bool is_deletion, bool is_deletion,
ExceptionState& exception_state) { ExceptionState& exception_state) {
network::mojom::blink::CanonicalCookiePtr canonical_cookie = base::Optional<WebCanonicalCookie> canonical_cookie = ToWebCanonicalCookie(
ToCanonicalCookie(default_cookie_url_, name, value, is_deletion, options, default_cookie_url_, name, value, is_deletion, options, exception_state);
exception_state); if (!canonical_cookie) {
if (canonical_cookie.is_null()) DCHECK(exception_state.HadException());
return ScriptPromise(); // ToCanonicalCookie has thrown an exception. return ScriptPromise();
}
if (!backend_) { if (!backend_) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
...@@ -601,7 +597,7 @@ ScriptPromise CookieStore::DoWrite(ScriptState* script_state, ...@@ -601,7 +597,7 @@ ScriptPromise CookieStore::DoWrite(ScriptState* script_state,
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
backend_->SetCanonicalCookie( backend_->SetCanonicalCookie(
std::move(canonical_cookie), default_cookie_url_, std::move(canonical_cookie.value()), default_cookie_url_,
default_site_for_cookies_, default_site_for_cookies_,
WTF::Bind(&CookieStore::OnSetCanonicalCookieResult, WTF::Bind(&CookieStore::OnSetCanonicalCookieResult,
WrapPersistent(resolver))); WrapPersistent(resolver)));
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding.h"
#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h" #include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h"
#include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom-blink.h" #include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom-blink.h"
#include "third_party/blink/public/platform/web_canonical_cookie.h"
#include "third_party/blink/renderer/bindings/core/v8/exception_state.h" #include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h" #include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
...@@ -101,7 +102,7 @@ class CookieStore final : public EventTargetWithInlineData, ...@@ -101,7 +102,7 @@ class CookieStore final : public EventTargetWithInlineData,
void RemoveAllEventListeners() override; void RemoveAllEventListeners() override;
// RestrictedCookieChangeListener // RestrictedCookieChangeListener
void OnCookieChange(network::mojom::blink::CanonicalCookiePtr, void OnCookieChange(const WebCanonicalCookie&,
network::mojom::blink::CookieChangeCause) override; network::mojom::blink::CookieChangeCause) override;
protected: protected:
...@@ -113,8 +114,7 @@ class CookieStore final : public EventTargetWithInlineData, ...@@ -113,8 +114,7 @@ class CookieStore final : public EventTargetWithInlineData,
private: private:
using DoReadBackendResultConverter = using DoReadBackendResultConverter =
void (*)(ScriptPromiseResolver*, void (*)(ScriptPromiseResolver*, const Vector<WebCanonicalCookie>&);
Vector<network::mojom::blink::CanonicalCookiePtr>);
CookieStore(ExecutionContext*, CookieStore(ExecutionContext*,
network::mojom::blink::RestrictedCookieManagerPtr backend, network::mojom::blink::RestrictedCookieManagerPtr backend,
...@@ -136,19 +136,19 @@ class CookieStore final : public EventTargetWithInlineData, ...@@ -136,19 +136,19 @@ class CookieStore final : public EventTargetWithInlineData,
// the promise result expected by CookieStore.getAll. // the promise result expected by CookieStore.getAll.
static void GetAllForUrlToGetAllResult( static void GetAllForUrlToGetAllResult(
ScriptPromiseResolver*, ScriptPromiseResolver*,
Vector<network::mojom::blink::CanonicalCookiePtr> backend_result); const Vector<WebCanonicalCookie>& backend_result);
// Converts the result of a RestrictedCookieManager::GetAllForUrl mojo call to // Converts the result of a RestrictedCookieManager::GetAllForUrl mojo call to
// the promise result expected by CookieStore.get. // the promise result expected by CookieStore.get.
static void GetAllForUrlToGetResult( static void GetAllForUrlToGetResult(
ScriptPromiseResolver*, ScriptPromiseResolver*,
Vector<network::mojom::blink::CanonicalCookiePtr> backend_result); const Vector<WebCanonicalCookie>& backend_result);
// Converts the result of a RestrictedCookieManager::GetAllForUrl mojo call to // Converts the result of a RestrictedCookieManager::GetAllForUrl mojo call to
// the promise result expected by CookieStore.has. // the promise result expected by CookieStore.has.
static void GetAllForUrlToHasResult( static void GetAllForUrlToHasResult(
ScriptPromiseResolver*, ScriptPromiseResolver*,
Vector<network::mojom::blink::CanonicalCookiePtr> backend_result); const Vector<WebCanonicalCookie>& backend_result);
// Common code in CookieStore::delete and CookieStore::set. // Common code in CookieStore::delete and CookieStore::set.
ScriptPromise DoWrite(ScriptState*, ScriptPromise DoWrite(ScriptState*,
......
...@@ -518,6 +518,7 @@ jumbo_component("platform") { ...@@ -518,6 +518,7 @@ jumbo_component("platform") {
"exported/web_audio_device.cc", "exported/web_audio_device.cc",
"exported/web_blob_info.cc", "exported/web_blob_info.cc",
"exported/web_cache.cc", "exported/web_cache.cc",
"exported/web_canonical_cookie.cc",
"exported/web_canvas_capture_handler.cc", "exported/web_canvas_capture_handler.cc",
"exported/web_coalesced_input_event.cc", "exported/web_coalesced_input_event.cc",
"exported/web_content_decryption_module.cc", "exported/web_content_decryption_module.cc",
...@@ -1232,6 +1233,8 @@ jumbo_component("platform") { ...@@ -1232,6 +1233,8 @@ jumbo_component("platform") {
"mojo/big_string_mojom_traits.h", "mojo/big_string_mojom_traits.h",
"mojo/bluetooth_struct_traits.cc", "mojo/bluetooth_struct_traits.cc",
"mojo/bluetooth_struct_traits.h", "mojo/bluetooth_struct_traits.h",
"mojo/canonical_cookie_mojom_traits.cc",
"mojo/canonical_cookie_mojom_traits.h",
"mojo/fetch_api_request_struct_traits.cc", "mojo/fetch_api_request_struct_traits.cc",
"mojo/interface_invalidator.cc", "mojo/interface_invalidator.cc",
"mojo/interface_invalidator.h", "mojo/interface_invalidator.h",
...@@ -1746,6 +1749,7 @@ jumbo_source_set("blink_platform_unittests_sources") { ...@@ -1746,6 +1749,7 @@ jumbo_source_set("blink_platform_unittests_sources") {
"decimal_test.cc", "decimal_test.cc",
"drag_image_test.cc", "drag_image_test.cc",
"exported/file_path_conversion_test.cc", "exported/file_path_conversion_test.cc",
"exported/web_canonical_cookie_test.cc",
"exported/web_cors_test.cc", "exported/web_cors_test.cc",
"exported/web_string_test.cc", "exported/web_string_test.cc",
"feature_policy/feature_policy_test.cc", "feature_policy/feature_policy_test.cc",
......
include_rules = [
"+net/cookies/canonical_cookie.h",
"+net/cookies/cookie_constants.h",
"+net/cookies/canonical_cookie.h",
"+net/cookies/cookie_constants.h",
]
// Copyright 2018 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 "third_party/blink/public/platform/web_canonical_cookie.h"
#include <memory>
#include <vector>
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_constants.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "url/gurl.h"
// Assumptions made by static_casts used in this file.
STATIC_ASSERT_ENUM(net::CookieSameSite::NO_RESTRICTION,
network::mojom::CookieSameSite::NO_RESTRICTION);
STATIC_ASSERT_ENUM(net::CookieSameSite::LAX_MODE,
network::mojom::CookieSameSite::LAX_MODE);
STATIC_ASSERT_ENUM(net::CookieSameSite::STRICT_MODE,
network::mojom::CookieSameSite::STRICT_MODE);
STATIC_ASSERT_ENUM(net::CookieSameSite::DEFAULT_MODE,
blink::WebCanonicalCookie::kDefaultSameSiteMode);
STATIC_ASSERT_ENUM(net::CookiePriority::COOKIE_PRIORITY_LOW,
network::mojom::CookiePriority::LOW);
STATIC_ASSERT_ENUM(net::CookiePriority::COOKIE_PRIORITY_MEDIUM,
network::mojom::CookiePriority::MEDIUM);
STATIC_ASSERT_ENUM(net::CookiePriority::COOKIE_PRIORITY_HIGH,
network::mojom::CookiePriority::HIGH);
STATIC_ASSERT_ENUM(net::CookiePriority::COOKIE_PRIORITY_DEFAULT,
blink::WebCanonicalCookie::kDefaultPriority);
namespace blink {
namespace {
net::CanonicalCookie ToNetCanonicalCookie(const WebCanonicalCookie& cookie) {
net::CanonicalCookie net_cookie(
cookie.Name().Utf8(), cookie.Value().Utf8(), cookie.Domain().Utf8(),
cookie.Path().Utf8(), cookie.CreationDate(), cookie.ExpiryDate(),
cookie.LastAccessDate(), cookie.IsSecure(), cookie.IsHttpOnly(),
static_cast<net::CookieSameSite>(cookie.SameSite()),
static_cast<net::CookiePriority>(cookie.Priority()));
DCHECK(net_cookie.IsCanonical());
return net_cookie;
}
} // namespace
WebCanonicalCookie::WebCanonicalCookie() = default;
WebCanonicalCookie::WebCanonicalCookie(WebString name,
WebString value,
WebString domain,
WebString path,
base::Time creation,
base::Time expiration,
base::Time last_access,
bool is_secure,
bool is_http_only,
network::mojom::CookieSameSite same_site,
network::mojom::CookiePriority priority)
: name_(std::move(name)),
value_(std::move(value)),
domain_(std::move(domain)),
path_(std::move(path)),
creation_(creation),
expiration_(expiration),
last_access_(last_access),
is_secure_(is_secure),
is_http_only_(is_http_only),
same_site_(same_site),
priority_(priority) {
DCHECK(ToNetCanonicalCookie(*this).IsCanonical());
}
WebCanonicalCookie::WebCanonicalCookie(const WebCanonicalCookie& other) =
default;
WebCanonicalCookie& WebCanonicalCookie::operator=(
const WebCanonicalCookie& other) = default;
WebCanonicalCookie::~WebCanonicalCookie() = default;
// static
String WebCanonicalCookie::BuildCookieLine(
const Vector<WebCanonicalCookie>& cookies) {
std::vector<net::CanonicalCookie> copy;
copy.reserve(cookies.size());
for (const auto& cookie : cookies)
copy.push_back(ToNetCanonicalCookie(cookie));
return WebString::FromUTF8(net::CanonicalCookie::BuildCookieLine(copy));
}
namespace {
// TODO(crbug.com/851889): WebURL::operator GURL() is only available if
// !INSIDE_BLINK. Remove ToGURL() when this changes.
GURL ToGURL(const WebURL& url) {
return url.IsNull()
? GURL()
: GURL(url.GetString().Utf8(), url.GetParsed(), url.IsValid());
}
} // namespace
// static
base::Optional<WebCanonicalCookie> WebCanonicalCookie::Create(
const WebURL& url,
const WebString& cookie_line,
base::Time creation_time) {
net::CookieOptions options;
std::unique_ptr<net::CanonicalCookie> cookie = net::CanonicalCookie::Create(
ToGURL(url), cookie_line.Utf8(), creation_time, options);
if (!cookie)
return base::nullopt;
return WebCanonicalCookie(
WebString::FromUTF8(cookie->Name()), WebString::FromUTF8(cookie->Value()),
WebString::FromUTF8(cookie->Domain()),
WebString::FromUTF8(cookie->Path()), cookie->CreationDate(),
cookie->ExpiryDate(), cookie->LastAccessDate(), cookie->IsSecure(),
cookie->IsHttpOnly(),
static_cast<network::mojom::CookieSameSite>(cookie->SameSite()),
static_cast<network::mojom::CookiePriority>(cookie->Priority()));
}
// static
base::Optional<WebCanonicalCookie> WebCanonicalCookie::Create(
WebString name,
WebString value,
WebString domain,
WebString path,
base::Time creation,
base::Time expiration,
base::Time last_access,
bool is_secure,
bool is_http_only,
network::mojom::CookieSameSite same_site,
network::mojom::CookiePriority priority) {
net::CanonicalCookie net_cookie(name.Utf8(), value.Utf8(), domain.Utf8(),
path.Utf8(), creation, expiration,
last_access, is_secure, is_http_only,
static_cast<net::CookieSameSite>(same_site),
static_cast<net::CookiePriority>(priority));
if (!net_cookie.IsCanonical())
return base::nullopt;
return WebCanonicalCookie(std::move(name), std::move(value),
std::move(domain), std::move(path), creation,
expiration, last_access, is_secure, is_http_only,
same_site, priority);
}
constexpr const network::mojom::CookieSameSite
WebCanonicalCookie::kDefaultSameSiteMode;
constexpr const network::mojom::CookiePriority
WebCanonicalCookie::kDefaultPriority;
} // namespace blink
// Copyright 2018 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 "third_party/blink/public/platform/web_canonical_cookie.h"
#include <initializer_list>
#include "base/optional.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
TEST(WebCanonicalCookieTest, Defaults) {
WebCanonicalCookie cookie;
EXPECT_EQ(WebString(), cookie.Name());
EXPECT_EQ(WebString(), cookie.Value());
EXPECT_EQ(WebString(), cookie.Domain());
EXPECT_EQ(WebString(), cookie.Path());
EXPECT_EQ(base::Time(), cookie.CreationDate());
EXPECT_EQ(base::Time(), cookie.ExpiryDate());
EXPECT_EQ(base::Time(), cookie.LastAccessDate());
EXPECT_FALSE(cookie.IsSecure());
EXPECT_FALSE(cookie.IsHttpOnly());
EXPECT_EQ(WebCanonicalCookie::kDefaultSameSiteMode, cookie.SameSite());
EXPECT_EQ(WebCanonicalCookie::kDefaultPriority, cookie.Priority());
}
TEST(WebCanonicalCookieTest, CreationFailure) {
const WebURL url(KURL("http://example.com"));
// Invalid cookie lines cause nullopt to be returned.
EXPECT_FALSE(
WebCanonicalCookie::Create(url, "\x01", base::Time::Now()).has_value());
// Invalid names cause nullopt to be returned.
EXPECT_FALSE(WebCanonicalCookie::Create(
"\x01", "value", "domain", "/path", base::Time::Now(),
base::Time::Now(), base::Time::Now(), false, false,
WebCanonicalCookie::kDefaultSameSiteMode,
WebCanonicalCookie::kDefaultPriority)
.has_value());
}
TEST(WebCanonicalCookieTest, Properties) {
const base::Time t1 = base::Time::FromDoubleT(1);
const base::Time t2 = base::Time::FromDoubleT(2);
const base::Time t3 = base::Time::FromDoubleT(3);
ASSERT_NE(t1, t2);
ASSERT_NE(t1, t3);
ASSERT_NE(t2, t3);
base::Optional<WebCanonicalCookie> cookie_opt = WebCanonicalCookie::Create(
"name", "value", "domain", "/path", t1, t2, t3, true, true,
network::mojom::CookieSameSite::STRICT_MODE,
network::mojom::CookiePriority::HIGH);
ASSERT_TRUE(cookie_opt);
WebCanonicalCookie& cookie = cookie_opt.value();
EXPECT_EQ("name", cookie.Name());
EXPECT_EQ("value", cookie.Value());
EXPECT_EQ("domain", cookie.Domain());
EXPECT_EQ("/path", cookie.Path());
EXPECT_EQ(t1, cookie.CreationDate());
EXPECT_EQ(t2, cookie.ExpiryDate());
EXPECT_EQ(t3, cookie.LastAccessDate());
EXPECT_TRUE(cookie.IsSecure());
EXPECT_TRUE(cookie.IsHttpOnly());
EXPECT_EQ(network::mojom::CookieSameSite::STRICT_MODE, cookie.SameSite());
EXPECT_EQ(network::mojom::CookiePriority::HIGH, cookie.Priority());
// Exercise WebCookieSameSite values.
for (auto same_site : {network::mojom::CookieSameSite::NO_RESTRICTION,
network::mojom::CookieSameSite::LAX_MODE,
network::mojom::CookieSameSite::STRICT_MODE,
WebCanonicalCookie::kDefaultSameSiteMode}) {
EXPECT_EQ(same_site,
WebCanonicalCookie::Create("name", "value", "domain", "/path", t1,
t2, t3, false, false, same_site,
WebCanonicalCookie::kDefaultPriority)
->SameSite());
}
// Exercise WebCookiePriority values.
for (auto priority : {network::mojom::CookiePriority::LOW,
network::mojom::CookiePriority::MEDIUM,
network::mojom::CookiePriority::HIGH,
WebCanonicalCookie::kDefaultPriority}) {
EXPECT_EQ(priority,
WebCanonicalCookie::Create(
"name", "value", "domain", "/path", t1, t2, t3, false, false,
WebCanonicalCookie::kDefaultSameSiteMode, priority)
->Priority());
}
}
TEST(WebCanonicalCookieTest, BuildLine) {
const WebURL url(KURL("http://example.com"));
Vector<WebCanonicalCookie> cookies;
cookies.push_back(
WebCanonicalCookie::Create(url, "a=1", base::Time::Now()).value());
EXPECT_EQ("a=1", WebCanonicalCookie::BuildCookieLine(cookies));
cookies.push_back(
WebCanonicalCookie::Create(url, "b=2", base::Time::Now()).value());
EXPECT_EQ("a=1; b=2", WebCanonicalCookie::BuildCookieLine(cookies));
}
} // namespace blink
...@@ -15,6 +15,7 @@ include_rules = [ ...@@ -15,6 +15,7 @@ include_rules = [
"+mojo/public/cpp/bindings/binding.h", "+mojo/public/cpp/bindings/binding.h",
"+mojo/public/mojom/base/string16.mojom-blink.h", "+mojo/public/mojom/base/string16.mojom-blink.h",
"+services/network/public/mojom/fetch_api.mojom-blink.h", "+services/network/public/mojom/fetch_api.mojom-blink.h",
"+services/network/public/mojom/restricted_cookie_manager.mojom-blink.h",
"+skia/public/interfaces/bitmap_skbitmap_struct_traits.h", "+skia/public/interfaces/bitmap_skbitmap_struct_traits.h",
"+third_party/blink/renderer/platform/blob/blob_data.h", "+third_party/blink/renderer/platform/blob/blob_data.h",
......
...@@ -11,6 +11,7 @@ typemaps = [ ...@@ -11,6 +11,7 @@ typemaps = [
"//third_party/blink/renderer/platform/blob/serialized_blob.typemap", "//third_party/blink/renderer/platform/blob/serialized_blob.typemap",
"//third_party/blink/renderer/platform/mojo/big_buffer.typemap", "//third_party/blink/renderer/platform/mojo/big_buffer.typemap",
"//third_party/blink/renderer/platform/mojo/big_string.typemap", "//third_party/blink/renderer/platform/mojo/big_string.typemap",
"//third_party/blink/renderer/platform/mojo/canonical_cookie.typemap",
"//third_party/blink/renderer/platform/mojo/file.typemap", "//third_party/blink/renderer/platform/mojo/file.typemap",
"//third_party/blink/renderer/platform/mojo/geometry.typemap", "//third_party/blink/renderer/platform/mojo/geometry.typemap",
"//third_party/blink/renderer/platform/mojo/kurl.typemap", "//third_party/blink/renderer/platform/mojo/kurl.typemap",
......
# Copyright 2018 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.
mojom = "//services/network/public/mojom/cookie_manager.mojom"
public_headers =
[ "//third_party/blink/public/platform/web_canonical_cookie.h" ]
traits_headers = [
"//third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h",
]
deps = [
"//mojo/public/cpp/bindings",
]
type_mappings = [ "network.mojom.CanonicalCookie=::blink::WebCanonicalCookie" ]
// Copyright 2018 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 "third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h"
#include "base/optional.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "mojo/public/cpp/bindings/string_traits_wtf.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace mojo {
// static
WTF::String StructTraits<
network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::name(const blink::WebCanonicalCookie& c) {
return c.Name();
}
// static
WTF::String StructTraits<
network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::value(const blink::WebCanonicalCookie& c) {
return c.Value();
}
// static
WTF::String StructTraits<
network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::domain(const blink::WebCanonicalCookie& c) {
return c.Domain();
}
// static
WTF::String StructTraits<
network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::path(const blink::WebCanonicalCookie& c) {
return c.Path();
}
// static
base::Time StructTraits<
network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::creation(const blink::WebCanonicalCookie& c) {
return c.CreationDate();
}
// static
base::Time StructTraits<
network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::expiry(const blink::WebCanonicalCookie& c) {
return c.ExpiryDate();
}
// static
base::Time StructTraits<network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::
last_access(const blink::WebCanonicalCookie& c) {
return c.LastAccessDate();
}
// static
bool StructTraits<
network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::secure(const blink::WebCanonicalCookie& c) {
return c.IsSecure();
}
// static
bool StructTraits<
network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::httponly(const blink::WebCanonicalCookie& c) {
return c.IsHttpOnly();
}
// static
network::mojom::CookieSameSite
StructTraits<network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::
site_restrictions(const blink::WebCanonicalCookie& c) {
return c.SameSite();
}
// static
network::mojom::CookiePriority StructTraits<
network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::priority(const blink::WebCanonicalCookie& c) {
return c.Priority();
}
// static
bool StructTraits<network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie>::
Read(network::mojom::CanonicalCookieDataView cookie,
blink::WebCanonicalCookie* out) {
WTF::String name;
if (!cookie.ReadName(&name))
return false;
WTF::String value;
if (!cookie.ReadValue(&value))
return false;
WTF::String domain;
if (!cookie.ReadDomain(&domain))
return false;
WTF::String path;
if (!cookie.ReadPath(&path))
return false;
base::Time creation;
if (!cookie.ReadCreation(&creation))
return false;
base::Time expiry;
if (!cookie.ReadExpiry(&expiry))
return false;
base::Time last_access;
if (!cookie.ReadLastAccess(&last_access))
return false;
network::mojom::CookieSameSite site_restrictions;
if (!cookie.ReadSiteRestrictions(&site_restrictions))
return false;
network::mojom::CookiePriority priority;
if (!cookie.ReadPriority(&priority))
return false;
base::Optional<blink::WebCanonicalCookie> created =
blink::WebCanonicalCookie::Create(
name, value, domain, path, creation, expiry, last_access,
cookie.secure(), cookie.httponly(), site_restrictions, priority);
if (!created)
return false;
*out = std::move(created).value();
return true;
}
} // namespace mojo
// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_CANONICAL_COOKIE_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_CANONICAL_COOKIE_MOJOM_TRAITS_H_
#include "base/time/time.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h"
#include "third_party/blink/public/platform/web_canonical_cookie.h"
#include "third_party/blink/public/platform/web_string.h"
namespace mojo {
template <>
struct PLATFORM_EXPORT StructTraits<network::mojom::CanonicalCookieDataView,
blink::WebCanonicalCookie> {
static WTF::String name(const blink::WebCanonicalCookie& c);
static WTF::String value(const blink::WebCanonicalCookie& c);
static WTF::String domain(const blink::WebCanonicalCookie& c);
static WTF::String path(const blink::WebCanonicalCookie& c);
static base::Time creation(const blink::WebCanonicalCookie& c);
static base::Time expiry(const blink::WebCanonicalCookie& c);
static base::Time last_access(const blink::WebCanonicalCookie& c);
static bool secure(const blink::WebCanonicalCookie& c);
static bool httponly(const blink::WebCanonicalCookie& c);
static network::mojom::CookieSameSite site_restrictions(
const blink::WebCanonicalCookie& c);
static network::mojom::CookiePriority priority(
const blink::WebCanonicalCookie& c);
static bool Read(network::mojom::CanonicalCookieDataView cookie,
blink::WebCanonicalCookie* out);
};
} // namespace mojo
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_CANONICAL_COOKIE_MOJOM_TRAITS_H_
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