|  | // 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_ARC_MEDIA_SOURCE_H_ | 
|  | #define CHROME_BROWSER_ASH_FILEAPI_RECENT_ARC_MEDIA_SOURCE_H_ | 
|  |  | 
|  | #include <cstdint> | 
|  | #include <map> | 
|  | #include <memory> | 
|  | #include <optional> | 
|  | #include <set> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/containers/id_map.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/arc/fileapi/arc_documents_provider_root.h" | 
|  | #include "chrome/browser/ash/fileapi/recent_source.h" | 
|  | #include "chrome/browser/profiles/profile.h" | 
|  | #include "chromeos/ash/experiences/arc/mojom/file_system.mojom.h" | 
|  |  | 
|  | class Profile; | 
|  |  | 
|  | namespace ash { | 
|  |  | 
|  | class RecentFile; | 
|  |  | 
|  | // RecentSource implementation for ARC media view. This class is not designed to | 
|  | // be used by itself. Instead, it is instantiated and used by the RecentModel to | 
|  | // retrieve recent files from ARC media view. | 
|  | // | 
|  | // All member functions must be called on the UI thread. | 
|  | class RecentArcMediaSource : public RecentSource { | 
|  | public: | 
|  | // Creates a recent file sources that scans Arc media. The `profile` is used | 
|  | // to arc::ArcFileSystemOperationRunner and arc::ArcDocumentsProviderRootMap | 
|  | // for retrieving recent files and scanning ARC directories, respectively. The | 
|  | // `root_id` must be one of the know ARC root IDs, denoting Documents, Videos, | 
|  | // Images or Audio roots. | 
|  | RecentArcMediaSource(Profile* profile, const std::string& root_id); | 
|  |  | 
|  | RecentArcMediaSource(const RecentArcMediaSource&) = delete; | 
|  | RecentArcMediaSource& operator=(const RecentArcMediaSource&) = delete; | 
|  |  | 
|  | ~RecentArcMediaSource() override; | 
|  |  | 
|  | // Overrides the base class method to launch searches for recent file in the | 
|  | // root identified by the `root_id` parameter given at the construction time. | 
|  | void GetRecentFiles(const Params& params, | 
|  | GetRecentFilesCallback callback) override; | 
|  |  | 
|  | // Overrides the base class Stop method to return partial results collected | 
|  | // before the timeout call. This method must be called on the UI thread. | 
|  | std::vector<RecentFile> Stop(const int32_t call_id) override; | 
|  |  | 
|  | // Causes laggy performance for this source. This is to be only used in tests. | 
|  | void SetLagForTesting(const base::TimeDelta& lag); | 
|  |  | 
|  | // The name of the metric under which recent file access statistics for ARC | 
|  | // are recorded. | 
|  | static const char kLoadHistogramName[]; | 
|  |  | 
|  | private: | 
|  | // Call context stores information specific to a single GetRecentFiles call. | 
|  | // If multiple calls are issued each will have its own context. | 
|  | struct CallContext { | 
|  | CallContext(const Params& params, GetRecentFilesCallback callback); | 
|  | // Move constructor needed as callback cannot be copied. | 
|  | CallContext(CallContext&& context); | 
|  | ~CallContext(); | 
|  |  | 
|  | // The parameters of the GetRecentFiles call. | 
|  | const Params params; | 
|  |  | 
|  | // The callback to be called once all files are gathered. We do not know | 
|  | // ahead of time when this may be the case, due to nested directories. | 
|  | // Thus this class behaves similarly to a Barrier class, except that the | 
|  | // number of times the barrier has to be called varies. | 
|  | GetRecentFilesCallback callback; | 
|  |  | 
|  | // Time when this call started. | 
|  | base::TimeTicks build_start_time; | 
|  |  | 
|  | // Number of in-flight ReadDirectory() calls by ScanDirectory(). | 
|  | int num_inflight_readdirs = 0; | 
|  |  | 
|  | // Maps a document ID to a RecentFile. In OnGotRecentDocuments(), this map | 
|  | // is initialized with document IDs returned by GetRecentDocuments(), and | 
|  | // its values are filled as we scan the tree in ScanDirectory(). | 
|  | // In case of multiple files with the same document ID found, the file with | 
|  | // lexicographically smallest URL is kept. A nullopt value means the | 
|  | // corresponding file is not (yet) found. | 
|  | std::map<std::string, std::optional<RecentFile>> document_id_to_file; | 
|  | }; | 
|  |  | 
|  | // Returns whether or not this scanner supports files with the given type. | 
|  | bool MatchesFileType(FileType file_type) const; | 
|  |  | 
|  | // Extra method that allows us to insert an optional lag between the runner | 
|  | // being done and the OnGotRecentDocuments being called. | 
|  | void OnRunnerDone( | 
|  | const int32_t call_id, | 
|  | std::optional<std::vector<arc::mojom::DocumentPtr>> maybe_documents); | 
|  |  | 
|  | // The method called once recent document pointers have been retrieved. This | 
|  | // may take place immediately after the runner was done, or with a small lag | 
|  | // that helps testing the interaction with the Stop method. | 
|  | void OnGotRecentDocuments( | 
|  | const int32_t call_id, | 
|  | std::optional<std::vector<arc::mojom::DocumentPtr>> maybe_documents); | 
|  |  | 
|  | // Starts scanning of the directory with the given path. | 
|  | void ScanDirectory(const int32_t call_id, const base::FilePath& path); | 
|  |  | 
|  | // The method called once a scan of directory is completed. | 
|  | void OnDirectoryRead( | 
|  | const int32_t call_id, | 
|  | const base::FilePath& path, | 
|  | base::File::Error result, | 
|  | std::vector<arc::ArcDocumentsProviderRoot::ThinFileInfo> files); | 
|  |  | 
|  | // Invoked once traversing of the directory hirerachy is finished. | 
|  | void OnComplete(const int32_t call_id); | 
|  |  | 
|  | // Creates a complete FileSystemURL for the given `path`, with the | 
|  | // help of `relative_mount_path_`. | 
|  | storage::FileSystemURL BuildDocumentsProviderUrl( | 
|  | const Params& params, | 
|  | const base::FilePath& path) const; | 
|  |  | 
|  | bool WillArcFileSystemOperationsRunImmediately(); | 
|  |  | 
|  | // A map from the call ID to the call context. | 
|  | base::IDMap<std::unique_ptr<CallContext>> context_map_; | 
|  |  | 
|  | // The profile for which this recent source was created. | 
|  | const raw_ptr<Profile> profile_; | 
|  |  | 
|  | // The ARC root, such as Documents, Images, Media or Audio. | 
|  | const std::string root_id_; | 
|  |  | 
|  | // The path at which the given ARC system is mounted. | 
|  | const base::FilePath relative_mount_path_; | 
|  |  | 
|  | // The artificial lag introduced to this root for test purposes. | 
|  | base::TimeDelta lag_; | 
|  |  | 
|  | // Timer; only allocated if the lag is positive. | 
|  | std::unique_ptr<base::OneShotTimer> timer_; | 
|  |  | 
|  | base::WeakPtrFactory<RecentArcMediaSource> weak_ptr_factory_{this}; | 
|  | }; | 
|  |  | 
|  | }  // namespace ash | 
|  |  | 
|  | #endif  // CHROME_BROWSER_ASH_FILEAPI_RECENT_ARC_MEDIA_SOURCE_H_ |