1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/cookie_store/cookie_change_subscription.h"
6 
7 #include <utility>
8 
9 #include "content/browser/cookie_store/cookie_change_subscriptions.pb.h"
10 
11 namespace content {
12 
13 namespace {
14 
15 #define STATIC_ASSERT_ENUM(a, b)                            \
16   static_assert(static_cast<int>(a) == static_cast<int>(b), \
17                 "mismatching enums: " #a)
18 
19 STATIC_ASSERT_ENUM(network::mojom::CookieMatchType::EQUALS,
20                    proto::CookieMatchType::EQUALS);
21 STATIC_ASSERT_ENUM(network::mojom::CookieMatchType::STARTS_WITH,
22                    proto::CookieMatchType::STARTS_WITH);
23 
CookieMatchTypeToProto(network::mojom::CookieMatchType match_type)24 proto::CookieMatchType CookieMatchTypeToProto(
25     network::mojom::CookieMatchType match_type) {
26   switch (match_type) {
27     case network::mojom::CookieMatchType::EQUALS:
28       return proto::CookieMatchType::EQUALS;
29     case ::network::mojom::CookieMatchType::STARTS_WITH:
30       return proto::CookieMatchType::STARTS_WITH;
31   }
32   NOTREACHED();
33   return proto::CookieMatchType::EQUALS;
34 }
35 
CookieMatchTypeFromProto(proto::CookieMatchType match_type_proto)36 network::mojom::CookieMatchType CookieMatchTypeFromProto(
37     proto::CookieMatchType match_type_proto) {
38   switch (match_type_proto) {
39     case proto::CookieMatchType::EQUALS:
40       return network::mojom::CookieMatchType::EQUALS;
41     case proto::CookieMatchType::STARTS_WITH:
42       return ::network::mojom::CookieMatchType::STARTS_WITH;
43     default:
44       // The on-disk value was corrupted.
45       return network::mojom::CookieMatchType::EQUALS;
46   }
47 }
48 
49 }  // namespace
50 
51 // static
52 std::vector<std::unique_ptr<CookieChangeSubscription>>
DeserializeVector(const std::string & proto_string,int64_t service_worker_registration_id)53 CookieChangeSubscription::DeserializeVector(
54     const std::string& proto_string,
55     int64_t service_worker_registration_id) {
56   std::vector<std::unique_ptr<CookieChangeSubscription>> subscriptions;
57 
58   proto::CookieChangeSubscriptionsProto subscriptions_proto;
59   if (!subscriptions_proto.ParseFromString(proto_string))
60     return subscriptions;
61 
62   int subscription_count = subscriptions_proto.subscriptions_size();
63   subscriptions.reserve(subscription_count);
64   for (int i = 0; i < subscription_count; ++i) {
65     std::unique_ptr<CookieChangeSubscription> subscription =
66         CookieChangeSubscription::Create(subscriptions_proto.subscriptions(i),
67                                          service_worker_registration_id);
68     if (!subscription)
69       continue;
70     subscriptions.push_back(std::move(subscription));
71   }
72 
73   return subscriptions;
74 }
75 
76 // static
SerializeVector(const std::vector<std::unique_ptr<CookieChangeSubscription>> & subscriptions)77 std::string CookieChangeSubscription::SerializeVector(
78     const std::vector<std::unique_ptr<CookieChangeSubscription>>&
79         subscriptions) {
80   DCHECK(!subscriptions.empty());
81   proto::CookieChangeSubscriptionsProto subscriptions_proto;
82   for (const auto& subscription : subscriptions)
83     subscription->Serialize(subscriptions_proto.add_subscriptions());
84   return subscriptions_proto.SerializeAsString();
85 }
86 
87 // static
88 std::vector<blink::mojom::CookieChangeSubscriptionPtr>
ToMojoVector(const std::vector<std::unique_ptr<CookieChangeSubscription>> & subscriptions)89 CookieChangeSubscription::ToMojoVector(
90     const std::vector<std::unique_ptr<CookieChangeSubscription>>&
91         subscriptions) {
92   std::vector<blink::mojom::CookieChangeSubscriptionPtr> mojo_subscriptions;
93   mojo_subscriptions.reserve(subscriptions.size());
94   for (const auto& subscription : subscriptions) {
95     auto mojo_subscription = blink::mojom::CookieChangeSubscription::New();
96     subscription->Serialize(mojo_subscription.get());
97     mojo_subscriptions.push_back(std::move(mojo_subscription));
98   }
99   return mojo_subscriptions;
100 }
101 
102 // static
Create(proto::CookieChangeSubscriptionProto proto,int64_t service_worker_registration_id)103 std::unique_ptr<CookieChangeSubscription> CookieChangeSubscription::Create(
104     proto::CookieChangeSubscriptionProto proto,
105     int64_t service_worker_registration_id) {
106   GURL url(proto.url());
107   if (!url.is_valid())
108     return nullptr;
109 
110   std::string name = proto.name();
111   ::network::mojom::CookieMatchType match_type =
112       CookieMatchTypeFromProto(proto.match_type());
113 
114   return std::make_unique<CookieChangeSubscription>(
115       std::move(url), std::move(name), match_type,
116       service_worker_registration_id);
117 }
118 
119 CookieChangeSubscription::~CookieChangeSubscription() = default;
120 
CookieChangeSubscription(blink::mojom::CookieChangeSubscriptionPtr mojo_subscription,int64_t service_worker_registration_id)121 CookieChangeSubscription::CookieChangeSubscription(
122     blink::mojom::CookieChangeSubscriptionPtr mojo_subscription,
123     int64_t service_worker_registration_id)
124     : url_(std::move(mojo_subscription->url)),
125       name_(std::move(mojo_subscription->name)),
126       match_type_(mojo_subscription->match_type),
127       service_worker_registration_id_(service_worker_registration_id) {}
128 
CookieChangeSubscription(GURL url,std::string name,::network::mojom::CookieMatchType match_type,int64_t service_worker_registration_id)129 CookieChangeSubscription::CookieChangeSubscription(
130     GURL url,
131     std::string name,
132     ::network::mojom::CookieMatchType match_type,
133     int64_t service_worker_registration_id)
134     : url_(std::move(url)),
135       name_(std::move(name)),
136       match_type_(match_type),
137       service_worker_registration_id_(service_worker_registration_id) {}
138 
Serialize(proto::CookieChangeSubscriptionProto * proto) const139 void CookieChangeSubscription::Serialize(
140     proto::CookieChangeSubscriptionProto* proto) const {
141   proto->set_match_type(CookieMatchTypeToProto(match_type_));
142   proto->set_name(name_);
143   proto->set_url(url_.spec());
144 }
145 
Serialize(blink::mojom::CookieChangeSubscription * mojo_subscription) const146 void CookieChangeSubscription::Serialize(
147     blink::mojom::CookieChangeSubscription* mojo_subscription) const {
148   mojo_subscription->url = url_;
149   mojo_subscription->name = name_;
150   mojo_subscription->match_type = match_type_;
151 }
152 
ShouldObserveChangeTo(const net::CanonicalCookie & cookie,net::CookieAccessSemantics access_semantics) const153 bool CookieChangeSubscription::ShouldObserveChangeTo(
154     const net::CanonicalCookie& cookie,
155     net::CookieAccessSemantics access_semantics) const {
156   switch (match_type_) {
157     case ::network::mojom::CookieMatchType::EQUALS:
158       if (cookie.Name() != name_)
159         return false;
160       break;
161     case ::network::mojom::CookieMatchType::STARTS_WITH:
162       if (!base::StartsWith(cookie.Name(), name_, base::CompareCase::SENSITIVE))
163         return false;
164       break;
165   }
166 
167   net::CookieOptions net_options;
168   net_options.set_same_site_cookie_context(
169       net::CookieOptions::SameSiteCookieContext::MakeInclusive());
170 
171   return cookie.IncludeForRequestURL(url_, net_options, access_semantics)
172       .status.IsInclude();
173 }
174 
operator ==(const CookieChangeSubscription & lhs,const CookieChangeSubscription & rhs)175 bool operator==(const CookieChangeSubscription& lhs,
176                 const CookieChangeSubscription& rhs) {
177   return (lhs.match_type() == rhs.match_type()) && (lhs.name() == rhs.name()) &&
178          (lhs.url() == rhs.url());
179 }
180 
181 }  // namespace content
182