#ifndef EXTENSIONS_BROWSER_API_STORAGE_SESSION_STORAGE_MANAGER_H_
#define EXTENSIONS_BROWSER_API_STORAGE_SESSION_STORAGE_MANAGER_H_
#include <map>
#include <string>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/values.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/extension_id.h"
class BrowserContextKeyedServiceFactory;
namespace extensions {
class SessionStorageManager : public KeyedService,
public ExtensionRegistryObserver {
public:
struct ValueChange {
ValueChange(std::string key,
std::optional<base::Value> old_value,
base::Value* new_value);
~ValueChange();
ValueChange(const ValueChange& other) = delete;
ValueChange& operator=(const ValueChange& other) = delete;
ValueChange(ValueChange&& other);
std::string key;
std::optional<base::Value> old_value;
raw_ptr<const base::Value, DanglingUntriaged> new_value;
};
SessionStorageManager(size_t quota_bytes_per_extension,
content::BrowserContext* browser_context);
~SessionStorageManager() override;
SessionStorageManager(const SessionStorageManager& other) = delete;
SessionStorageManager& operator=(SessionStorageManager& other) = delete;
static SessionStorageManager* GetForBrowserContext(
content::BrowserContext* browser_context);
static BrowserContextKeyedServiceFactory* GetFactory();
std::vector<std::string> GetKeys(const ExtensionId& extension_id) const;
const base::Value* Get(const ExtensionId& extension_id,
const std::string& key) const;
std::map<std::string, const base::Value*> Get(
const ExtensionId& extension_id,
const std::vector<std::string>& keys) const;
std::map<std::string, const base::Value*> GetAll(
const ExtensionId& extension_id) const;
bool Set(const ExtensionId& extension_id,
std::map<std::string, base::Value> values,
std::vector<ValueChange>& changes,
std::string* error);
void Remove(const ExtensionId& extension_id,
const std::vector<std::string>& keys,
std::vector<ValueChange>& changes);
void Remove(const ExtensionId& extension_id,
const std::string& key,
std::vector<ValueChange>& changes);
void Clear(const ExtensionId& extension_id);
void Clear(const ExtensionId& extension_id,
std::vector<ValueChange>& changes);
size_t GetBytesInUse(const ExtensionId& extension_id,
const std::vector<std::string>& keys) const;
size_t GetBytesInUse(const ExtensionId& extension_id,
const std::string& key) const;
size_t GetTotalBytesInUse(const ExtensionId& extension_id) const;
private:
struct SessionValue {
SessionValue(base::Value value, size_t size);
base::Value value;
size_t size;
};
class ExtensionStorage {
public:
explicit ExtensionStorage(size_t quota_bytes);
~ExtensionStorage();
std::vector<std::string> GetKeys() const;
std::map<std::string, const base::Value*> Get(
const std::vector<std::string>& keys) const;
std::map<std::string, const base::Value*> GetAll() const;
bool Set(std::map<std::string, base::Value> input_values,
std::vector<ValueChange>& changes,
std::string* error);
void Remove(const std::vector<std::string>& keys,
std::vector<ValueChange>& changes);
void Clear(std::vector<ValueChange>& changes);
void Clear();
size_t GetBytesInUse(const std::vector<std::string>& keys) const;
size_t GetTotalBytesInUse() const;
private:
size_t CalculateUsage(std::map<std::string, base::Value> input_values,
std::map<std::string, std::unique_ptr<SessionValue>>&
session_values) const;
size_t quota_bytes_;
size_t used_total_ = 0;
std::map<std::string, std::unique_ptr<SessionValue>> values_;
};
void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason reason) override;
base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observation_{this};
std::map<ExtensionId, std::unique_ptr<ExtensionStorage>> extensions_storage_;
const size_t quota_bytes_per_extension_;
};
}
#endif