// Copyright 2017 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_COOKIE_MANAGER_H_ #define SERVICES_NETWORK_COOKIE_MANAGER_H_ #include #include #include #include "base/component_export.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "components/content_settings/core/common/content_settings.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/bindings/remote.h" #include "net/cookies/cookie_change_dispatcher.h" #include "net/cookies/cookie_deletion_info.h" #include "services/network/cookie_settings.h" #include "services/network/public/mojom/cookie_manager.mojom.h" namespace net { class CookieStore; class URLRequestContext; } // namespace net class GURL; namespace network { class FirstPartySetsAccessDelegate; class SessionCleanupCookieStore; // Wrap a cookie store in an implementation of the mojo cookie interface. class COMPONENT_EXPORT(NETWORK_SERVICE) CookieManager : public mojom::CookieManager { public: // Construct a CookieService that can serve mojo requests for the underlying // cookie store. |url_request_context->cookie_store()| must outlive this // object. `*first_party_sets_access_delegate` must outlive // `url_request_context->cookie_store()`. CookieManager( net::URLRequestContext* url_request_context, FirstPartySetsAccessDelegate* const first_party_sets_access_delegate, scoped_refptr session_cleanup_cookie_store, mojom::CookieManagerParamsPtr params); CookieManager(const CookieManager&) = delete; CookieManager& operator=(const CookieManager&) = delete; ~CookieManager() override; const CookieSettings& cookie_settings() const { return cookie_settings_; } // Bind a cookie receiver to this object. Mojo messages // coming through the associated pipe will be served by this object. void AddReceiver(mojo::PendingReceiver receiver); // TODO(rdsmith): Add a verion of AddRequest that does renderer-appropriate // security checks on bindings coming through that interface. // mojom::CookieManager void GetAllCookies(GetAllCookiesCallback callback) override; void GetAllCookiesWithAccessSemantics( GetAllCookiesWithAccessSemanticsCallback callback) override; void GetCookieList( const GURL& url, const net::CookieOptions& cookie_options, const net::CookiePartitionKeyCollection& cookie_partition_key_collection, GetCookieListCallback callback) override; void SetCanonicalCookie(const net::CanonicalCookie& cookie, const GURL& source_url, const net::CookieOptions& cookie_options, SetCanonicalCookieCallback callback) override; void DeleteCanonicalCookie(const net::CanonicalCookie& cookie, DeleteCanonicalCookieCallback callback) override; void SetContentSettings(const ContentSettingsForOneType& settings) override; void DeleteCookies(mojom::CookieDeletionFilterPtr filter, DeleteCookiesCallback callback) override; void DeleteSessionOnlyCookies( DeleteSessionOnlyCookiesCallback callback) override; void AddCookieChangeListener( const GURL& url, const absl::optional& name, mojo::PendingRemote listener) override; void AddGlobalChangeListener( mojo::PendingRemote listener) override; void CloneInterface( mojo::PendingReceiver new_interface) override; size_t GetClientsBoundForTesting() const { return receivers_.size(); } size_t GetListenersRegisteredForTesting() const { return listener_registrations_.size(); } void FlushCookieStore(FlushCookieStoreCallback callback) override; void AllowFileSchemeCookies(bool allow, AllowFileSchemeCookiesCallback callback) override; void SetForceKeepSessionState() override; void BlockThirdPartyCookies(bool block) override; void SetContentSettingsForLegacyCookieAccess( const ContentSettingsForOneType& settings) override; void SetStorageAccessGrantSettings( const ContentSettingsForOneType& settings, SetStorageAccessGrantSettingsCallback callback) override; // Configures |out| based on |params|. (This doesn't honor // allow_file_scheme_cookies, which affects the cookie store rather than the // settings). static void ConfigureCookieSettings( const network::mojom::CookieManagerParams& params, CookieSettings* out); // Causes the next call to GetCookieList to crash the process. static void CrashOnGetCookieList(); // Will convert a site's partitioned cookies into unpartitioned cookies. This // may result in multiple cookies which have the same (partition_key, name, // host_key, path), which violates the database's unique constraint. The // algorithm we use to coalesce the cookies into a single unpartitioned cookie // is the following: // // 1. If one of the cookies has no partition key (i.e. it is unpartitioned) // choose this cookie. // // 2. Choose the partitioned cookie with the most recent last_access_time. // // This function is a no-op when PartitionedCookies are disabled or // PartitionedCookiesBypassOriginTrial is enabled. // TODO(crbug.com/1296161): Delete this when the partitioned cookies Origin // Trial ends. void ConvertPartitionedCookiesToUnpartitioned(const GURL& url) override; private: // State associated with a CookieChangeListener. struct ListenerRegistration { ListenerRegistration(); ListenerRegistration(const ListenerRegistration&) = delete; ListenerRegistration& operator=(const ListenerRegistration&) = delete; ~ListenerRegistration(); // Translates a CookieStore change callback to a CookieChangeListener call. void DispatchCookieStoreChange(const net::CookieChangeInfo& change); // Owns the callback registration in the store. std::unique_ptr subscription; // The observer receiving change notifications. mojo::Remote listener; }; // Handles connection errors on change listener pipes. void RemoveChangeListener(ListenerRegistration* registration); // Called after getting the First-Party-Set-aware partition key when setting a // cookie. `adjusted_cookie_partition_key` holds a bool representing whether // the cookie needs to be recreated (due to using the wrong partition key); // and the partition key to use when recreating the cookie (for any reason). void OnGotFirstPartySetPartitionKeyForSet( const GURL& source_url, const net::CookieOptions& cookie_options, std::unique_ptr cookie, SetCanonicalCookieCallback callback, std::pair> adjusted_cookie_partition_key); // Called after getting the First-Party-Set-aware partition key when deleting // a cookie. void OnGotFirstPartySetPartitionKeyForDelete( std::unique_ptr cookie, DeleteCanonicalCookieCallback callback, bool cookie_partition_keys_match); void OnGotCookiePartitionKeyCollection( const GURL& url, const net::CookieOptions& cookie_options, GetCookieListCallback callback, net::CookiePartitionKeyCollection cookie_partition_key_collection); const raw_ptr cookie_store_; scoped_refptr session_cleanup_cookie_store_; mojo::ReceiverSet receivers_; std::vector> listener_registrations_; // Note: RestrictedCookieManager and CookieAccessDelegate store pointers to // |cookie_settings_|. CookieSettings cookie_settings_; base::WeakPtrFactory weak_factory_{this}; }; COMPONENT_EXPORT(NETWORK_SERVICE) net::CookieDeletionInfo DeletionFilterToInfo( mojom::CookieDeletionFilterPtr filter); } // namespace network #endif // SERVICES_NETWORK_COOKIE_MANAGER_H_