1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_FLOATING_SSO_FLOATING_SSO_SERVICE_H_
#define CHROME_BROWSER_ASH_FLOATING_SSO_FLOATING_SSO_SERVICE_H_
#include <memory>
#include "base/containers/flat_set.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "chrome/browser/ash/floating_sso/floating_sso_sync_bridge.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/sync/model/data_type_store.h"
#include "components/url_matcher/url_matcher.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_access_result.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
namespace syncer {
class DataTypeControllerDelegate;
} // namespace syncer
class PrefService;
namespace ash::floating_sso {
class FloatingSsoService : public KeyedService,
public network::mojom::CookieChangeListener,
public FloatingSsoSyncBridge::Observer {
public:
// Callback used to get a CookieManager.
using CookieManagerGetter =
base::RepeatingCallback<network::mojom::CookieManager*()>;
FloatingSsoService(PrefService* prefs,
std::unique_ptr<FloatingSsoSyncBridge> bridge,
CookieManagerGetter cookie_manager_getter);
FloatingSsoService(const FloatingSsoService&) = delete;
FloatingSsoService& operator=(const FloatingSsoService&) = delete;
~FloatingSsoService() override;
// KeyedService:
void Shutdown() override;
// network::mojom::CookieChangeListener:
void OnCookieChange(const net::CookieChangeInfo& change) override;
// FloatingSsoSyncBridge::Observer:
void OnCookiesAddedOrUpdatedRemotely(
const std::vector<net::CanonicalCookie>& cookies) override;
void OnCookiesRemovedRemotely(
const std::vector<net::CanonicalCookie>& cookies) override;
bool IsFloatingSsoEnabled();
// `callback` will be run once there are no cookie manager changes in
// progress. This can be called repeatedly but only the latest callback will
// be executed.
void RunWhenCookiesAreReady(base::OnceClosure callback);
// `callback` will be run once the bridge executes `MergeFullSyncData` method
// (which can only happen when Sync is being enabled for the first time on
// this client) and once conditions for `RunWhenCookiesAreReady` are also
// satisfied.
void RunWhenCookiesAreReadyOnFirstSync(base::OnceClosure callback);
base::WeakPtr<syncer::DataTypeControllerDelegate> GetControllerDelegate();
// Signal that this cookie shouldn't be overridden with remote
// entities on initial Sync cycle.
void MarkToNotOverride(const net::CanonicalCookie& cookie);
bool ShouldSyncCookiesForUrl(const GURL& url) const;
FloatingSsoSyncBridge* GetBridgeForTesting() { return bridge_.get(); }
bool IsBoundToCookieManagerForTesting() { return receiver_.is_bound(); }
private:
void RegisterPolicyListeners();
// Map the FloatingSsoDomainBlocklist and FloatingSsoDomainBlocklistExceptions
// policies to URL matchers.
void UpdateUrlMatchers();
// Check if the feature is enabled based on the corresponding enterprise
// policy. If yes, start observing cookies and uploading them to Sync, and
// apply cookies from Sync if needed. If not, stop all of the above.
void StartOrStop();
void MaybeStartListening();
void StopListening();
void BindToCookieManager();
void OnCookiesLoaded(const net::CookieList& cookies);
bool ShouldSyncCookie(const net::CanonicalCookie& cookie) const;
void OnConnectionError();
bool IsDomainAllowed(const GURL& url) const;
void OnCookieSet(net::CookieAccessResult result);
void OnCookieDeleted(bool success);
void DecrementChangesCountAndMaybeNotify();
raw_ptr<PrefService> prefs_ = nullptr;
// TODO(crbug.com/378091718): investigated lifetime issues when using
// raw_ptr<network::mojom::CookieManager> instead of a callback here.
CookieManagerGetter cookie_manager_getter_;
std::unique_ptr<FloatingSsoSyncBridge> bridge_;
base::ScopedObservation<FloatingSsoSyncBridge,
FloatingSsoSyncBridge::Observer>
scoped_observation_{this};
std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
// We fetch the accumulated cookies the first time the service is started, as
// well when the service stops listening and resumes due to setting changes.
// We do not fetch accumulated cookies when the connection to the cookie
// manager is disrupted because we attempt to reconnect right away.
bool fetch_accumulated_cookies_ = true;
// Count of changes (additions or deletions of cookies) currently being
// performed by `cookie_manager_`.
// TODO(crbug.com/377471962): Add explicit tests for this counter and for
// `on_no_changes_in_progress_callback_`.
int changes_in_progress_count_ = 0;
base::OnceClosure on_no_changes_in_progress_callback_;
mojo::Receiver<network::mojom::CookieChangeListener> receiver_{this};
std::unique_ptr<url_matcher::URLMatcher> block_url_matcher_;
std::unique_ptr<url_matcher::URLMatcher> except_url_matcher_;
};
} // namespace ash::floating_sso
#endif // CHROME_BROWSER_ASH_FLOATING_SSO_FLOATING_SSO_SERVICE_H_
|