File: session_storage_manager.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (206 lines) | stat: -rw-r--r-- 7,750 bytes parent folder | download | duplicates (6)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
// 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 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 {

// SessionStorageManager manages the content stored in memory by
// chrome.storage.session.
// This class is optimized to reduce the number of possible copies of
// base::Values; this is because these values could potentially be rather
// large in size. This results in some slightly unwieldy function
// signatures.
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;

    // Owned by the SessionStorageManager. Caller cannot rely on it after any
    // subsequent calls to SessionStorageManager methods.
    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;

  // Retrieves the SessionStorageManager for a given `browser_context`.
  static SessionStorageManager* GetForBrowserContext(
      content::BrowserContext* browser_context);

  // Retrieves the factory instance for the SessionStorageManager.
  static BrowserContextKeyedServiceFactory* GetFactory();

  // Returns a vector with all keys found in storage for the given
  // `extension_id`.
  std::vector<std::string> GetKeys(const ExtensionId& extension_id) const;

  // Returns the value for the given `extension_id` and `key`, or null if none
  // exists.
  const base::Value* Get(const ExtensionId& extension_id,
                         const std::string& key) const;

  // Returns a map with keys and values found in storage for the given
  // `extension_id`.
  std::map<std::string, const base::Value*> Get(
      const ExtensionId& extension_id,
      const std::vector<std::string>& keys) const;

  // Returns a map with all keys and values found in storage for the given
  // `extension_id`.
  std::map<std::string, const base::Value*> GetAll(
      const ExtensionId& extension_id) const;

  // Stores multiple `values` for an `extension_id`. If storing the values
  // succeeds, returns true and populates `changes` with the inserted values. If
  // storing the values fails (e.g. due to going over quota), returns false and
  // leaves `changes` untouched, storing an error in `error`.
  bool Set(const ExtensionId& extension_id,
           std::map<std::string, base::Value> values,
           std::vector<ValueChange>& changes,
           std::string* error);

  // Removes multiple `keys` for an `extension_id`. Populates `changes` with the
  // removed values.
  void Remove(const ExtensionId& extension_id,
              const std::vector<std::string>& keys,
              std::vector<ValueChange>& changes);

  // Removes a `key` for an `extension_id`. Populates `changes` with the removed
  // value.
  void Remove(const ExtensionId& extension_id,
              const std::string& key,
              std::vector<ValueChange>& changes);

  // Clears all keys for an `extension_id`.
  void Clear(const ExtensionId& extension_id);

  // Clears all keys for an `extension_id`. Populates `changes` with the cleared
  // values.
  void Clear(const ExtensionId& extension_id,
             std::vector<ValueChange>& changes);

  // Gets the total amount of bytes being used by multiple keys and values of
  // the given `extension_id`.
  size_t GetBytesInUse(const ExtensionId& extension_id,
                       const std::vector<std::string>& keys) const;

  // Gets the total amount of bytes being used by a key for the given
  // `extension_id`.
  size_t GetBytesInUse(const ExtensionId& extension_id,
                       const std::string& key) const;

  // Gets the total amount of bytes being used by the given `extension_id`.
  size_t GetTotalBytesInUse(const ExtensionId& extension_id) const;

 private:
  struct SessionValue {
    SessionValue(base::Value value, size_t size);

    base::Value value;

    // Total bytes in use by value and key that points to this object.
    size_t size;
  };

  class ExtensionStorage {
   public:
    explicit ExtensionStorage(size_t quota_bytes);
    ~ExtensionStorage();

    // Returns a vector with keys found in storage.
    std::vector<std::string> GetKeys() const;

    // Returns a map with keys and values found in storage.
    std::map<std::string, const base::Value*> Get(
        const std::vector<std::string>& keys) const;

    // Returns a map with all keys and values found in storage.
    std::map<std::string, const base::Value*> GetAll() const;

    // Stores the input values in the values map, and updates the changes list
    // if a change occurs. If storing fails, returns false and populates
    // `error`.
    bool Set(std::map<std::string, base::Value> input_values,
             std::vector<ValueChange>& changes,
             std::string* error);

    // Removes multiple keys from the storage.
    void Remove(const std::vector<std::string>& keys,
                std::vector<ValueChange>& changes);

    // Clears the storage.
    void Clear(std::vector<ValueChange>& changes);
    void Clear();

    // Gets the total amount of bytes being used by multiple keys and values.
    size_t GetBytesInUse(const std::vector<std::string>& keys) const;

    // Gets the total amount of bytes stored.
    size_t GetTotalBytesInUse() const;

   private:
    // Returns the updated usage for the input values and adds them as session
    // values if there is available space, or returns the max quota bytes.
    size_t CalculateUsage(std::map<std::string, base::Value> input_values,
                          std::map<std::string, std::unique_ptr<SessionValue>>&
                              session_values) const;

    // The total quota in bytes.
    size_t quota_bytes_;

    // Total bytes stored in session by the extension. Includes both keys and
    // values.
    size_t used_total_ = 0;

    // Map of value key to its session value.
    std::map<std::string, std::unique_ptr<SessionValue>> values_;
  };

  // ExtensionRegistryObserver:
  void OnExtensionUnloaded(content::BrowserContext* browser_context,
                           const Extension* extension,
                           UnloadedExtensionReason reason) override;

  base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver>
      extension_registry_observation_{this};

  // Map of extension id to its storage.
  std::map<ExtensionId, std::unique_ptr<ExtensionStorage>> extensions_storage_;

  // The total quota for each extension in bytes.
  const size_t quota_bytes_per_extension_;
};

}  // namespace extensions

#endif  // EXTENSIONS_BROWSER_API_STORAGE_SESSION_STORAGE_MANAGER_H_