File: file_system_access_observation_group.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (187 lines) | stat: -rw-r--r-- 7,021 bytes parent folder | download | duplicates (5)
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
// 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 CONTENT_BROWSER_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_OBSERVATION_GROUP_H_
#define CONTENT_BROWSER_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_OBSERVATION_GROUP_H_

#include <list>

#include "base/functional/callback.h"
#include "base/observer_list_types.h"
#include "base/scoped_observation.h"
#include "base/scoped_observation_traits.h"
#include "content/browser/file_system_access/file_system_access_change_source.h"
#include "content/browser/file_system_access/file_system_access_observer_quota_manager.h"
#include "content/browser/file_system_access/file_system_access_watch_scope.h"

namespace content {
class FileSystemAccessWatcherManager;

// Represents a group of observations that all have the same
// `FileSystemAccessChangeSource` and `base::StorageKey`. This is created and
// maintained by the `FileSystemAccessWatcherManager`.
//
// Instances of this class must be accessed exclusively on the UI thread. Owned
// by the `FileSystemAccessWatcherManager`.
//
// TODO(crbug.com/376134535): Once the watcher manager layer is removed, the
// base class should be `FileSystemAccessChangeSource::RawChangeObserver` rather
// than `base::CheckedObserver`.
class CONTENT_EXPORT FileSystemAccessObservationGroup
    : public base::CheckedObserver {
 public:
  // Describes a change to some location in a file system.
  struct CONTENT_EXPORT Change {
    Change(storage::FileSystemURL url,
           FileSystemAccessChangeSource::ChangeInfo change_info);
    ~Change();

    // Copyable and movable.
    Change(const Change&);
    Change(Change&&) noexcept;
    Change& operator=(const Change&);
    Change& operator=(Change&&) noexcept;

    storage::FileSystemURL url;
    FileSystemAccessChangeSource::ChangeInfo change_info;

    bool operator==(const Change& other) const {
      return url == other.url && change_info == other.change_info;
    }
  };

  // An observer of a `FileSystemAccessObservationGroup`.
  //
  // The common source/observer pattern is for the source to provide an abstract
  // class for observers to implement. Here we instead fully implement the
  // observer and let end observers set a callback for its events.
  //
  // This pattern is chosen because we want the lifetime of the
  // `FileSystemAccessObservationGroup` to be tied to its `Observer`. We don't
  // want there to be an empty `FileSystemAccessObservationGroup`, so the
  // creator of the `FileSystemAccessObservationGroup` should be able to
  // immediately create an `Observer`.
  class CONTENT_EXPORT Observer : public base::CheckedObserver {
   public:
    using OnChangesCallback = base::RepeatingCallback<void(
        const std::optional<std::list<Change>>& changes_or_error)>;

    ~Observer() override;

    // Not copyable or movable.
    Observer(const Observer&) = delete;
    Observer(Observer&&) = delete;
    Observer& operator=(const Observer&) = delete;
    Observer& operator=(Observer&&) = delete;

    // Set the callback to which changes will be reported. It is illegal to call
    // this method more than once.
    void SetCallback(OnChangesCallback on_change_callback);

    const FileSystemAccessWatchScope& scope() const {
      DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

      return obs_.GetSource()->scope();
    }

    FileSystemAccessObservationGroup* GetObservationGroupForTesting() {
      DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
      return obs_.GetSource();
    }

   private:
    friend FileSystemAccessObservationGroup;

    explicit Observer(FileSystemAccessObservationGroup& observation_group);

    void NotifyOfChanges(
        const std::optional<std::list<Change>>& changes_or_error);

    SEQUENCE_CHECKER(sequence_checker_);

    OnChangesCallback on_change_callback_ GUARDED_BY_CONTEXT(sequence_checker_);

    base::ScopedObservation<FileSystemAccessObservationGroup, Observer> obs_
        GUARDED_BY_CONTEXT(sequence_checker_){this};
  };

  using OnUsageChangeCallback = FilePathWatcher::UsageChangeCallback;

  explicit FileSystemAccessObservationGroup(
      FileSystemAccessObserverQuotaManager::Handle quota_manager_handle,
      FileSystemAccessWatcherManager& watcher_manager,
      blink::StorageKey storage_key,
      FileSystemAccessWatchScope scope,
      base::PassKey<FileSystemAccessWatcherManager> pass_key);
  ~FileSystemAccessObservationGroup() override;

  // Not copyable or movable.
  FileSystemAccessObservationGroup(const FileSystemAccessObservationGroup&) =
      delete;
  FileSystemAccessObservationGroup(FileSystemAccessObservationGroup&&) = delete;
  FileSystemAccessObservationGroup& operator=(
      const FileSystemAccessObservationGroup&) = delete;
  FileSystemAccessObservationGroup& operator=(
      FileSystemAccessObservationGroup&&) = delete;

  // Set the callback to which usage changes will be reported. It is illegal to
  // call this method more than once.
  void SetOnUsageCallbackForTesting(
      OnUsageChangeCallback on_usage_change_callback);

  FileSystemAccessObserverQuotaManager* GetQuotaManagerForTesting() {
    return quota_manager_handle_.GetQuotaManagerForTesting();  // IN-TEST
  }

 private:
  friend FileSystemAccessWatcherManager;
  friend base::ScopedObservationTraits<FileSystemAccessObservationGroup,
                                       Observer>;

  using UsageChangeResult =
      FileSystemAccessObserverQuotaManager::UsageChangeResult;

  std::unique_ptr<Observer> CreateObserver();

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  void NotifyOfChanges(
      const std::optional<std::list<Change>>& changes_or_error);

  void NotifyOfUsageChange(size_t old_usage, size_t new_usage);

  const FileSystemAccessWatchScope& scope() const { return scope_; }

  SEQUENCE_CHECKER(sequence_checker_);

  const blink::StorageKey storage_key_;
  const FileSystemAccessWatchScope scope_;

  // Observations to which this instance will notify of changes within their
  // respective scope.
  base::ObserverList<Observer> observations_
      GUARDED_BY_CONTEXT(sequence_checker_);

  OnUsageChangeCallback on_usage_change_callback_;

  // The quota manager for our storage key.
  FileSystemAccessObserverQuotaManager::Handle quota_manager_handle_;

  // The `FileSystemAccessWatcherManager` that we're observing. Safe because
  // `watcher_manager_` owns this.
  //
  // We use this instead of a `ScopedObservation` because
  // `ScopedObservationTraits` needs a full interface definition rather than a
  // forward declaration of `FileSystemAccessWatcherManager`. It's not worth
  // defining a custom `ScopedObservationTraits` for the minimum value
  // `ScopedObservation` brings.
  base::raw_ref<FileSystemAccessWatcherManager> watcher_manager_;

  bool received_quota_error_ = false;
};

}  // namespace content

#endif  // CONTENT_BROWSER_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_OBSERVATION_GROUP_H_