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