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

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: Review ready. 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
38 // A special wathcer ID indicating this watcher is being installed.
39 // Though we have an entry in ArcDocumentsProviderRoot, we are still in the
40 // middle of asking the remote ArcFileSystemService to install a watcher.
41 // Once the installation finishes, the entry will be replaced with a correct
42 // watcher ID or kOrphanWatcherId if the installation is failed.
43 // We use this value to allow AddWatcher() to return immediately.
44 //
45 // TODO(crbug.com/698624): Remove this hack. It was introduced because Files
46 // app freezes until AddWatcher() finishes, but it should be handled in Files
47 // app rather than here.
48 constexpr int64_t kInstallInProgressWatcherId = -2;
49
29 // Computes a file name for a document. 50 // Computes a file name for a document.
30 // TODO(crbug.com/675868): Consolidate with the similar logic for Drive. 51 // TODO(crbug.com/675868): Consolidate with the similar logic for Drive.
31 base::FilePath::StringType GetFileNameForDocument( 52 base::FilePath::StringType GetFileNameForDocument(
32 const mojom::DocumentPtr& document) { 53 const mojom::DocumentPtr& document) {
33 base::FilePath::StringType filename = document->display_name; 54 base::FilePath::StringType filename = document->display_name;
34 55
35 // Replace path separators appearing in the file name. 56 // Replace path separators appearing in the file name.
36 // Chrome OS is POSIX and kSeparators is "/". 57 // Chrome OS is POSIX and kSeparators is "/".
37 base::ReplaceChars(filename, base::FilePath::kSeparators, "_", &filename); 58 base::ReplaceChars(filename, base::FilePath::kSeparators, "_", &filename);
38 59
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 120
100 void ArcDocumentsProviderRoot::AddWatcher( 121 void ArcDocumentsProviderRoot::AddWatcher(
101 const base::FilePath& path, 122 const base::FilePath& path,
102 const WatcherCallback& watcher_callback, 123 const WatcherCallback& watcher_callback,
103 const StatusCallback& callback) { 124 const StatusCallback& callback) {
104 DCHECK_CURRENTLY_ON(BrowserThread::IO); 125 DCHECK_CURRENTLY_ON(BrowserThread::IO);
105 if (path_to_watcher_id_.count(path)) { 126 if (path_to_watcher_id_.count(path)) {
106 callback.Run(base::File::FILE_ERROR_FAILED); 127 callback.Run(base::File::FILE_ERROR_FAILED);
107 return; 128 return;
108 } 129 }
130 // HACK: Invoke |callback| immediately.
131 //
132 // TODO(crbug.com/698624): Remove this hack. It was introduced because Files
133 // app freezes until AddWatcher() finishes, but it should be handled in Files
134 // app rather than here.
135 path_to_watcher_id_.insert(std::make_pair(path, kInstallInProgressWatcherId));
136 callback.Run(base::File::FILE_OK);
hidehiko 2017/03/09 15:28:34 Looks there is a regression race and/or leak? - Ad
Shuhei Takahashi 2017/03/10 04:29:59 I'm afraid I don't understand your point correctly
Shuhei Takahashi 2017/03/10 09:17:23 After offline chat, we decided to assign IDs to wa
109 ResolveToDocumentId( 137 ResolveToDocumentId(
110 path, 138 path, base::Bind(&ArcDocumentsProviderRoot::AddWatcherWithDocumentId,
111 base::Bind(&ArcDocumentsProviderRoot::AddWatcherWithDocumentId, 139 weak_ptr_factory_.GetWeakPtr(), path, watcher_callback));
112 weak_ptr_factory_.GetWeakPtr(), path, watcher_callback,
113 callback));
114 } 140 }
115 141
116 void ArcDocumentsProviderRoot::RemoveWatcher(const base::FilePath& path, 142 void ArcDocumentsProviderRoot::RemoveWatcher(const base::FilePath& path,
117 const StatusCallback& callback) { 143 const StatusCallback& callback) {
118 DCHECK_CURRENTLY_ON(BrowserThread::IO); 144 DCHECK_CURRENTLY_ON(BrowserThread::IO);
119 auto iter = path_to_watcher_id_.find(path); 145 auto iter = path_to_watcher_id_.find(path);
120 if (iter == path_to_watcher_id_.end()) { 146 if (iter == path_to_watcher_id_.end()) {
121 callback.Run(base::File::FILE_ERROR_FAILED); 147 callback.Run(base::File::FILE_ERROR_FAILED);
122 return; 148 return;
123 } 149 }
(...skipping 18 matching lines...) Expand all
142 ResolveToDocumentId( 168 ResolveToDocumentId(
143 path, 169 path,
144 base::Bind(&ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId, 170 base::Bind(&ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId,
145 weak_ptr_factory_.GetWeakPtr(), callback)); 171 weak_ptr_factory_.GetWeakPtr(), callback));
146 } 172 }
147 173
148 void ArcDocumentsProviderRoot::OnWatchersCleared() { 174 void ArcDocumentsProviderRoot::OnWatchersCleared() {
149 DCHECK_CURRENTLY_ON(BrowserThread::IO); 175 DCHECK_CURRENTLY_ON(BrowserThread::IO);
150 // Mark all watchers orphan. 176 // Mark all watchers orphan.
151 for (auto& entry : path_to_watcher_id_) 177 for (auto& entry : path_to_watcher_id_)
152 entry.second = -1; 178 entry.second = kOrphanWatcherId;
153 } 179 }
154 180
155 void ArcDocumentsProviderRoot::GetFileInfoWithDocumentId( 181 void ArcDocumentsProviderRoot::GetFileInfoWithDocumentId(
156 const GetFileInfoCallback& callback, 182 const GetFileInfoCallback& callback,
157 const std::string& document_id) { 183 const std::string& document_id) {
158 DCHECK_CURRENTLY_ON(BrowserThread::IO); 184 DCHECK_CURRENTLY_ON(BrowserThread::IO);
159 if (document_id.empty()) { 185 if (document_id.empty()) {
160 callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info()); 186 callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info());
161 return; 187 return;
162 } 188 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 entry_list.emplace_back(pair.first, pair.second.is_directory 252 entry_list.emplace_back(pair.first, pair.second.is_directory
227 ? storage::DirectoryEntry::DIRECTORY 253 ? storage::DirectoryEntry::DIRECTORY
228 : storage::DirectoryEntry::FILE); 254 : storage::DirectoryEntry::FILE);
229 } 255 }
230 callback.Run(base::File::FILE_OK, entry_list, false /* has_more */); 256 callback.Run(base::File::FILE_OK, entry_list, false /* has_more */);
231 } 257 }
232 258
233 void ArcDocumentsProviderRoot::AddWatcherWithDocumentId( 259 void ArcDocumentsProviderRoot::AddWatcherWithDocumentId(
234 const base::FilePath& path, 260 const base::FilePath& path,
235 const WatcherCallback& watcher_callback, 261 const WatcherCallback& watcher_callback,
236 const StatusCallback& callback,
237 const std::string& document_id) { 262 const std::string& document_id) {
238 DCHECK_CURRENTLY_ON(BrowserThread::IO); 263 DCHECK_CURRENTLY_ON(BrowserThread::IO);
239 if (document_id.empty()) { 264
240 callback.Run(base::File::FILE_ERROR_NOT_FOUND); 265 auto iter = path_to_watcher_id_.find(path);
266 if (iter == path_to_watcher_id_.end() ||
267 iter->second != kInstallInProgressWatcherId) {
268 // Multiple watchers have been installed on the same file path in a race.
269 // Following the contract of WatcherManager, we reject all except the first.
241 return; 270 return;
242 } 271 }
272 DCHECK_EQ(kInstallInProgressWatcherId, iter->second);
273
274 if (document_id.empty()) {
275 iter->second = kOrphanWatcherId;
276 return;
277 }
278
243 // Start observing ArcFileSystemOperationRunner if we have not. 279 // Start observing ArcFileSystemOperationRunner if we have not.
244 if (!observer_wrapper_) { 280 if (!observer_wrapper_) {
245 observer_wrapper_ = 281 observer_wrapper_ =
246 new file_system_operation_runner_util::ObserverIOThreadWrapper(this); 282 new file_system_operation_runner_util::ObserverIOThreadWrapper(this);
247 file_system_operation_runner_util::AddObserverOnIOThread(observer_wrapper_); 283 file_system_operation_runner_util::AddObserverOnIOThread(observer_wrapper_);
248 } 284 }
285
249 file_system_operation_runner_util::AddWatcherOnIOThread( 286 file_system_operation_runner_util::AddWatcherOnIOThread(
250 authority_, document_id, watcher_callback, 287 authority_, document_id, watcher_callback,
251 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAdded, 288 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAdded,
252 weak_ptr_factory_.GetWeakPtr(), path, callback)); 289 weak_ptr_factory_.GetWeakPtr(), path));
253 } 290 }
254 291
255 void ArcDocumentsProviderRoot::OnWatcherAdded(const base::FilePath& path, 292 void ArcDocumentsProviderRoot::OnWatcherAdded(const base::FilePath& path,
256 const StatusCallback& callback,
257 int64_t watcher_id) { 293 int64_t watcher_id) {
258 DCHECK_CURRENTLY_ON(BrowserThread::IO); 294 DCHECK_CURRENTLY_ON(BrowserThread::IO);
259 if (watcher_id < 0) { 295
260 callback.Run(base::File::FILE_ERROR_FAILED); 296 auto iter = path_to_watcher_id_.find(path);
261 return; 297 if (iter == path_to_watcher_id_.end() ||
262 } 298 iter->second != kInstallInProgressWatcherId) {
263 if (path_to_watcher_id_.count(path)) {
264 // Multiple watchers have been installed on the same file path in a race. 299 // 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. 300 // Following the contract of WatcherManager, we reject all except the first.
266 file_system_operation_runner_util::RemoveWatcherOnIOThread( 301 file_system_operation_runner_util::RemoveWatcherOnIOThread(
267 watcher_id, 302 watcher_id,
268 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAddedButRemoved, 303 base::Bind(&ArcDocumentsProviderRoot::OnWatcherAddedButRemoved,
269 weak_ptr_factory_.GetWeakPtr(), callback)); 304 weak_ptr_factory_.GetWeakPtr()));
270 return; 305 return;
271 } 306 }
272 path_to_watcher_id_.insert(std::make_pair(path, watcher_id)); 307 DCHECK_EQ(kInstallInProgressWatcherId, iter->second);
273 callback.Run(base::File::FILE_OK); 308
309 iter->second = watcher_id < 0 ? kOrphanWatcherId : watcher_id;
274 } 310 }
275 311
276 void ArcDocumentsProviderRoot::OnWatcherAddedButRemoved( 312 void ArcDocumentsProviderRoot::OnWatcherAddedButRemoved(bool success) {
277 const StatusCallback& callback,
278 bool success) {
279 DCHECK_CURRENTLY_ON(BrowserThread::IO); 313 DCHECK_CURRENTLY_ON(BrowserThread::IO);
280 callback.Run(base::File::FILE_ERROR_FAILED); 314 // Ignore |success|.
281 } 315 }
282 316
283 void ArcDocumentsProviderRoot::OnWatcherRemoved(const StatusCallback& callback, 317 void ArcDocumentsProviderRoot::OnWatcherRemoved(const StatusCallback& callback,
284 bool success) { 318 bool success) {
285 DCHECK_CURRENTLY_ON(BrowserThread::IO); 319 DCHECK_CURRENTLY_ON(BrowserThread::IO);
286 callback.Run(success ? base::File::FILE_OK : base::File::FILE_ERROR_FAILED); 320 callback.Run(success ? base::File::FILE_OK : base::File::FILE_ERROR_FAILED);
287 } 321 }
288 322
289 void ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId( 323 void ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId(
290 const ResolveToContentUrlCallback& callback, 324 const ResolveToContentUrlCallback& callback,
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 429
396 mapping[filename] = 430 mapping[filename] =
397 ThinDocument{document->document_id, 431 ThinDocument{document->document_id,
398 document->mime_type == kAndroidDirectoryMimeType}; 432 document->mime_type == kAndroidDirectoryMimeType};
399 } 433 }
400 434
401 callback.Run(base::File::FILE_OK, std::move(mapping)); 435 callback.Run(base::File::FILE_OK, std::move(mapping));
402 } 436 }
403 437
404 } // namespace arc 438 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698