restricted_cookie_manager.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // Copyright 2017 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. #ifndef SERVICES_NETWORK_RESTRICTED_COOKIE_MANAGER_H_
  5. #define SERVICES_NETWORK_RESTRICTED_COOKIE_MANAGER_H_
  6. #include <set>
  7. #include <string>
  8. #include <tuple>
  9. #include "base/component_export.h"
  10. #include "base/containers/linked_list.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/memory/weak_ptr.h"
  13. #include "base/sequence_checker.h"
  14. #include "base/threading/sequenced_task_runner_handle.h"
  15. #include "mojo/public/cpp/bindings/remote.h"
  16. #include "net/base/isolation_info.h"
  17. #include "net/cookies/canonical_cookie.h"
  18. #include "net/cookies/cookie_change_dispatcher.h"
  19. #include "net/cookies/cookie_inclusion_status.h"
  20. #include "net/cookies/cookie_partition_key_collection.h"
  21. #include "net/cookies/cookie_store.h"
  22. #include "net/cookies/first_party_set_metadata.h"
  23. #include "services/network/public/mojom/cookie_access_observer.mojom.h"
  24. #include "services/network/public/mojom/restricted_cookie_manager.mojom.h"
  25. #include "url/gurl.h"
  26. #include "url/origin.h"
  27. namespace net {
  28. class CookieStore;
  29. class SiteForCookies;
  30. } // namespace net
  31. namespace network {
  32. struct CookieWithAccessResultComparer {
  33. bool operator()(
  34. const net::CookieWithAccessResult& cookie_with_access_result1,
  35. const net::CookieWithAccessResult& cookie_with_access_result2) const;
  36. };
  37. using CookieAccesses =
  38. std::set<net::CookieWithAccessResult, CookieWithAccessResultComparer>;
  39. using CookieAccessesByURLAndSite =
  40. std::map<std::pair<GURL, net::SiteForCookies>,
  41. std::unique_ptr<CookieAccesses>>;
  42. class CookieSettings;
  43. // RestrictedCookieManager implementation.
  44. //
  45. // Instances of this class must be created and used on the sequence that hosts
  46. // the CookieStore passed to the constructor.
  47. class COMPONENT_EXPORT(NETWORK_SERVICE) RestrictedCookieManager
  48. : public mojom::RestrictedCookieManager {
  49. public:
  50. // All the pointers passed to the constructor are expected to point to
  51. // objects that will outlive `this`.
  52. //
  53. // `origin` represents the domain for which the RestrictedCookieManager can
  54. // access cookies. It could either be a frame origin when `role` is
  55. // RestrictedCookieManagerRole::SCRIPT (a script scoped to a particular
  56. // document's frame)), or a request origin when `role` is
  57. // RestrictedCookieManagerRole::NETWORK (a network request).
  58. //
  59. // `isolation_info` must be fully populated, its `frame_origin` field should
  60. // not be used for cookie access decisions, but should be the same as `origin`
  61. // if the `role` is mojom::RestrictedCookieManagerRole::SCRIPT.
  62. //
  63. // `first_party_set_metadata` should have been previously computed by
  64. // `ComputeFirstPartySetMetadata` using the same `origin`, `cookie_store` and
  65. // `isolation_info` as were passed in here.
  66. RestrictedCookieManager(
  67. mojom::RestrictedCookieManagerRole role,
  68. net::CookieStore* cookie_store,
  69. const CookieSettings& cookie_settings,
  70. const url::Origin& origin,
  71. const net::IsolationInfo& isolation_info,
  72. mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer,
  73. bool first_party_sets_enabled,
  74. net::FirstPartySetMetadata first_party_set_metadata);
  75. RestrictedCookieManager(const RestrictedCookieManager&) = delete;
  76. RestrictedCookieManager& operator=(const RestrictedCookieManager&) = delete;
  77. ~RestrictedCookieManager() override;
  78. void OverrideOriginForTesting(const url::Origin& new_origin) {
  79. origin_ = new_origin;
  80. }
  81. // This spins the event loop, since the cookie partition key may be computed
  82. // asynchronously.
  83. void OverrideIsolationInfoForTesting(
  84. const net::IsolationInfo& new_isolation_info);
  85. const CookieSettings& cookie_settings() const { return cookie_settings_; }
  86. void GetAllForUrl(const GURL& url,
  87. const net::SiteForCookies& site_for_cookies,
  88. const url::Origin& top_frame_origin,
  89. mojom::CookieManagerGetOptionsPtr options,
  90. bool partitioned_cookies_runtime_feature_enabled,
  91. GetAllForUrlCallback callback) override;
  92. void SetCanonicalCookie(const net::CanonicalCookie& cookie,
  93. const GURL& url,
  94. const net::SiteForCookies& site_for_cookies,
  95. const url::Origin& top_frame_origin,
  96. net::CookieInclusionStatus status,
  97. SetCanonicalCookieCallback callback) override;
  98. void AddChangeListener(
  99. const GURL& url,
  100. const net::SiteForCookies& site_for_cookies,
  101. const url::Origin& top_frame_origin,
  102. mojo::PendingRemote<mojom::CookieChangeListener> listener,
  103. AddChangeListenerCallback callback) override;
  104. void SetCookieFromString(const GURL& url,
  105. const net::SiteForCookies& site_for_cookies,
  106. const url::Origin& top_frame_origin,
  107. const std::string& cookie,
  108. bool partitioned_cookies_runtime_feature_enabled,
  109. SetCookieFromStringCallback callback) override;
  110. void GetCookiesString(const GURL& url,
  111. const net::SiteForCookies& site_for_cookies,
  112. const url::Origin& top_frame_origin,
  113. bool partitioned_cookies_runtime_feature_enabled,
  114. GetCookiesStringCallback callback) override;
  115. void CookiesEnabledFor(const GURL& url,
  116. const net::SiteForCookies& site_for_cookies,
  117. const url::Origin& top_frame_origin,
  118. CookiesEnabledForCallback callback) override;
  119. // Computes the First-Party Set metadata corresponding to the given `origin`,
  120. // `cookie_store`, and `isolation_info`.
  121. //
  122. // May invoke `callback` either synchronously or asynchronously.
  123. static void ComputeFirstPartySetMetadata(
  124. const url::Origin& origin,
  125. const net::CookieStore* cookie_store,
  126. const net::IsolationInfo& isolation_info,
  127. base::OnceCallback<void(net::FirstPartySetMetadata)> callback);
  128. // This is a temporary method for the partitioned cookies (aka CHIPS) origin
  129. // trial.
  130. //
  131. // This method allows RCM to convert any sites' partitioned cookies to
  132. // unpartitioned. It should only exist for the duration of the CHIPS OT and
  133. // should be deleted shortly after, since it gives untrusted processes the
  134. // ability to convert any site's partitioned cookies to unpartitioned.
  135. //
  136. // Since CHIPS is still an experimental API, giving RCM this privilege should
  137. // not be a major risk. However, before CHIPS goes live this method should be
  138. // deleted.
  139. // TODO(https://crbug.com/1296161): Delete this function.
  140. void ConvertPartitionedCookiesToUnpartitioned(const GURL& url) override;
  141. private:
  142. // The state associated with a CookieChangeListener.
  143. class Listener;
  144. // Returns true if the RCM instance can read and/or set partitioned cookies.
  145. bool IsPartitionedCookiesEnabled() const;
  146. // Feeds a net::CookieList to a GetAllForUrl() callback.
  147. void CookieListToGetAllForUrlCallback(
  148. const GURL& url,
  149. const net::SiteForCookies& site_for_cookies,
  150. const url::Origin& top_frame_origin,
  151. const net::CookieOptions& net_options,
  152. mojom::CookieManagerGetOptionsPtr options,
  153. GetAllForUrlCallback callback,
  154. const net::CookieAccessResultList& cookie_list,
  155. const net::CookieAccessResultList& excluded_cookies);
  156. // Reports the result of setting the cookie to |network_context_client_|, and
  157. // invokes the user callback.
  158. void SetCanonicalCookieResult(const GURL& url,
  159. const net::SiteForCookies& site_for_cookies,
  160. const net::CanonicalCookie& cookie,
  161. const net::CookieOptions& net_options,
  162. SetCanonicalCookieCallback user_callback,
  163. net::CookieAccessResult access_result);
  164. // Called when the Mojo pipe associated with a listener is closed.
  165. void RemoveChangeListener(Listener* listener);
  166. // Ensures that this instance may access the cookies for a given URL.
  167. //
  168. // Returns true if the access should be allowed, or false if it should be
  169. // blocked.
  170. //
  171. // |cookie_being_set| should be non-nullptr if setting a cookie, and should be
  172. // nullptr otherwise (getting cookies, subscribing to cookie changes).
  173. //
  174. // If the access would not be allowed, this helper calls
  175. // mojo::ReportBadMessage(), which closes the pipe.
  176. bool ValidateAccessToCookiesAt(
  177. const GURL& url,
  178. const net::SiteForCookies& site_for_cookies,
  179. const url::Origin& top_frame_origin,
  180. const net::CanonicalCookie* cookie_being_set = nullptr);
  181. const net::SiteForCookies& BoundSiteForCookies() const {
  182. return isolation_info_.site_for_cookies();
  183. }
  184. const url::Origin& BoundTopFrameOrigin() const {
  185. return isolation_info_.top_frame_origin().value();
  186. }
  187. CookieAccesses* GetCookieAccessesForURLAndSite(
  188. const GURL& url,
  189. const net::SiteForCookies& site_for_cookies);
  190. // Returns true if the RCM should skip sending a cookie access notification
  191. // to the |cookie_observer_| for the cookie in |cookie_item|.
  192. bool SkipAccessNotificationForCookieItem(
  193. CookieAccesses* cookie_accesses,
  194. const net::CookieWithAccessResult& cookie_item);
  195. // Called while overriding the cookie_partition_key during testing.
  196. void OnGotFirstPartySetMetadataForTesting(
  197. base::OnceClosure done_closure,
  198. net::FirstPartySetMetadata first_party_set_metadata);
  199. const mojom::RestrictedCookieManagerRole role_;
  200. const raw_ptr<net::CookieStore> cookie_store_;
  201. const CookieSettings& cookie_settings_;
  202. url::Origin origin_;
  203. // Holds the browser-provided site_for_cookies and top_frame_origin to which
  204. // this RestrictedCookieManager is bound. (The frame_origin field is not used
  205. // directly, but must match the `origin_` if the RCM role is SCRIPT.)
  206. net::IsolationInfo isolation_info_;
  207. mojo::Remote<mojom::CookieAccessObserver> cookie_observer_;
  208. base::LinkedList<Listener> listeners_;
  209. SEQUENCE_CHECKER(sequence_checker_);
  210. // The First-Party Set metadata for the context this RestrictedCookieManager
  211. // is associated with.
  212. net::FirstPartySetMetadata first_party_set_metadata_;
  213. // Cookie partition key that the instance of RestrictedCookieManager will have
  214. // access to. Must be set only in the constructor or in *ForTesting methods.
  215. absl::optional<net::CookiePartitionKey> cookie_partition_key_;
  216. // CookiePartitionKeyCollection that is either empty if
  217. // `cookie_partition_key_` is nullopt. If `cookie_partition_key_` is not null,
  218. // the key collection contains its value. Must be kept in sync with
  219. // `cookie_partition_key_`.
  220. net::CookiePartitionKeyCollection cookie_partition_key_collection_;
  221. // Contains a mapping of url/site -> recent cookie updates for duplicate
  222. // update filtering.
  223. CookieAccessesByURLAndSite recent_cookie_accesses_;
  224. const bool first_party_sets_enabled_;
  225. base::WeakPtrFactory<RestrictedCookieManager> weak_ptr_factory_{this};
  226. };
  227. } // namespace network
  228. #endif // SERVICES_NETWORK_RESTRICTED_COOKIE_MANAGER_H_