chromium/android_webview/browser/aw_browser_context_store.h

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ANDROID_WEBVIEW_BROWSER_AW_BROWSER_CONTEXT_STORE_H_
#define ANDROID_WEBVIEW_BROWSER_AW_BROWSER_CONTEXT_STORE_H_

#include <map>
#include <memory>
#include <string>

#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/no_destructor.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"

namespace android_webview {

namespace prefs {

// List of profile dictionaries.
constexpr char kProfileListPref[] = "profile.list";

// Counter for assigning profile numbers (without reuse). Stores the last
// assigned number, or 0 if never used, which is the same as the total number of
// non-default profiles ever created.
constexpr char kProfileCounterPref[] = "profile.counter";

}  // namespace prefs

class AwBrowserContext;

// AwBrowserContextStore is the container for AwBrowserContexts.
//
// - Owns and manages the lifetimes of instantiated AwBrowserContexts
//   ("Profiles").
//
// - Keeps track of the profiles instantiated into memory and the profiles saved
//   to disk (via the local_state pref_service), including mappings between
//   profile names and directory names.
//
// Most profiles are created and instantiated lazily (via the Get method).
// However, there is a special "Default" profile which is always created and
// instantiated on startup.
// Lifetime: Singleton
class AwBrowserContextStore final {
 public:
  static constexpr char kDefaultContextName[] = "Default";
  static constexpr char kDefaultContextPath[] = "Default";

  enum class DeletionResult {
    kDeleted,
    kDoesNotExist,
    kInUse,
  };

  ~AwBrowserContextStore() = delete;
  AwBrowserContextStore(const AwBrowserContextStore&) = delete;
  AwBrowserContextStore& operator=(const AwBrowserContextStore&) = delete;

  // Initialize the store if needed and then get a pointer to it.
  static AwBrowserContextStore* GetOrCreateInstance();
  // CHECK the store is initialized and then get a pointer to it.
  static AwBrowserContextStore* GetInstance();

  // Get the default context. This will never return null.
  AwBrowserContext* GetDefault() const;
  // Check if a named context exists (on disk or in memory). The context does
  // not need to be instantiated. The result is given to the callback once
  // determined.
  bool Exists(const std::string& name) const;
  // Instantiate and get the context with the given name. If the context does
  // not already exist (on disk or in memory), it is created if create_if_needed
  // is true, otherwise no context is instantiated and nullptr is returned.
  AwBrowserContext* Get(const std::string& name, bool create_if_needed);
  // Get a list of all contexts' names (on disk and in memory).
  std::vector<std::string> List() const;
  // Delete the named context if possible.
  DeletionResult Delete(const std::string& name);

  // Get the relative path for the named context. The context must exist (on
  // disk or in memory), but does not need to be instantiated.
  base::FilePath GetRelativePathForTesting(const std::string& name) const;

  static void RegisterPrefs(PrefRegistrySimple* registry);

 private:
  friend class base::NoDestructor<AwBrowserContextStore>;

  struct Entry {
    Entry();
    explicit Entry(base::FilePath&& path,
                   std::unique_ptr<AwBrowserContext>&& instance);
    ~Entry();
    Entry(Entry&&);
    Entry(const Entry&) = delete;
    Entry& operator=(const Entry&) = delete;

    base::FilePath path;
    std::unique_ptr<AwBrowserContext> instance;
  };

  // Create the global store of all AwBrowserContexts. The default context is
  // pre-loaded into the store, which may involve blocking IO.
  explicit AwBrowserContextStore(PrefService* pref_service);

  // Registers a new (default or non-default) context with the given name and
  // ensures filesystem state is ready for the context to be
  // initialized. Returns a pointer to the entry inserted into contexts_. This
  // does not instantiate the context in-process.
  //
  // It is illegal to create a context which already exists.
  Entry* CreateNewContext(std::string_view name);
  // Finds and reserves a non-default profile number which hasn't previously
  // been assigned to any profile (even deleted ones).
  int AssignNewProfileNumber();

  // (local_state) PrefService which is used to persist information about the
  // profiles that exist on disk.
  const raw_ref<PrefService> prefs_;

  // Map of all existing (on disk and in memory) profiles, including ones which
  // haven't been instantiated.
  std::map<std::string, Entry> contexts_;
  // The default context is initialized during store construction. Once the
  // store is created, this pointer will be non-null.
  raw_ptr<AwBrowserContext> default_context_;
};

}  // namespace android_webview

#endif  // ANDROID_WEBVIEW_BROWSER_AW_BROWSER_CONTEXT_STORE_H_