| // 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 "content/browser/cookie_store/cookie_change_subscription.h" |
| |
| #include <utility> |
| |
| #include "content/browser/cookie_store/cookie_change_subscriptions.pb.h" |
| #include "net/cookies/cookie_constants.h" |
| #include "net/cookies/cookie_util.h" |
| #include "net/cookies/same_party_context.h" |
| #include "services/network/public/cpp/is_potentially_trustworthy.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| #define STATIC_ASSERT_ENUM(a, b) \ |
| static_assert(static_cast<int>(a) == static_cast<int>(b), \ |
| "mismatching enums: " #a) |
| |
| STATIC_ASSERT_ENUM(network::mojom::CookieMatchType::EQUALS, |
| proto::CookieMatchType::EQUALS); |
| STATIC_ASSERT_ENUM(network::mojom::CookieMatchType::STARTS_WITH, |
| proto::CookieMatchType::STARTS_WITH); |
| |
| proto::CookieMatchType CookieMatchTypeToProto( |
| network::mojom::CookieMatchType match_type) { |
| switch (match_type) { |
| case network::mojom::CookieMatchType::EQUALS: |
| return proto::CookieMatchType::EQUALS; |
| case ::network::mojom::CookieMatchType::STARTS_WITH: |
| return proto::CookieMatchType::STARTS_WITH; |
| } |
| NOTREACHED(); |
| return proto::CookieMatchType::EQUALS; |
| } |
| |
| network::mojom::CookieMatchType CookieMatchTypeFromProto( |
| proto::CookieMatchType match_type_proto) { |
| switch (match_type_proto) { |
| case proto::CookieMatchType::EQUALS: |
| return network::mojom::CookieMatchType::EQUALS; |
| case proto::CookieMatchType::STARTS_WITH: |
| return ::network::mojom::CookieMatchType::STARTS_WITH; |
| default: |
| // The on-disk value was corrupted. |
| return network::mojom::CookieMatchType::EQUALS; |
| } |
| } |
| |
| } // namespace |
| |
| // static |
| std::vector<std::unique_ptr<CookieChangeSubscription>> |
| CookieChangeSubscription::DeserializeVector( |
| const std::string& proto_string, |
| int64_t service_worker_registration_id) { |
| std::vector<std::unique_ptr<CookieChangeSubscription>> subscriptions; |
| |
| proto::CookieChangeSubscriptionsProto subscriptions_proto; |
| if (!subscriptions_proto.ParseFromString(proto_string)) |
| return subscriptions; |
| |
| int subscription_count = subscriptions_proto.subscriptions_size(); |
| subscriptions.reserve(subscription_count); |
| for (int i = 0; i < subscription_count; ++i) { |
| std::unique_ptr<CookieChangeSubscription> subscription = |
| CookieChangeSubscription::Create(subscriptions_proto.subscriptions(i), |
| service_worker_registration_id); |
| if (!subscription) |
| continue; |
| subscriptions.push_back(std::move(subscription)); |
| } |
| |
| return subscriptions; |
| } |
| |
| // static |
| std::string CookieChangeSubscription::SerializeVector( |
| const std::vector<std::unique_ptr<CookieChangeSubscription>>& |
| subscriptions) { |
| DCHECK(!subscriptions.empty()); |
| proto::CookieChangeSubscriptionsProto subscriptions_proto; |
| for (const auto& subscription : subscriptions) |
| subscription->Serialize(subscriptions_proto.add_subscriptions()); |
| return subscriptions_proto.SerializeAsString(); |
| } |
| |
| // static |
| std::vector<blink::mojom::CookieChangeSubscriptionPtr> |
| CookieChangeSubscription::ToMojoVector( |
| const std::vector<std::unique_ptr<CookieChangeSubscription>>& |
| subscriptions) { |
| std::vector<blink::mojom::CookieChangeSubscriptionPtr> mojo_subscriptions; |
| mojo_subscriptions.reserve(subscriptions.size()); |
| for (const auto& subscription : subscriptions) { |
| auto mojo_subscription = blink::mojom::CookieChangeSubscription::New(); |
| subscription->Serialize(mojo_subscription.get()); |
| mojo_subscriptions.push_back(std::move(mojo_subscription)); |
| } |
| return mojo_subscriptions; |
| } |
| |
| // static |
| std::unique_ptr<CookieChangeSubscription> CookieChangeSubscription::Create( |
| proto::CookieChangeSubscriptionProto proto, |
| int64_t service_worker_registration_id) { |
| GURL url(proto.url()); |
| if (!url.is_valid()) |
| return nullptr; |
| |
| std::string name = proto.name(); |
| ::network::mojom::CookieMatchType match_type = |
| CookieMatchTypeFromProto(proto.match_type()); |
| |
| return std::make_unique<CookieChangeSubscription>( |
| std::move(url), std::move(name), match_type, |
| service_worker_registration_id); |
| } |
| |
| CookieChangeSubscription::~CookieChangeSubscription() = default; |
| |
| CookieChangeSubscription::CookieChangeSubscription( |
| blink::mojom::CookieChangeSubscriptionPtr mojo_subscription, |
| int64_t service_worker_registration_id) |
| : url_(std::move(mojo_subscription->url)), |
| name_(std::move(mojo_subscription->name)), |
| match_type_(mojo_subscription->match_type), |
| service_worker_registration_id_(service_worker_registration_id) {} |
| |
| CookieChangeSubscription::CookieChangeSubscription( |
| GURL url, |
| std::string name, |
| ::network::mojom::CookieMatchType match_type, |
| int64_t service_worker_registration_id) |
| : url_(std::move(url)), |
| name_(std::move(name)), |
| match_type_(match_type), |
| service_worker_registration_id_(service_worker_registration_id) {} |
| |
| void CookieChangeSubscription::Serialize( |
| proto::CookieChangeSubscriptionProto* proto) const { |
| proto->set_match_type(CookieMatchTypeToProto(match_type_)); |
| proto->set_name(name_); |
| proto->set_url(url_.spec()); |
| } |
| |
| void CookieChangeSubscription::Serialize( |
| blink::mojom::CookieChangeSubscription* mojo_subscription) const { |
| mojo_subscription->url = url_; |
| mojo_subscription->name = name_; |
| mojo_subscription->match_type = match_type_; |
| } |
| |
| bool CookieChangeSubscription::ShouldObserveChangeTo( |
| const net::CanonicalCookie& cookie, |
| net::CookieAccessSemantics access_semantics) const { |
| switch (match_type_) { |
| case ::network::mojom::CookieMatchType::EQUALS: |
| if (cookie.Name() != name_) |
| return false; |
| break; |
| case ::network::mojom::CookieMatchType::STARTS_WITH: |
| if (!base::StartsWith(cookie.Name(), name_, base::CompareCase::SENSITIVE)) |
| return false; |
| break; |
| } |
| |
| // We assume that this is a same-site, same-party context. |
| net::CookieOptions net_options; |
| net_options.set_same_site_cookie_context( |
| net::CookieOptions::SameSiteCookieContext::MakeInclusive()); |
| net_options.set_same_party_context(net::SamePartyContext::MakeInclusive()); |
| // It doesn't matter which we choose here, since both SameParty and SameSite |
| // semantics should allow this access. But we make a choice to be explicit. |
| net_options.set_is_in_nontrivial_first_party_set(true); |
| |
| return cookie |
| .IncludeForRequestURL( |
| url_, net_options, |
| net::CookieAccessParams{ |
| access_semantics, |
| network::IsUrlPotentiallyTrustworthy(url_), |
| net::cookie_util::GetSamePartyStatus(cookie, net_options), |
| }) |
| .status.IsInclude(); |
| } |
| |
| bool operator==(const CookieChangeSubscription& lhs, |
| const CookieChangeSubscription& rhs) { |
| return (lhs.match_type() == rhs.match_type()) && (lhs.name() == rhs.name()) && |
| (lhs.url() == rhs.url()); |
| } |
| |
| } // namespace content |