File: recent_model.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 (236 lines) | stat: -rw-r--r-- 8,720 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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
// Copyright 2017 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_FILEAPI_RECENT_MODEL_H_
#define CHROME_BROWSER_ASH_FILEAPI_RECENT_MODEL_H_

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/containers/id_map.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/ash/fileapi/file_accumulator.h"
#include "chrome/browser/ash/fileapi/recent_file.h"
#include "chrome/browser/ash/fileapi/recent_source.h"
#include "chrome/common/extensions/api/file_manager_private.h"
#include "components/keyed_service/core/keyed_service.h"
#include "storage/browser/file_system/file_system_url.h"

class GURL;
class Profile;

namespace storage {

class FileSystemContext;

}  // namespace storage

namespace ash {

// The specifications of conditions on recent sources. Only volumes of the given
// type are searched for recent files.
struct RecentSourceSpec {
  // The type of volume that is to be scanned.
  extensions::api::file_manager_private::VolumeType volume_type;
};

// The options that impact how the search for recent files is carried out. The
// default values for the options is to look for files that were modified in the
// last 30 days, with no limit to how long the scan can take, returning any type
// of files, but no more than 1000. If possible files will be returned from the
// recent cache.
//
// It is critical that you specify the source_list to be all sources that you
// wish to search. By default the source list is empty, meaning that nothing
// is searched.
struct RecentModelOptions {
  RecentModelOptions();
  ~RecentModelOptions();

  // How far back to accept files.
  base::TimeDelta now_delta = base::Days(30);

  // The maximum time the scan for recent files can take. Sources that do
  // not complete before the timeout do not contribute to returned results.
  base::TimeDelta scan_timeout = base::TimeDelta::Max();

  // The maximum number of files to be returned.
  size_t max_files = 1000u;

  // Whether or not to invalidate the cache; if this flag is true, even if
  // there are cached results, they are not returned. Instead a full scan
  // of sources is performed.
  bool invalidate_cache = false;

  // The type of files to be returned.
  RecentSource::FileType file_type = RecentSource::FileType::kAll;

  // A vector of recent sources specifications. Only sources matching the
  // specification are going to be used when retrieving recent files. This field
  // must be non-empty.
  std::vector<RecentSourceSpec> source_specs;
};

// Implements a service that returns files matching a given query, type, with
// the given modification date. A typical use is shown below:
//
// RecentModel* model = RecentModelFactory::GetForProfile(user_profile);
// GetRecentFilesCallback callback = base:Bind(...);
// FileSystemContext* context = GetFileSystemContextForRenderFrameHost(
//     user_profile, render_frame_host());
//
// // Requests files from local disk, with names containing "foo", modified
// // within the last 30 days (default), classified as image (jpg, png, etc.),
// // without deleting cache from the previous call (default).
// ash::RecentModelOptions options;
// options.file_type = ash::RecentSource::FileType::kImage
// options.source_spec = {
//   { .volume_type = VolumeType::kDownloads },
// };
// model->GetRecentFiles(
//     context,
//     GURL("chrome://file-manager/"),
//     "foo",
//     options,
//     std::move(callback));
//
// In addition to the above flow, one can set the maximum duration for the
// GetRecentCall to take. Once that maximum duration is reached, whatever
// partial results are available, are returned.
//
// All member functions must be called on the UI thread.  However, this class
// supports multiple calls with varying parameters being issued in parallel.
class RecentModel : public KeyedService {
 public:
  // The name of the histogram used to record user metrics about total time
  // it took to fetch recent files.
  static constexpr char kLoadHistogramName[] = "FileBrowser.Recent.LoadTotal";

  using FileType = RecentSource::FileType;

  // Stores all parameters that identify either the current or cached search
  // performed by the recent model.
  struct SearchCriteria {
    // The query used to match against file names, e.g., "my-file".
    std::string query;
    // The maximum age of accepted files measured as a delta from now.
    base::TimeDelta now_delta;
    // The maximum number of files to  be returned.
    size_t max_files;
    // The type of files accepted, e.g., images, documents, etc.
    FileType file_type;

    bool operator==(const SearchCriteria& other) const = default;
  };

  using GetRecentFilesCallback =
      base::OnceCallback<void(const std::vector<RecentFile>& files)>;

  explicit RecentModel(Profile* profile);
  ~RecentModel() override;

  RecentModel(const RecentModel&) = delete;
  RecentModel& operator=(const RecentModel&) = delete;

  // Creates an instance with given sources. Only for testing.
  static std::unique_ptr<RecentModel> CreateForTest(
      std::vector<std::unique_ptr<RecentSource>> sources);

  // Returns a list of recent files by querying sources.
  // Files are sorted by descending order of last modified time.
  // Results might be internally cached for better performance.
  void GetRecentFiles(storage::FileSystemContext* file_system_context,
                      const GURL& origin,
                      const std::string& query,
                      const RecentModelOptions& options,
                      GetRecentFilesCallback callback);

  // KeyedService overrides:
  void Shutdown() override;

 private:
  explicit RecentModel(std::vector<std::unique_ptr<RecentSource>> sources);

  // Context for a single GetRecentFiles call.
  struct CallContext {
    CallContext(const SearchCriteria& search_criteria,
                GetRecentFilesCallback callback);
    CallContext(CallContext&& context);
    ~CallContext();

    // The parameters of the last query. These are used to check if the
    // cached content can be re-used.
    SearchCriteria search_criteria;

    // The callback to call once the results are collected.
    GetRecentFilesCallback callback;

    // Time when the build started.
    base::TimeTicks build_start_time;

    // The accumulator of files found by various recent sources.
    FileAccumulator accumulator;

    // The set of recent sources processing the current request.
    std::set<raw_ptr<RecentSource>> active_sources;
  };

  // The method called by each of the recent source workers, once they complete
  // their task. This method monitors the number of calls and once it is equal
  // to the number of started recent source workers, it calls
  // OnSearchCompleted method.
  void OnGotRecentFiles(RecentSource* source,
                        const base::Time& cutoff_time,
                        const int32_t call_id,
                        std::vector<RecentFile> files);

  // This method is called by OnGetRecentFiles once all started recent source
  // workers complete their tasks.
  void OnSearchCompleted(const int32_t call_id);

  void ClearCache();

  // The callback invoked by the deadline timer.
  void OnScanTimeout(const base::Time& cutoff_time, const int32_t call_id);

  // A map that stores a context for each call to GetRecentFiles. The context
  // exists only from the start of the call until it is completed or times out.
  base::IDMap<std::unique_ptr<CallContext>> context_map_;

  // A map from call ID to a timer that terminates the call.
  base::IDMap<std::unique_ptr<base::DeadlineTimer>> deadline_map_;

  // All known recent sources.
  std::vector<std::unique_ptr<RecentSource>> sources_;

  // Cached GetRecentFiles() response.
  std::optional<std::vector<RecentFile>> cached_files_ = std::nullopt;

  // The parameters of the last query. These are used to check if the
  // cached content can be re-used.
  SearchCriteria cached_search_criteria_;

  // Timer to clear the cache.
  base::OneShotTimer cache_clear_timer_;

  // The counter used to enumerate GetRecentFiles calls. This is used to stop
  // calls that take too long.
  int32_t call_id_ = 0;

  // If set, limits the length of time the GetRecentFiles method can take before
  // returning results, if any, in the callback.
  std::optional<base::TimeDelta> scan_timeout_duration_;

  base::WeakPtrFactory<RecentModel> weak_ptr_factory_{this};
};

}  // namespace ash

#endif  // CHROME_BROWSER_ASH_FILEAPI_RECENT_MODEL_H_