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