Chromium Code Reviews| 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 if (iter->second.inflight_request_id != kInvalidWatcherRequestId) { |
|
hidehiko
2017/03/14 16:56:13
I do not think you need individual condition here.
Shuhei Takahashi
2017/03/14 18:36:50
I agree.
| |
| 125 path_to_watcher_id_.erase(iter); | 143 // There is an in-flight request. Remove the entry to cancel it. |
| 126 if (watcher_id < 0) { | 144 path_to_watcher_data_.erase(iter); |
| 127 // This is an orphan watcher. Just remove an entry from | |
| 128 // |path_to_watcher_id_| and return success. | |
| 129 callback.Run(base::File::FILE_OK); | 145 callback.Run(base::File::FILE_OK); |
| 130 return; | 146 return; |
| 131 } | 147 } |
| 148 int64_t watcher_id = iter->second.id; | |
| 149 path_to_watcher_data_.erase(iter); | |
| 150 if (watcher_id == kInvalidWatcherId) { | |
| 151 // This is an invalid watcher. No need to send a request to the remote | |
| 152 // service. | |
| 153 callback.Run(base::File::FILE_OK); | |
| 154 return; | |
| 155 } | |
| 132 file_system_operation_runner_util::RemoveWatcherOnIOThread( | 156 file_system_operation_runner_util::RemoveWatcherOnIOThread( |
| 133 watcher_id, | 157 watcher_id, |
| 134 base::Bind(&ArcDocumentsProviderRoot::OnWatcherRemoved, | 158 base::Bind(&ArcDocumentsProviderRoot::OnWatcherRemoved, |
| 135 weak_ptr_factory_.GetWeakPtr(), callback)); | 159 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 136 } | 160 } |
| 137 | 161 |
| 138 void ArcDocumentsProviderRoot::ResolveToContentUrl( | 162 void ArcDocumentsProviderRoot::ResolveToContentUrl( |
| 139 const base::FilePath& path, | 163 const base::FilePath& path, |
| 140 const ResolveToContentUrlCallback& callback) { | 164 const ResolveToContentUrlCallback& callback) { |
| 141 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 165 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 142 ResolveToDocumentId( | 166 ResolveToDocumentId( |
| 143 path, | 167 path, |
| 144 base::Bind(&ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId, | 168 base::Bind(&ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId, |
| 145 weak_ptr_factory_.GetWeakPtr(), callback)); | 169 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 146 } | 170 } |
| 147 | 171 |
| 148 void ArcDocumentsProviderRoot::OnWatchersCleared() { | 172 void ArcDocumentsProviderRoot::OnWatchersCleared() { |
| 149 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 173 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 150 // Mark all watchers orphan. | 174 // Mark all watchers invalid. |
| 151 for (auto& entry : path_to_watcher_id_) | 175 for (auto& entry : path_to_watcher_data_) |
| 152 entry.second = -1; | 176 entry.second = kInvalidWatcherData; |
| 153 } | 177 } |
| 154 | 178 |
| 155 void ArcDocumentsProviderRoot::GetFileInfoWithDocumentId( | 179 void ArcDocumentsProviderRoot::GetFileInfoWithDocumentId( |
| 156 const GetFileInfoCallback& callback, | 180 const GetFileInfoCallback& callback, |
| 157 const std::string& document_id) { | 181 const std::string& document_id) { |
| 158 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 182 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 159 if (document_id.empty()) { | 183 if (document_id.empty()) { |
| 160 callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info()); | 184 callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info()); |
| 161 return; | 185 return; |
| 162 } | 186 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 for (const auto& pair : mapping) { | 249 for (const auto& pair : mapping) { |
| 226 entry_list.emplace_back(pair.first, pair.second.is_directory | 250 entry_list.emplace_back(pair.first, pair.second.is_directory |
| 227 ? storage::DirectoryEntry::DIRECTORY | 251 ? storage::DirectoryEntry::DIRECTORY |
| 228 : storage::DirectoryEntry::FILE); | 252 : storage::DirectoryEntry::FILE); |
| 229 } | 253 } |
| 230 callback.Run(base::File::FILE_OK, entry_list, false /* has_more */); | 254 callback.Run(base::File::FILE_OK, entry_list, false /* has_more */); |
| 231 } | 255 } |
| 232 | 256 |
| 233 void ArcDocumentsProviderRoot::AddWatcherWithDocumentId( | 257 void ArcDocumentsProviderRoot::AddWatcherWithDocumentId( |
| 234 const base::FilePath& path, | 258 const base::FilePath& path, |
| 259 uint64_t watcher_request_id, | |
| 235 const WatcherCallback& watcher_callback, | 260 const WatcherCallback& watcher_callback, |
| 236 const StatusCallback& callback, | |
| 237 const std::string& document_id) { | 261 const std::string& document_id) { |
| 238 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 262 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 263 | |
| 264 if (IsWatcherInflightRequestCanceled(path, watcher_request_id)) | |
| 265 return; | |
| 266 | |
| 239 if (document_id.empty()) { | 267 if (document_id.empty()) { |
| 240 callback.Run(base::File::FILE_ERROR_NOT_FOUND); | 268 DCHECK(path_to_watcher_data_.count(path)); |
| 269 path_to_watcher_data_[path] = kInvalidWatcherData; | |
| 241 return; | 270 return; |
| 242 } | 271 } |
| 272 | |
| 243 // Start observing ArcFileSystemOperationRunner if we have not. | 273 // Start observing ArcFileSystemOperationRunner if we have not. |
| 244 if (!observer_wrapper_) { | 274 if (!observer_wrapper_) { |
| 245 observer_wrapper_ = | 275 observer_wrapper_ = |
| 246 new file_system_operation_runner_util::ObserverIOThreadWrapper(this); | 276 new file_system_operation_runner_util::ObserverIOThreadWrapper(this); |
| 247 file_system_operation_runner_util::AddObserverOnIOThread(observer_wrapper_); | 277 file_system_operation_runner_util::AddObserverOnIOThread(observer_wrapper_); |
| 248 } | 278 } |
| 279 | |
| 249 file_system_operation_runner_util::AddWatcherOnIOThread( | 280 file_system_operation_runner_util::AddWatcherOnIOThread( |
| 250 authority_, document_id, watcher_callback, | 281 authority_, document_id, watcher_callback, |
| 251 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAdded, | 282 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAdded, |
| 252 weak_ptr_factory_.GetWeakPtr(), path, callback)); | 283 weak_ptr_factory_.GetWeakPtr(), path, watcher_request_id)); |
| 253 } | 284 } |
| 254 | 285 |
| 255 void ArcDocumentsProviderRoot::OnWatcherAdded(const base::FilePath& path, | 286 void ArcDocumentsProviderRoot::OnWatcherAdded(const base::FilePath& path, |
| 256 const StatusCallback& callback, | 287 uint64_t watcher_request_id, |
| 257 int64_t watcher_id) { | 288 int64_t watcher_id) { |
| 258 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 289 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 259 if (watcher_id < 0) { | 290 |
| 260 callback.Run(base::File::FILE_ERROR_FAILED); | 291 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( | 292 file_system_operation_runner_util::RemoveWatcherOnIOThread( |
| 267 watcher_id, | 293 watcher_id, |
| 268 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAddedButRemoved, | 294 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAddedButRemoved, |
| 269 weak_ptr_factory_.GetWeakPtr(), callback)); | 295 weak_ptr_factory_.GetWeakPtr())); |
| 270 return; | 296 return; |
| 271 } | 297 } |
| 272 path_to_watcher_id_.insert(std::make_pair(path, watcher_id)); | 298 |
| 273 callback.Run(base::File::FILE_OK); | 299 DCHECK(path_to_watcher_data_.count(path)); |
| 300 path_to_watcher_data_[path] = | |
| 301 WatcherData{watcher_id < 0 ? kInvalidWatcherId : watcher_id, | |
| 302 kInvalidWatcherRequestId}; | |
| 274 } | 303 } |
| 275 | 304 |
| 276 void ArcDocumentsProviderRoot::OnWatcherAddedButRemoved( | 305 void ArcDocumentsProviderRoot::OnWatcherAddedButRemoved(bool success) { |
| 277 const StatusCallback& callback, | |
| 278 bool success) { | |
| 279 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 306 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 280 callback.Run(base::File::FILE_ERROR_FAILED); | 307 // Ignore |success|. |
| 281 } | 308 } |
| 282 | 309 |
| 283 void ArcDocumentsProviderRoot::OnWatcherRemoved(const StatusCallback& callback, | 310 void ArcDocumentsProviderRoot::OnWatcherRemoved(const StatusCallback& callback, |
| 284 bool success) { | 311 bool success) { |
| 285 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 312 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 286 callback.Run(success ? base::File::FILE_OK : base::File::FILE_ERROR_FAILED); | 313 callback.Run(success ? base::File::FILE_OK : base::File::FILE_ERROR_FAILED); |
| 287 } | 314 } |
| 288 | 315 |
| 316 bool ArcDocumentsProviderRoot::IsWatcherInflightRequestCanceled( | |
| 317 const base::FilePath& path, | |
| 318 uint64_t watcher_request_id) const { | |
| 319 auto iter = path_to_watcher_data_.find(path); | |
| 320 return (iter == path_to_watcher_data_.end() || | |
| 321 iter->second.inflight_request_id != watcher_request_id); | |
| 322 } | |
| 323 | |
| 289 void ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId( | 324 void ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId( |
| 290 const ResolveToContentUrlCallback& callback, | 325 const ResolveToContentUrlCallback& callback, |
| 291 const std::string& document_id) { | 326 const std::string& document_id) { |
| 292 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 327 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 293 if (document_id.empty()) { | 328 if (document_id.empty()) { |
| 294 callback.Run(GURL()); | 329 callback.Run(GURL()); |
| 295 return; | 330 return; |
| 296 } | 331 } |
| 297 callback.Run(BuildDocumentUrl(authority_, document_id)); | 332 callback.Run(BuildDocumentUrl(authority_, document_id)); |
| 298 } | 333 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 395 | 430 |
| 396 mapping[filename] = | 431 mapping[filename] = |
| 397 ThinDocument{document->document_id, | 432 ThinDocument{document->document_id, |
| 398 document->mime_type == kAndroidDirectoryMimeType}; | 433 document->mime_type == kAndroidDirectoryMimeType}; |
| 399 } | 434 } |
| 400 | 435 |
| 401 callback.Run(base::File::FILE_OK, std::move(mapping)); | 436 callback.Run(base::File::FILE_OK, std::move(mapping)); |
| 402 } | 437 } |
| 403 | 438 |
| 404 } // namespace arc | 439 } // namespace arc |
| OLD | NEW |