chromium/chrome/browser/ash/crosapi/prefs_ash.h

// Copyright 2021 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_CROSAPI_PREFS_ASH_H_
#define CHROME_BROWSER_ASH_CROSAPI_PREFS_ASH_H_

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <utility>

#include "base/callback_list.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_manager_observer.h"
#include "chrome/browser/profiles/profile_observer.h"
#include "chromeos/crosapi/mojom/prefs.mojom.h"
#include "components/prefs/pref_change_registrar.h"
#include "extensions/browser/extension_pref_store.h"
#include "extensions/browser/extension_pref_value_map_factory.h"
#include "extensions/browser/extension_prefs.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote_set.h"

class PrefService;
class PrefChangeRegistrar;

namespace crosapi {

// The ash-chrome implementation of the Prefs crosapi interface.
// This class must only be used from the main thread.
class PrefsAsh : public mojom::Prefs,
                 public ProfileManagerObserver,
                 public ProfileObserver {
 public:
  PrefsAsh(ProfileManager* profile_manager, PrefService* local_state);
  PrefsAsh(const PrefsAsh&) = delete;
  PrefsAsh& operator=(const PrefsAsh&) = delete;
  ~PrefsAsh() override;

  void BindReceiver(mojo::PendingReceiver<mojom::Prefs> receiver);

  // crosapi::mojom::Prefs:
  void GetPref(mojom::PrefPath path, GetPrefCallback callback) override;
  void SetPref(mojom::PrefPath path,
               base::Value value,
               SetPrefCallback callback) override;
  void AddObserver(mojom::PrefPath path,
                   mojo::PendingRemote<mojom::PrefObserver> observer) override;
  void GetExtensionPrefWithControl(
      mojom::PrefPath path,
      GetExtensionPrefWithControlCallback callback) override;
  void ClearExtensionControlledPref(
      mojom::PrefPath path,
      ClearExtensionControlledPrefCallback callback) override;

  // ProfileManagerObserver:
  void OnProfileAdded(Profile* profile) override;
  void OnProfileManagerDestroying() override;

  // ProfileObserver:
  void OnProfileWillBeDestroyed(Profile* profile) override;

  // Used to inject |profile| as a primary profile for testing.
  void OnPrimaryProfileReadyForTesting(Profile* profile) {
    OnPrimaryProfileReady(profile);
  }

 private:
  FRIEND_TEST_ALL_PREFIXES(PrefsAshTest, LocalStatePrefs);
  FRIEND_TEST_ALL_PREFIXES(PrefsAshTest, CrosSettingsPrefs);

  enum class AshPrefSource {
    kNormal = 0,
    kExtensionControlled = 1,
    kCrosSettings = 2,
  };

  struct State {
    raw_ptr<PrefService, DanglingUntriaged> pref_service;
    raw_ptr<PrefChangeRegistrar> registrar;
    AshPrefSource pref_source;
    std::string path;
  };
  std::optional<State> GetState(mojom::PrefPath path);
  const base::Value* GetValueForState(std::optional<State> state);

  void OnPrefChanged(mojom::PrefPath path);
  void OnDisconnect(mojom::PrefPath path, mojo::RemoteSetElementId id);

  // Called when Primary logged in user profile is ready.
  void OnPrimaryProfileReady(Profile* profile);

  void OnAppTerminating();

  // In production, owned by g_browser_process, which outlives this object.
  const raw_ptr<PrefService, DanglingUntriaged> local_state_;

  PrefChangeRegistrar local_state_registrar_;
  std::unique_ptr<PrefChangeRegistrar> profile_prefs_registrar_;
  PrefChangeRegistrar extension_prefs_registrar_;

  // CrosSettings doesn't support PrefService and therefore also doesn't support
  // PrefChangeRegistrar, so track these separately.
  std::map<mojom::PrefPath, base::CallbackListSubscription> cros_settings_subs_;

  // This class supports any number of connections.
  mojo::ReceiverSet<mojom::Prefs> receivers_;

  // This class supports any number of observers.
  std::map<mojom::PrefPath, mojo::RemoteSet<mojom::PrefObserver>> observers_;

  // Observe profile destruction to reset prefs observation.
  base::ScopedObservation<Profile, ProfileObserver> profile_observation_{this};

  base::ScopedObservation<ProfileManager, ProfileManagerObserver>
      profile_manager_observation_{this};

  base::CallbackListSubscription on_app_terminating_subscription_;
  // Map of extension pref paths to preference names.
  std::map<mojom::PrefPath, std::string> extension_prefpath_to_name_;
};

}  // namespace crosapi

#endif  // CHROME_BROWSER_ASH_CROSAPI_PREFS_ASH_H_