1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/memory/singleton.h"
13 #include "base/optional.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "chrome/browser/chromeos/arc/arc_util.h"
16 #include "chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.h"
17 #include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
20 #include "components/arc/session/arc_bridge_service.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "url/gurl.h"
23
24 using content::BrowserThread;
25
26 namespace arc {
27 namespace {
28
29 // Singleton factory for ArcFileSystemOperationRunner.
30 class ArcFileSystemOperationRunnerFactory
31 : public internal::ArcBrowserContextKeyedServiceFactoryBase<
32 ArcFileSystemOperationRunner,
33 ArcFileSystemOperationRunnerFactory> {
34 public:
35 // Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
36 static constexpr const char* kName = "ArcFileSystemOperationRunnerFactory";
37
GetInstance()38 static ArcFileSystemOperationRunnerFactory* GetInstance() {
39 return base::Singleton<ArcFileSystemOperationRunnerFactory>::get();
40 }
41
42 private:
43 friend base::DefaultSingletonTraits<ArcFileSystemOperationRunnerFactory>;
ArcFileSystemOperationRunnerFactory()44 ArcFileSystemOperationRunnerFactory() {
45 DependsOn(ArcFileSystemBridge::GetFactory());
46 }
47 ~ArcFileSystemOperationRunnerFactory() override = default;
48 };
49
50 } // namespace
51
52 // static
53 ArcFileSystemOperationRunner*
GetForBrowserContext(content::BrowserContext * context)54 ArcFileSystemOperationRunner::GetForBrowserContext(
55 content::BrowserContext* context) {
56 return ArcFileSystemOperationRunnerFactory::GetForBrowserContext(context);
57 }
58
59 // static
GetFactory()60 BrowserContextKeyedServiceFactory* ArcFileSystemOperationRunner::GetFactory() {
61 return ArcFileSystemOperationRunnerFactory::GetInstance();
62 }
63
64 // static
65 std::unique_ptr<ArcFileSystemOperationRunner>
CreateForTesting(content::BrowserContext * context,ArcBridgeService * bridge_service)66 ArcFileSystemOperationRunner::CreateForTesting(
67 content::BrowserContext* context,
68 ArcBridgeService* bridge_service) {
69 // We can't use std::make_unique() here because we are calling a private
70 // constructor.
71 return base::WrapUnique<ArcFileSystemOperationRunner>(
72 new ArcFileSystemOperationRunner(context, bridge_service, false));
73 }
74
ArcFileSystemOperationRunner(content::BrowserContext * context,ArcBridgeService * bridge_service)75 ArcFileSystemOperationRunner::ArcFileSystemOperationRunner(
76 content::BrowserContext* context,
77 ArcBridgeService* bridge_service)
78 : ArcFileSystemOperationRunner(Profile::FromBrowserContext(context),
79 bridge_service,
80 true) {
81 DCHECK(context);
82 }
83
ArcFileSystemOperationRunner(content::BrowserContext * context,ArcBridgeService * bridge_service,bool set_should_defer_by_events)84 ArcFileSystemOperationRunner::ArcFileSystemOperationRunner(
85 content::BrowserContext* context,
86 ArcBridgeService* bridge_service,
87 bool set_should_defer_by_events)
88 : context_(context),
89 arc_bridge_service_(bridge_service),
90 set_should_defer_by_events_(set_should_defer_by_events) {
91 DCHECK_CURRENTLY_ON(BrowserThread::UI);
92
93 arc_bridge_service_->file_system()->AddObserver(this);
94
95 // ArcSessionManager may not exist in unit tests.
96 auto* arc_session_manager = ArcSessionManager::Get();
97 if (arc_session_manager)
98 arc_session_manager->AddObserver(this);
99
100 ArcFileSystemBridge::GetForBrowserContext(context_)->AddObserver(this);
101
102 OnStateChanged();
103 }
104
~ArcFileSystemOperationRunner()105 ArcFileSystemOperationRunner::~ArcFileSystemOperationRunner() {
106 DCHECK_CURRENTLY_ON(BrowserThread::UI);
107 // On destruction, deferred operations are discarded.
108 }
109
AddObserver(Observer * observer)110 void ArcFileSystemOperationRunner::AddObserver(Observer* observer) {
111 DCHECK_CURRENTLY_ON(BrowserThread::UI);
112 observer_list_.AddObserver(observer);
113 }
114
RemoveObserver(Observer * observer)115 void ArcFileSystemOperationRunner::RemoveObserver(Observer* observer) {
116 DCHECK_CURRENTLY_ON(BrowserThread::UI);
117 observer_list_.RemoveObserver(observer);
118 }
119
GetFileSize(const GURL & url,GetFileSizeCallback callback)120 void ArcFileSystemOperationRunner::GetFileSize(const GURL& url,
121 GetFileSizeCallback callback) {
122 DCHECK_CURRENTLY_ON(BrowserThread::UI);
123 if (should_defer_) {
124 deferred_operations_.emplace_back(base::BindOnce(
125 &ArcFileSystemOperationRunner::GetFileSize,
126 weak_ptr_factory_.GetWeakPtr(), url, std::move(callback)));
127 return;
128 }
129 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
130 arc_bridge_service_->file_system(), GetFileSize);
131 if (!file_system_instance) {
132 base::ThreadTaskRunnerHandle::Get()->PostTask(
133 FROM_HERE, base::BindOnce(std::move(callback), -1));
134 return;
135 }
136 file_system_instance->GetFileSize(url.spec(), std::move(callback));
137 }
138
GetMimeType(const GURL & url,GetMimeTypeCallback callback)139 void ArcFileSystemOperationRunner::GetMimeType(const GURL& url,
140 GetMimeTypeCallback callback) {
141 DCHECK_CURRENTLY_ON(BrowserThread::UI);
142 if (should_defer_) {
143 deferred_operations_.emplace_back(base::BindOnce(
144 &ArcFileSystemOperationRunner::GetMimeType,
145 weak_ptr_factory_.GetWeakPtr(), url, std::move(callback)));
146 return;
147 }
148 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
149 arc_bridge_service_->file_system(), GetMimeType);
150 if (!file_system_instance) {
151 base::ThreadTaskRunnerHandle::Get()->PostTask(
152 FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
153 return;
154 }
155 file_system_instance->GetMimeType(url.spec(), std::move(callback));
156 }
157
OpenFileToRead(const GURL & url,OpenFileToReadCallback callback)158 void ArcFileSystemOperationRunner::OpenFileToRead(
159 const GURL& url,
160 OpenFileToReadCallback callback) {
161 DCHECK_CURRENTLY_ON(BrowserThread::UI);
162 if (should_defer_) {
163 deferred_operations_.emplace_back(base::BindOnce(
164 &ArcFileSystemOperationRunner::OpenFileToRead,
165 weak_ptr_factory_.GetWeakPtr(), url, std::move(callback)));
166 return;
167 }
168 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
169 arc_bridge_service_->file_system(), OpenFileToRead);
170 if (!file_system_instance) {
171 base::ThreadTaskRunnerHandle::Get()->PostTask(
172 FROM_HERE, base::BindOnce(std::move(callback), mojo::ScopedHandle()));
173 return;
174 }
175 file_system_instance->OpenFileToRead(url.spec(), std::move(callback));
176 }
177
OpenThumbnail(const GURL & url,const gfx::Size & size,OpenThumbnailCallback callback)178 void ArcFileSystemOperationRunner::OpenThumbnail(
179 const GURL& url,
180 const gfx::Size& size,
181 OpenThumbnailCallback callback) {
182 DCHECK_CURRENTLY_ON(BrowserThread::UI);
183 if (should_defer_) {
184 deferred_operations_.emplace_back(base::BindOnce(
185 &ArcFileSystemOperationRunner::OpenThumbnail,
186 weak_ptr_factory_.GetWeakPtr(), url, size, std::move(callback)));
187 return;
188 }
189 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
190 arc_bridge_service_->file_system(), OpenThumbnail);
191 if (!file_system_instance) {
192 base::ThreadTaskRunnerHandle::Get()->PostTask(
193 FROM_HERE, base::BindOnce(std::move(callback), mojo::ScopedHandle()));
194 return;
195 }
196 file_system_instance->OpenThumbnail(url.spec(), size, std::move(callback));
197 }
198
OpenFileToWrite(const GURL & url,OpenFileToWriteCallback callback)199 void ArcFileSystemOperationRunner::OpenFileToWrite(
200 const GURL& url,
201 OpenFileToWriteCallback callback) {
202 DCHECK_CURRENTLY_ON(BrowserThread::UI);
203 if (should_defer_) {
204 deferred_operations_.emplace_back(base::BindOnce(
205 &ArcFileSystemOperationRunner::OpenFileToWrite,
206 weak_ptr_factory_.GetWeakPtr(), url, std::move(callback)));
207 return;
208 }
209 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
210 arc_bridge_service_->file_system(), OpenFileToWrite);
211 if (!file_system_instance) {
212 base::ThreadTaskRunnerHandle::Get()->PostTask(
213 FROM_HERE, base::BindOnce(std::move(callback), mojo::ScopedHandle()));
214 return;
215 }
216 file_system_instance->OpenFileToWrite(url.spec(), std::move(callback));
217 }
218
GetDocument(const std::string & authority,const std::string & document_id,GetDocumentCallback callback)219 void ArcFileSystemOperationRunner::GetDocument(const std::string& authority,
220 const std::string& document_id,
221 GetDocumentCallback callback) {
222 DCHECK_CURRENTLY_ON(BrowserThread::UI);
223 if (should_defer_) {
224 deferred_operations_.emplace_back(
225 base::BindOnce(&ArcFileSystemOperationRunner::GetDocument,
226 weak_ptr_factory_.GetWeakPtr(), authority, document_id,
227 std::move(callback)));
228 return;
229 }
230 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
231 arc_bridge_service_->file_system(), GetDocument);
232 if (!file_system_instance) {
233 base::ThreadTaskRunnerHandle::Get()->PostTask(
234 FROM_HERE, base::BindOnce(std::move(callback), mojom::DocumentPtr()));
235 return;
236 }
237 file_system_instance->GetDocument(authority, document_id,
238 std::move(callback));
239 }
240
GetChildDocuments(const std::string & authority,const std::string & parent_document_id,GetChildDocumentsCallback callback)241 void ArcFileSystemOperationRunner::GetChildDocuments(
242 const std::string& authority,
243 const std::string& parent_document_id,
244 GetChildDocumentsCallback callback) {
245 DCHECK_CURRENTLY_ON(BrowserThread::UI);
246 if (should_defer_) {
247 deferred_operations_.emplace_back(
248 base::BindOnce(&ArcFileSystemOperationRunner::GetChildDocuments,
249 weak_ptr_factory_.GetWeakPtr(), authority,
250 parent_document_id, std::move(callback)));
251 return;
252 }
253 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
254 arc_bridge_service_->file_system(), GetChildDocuments);
255 if (!file_system_instance) {
256 base::ThreadTaskRunnerHandle::Get()->PostTask(
257 FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
258 return;
259 }
260 file_system_instance->GetChildDocuments(authority, parent_document_id,
261 std::move(callback));
262 }
263
GetRecentDocuments(const std::string & authority,const std::string & root_id,GetRecentDocumentsCallback callback)264 void ArcFileSystemOperationRunner::GetRecentDocuments(
265 const std::string& authority,
266 const std::string& root_id,
267 GetRecentDocumentsCallback callback) {
268 DCHECK_CURRENTLY_ON(BrowserThread::UI);
269 if (should_defer_) {
270 deferred_operations_.emplace_back(
271 base::BindOnce(&ArcFileSystemOperationRunner::GetRecentDocuments,
272 weak_ptr_factory_.GetWeakPtr(), authority, root_id,
273 std::move(callback)));
274 return;
275 }
276 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
277 arc_bridge_service_->file_system(), GetRecentDocuments);
278 if (!file_system_instance) {
279 base::ThreadTaskRunnerHandle::Get()->PostTask(
280 FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
281 return;
282 }
283 file_system_instance->GetRecentDocuments(authority, root_id,
284 std::move(callback));
285 }
286
GetRoots(GetRootsCallback callback)287 void ArcFileSystemOperationRunner::GetRoots(GetRootsCallback callback) {
288 DCHECK_CURRENTLY_ON(BrowserThread::UI);
289 if (should_defer_) {
290 deferred_operations_.emplace_back(
291 base::BindOnce(&ArcFileSystemOperationRunner::GetRoots,
292 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
293 return;
294 }
295 auto* file_system_instance =
296 ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->file_system(), GetRoots);
297 if (!file_system_instance) {
298 base::ThreadTaskRunnerHandle::Get()->PostTask(
299 FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
300 return;
301 }
302 file_system_instance->GetRoots(std::move(callback));
303 }
304
DeleteDocument(const std::string & authority,const std::string & document_id,DeleteDocumentCallback callback)305 void ArcFileSystemOperationRunner::DeleteDocument(
306 const std::string& authority,
307 const std::string& document_id,
308 DeleteDocumentCallback callback) {
309 if (should_defer_) {
310 deferred_operations_.emplace_back(
311 base::BindOnce(&ArcFileSystemOperationRunner::DeleteDocument,
312 weak_ptr_factory_.GetWeakPtr(), authority, document_id,
313 std::move(callback)));
314 return;
315 }
316 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
317 arc_bridge_service_->file_system(), DeleteDocument);
318 if (!file_system_instance) {
319 base::ThreadTaskRunnerHandle::Get()->PostTask(
320 FROM_HERE, base::BindOnce(std::move(callback), false));
321 return;
322 }
323 file_system_instance->DeleteDocument(authority, document_id,
324 std::move(callback));
325 }
326
RenameDocument(const std::string & authority,const std::string & document_id,const std::string & display_name,RenameDocumentCallback callback)327 void ArcFileSystemOperationRunner::RenameDocument(
328 const std::string& authority,
329 const std::string& document_id,
330 const std::string& display_name,
331 RenameDocumentCallback callback) {
332 if (should_defer_) {
333 deferred_operations_.emplace_back(
334 base::BindOnce(&ArcFileSystemOperationRunner::RenameDocument,
335 weak_ptr_factory_.GetWeakPtr(), authority, document_id,
336 display_name, std::move(callback)));
337 return;
338 }
339 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
340 arc_bridge_service_->file_system(), RenameDocument);
341 if (!file_system_instance) {
342 base::ThreadTaskRunnerHandle::Get()->PostTask(
343 FROM_HERE, base::BindOnce(std::move(callback), mojom::DocumentPtr()));
344 return;
345 }
346 file_system_instance->RenameDocument(authority, document_id, display_name,
347 std::move(callback));
348 }
349
CreateDocument(const std::string & authority,const std::string & parent_document_id,const std::string & mime_type,const std::string & display_name,CreateDocumentCallback callback)350 void ArcFileSystemOperationRunner::CreateDocument(
351 const std::string& authority,
352 const std::string& parent_document_id,
353 const std::string& mime_type,
354 const std::string& display_name,
355 CreateDocumentCallback callback) {
356 if (should_defer_) {
357 deferred_operations_.emplace_back(base::BindOnce(
358 &ArcFileSystemOperationRunner::CreateDocument,
359 weak_ptr_factory_.GetWeakPtr(), authority, parent_document_id,
360 mime_type, display_name, std::move(callback)));
361 return;
362 }
363 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
364 arc_bridge_service_->file_system(), CreateDocument);
365 if (!file_system_instance) {
366 base::ThreadTaskRunnerHandle::Get()->PostTask(
367 FROM_HERE, base::BindOnce(std::move(callback), mojom::DocumentPtr()));
368 return;
369 }
370 file_system_instance->CreateDocument(authority, parent_document_id, mime_type,
371 display_name, std::move(callback));
372 }
373
CopyDocument(const std::string & authority,const std::string & source_document_id,const std::string & target_parent_document_id,CopyDocumentCallback callback)374 void ArcFileSystemOperationRunner::CopyDocument(
375 const std::string& authority,
376 const std::string& source_document_id,
377 const std::string& target_parent_document_id,
378 CopyDocumentCallback callback) {
379 if (should_defer_) {
380 deferred_operations_.emplace_back(base::BindOnce(
381 &ArcFileSystemOperationRunner::CopyDocument,
382 weak_ptr_factory_.GetWeakPtr(), authority, source_document_id,
383 target_parent_document_id, std::move(callback)));
384 return;
385 }
386 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
387 arc_bridge_service_->file_system(), CopyDocument);
388 if (!file_system_instance) {
389 base::ThreadTaskRunnerHandle::Get()->PostTask(
390 FROM_HERE, base::BindOnce(std::move(callback), mojom::DocumentPtr()));
391 return;
392 }
393 file_system_instance->CopyDocument(authority, source_document_id,
394 target_parent_document_id,
395 std::move(callback));
396 }
397
MoveDocument(const std::string & authority,const std::string & source_document_id,const std::string & source_parent_document_id,const std::string & target_parent_document_id,MoveDocumentCallback callback)398 void ArcFileSystemOperationRunner::MoveDocument(
399 const std::string& authority,
400 const std::string& source_document_id,
401 const std::string& source_parent_document_id,
402 const std::string& target_parent_document_id,
403 MoveDocumentCallback callback) {
404 if (should_defer_) {
405 deferred_operations_.emplace_back(
406 base::BindOnce(&ArcFileSystemOperationRunner::MoveDocument,
407 weak_ptr_factory_.GetWeakPtr(), authority,
408 source_document_id, source_parent_document_id,
409 target_parent_document_id, std::move(callback)));
410 return;
411 }
412 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
413 arc_bridge_service_->file_system(), MoveDocument);
414 if (!file_system_instance) {
415 base::ThreadTaskRunnerHandle::Get()->PostTask(
416 FROM_HERE, base::BindOnce(std::move(callback), mojom::DocumentPtr()));
417 return;
418 }
419 file_system_instance->MoveDocument(
420 authority, source_document_id, source_parent_document_id,
421 target_parent_document_id, std::move(callback));
422 }
423
AddWatcher(const std::string & authority,const std::string & document_id,const WatcherCallback & watcher_callback,AddWatcherCallback callback)424 void ArcFileSystemOperationRunner::AddWatcher(
425 const std::string& authority,
426 const std::string& document_id,
427 const WatcherCallback& watcher_callback,
428 AddWatcherCallback callback) {
429 DCHECK_CURRENTLY_ON(BrowserThread::UI);
430 if (should_defer_) {
431 deferred_operations_.emplace_back(
432 base::BindOnce(&ArcFileSystemOperationRunner::AddWatcher,
433 weak_ptr_factory_.GetWeakPtr(), authority, document_id,
434 watcher_callback, std::move(callback)));
435 return;
436 }
437 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
438 arc_bridge_service_->file_system(), AddWatcher);
439 if (!file_system_instance) {
440 base::ThreadTaskRunnerHandle::Get()->PostTask(
441 FROM_HERE, base::BindOnce(std::move(callback), -1));
442 return;
443 }
444 file_system_instance->AddWatcher(
445 authority, document_id,
446 base::BindOnce(&ArcFileSystemOperationRunner::OnWatcherAdded,
447 weak_ptr_factory_.GetWeakPtr(), watcher_callback,
448 std::move(callback)));
449 }
450
RemoveWatcher(int64_t watcher_id,RemoveWatcherCallback callback)451 void ArcFileSystemOperationRunner::RemoveWatcher(
452 int64_t watcher_id,
453 RemoveWatcherCallback callback) {
454 DCHECK_CURRENTLY_ON(BrowserThread::UI);
455 // RemoveWatcher() is never deferred since watchers do not persist across
456 // container reboots.
457 if (should_defer_) {
458 base::ThreadTaskRunnerHandle::Get()->PostTask(
459 FROM_HERE, base::BindOnce(std::move(callback), false));
460 return;
461 }
462
463 // Unregister from |watcher_callbacks_| now because we will do it even if
464 // the remote method fails anyway. This is an implementation detail, so
465 // users must not assume registered callbacks are immediately invalidated.
466 auto iter = watcher_callbacks_.find(watcher_id);
467 if (iter == watcher_callbacks_.end()) {
468 base::ThreadTaskRunnerHandle::Get()->PostTask(
469 FROM_HERE, base::BindOnce(std::move(callback), false));
470 return;
471 }
472 watcher_callbacks_.erase(iter);
473
474 auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
475 arc_bridge_service_->file_system(), RemoveWatcher);
476 if (!file_system_instance) {
477 base::ThreadTaskRunnerHandle::Get()->PostTask(
478 FROM_HERE, base::BindOnce(std::move(callback), false));
479 return;
480 }
481 file_system_instance->RemoveWatcher(watcher_id, std::move(callback));
482 }
483
Shutdown()484 void ArcFileSystemOperationRunner::Shutdown() {
485 DCHECK_CURRENTLY_ON(BrowserThread::UI);
486 ArcFileSystemBridge::GetForBrowserContext(context_)->RemoveObserver(this);
487
488 // ArcSessionManager may not exist in unit tests.
489 auto* arc_session_manager = ArcSessionManager::Get();
490 if (arc_session_manager)
491 arc_session_manager->RemoveObserver(this);
492
493 arc_bridge_service_->file_system()->RemoveObserver(this);
494 }
495
OnDocumentChanged(int64_t watcher_id,ChangeType type)496 void ArcFileSystemOperationRunner::OnDocumentChanged(int64_t watcher_id,
497 ChangeType type) {
498 DCHECK_CURRENTLY_ON(BrowserThread::UI);
499 auto iter = watcher_callbacks_.find(watcher_id);
500 if (iter == watcher_callbacks_.end()) {
501 // This may happen in a race condition with documents changes and
502 // RemoveWatcher().
503 return;
504 }
505 WatcherCallback watcher_callback = iter->second;
506 watcher_callback.Run(type);
507 }
508
OnArcPlayStoreEnabledChanged(bool enabled)509 void ArcFileSystemOperationRunner::OnArcPlayStoreEnabledChanged(bool enabled) {
510 DCHECK_CURRENTLY_ON(BrowserThread::UI);
511 OnStateChanged();
512 }
513
OnConnectionReady()514 void ArcFileSystemOperationRunner::OnConnectionReady() {
515 DCHECK_CURRENTLY_ON(BrowserThread::UI);
516 OnStateChanged();
517 }
518
OnConnectionClosed()519 void ArcFileSystemOperationRunner::OnConnectionClosed() {
520 DCHECK_CURRENTLY_ON(BrowserThread::UI);
521 // ArcFileSystemService and watchers are gone.
522 watcher_callbacks_.clear();
523 for (auto& observer : observer_list_)
524 observer.OnWatchersCleared();
525 OnStateChanged();
526 }
527
OnWatcherAdded(const WatcherCallback & watcher_callback,AddWatcherCallback callback,int64_t watcher_id)528 void ArcFileSystemOperationRunner::OnWatcherAdded(
529 const WatcherCallback& watcher_callback,
530 AddWatcherCallback callback,
531 int64_t watcher_id) {
532 DCHECK_CURRENTLY_ON(BrowserThread::UI);
533 if (watcher_id < 0) {
534 std::move(callback).Run(-1);
535 return;
536 }
537 if (watcher_callbacks_.count(watcher_id)) {
538 NOTREACHED();
539 std::move(callback).Run(-1);
540 return;
541 }
542 watcher_callbacks_.insert(std::make_pair(watcher_id, watcher_callback));
543 std::move(callback).Run(watcher_id);
544 }
545
OnStateChanged()546 void ArcFileSystemOperationRunner::OnStateChanged() {
547 DCHECK_CURRENTLY_ON(BrowserThread::UI);
548 if (set_should_defer_by_events_) {
549 SetShouldDefer(IsArcPlayStoreEnabledForProfile(
550 Profile::FromBrowserContext(context_)) &&
551 !arc_bridge_service_->file_system()->IsConnected());
552 }
553 }
554
SetShouldDefer(bool should_defer)555 void ArcFileSystemOperationRunner::SetShouldDefer(bool should_defer) {
556 DCHECK_CURRENTLY_ON(BrowserThread::UI);
557
558 should_defer_ = should_defer;
559
560 if (should_defer_)
561 return;
562
563 // Run deferred operations.
564 std::vector<base::OnceClosure> deferred_operations;
565 deferred_operations.swap(deferred_operations_);
566 for (base::OnceClosure& operation : deferred_operations)
567 std::move(operation).Run();
568
569 // No deferred operations should be left at this point.
570 DCHECK(deferred_operations_.empty());
571 }
572
573 } // namespace arc
574