Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.cc

Issue 2726373002: mediaview: Hack to avoid Files app to freeze soon after login. (Closed)
Patch Set: Assign ID to watcher requests. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/files/file.h" 12 #include "base/files/file.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
15 #include "base/strings/string_util.h" 15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
17 #include "base/time/time.h" 17 #include "base/time/time.h"
18 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h" 18 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h"
19 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
20 #include "url/gurl.h" 20 #include "url/gurl.h"
21 21
22 using content::BrowserThread; 22 using content::BrowserThread;
23 using EntryList = storage::AsyncFileUtil::EntryList; 23 using EntryList = storage::AsyncFileUtil::EntryList;
24 24
25 namespace arc { 25 namespace arc {
26 26
27 namespace { 27 namespace {
28 28
29 // A special watcher ID indicating this watcher is orphaned.
30 // Though we have an entry in ArcDocumentsProviderRoot, the remote
31 // ArcFileSystemService does not have a corresponding watcher. This happens
32 // when, for example, AddWatcher() is called for non-existent files or the
33 // remote service crashes.
34 // We use this value to allow RemoveWatcher() to succeed even after the remote
35 // service forgets watchers.
36 constexpr int64_t kOrphanWatcherId = -1;
37
29 // Computes a file name for a document. 38 // Computes a file name for a document.
30 // TODO(crbug.com/675868): Consolidate with the similar logic for Drive. 39 // TODO(crbug.com/675868): Consolidate with the similar logic for Drive.
31 base::FilePath::StringType GetFileNameForDocument( 40 base::FilePath::StringType GetFileNameForDocument(
32 const mojom::DocumentPtr& document) { 41 const mojom::DocumentPtr& document) {
33 base::FilePath::StringType filename = document->display_name; 42 base::FilePath::StringType filename = document->display_name;
34 43
35 // Replace path separators appearing in the file name. 44 // Replace path separators appearing in the file name.
36 // Chrome OS is POSIX and kSeparators is "/". 45 // Chrome OS is POSIX and kSeparators is "/".
37 base::ReplaceChars(filename, base::FilePath::kSeparators, "_", &filename); 46 base::ReplaceChars(filename, base::FilePath::kSeparators, "_", &filename);
38 47
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
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_id_.count(path) ||
115 path_to_watcher_request_id_.count(path)) {
106 callback.Run(base::File::FILE_ERROR_FAILED); 116 callback.Run(base::File::FILE_ERROR_FAILED);
107 return; 117 return;
108 } 118 }
119 uint64_t watcher_request_id = next_watcher_request_id_++;
120 path_to_watcher_request_id_.insert(std::make_pair(path, 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);
137 auto iter_request = path_to_watcher_request_id_.find(path);
138 if (iter_request != path_to_watcher_request_id_.end()) {
139 path_to_watcher_request_id_.erase(iter_request);
140 callback.Run(base::File::FILE_OK);
141 return;
142 }
119 auto iter = path_to_watcher_id_.find(path); 143 auto iter = path_to_watcher_id_.find(path);
120 if (iter == path_to_watcher_id_.end()) { 144 if (iter == path_to_watcher_id_.end()) {
121 callback.Run(base::File::FILE_ERROR_FAILED); 145 callback.Run(base::File::FILE_ERROR_FAILED);
122 return; 146 return;
123 } 147 }
124 int64_t watcher_id = iter->second; 148 int64_t watcher_id = iter->second;
125 path_to_watcher_id_.erase(iter); 149 path_to_watcher_id_.erase(iter);
126 if (watcher_id < 0) { 150 if (watcher_id < 0) {
127 // This is an orphan watcher. Just remove an entry from 151 // This is an orphan watcher. Just remove an entry from
128 // |path_to_watcher_id_| and return success. 152 // |path_to_watcher_id_| and return success.
(...skipping 13 matching lines...) Expand all
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 orphan.
151 for (auto& entry : path_to_watcher_id_) 175 for (auto& entry : path_to_watcher_id_)
152 entry.second = -1; 176 entry.second = kOrphanWatcherId;
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
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 (IsWatcherRequestCanceled(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_id_.count(path));
269 path_to_watcher_id_.insert(std::make_pair(path, kOrphanWatcherId));
270 path_to_watcher_request_id_.erase(path);
241 return; 271 return;
242 } 272 }
273
243 // Start observing ArcFileSystemOperationRunner if we have not. 274 // Start observing ArcFileSystemOperationRunner if we have not.
244 if (!observer_wrapper_) { 275 if (!observer_wrapper_) {
245 observer_wrapper_ = 276 observer_wrapper_ =
246 new file_system_operation_runner_util::ObserverIOThreadWrapper(this); 277 new file_system_operation_runner_util::ObserverIOThreadWrapper(this);
247 file_system_operation_runner_util::AddObserverOnIOThread(observer_wrapper_); 278 file_system_operation_runner_util::AddObserverOnIOThread(observer_wrapper_);
248 } 279 }
280
249 file_system_operation_runner_util::AddWatcherOnIOThread( 281 file_system_operation_runner_util::AddWatcherOnIOThread(
250 authority_, document_id, watcher_callback, 282 authority_, document_id, watcher_callback,
251 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAdded, 283 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAdded,
252 weak_ptr_factory_.GetWeakPtr(), path, callback)); 284 weak_ptr_factory_.GetWeakPtr(), path, watcher_request_id));
253 } 285 }
254 286
255 void ArcDocumentsProviderRoot::OnWatcherAdded(const base::FilePath& path, 287 void ArcDocumentsProviderRoot::OnWatcherAdded(const base::FilePath& path,
256 const StatusCallback& callback, 288 uint64_t watcher_request_id,
257 int64_t watcher_id) { 289 int64_t watcher_id) {
258 DCHECK_CURRENTLY_ON(BrowserThread::IO); 290 DCHECK_CURRENTLY_ON(BrowserThread::IO);
259 if (watcher_id < 0) { 291
260 callback.Run(base::File::FILE_ERROR_FAILED); 292 if (IsWatcherRequestCanceled(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( 293 file_system_operation_runner_util::RemoveWatcherOnIOThread(
267 watcher_id, 294 watcher_id,
268 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAddedButRemoved, 295 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAddedButRemoved,
269 weak_ptr_factory_.GetWeakPtr(), callback)); 296 weak_ptr_factory_.GetWeakPtr()));
270 return; 297 return;
271 } 298 }
272 path_to_watcher_id_.insert(std::make_pair(path, watcher_id)); 299
273 callback.Run(base::File::FILE_OK); 300 DCHECK(!path_to_watcher_id_.count(path));
301 path_to_watcher_id_.insert(
302 std::make_pair(path, watcher_id < 0 ? kOrphanWatcherId : watcher_id));
303 path_to_watcher_request_id_.erase(path);
274 } 304 }
275 305
276 void ArcDocumentsProviderRoot::OnWatcherAddedButRemoved( 306 void ArcDocumentsProviderRoot::OnWatcherAddedButRemoved(bool success) {
277 const StatusCallback& callback,
278 bool success) {
279 DCHECK_CURRENTLY_ON(BrowserThread::IO); 307 DCHECK_CURRENTLY_ON(BrowserThread::IO);
280 callback.Run(base::File::FILE_ERROR_FAILED); 308 // Ignore |success|.
281 } 309 }
282 310
283 void ArcDocumentsProviderRoot::OnWatcherRemoved(const StatusCallback& callback, 311 void ArcDocumentsProviderRoot::OnWatcherRemoved(const StatusCallback& callback,
284 bool success) { 312 bool success) {
285 DCHECK_CURRENTLY_ON(BrowserThread::IO); 313 DCHECK_CURRENTLY_ON(BrowserThread::IO);
286 callback.Run(success ? base::File::FILE_OK : base::File::FILE_ERROR_FAILED); 314 callback.Run(success ? base::File::FILE_OK : base::File::FILE_ERROR_FAILED);
287 } 315 }
288 316
317 bool ArcDocumentsProviderRoot::IsWatcherRequestCanceled(
318 const base::FilePath& path,
319 uint64_t watcher_request_id) {
320 auto iter = path_to_watcher_request_id_.find(path);
321 return (iter == path_to_watcher_request_id_.end() ||
322 iter->second != watcher_request_id);
323 }
324
289 void ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId( 325 void ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId(
290 const ResolveToContentUrlCallback& callback, 326 const ResolveToContentUrlCallback& callback,
291 const std::string& document_id) { 327 const std::string& document_id) {
292 DCHECK_CURRENTLY_ON(BrowserThread::IO); 328 DCHECK_CURRENTLY_ON(BrowserThread::IO);
293 if (document_id.empty()) { 329 if (document_id.empty()) {
294 callback.Run(GURL()); 330 callback.Run(GURL());
295 return; 331 return;
296 } 332 }
297 callback.Run(BuildDocumentUrl(authority_, document_id)); 333 callback.Run(BuildDocumentUrl(authority_, document_id));
298 } 334 }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 431
396 mapping[filename] = 432 mapping[filename] =
397 ThinDocument{document->document_id, 433 ThinDocument{document->document_id,
398 document->mime_type == kAndroidDirectoryMimeType}; 434 document->mime_type == kAndroidDirectoryMimeType};
399 } 435 }
400 436
401 callback.Run(base::File::FILE_OK, std::move(mapping)); 437 callback.Run(base::File::FILE_OK, std::move(mapping));
402 } 438 }
403 439
404 } // namespace arc 440 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698