| 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 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h" | 5 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 extension) == possible_extensions.end()) { | 58 extension) == possible_extensions.end()) { |
| 59 filename = | 59 filename = |
| 60 base::FilePath(filename).AddExtension(possible_extensions[0]).value(); | 60 base::FilePath(filename).AddExtension(possible_extensions[0]).value(); |
| 61 } | 61 } |
| 62 | 62 |
| 63 return filename; | 63 return filename; |
| 64 } | 64 } |
| 65 | 65 |
| 66 } // namespace | 66 } // namespace |
| 67 | 67 |
| 68 // static |
| 69 const int64_t ArcDocumentsProviderRoot::kInvalidWatcherId = -1; |
| 70 // static |
| 71 const uint64_t ArcDocumentsProviderRoot::kInvalidWatcherRequestId = 0; |
| 72 // static |
| 73 const ArcDocumentsProviderRoot::WatcherData |
| 74 ArcDocumentsProviderRoot::kInvalidWatcherData = {kInvalidWatcherId, |
| 75 kInvalidWatcherRequestId}; |
| 76 |
| 68 ArcDocumentsProviderRoot::ArcDocumentsProviderRoot( | 77 ArcDocumentsProviderRoot::ArcDocumentsProviderRoot( |
| 69 const std::string& authority, | 78 const std::string& authority, |
| 70 const std::string& root_document_id) | 79 const std::string& root_document_id) |
| 71 : authority_(authority), | 80 : authority_(authority), |
| 72 root_document_id_(root_document_id), | 81 root_document_id_(root_document_id), |
| 73 weak_ptr_factory_(this) {} | 82 weak_ptr_factory_(this) {} |
| 74 | 83 |
| 75 ArcDocumentsProviderRoot::~ArcDocumentsProviderRoot() { | 84 ArcDocumentsProviderRoot::~ArcDocumentsProviderRoot() { |
| 76 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 85 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 77 if (observer_wrapper_) | 86 if (observer_wrapper_) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 95 ResolveToDocumentId( | 104 ResolveToDocumentId( |
| 96 path, base::Bind(&ArcDocumentsProviderRoot::ReadDirectoryWithDocumentId, | 105 path, base::Bind(&ArcDocumentsProviderRoot::ReadDirectoryWithDocumentId, |
| 97 weak_ptr_factory_.GetWeakPtr(), callback)); | 106 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 98 } | 107 } |
| 99 | 108 |
| 100 void ArcDocumentsProviderRoot::AddWatcher( | 109 void ArcDocumentsProviderRoot::AddWatcher( |
| 101 const base::FilePath& path, | 110 const base::FilePath& path, |
| 102 const WatcherCallback& watcher_callback, | 111 const WatcherCallback& watcher_callback, |
| 103 const StatusCallback& callback) { | 112 const StatusCallback& callback) { |
| 104 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 113 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 105 if (path_to_watcher_id_.count(path)) { | 114 if (path_to_watcher_data_.count(path)) { |
| 106 callback.Run(base::File::FILE_ERROR_FAILED); | 115 callback.Run(base::File::FILE_ERROR_FAILED); |
| 107 return; | 116 return; |
| 108 } | 117 } |
| 118 uint64_t watcher_request_id = next_watcher_request_id_++; |
| 119 path_to_watcher_data_.insert( |
| 120 std::make_pair(path, WatcherData{kInvalidWatcherId, watcher_request_id})); |
| 109 ResolveToDocumentId( | 121 ResolveToDocumentId( |
| 110 path, | 122 path, base::Bind(&ArcDocumentsProviderRoot::AddWatcherWithDocumentId, |
| 111 base::Bind(&ArcDocumentsProviderRoot::AddWatcherWithDocumentId, | 123 weak_ptr_factory_.GetWeakPtr(), path, watcher_request_id, |
| 112 weak_ptr_factory_.GetWeakPtr(), path, watcher_callback, | 124 watcher_callback)); |
| 113 callback)); | 125 |
| 126 // HACK: Invoke |callback| immediately. |
| 127 // |
| 128 // TODO(crbug.com/698624): Remove this hack. It was introduced because Files |
| 129 // app freezes until AddWatcher() finishes, but it should be handled in Files |
| 130 // app rather than here. |
| 131 callback.Run(base::File::FILE_OK); |
| 114 } | 132 } |
| 115 | 133 |
| 116 void ArcDocumentsProviderRoot::RemoveWatcher(const base::FilePath& path, | 134 void ArcDocumentsProviderRoot::RemoveWatcher(const base::FilePath& path, |
| 117 const StatusCallback& callback) { | 135 const StatusCallback& callback) { |
| 118 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 136 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 119 auto iter = path_to_watcher_id_.find(path); | 137 auto iter = path_to_watcher_data_.find(path); |
| 120 if (iter == path_to_watcher_id_.end()) { | 138 if (iter == path_to_watcher_data_.end()) { |
| 121 callback.Run(base::File::FILE_ERROR_FAILED); | 139 callback.Run(base::File::FILE_ERROR_FAILED); |
| 122 return; | 140 return; |
| 123 } | 141 } |
| 124 int64_t watcher_id = iter->second; | 142 int64_t watcher_id = iter->second.id; |
| 125 path_to_watcher_id_.erase(iter); | 143 path_to_watcher_data_.erase(iter); |
| 126 if (watcher_id < 0) { | 144 if (watcher_id == kInvalidWatcherId) { |
| 127 // This is an orphan watcher. Just remove an entry from | 145 // This is an invalid watcher. No need to send a request to the remote |
| 128 // |path_to_watcher_id_| and return success. | 146 // service. |
| 129 callback.Run(base::File::FILE_OK); | 147 callback.Run(base::File::FILE_OK); |
| 130 return; | 148 return; |
| 131 } | 149 } |
| 132 file_system_operation_runner_util::RemoveWatcherOnIOThread( | 150 file_system_operation_runner_util::RemoveWatcherOnIOThread( |
| 133 watcher_id, | 151 watcher_id, |
| 134 base::Bind(&ArcDocumentsProviderRoot::OnWatcherRemoved, | 152 base::Bind(&ArcDocumentsProviderRoot::OnWatcherRemoved, |
| 135 weak_ptr_factory_.GetWeakPtr(), callback)); | 153 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 136 } | 154 } |
| 137 | 155 |
| 138 void ArcDocumentsProviderRoot::ResolveToContentUrl( | 156 void ArcDocumentsProviderRoot::ResolveToContentUrl( |
| 139 const base::FilePath& path, | 157 const base::FilePath& path, |
| 140 const ResolveToContentUrlCallback& callback) { | 158 const ResolveToContentUrlCallback& callback) { |
| 141 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 159 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 142 ResolveToDocumentId( | 160 ResolveToDocumentId( |
| 143 path, | 161 path, |
| 144 base::Bind(&ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId, | 162 base::Bind(&ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId, |
| 145 weak_ptr_factory_.GetWeakPtr(), callback)); | 163 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 146 } | 164 } |
| 147 | 165 |
| 148 void ArcDocumentsProviderRoot::OnWatchersCleared() { | 166 void ArcDocumentsProviderRoot::OnWatchersCleared() { |
| 149 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 167 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 150 // Mark all watchers orphan. | 168 // Mark all watchers invalid. |
| 151 for (auto& entry : path_to_watcher_id_) | 169 for (auto& entry : path_to_watcher_data_) |
| 152 entry.second = -1; | 170 entry.second = kInvalidWatcherData; |
| 153 } | 171 } |
| 154 | 172 |
| 155 void ArcDocumentsProviderRoot::GetFileInfoWithDocumentId( | 173 void ArcDocumentsProviderRoot::GetFileInfoWithDocumentId( |
| 156 const GetFileInfoCallback& callback, | 174 const GetFileInfoCallback& callback, |
| 157 const std::string& document_id) { | 175 const std::string& document_id) { |
| 158 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 176 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 159 if (document_id.empty()) { | 177 if (document_id.empty()) { |
| 160 callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info()); | 178 callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info()); |
| 161 return; | 179 return; |
| 162 } | 180 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 for (const auto& pair : mapping) { | 243 for (const auto& pair : mapping) { |
| 226 entry_list.emplace_back(pair.first, pair.second.is_directory | 244 entry_list.emplace_back(pair.first, pair.second.is_directory |
| 227 ? storage::DirectoryEntry::DIRECTORY | 245 ? storage::DirectoryEntry::DIRECTORY |
| 228 : storage::DirectoryEntry::FILE); | 246 : storage::DirectoryEntry::FILE); |
| 229 } | 247 } |
| 230 callback.Run(base::File::FILE_OK, entry_list, false /* has_more */); | 248 callback.Run(base::File::FILE_OK, entry_list, false /* has_more */); |
| 231 } | 249 } |
| 232 | 250 |
| 233 void ArcDocumentsProviderRoot::AddWatcherWithDocumentId( | 251 void ArcDocumentsProviderRoot::AddWatcherWithDocumentId( |
| 234 const base::FilePath& path, | 252 const base::FilePath& path, |
| 253 uint64_t watcher_request_id, |
| 235 const WatcherCallback& watcher_callback, | 254 const WatcherCallback& watcher_callback, |
| 236 const StatusCallback& callback, | |
| 237 const std::string& document_id) { | 255 const std::string& document_id) { |
| 238 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 256 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 257 |
| 258 if (IsWatcherInflightRequestCanceled(path, watcher_request_id)) |
| 259 return; |
| 260 |
| 239 if (document_id.empty()) { | 261 if (document_id.empty()) { |
| 240 callback.Run(base::File::FILE_ERROR_NOT_FOUND); | 262 DCHECK(path_to_watcher_data_.count(path)); |
| 263 path_to_watcher_data_[path] = kInvalidWatcherData; |
| 241 return; | 264 return; |
| 242 } | 265 } |
| 266 |
| 243 // Start observing ArcFileSystemOperationRunner if we have not. | 267 // Start observing ArcFileSystemOperationRunner if we have not. |
| 244 if (!observer_wrapper_) { | 268 if (!observer_wrapper_) { |
| 245 observer_wrapper_ = | 269 observer_wrapper_ = |
| 246 new file_system_operation_runner_util::ObserverIOThreadWrapper(this); | 270 new file_system_operation_runner_util::ObserverIOThreadWrapper(this); |
| 247 file_system_operation_runner_util::AddObserverOnIOThread(observer_wrapper_); | 271 file_system_operation_runner_util::AddObserverOnIOThread(observer_wrapper_); |
| 248 } | 272 } |
| 273 |
| 249 file_system_operation_runner_util::AddWatcherOnIOThread( | 274 file_system_operation_runner_util::AddWatcherOnIOThread( |
| 250 authority_, document_id, watcher_callback, | 275 authority_, document_id, watcher_callback, |
| 251 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAdded, | 276 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAdded, |
| 252 weak_ptr_factory_.GetWeakPtr(), path, callback)); | 277 weak_ptr_factory_.GetWeakPtr(), path, watcher_request_id)); |
| 253 } | 278 } |
| 254 | 279 |
| 255 void ArcDocumentsProviderRoot::OnWatcherAdded(const base::FilePath& path, | 280 void ArcDocumentsProviderRoot::OnWatcherAdded(const base::FilePath& path, |
| 256 const StatusCallback& callback, | 281 uint64_t watcher_request_id, |
| 257 int64_t watcher_id) { | 282 int64_t watcher_id) { |
| 258 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 283 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 259 if (watcher_id < 0) { | 284 |
| 260 callback.Run(base::File::FILE_ERROR_FAILED); | 285 if (IsWatcherInflightRequestCanceled(path, watcher_request_id)) { |
| 261 return; | |
| 262 } | |
| 263 if (path_to_watcher_id_.count(path)) { | |
| 264 // Multiple watchers have been installed on the same file path in a race. | |
| 265 // Following the contract of WatcherManager, we reject all except the first. | |
| 266 file_system_operation_runner_util::RemoveWatcherOnIOThread( | 286 file_system_operation_runner_util::RemoveWatcherOnIOThread( |
| 267 watcher_id, | 287 watcher_id, |
| 268 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAddedButRemoved, | 288 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAddedButRemoved, |
| 269 weak_ptr_factory_.GetWeakPtr(), callback)); | 289 weak_ptr_factory_.GetWeakPtr())); |
| 270 return; | 290 return; |
| 271 } | 291 } |
| 272 path_to_watcher_id_.insert(std::make_pair(path, watcher_id)); | 292 |
| 273 callback.Run(base::File::FILE_OK); | 293 DCHECK(path_to_watcher_data_.count(path)); |
| 294 path_to_watcher_data_[path] = |
| 295 WatcherData{watcher_id < 0 ? kInvalidWatcherId : watcher_id, |
| 296 kInvalidWatcherRequestId}; |
| 274 } | 297 } |
| 275 | 298 |
| 276 void ArcDocumentsProviderRoot::OnWatcherAddedButRemoved( | 299 void ArcDocumentsProviderRoot::OnWatcherAddedButRemoved(bool success) { |
| 277 const StatusCallback& callback, | |
| 278 bool success) { | |
| 279 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 300 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 280 callback.Run(base::File::FILE_ERROR_FAILED); | 301 // Ignore |success|. |
| 281 } | 302 } |
| 282 | 303 |
| 283 void ArcDocumentsProviderRoot::OnWatcherRemoved(const StatusCallback& callback, | 304 void ArcDocumentsProviderRoot::OnWatcherRemoved(const StatusCallback& callback, |
| 284 bool success) { | 305 bool success) { |
| 285 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 306 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 286 callback.Run(success ? base::File::FILE_OK : base::File::FILE_ERROR_FAILED); | 307 callback.Run(success ? base::File::FILE_OK : base::File::FILE_ERROR_FAILED); |
| 287 } | 308 } |
| 288 | 309 |
| 310 bool ArcDocumentsProviderRoot::IsWatcherInflightRequestCanceled( |
| 311 const base::FilePath& path, |
| 312 uint64_t watcher_request_id) const { |
| 313 auto iter = path_to_watcher_data_.find(path); |
| 314 return (iter == path_to_watcher_data_.end() || |
| 315 iter->second.inflight_request_id != watcher_request_id); |
| 316 } |
| 317 |
| 289 void ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId( | 318 void ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId( |
| 290 const ResolveToContentUrlCallback& callback, | 319 const ResolveToContentUrlCallback& callback, |
| 291 const std::string& document_id) { | 320 const std::string& document_id) { |
| 292 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 321 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 293 if (document_id.empty()) { | 322 if (document_id.empty()) { |
| 294 callback.Run(GURL()); | 323 callback.Run(GURL()); |
| 295 return; | 324 return; |
| 296 } | 325 } |
| 297 callback.Run(BuildDocumentUrl(authority_, document_id)); | 326 callback.Run(BuildDocumentUrl(authority_, document_id)); |
| 298 } | 327 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 | 424 |
| 396 mapping[filename] = | 425 mapping[filename] = |
| 397 ThinDocument{document->document_id, | 426 ThinDocument{document->document_id, |
| 398 document->mime_type == kAndroidDirectoryMimeType}; | 427 document->mime_type == kAndroidDirectoryMimeType}; |
| 399 } | 428 } |
| 400 | 429 |
| 401 callback.Run(base::File::FILE_OK, std::move(mapping)); | 430 callback.Run(base::File::FILE_OK, std::move(mapping)); |
| 402 } | 431 } |
| 403 | 432 |
| 404 } // namespace arc | 433 } // namespace arc |
| OLD | NEW |