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_
|