| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_DOCUMENTS_PROVIDER_ROOT_H_ | 5 #ifndef CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_DOCUMENTS_PROVIDER_ROOT_H_ |
| 6 #define CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_DOCUMENTS_PROVIDER_ROOT_H_ | 6 #define CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_DOCUMENTS_PROVIDER_ROOT_H_ |
| 7 | 7 |
| 8 #include <stdint.h> |
| 9 |
| 8 #include <map> | 10 #include <map> |
| 9 #include <string> | 11 #include <string> |
| 10 #include <vector> | 12 #include <vector> |
| 11 | 13 |
| 12 #include "base/callback_forward.h" | 14 #include "base/callback_forward.h" |
| 13 #include "base/files/file_path.h" | 15 #include "base/files/file_path.h" |
| 14 #include "base/macros.h" | 16 #include "base/macros.h" |
| 17 #include "base/memory/ref_counted.h" |
| 15 #include "base/memory/weak_ptr.h" | 18 #include "base/memory/weak_ptr.h" |
| 16 #include "base/optional.h" | 19 #include "base/optional.h" |
| 20 #include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h
" |
| 21 #include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_u
til.h" |
| 17 #include "components/arc/common/file_system.mojom.h" | 22 #include "components/arc/common/file_system.mojom.h" |
| 18 #include "storage/browser/fileapi/async_file_util.h" | 23 #include "storage/browser/fileapi/async_file_util.h" |
| 24 #include "storage/browser/fileapi/watcher_manager.h" |
| 19 | 25 |
| 20 class GURL; | 26 class GURL; |
| 21 | 27 |
| 22 namespace arc { | 28 namespace arc { |
| 23 | 29 |
| 24 // Represents a file system root in Android Documents Provider. | 30 // Represents a file system root in Android Documents Provider. |
| 25 // | 31 // |
| 26 // All methods must be called on the IO thread. | 32 // All methods must be called on the IO thread. |
| 27 // If this object is deleted while there are in-flight operations, callbacks | 33 // If this object is deleted while there are in-flight operations, callbacks |
| 28 // for those operations will be never called. | 34 // for those operations will be never called. |
| 29 class ArcDocumentsProviderRoot { | 35 class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer { |
| 30 public: | 36 public: |
| 31 using GetFileInfoCallback = storage::AsyncFileUtil::GetFileInfoCallback; | 37 using GetFileInfoCallback = storage::AsyncFileUtil::GetFileInfoCallback; |
| 32 using ReadDirectoryCallback = storage::AsyncFileUtil::ReadDirectoryCallback; | 38 using ReadDirectoryCallback = storage::AsyncFileUtil::ReadDirectoryCallback; |
| 39 using ChangeType = storage::WatcherManager::ChangeType; |
| 40 using WatcherCallback = base::Callback<void(ChangeType type)>; |
| 41 using StatusCallback = base::Callback<void(base::File::Error error)>; |
| 33 using ResolveToContentUrlCallback = | 42 using ResolveToContentUrlCallback = |
| 34 base::Callback<void(const GURL& content_url)>; | 43 base::Callback<void(const GURL& content_url)>; |
| 35 | 44 |
| 36 ArcDocumentsProviderRoot(const std::string& authority, | 45 ArcDocumentsProviderRoot(const std::string& authority, |
| 37 const std::string& root_document_id); | 46 const std::string& root_document_id); |
| 38 ~ArcDocumentsProviderRoot(); | 47 ~ArcDocumentsProviderRoot() override; |
| 39 | 48 |
| 40 // Queries information of a file just like AsyncFileUtil.GetFileInfo(). | 49 // Queries information of a file just like AsyncFileUtil.GetFileInfo(). |
| 41 void GetFileInfo(const base::FilePath& path, | 50 void GetFileInfo(const base::FilePath& path, |
| 42 const GetFileInfoCallback& callback); | 51 const GetFileInfoCallback& callback); |
| 43 | 52 |
| 44 // Queries a list of files under a directory just like | 53 // Queries a list of files under a directory just like |
| 45 // AsyncFileUtil.ReadDirectory(). | 54 // AsyncFileUtil.ReadDirectory(). |
| 46 void ReadDirectory(const base::FilePath& path, | 55 void ReadDirectory(const base::FilePath& path, |
| 47 const ReadDirectoryCallback& callback); | 56 const ReadDirectoryCallback& callback); |
| 48 | 57 |
| 58 // Installs a document watcher. |
| 59 // |
| 60 // It is not allowed to install multiple watchers at the same file path; |
| 61 // if attempted, duplicated requests will fail. |
| 62 // |
| 63 // Currently, watchers can be installed only on directories, and only |
| 64 // directory content changes are notified. The result of installing a watcher |
| 65 // to a non-directory in unspecified. |
| 66 // |
| 67 // NOTES ABOUT CORRECTNESS AND CONSISTENCY: |
| 68 // |
| 69 // Document watchers are not always correct and they may miss some updates or |
| 70 // even notify incorrect update events for several reasons, such as: |
| 71 // |
| 72 // - Directory moves: Currently a watcher will misbehave if the watched |
| 73 // directory is moved to another location. This is acceptable for now |
| 74 // since we whitelist MediaDocumentsProvider only. |
| 75 // - Duplicated file name handling in this class: The same reason as |
| 76 // directory moves. This may happen even with MediaDocumentsProvider, |
| 77 // but the chance will not be very high. |
| 78 // - File system operation races: For example, an watcher can be installed |
| 79 // to a non-directory in a race condition. |
| 80 // - Broken DocumentsProviders: For example, we get no notification if a |
| 81 // document provider does not call setNotificationUri(). |
| 82 // |
| 83 // However, consistency of installed watchers is guaranteed. That is, after |
| 84 // a watcher is installed on a file path X, an attempt to uninstall a watcher |
| 85 // at X will always succeed. |
| 86 // |
| 87 // Unfortunately it is too difficult (or maybe theoretically impossible) to |
| 88 // implement a perfect Android document watcher which never misses document |
| 89 // updates. So the current implementation gives up correctness, but instead |
| 90 // focuses on following two goals: |
| 91 // |
| 92 // 1. Keep the implementation simple, rather than trying hard to catch |
| 93 // race conditions or minor cases. Even if we return wrong results, the |
| 94 // worst consequence is just that users do not see the latest contents |
| 95 // until they refresh UI. |
| 96 // |
| 97 // 2. Keep consistency of installed watchers so that the caller can avoid |
| 98 // dangling watchers. |
| 99 void AddWatcher(const base::FilePath& path, |
| 100 const WatcherCallback& watcher_callback, |
| 101 const StatusCallback& callback); |
| 102 |
| 103 // Uninstalls a document watcher. |
| 104 // See the documentation of AddWatcher() above. |
| 105 void RemoveWatcher(const base::FilePath& path, |
| 106 const StatusCallback& callback); |
| 107 |
| 49 // Resolves a file path into a content:// URL pointing to the file | 108 // Resolves a file path into a content:// URL pointing to the file |
| 50 // on DocumentsProvider. Returns URL that can be passed to | 109 // on DocumentsProvider. Returns URL that can be passed to |
| 51 // ArcContentFileSystemFileSystemReader to read the content. | 110 // ArcContentFileSystemFileSystemReader to read the content. |
| 52 // On errors, an invalid GURL is returned. | 111 // On errors, an invalid GURL is returned. |
| 53 void ResolveToContentUrl(const base::FilePath& path, | 112 void ResolveToContentUrl(const base::FilePath& path, |
| 54 const ResolveToContentUrlCallback& callback); | 113 const ResolveToContentUrlCallback& callback); |
| 55 | 114 |
| 115 // ArcFileSystemOperationRunner::Observer overrides: |
| 116 void OnWatchersCleared() override; |
| 117 |
| 56 private: | 118 private: |
| 57 // Thin representation of a document in documents provider. | 119 // Thin representation of a document in documents provider. |
| 58 struct ThinDocument { | 120 struct ThinDocument { |
| 59 std::string document_id; | 121 std::string document_id; |
| 60 bool is_directory; | 122 bool is_directory; |
| 61 }; | 123 }; |
| 62 | 124 |
| 63 // Mapping from a file name to a ThinDocument. | 125 // Mapping from a file name to a ThinDocument. |
| 64 using NameToThinDocumentMap = | 126 using NameToThinDocumentMap = |
| 65 std::map<base::FilePath::StringType, ThinDocument>; | 127 std::map<base::FilePath::StringType, ThinDocument>; |
| 66 | 128 |
| 67 using ResolveToDocumentIdCallback = | 129 using ResolveToDocumentIdCallback = |
| 68 base::Callback<void(const std::string& document_id)>; | 130 base::Callback<void(const std::string& document_id)>; |
| 69 using ReadDirectoryInternalCallback = | 131 using ReadDirectoryInternalCallback = |
| 70 base::Callback<void(base::File::Error error, | 132 base::Callback<void(base::File::Error error, |
| 71 NameToThinDocumentMap mapping)>; | 133 NameToThinDocumentMap mapping)>; |
| 72 | 134 |
| 73 void GetFileInfoWithDocumentId(const GetFileInfoCallback& callback, | 135 void GetFileInfoWithDocumentId(const GetFileInfoCallback& callback, |
| 74 const std::string& document_id); | 136 const std::string& document_id); |
| 75 void GetFileInfoWithDocument(const GetFileInfoCallback& callback, | 137 void GetFileInfoWithDocument(const GetFileInfoCallback& callback, |
| 76 mojom::DocumentPtr document); | 138 mojom::DocumentPtr document); |
| 77 | 139 |
| 78 void ReadDirectoryWithDocumentId(const ReadDirectoryCallback& callback, | 140 void ReadDirectoryWithDocumentId(const ReadDirectoryCallback& callback, |
| 79 const std::string& document_id); | 141 const std::string& document_id); |
| 80 void ReadDirectoryWithNameToThinDocumentMap( | 142 void ReadDirectoryWithNameToThinDocumentMap( |
| 81 const ReadDirectoryCallback& callback, | 143 const ReadDirectoryCallback& callback, |
| 82 base::File::Error error, | 144 base::File::Error error, |
| 83 NameToThinDocumentMap mapping); | 145 NameToThinDocumentMap mapping); |
| 84 | 146 |
| 147 void AddWatcherWithDocumentId(const base::FilePath& path, |
| 148 const WatcherCallback& watcher_callback, |
| 149 const StatusCallback& callback, |
| 150 const std::string& document_id); |
| 151 void OnWatcherAdded(const base::FilePath& path, |
| 152 const StatusCallback& callback, |
| 153 int64_t watcher_id); |
| 154 void OnWatcherAddedButRemoved(const StatusCallback& callback, bool success); |
| 155 |
| 156 void OnWatcherRemoved(const StatusCallback& callback, bool success); |
| 157 |
| 85 void ResolveToContentUrlWithDocumentId( | 158 void ResolveToContentUrlWithDocumentId( |
| 86 const ResolveToContentUrlCallback& callback, | 159 const ResolveToContentUrlCallback& callback, |
| 87 const std::string& document_id); | 160 const std::string& document_id); |
| 88 | 161 |
| 89 // Resolves |path| to a document ID. Failures are indicated by an empty | 162 // Resolves |path| to a document ID. Failures are indicated by an empty |
| 90 // document ID. | 163 // document ID. |
| 91 void ResolveToDocumentId(const base::FilePath& path, | 164 void ResolveToDocumentId(const base::FilePath& path, |
| 92 const ResolveToDocumentIdCallback& callback); | 165 const ResolveToDocumentIdCallback& callback); |
| 93 void ResolveToDocumentIdRecursively( | 166 void ResolveToDocumentIdRecursively( |
| 94 const std::string& document_id, | 167 const std::string& document_id, |
| 95 const std::vector<base::FilePath::StringType>& components, | 168 const std::vector<base::FilePath::StringType>& components, |
| 96 const ResolveToDocumentIdCallback& callback); | 169 const ResolveToDocumentIdCallback& callback); |
| 97 void ResolveToDocumentIdRecursivelyWithNameToThinDocumentMap( | 170 void ResolveToDocumentIdRecursivelyWithNameToThinDocumentMap( |
| 98 const std::vector<base::FilePath::StringType>& components, | 171 const std::vector<base::FilePath::StringType>& components, |
| 99 const ResolveToDocumentIdCallback& callback, | 172 const ResolveToDocumentIdCallback& callback, |
| 100 base::File::Error error, | 173 base::File::Error error, |
| 101 NameToThinDocumentMap mapping); | 174 NameToThinDocumentMap mapping); |
| 102 | 175 |
| 103 // Enumerates child documents of a directory specified by |document_id|. | 176 // Enumerates child documents of a directory specified by |document_id|. |
| 104 // The result is returned as a NameToThinDocumentMap. | 177 // The result is returned as a NameToThinDocumentMap. |
| 105 void ReadDirectoryInternal(const std::string& document_id, | 178 void ReadDirectoryInternal(const std::string& document_id, |
| 106 const ReadDirectoryInternalCallback& callback); | 179 const ReadDirectoryInternalCallback& callback); |
| 107 void ReadDirectoryInternalWithChildDocuments( | 180 void ReadDirectoryInternalWithChildDocuments( |
| 108 const ReadDirectoryInternalCallback& callback, | 181 const ReadDirectoryInternalCallback& callback, |
| 109 base::Optional<std::vector<mojom::DocumentPtr>> maybe_children); | 182 base::Optional<std::vector<mojom::DocumentPtr>> maybe_children); |
| 110 | 183 |
| 111 const std::string authority_; | 184 const std::string authority_; |
| 112 const std::string root_document_id_; | 185 const std::string root_document_id_; |
| 186 |
| 187 // Map from a file path to a watcher ID. |
| 188 // |
| 189 // A watcher can be "orphan" when watchers are cleared as notified by |
| 190 // OnWatchersCleared() callback. Such watchers are still tracked here, |
| 191 // but they are not known by the remote service, so they are represented |
| 192 // by the invalid watcher ID (-1). |
| 193 // |
| 194 // Note that we do not use a document ID as a key here to guarantee that |
| 195 // a watch installed by AddWatcher() can be always identified in |
| 196 // RemoveWatcher() with the same file path specified. |
| 197 // See the documentation of AddWatcher() for more details. |
| 198 std::map<base::FilePath, int64_t> path_to_watcher_id_; |
| 199 |
| 200 // Can be null if this instance is not observing ArcFileSystemOperationRunner. |
| 201 // Observation is started on the first call of AddWatcher(). |
| 202 scoped_refptr<file_system_operation_runner_util::ObserverIOThreadWrapper> |
| 203 observer_wrapper_; |
| 204 |
| 113 base::WeakPtrFactory<ArcDocumentsProviderRoot> weak_ptr_factory_; | 205 base::WeakPtrFactory<ArcDocumentsProviderRoot> weak_ptr_factory_; |
| 114 | 206 |
| 115 DISALLOW_COPY_AND_ASSIGN(ArcDocumentsProviderRoot); | 207 DISALLOW_COPY_AND_ASSIGN(ArcDocumentsProviderRoot); |
| 116 }; | 208 }; |
| 117 | 209 |
| 118 } // namespace arc | 210 } // namespace arc |
| 119 | 211 |
| 120 #endif // CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_DOCUMENTS_PROVIDER_ROOT_H_ | 212 #endif // CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_DOCUMENTS_PROVIDER_ROOT_H_ |
| OLD | NEW |