1 // Copyright 2018 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 "third_party/blink/renderer/modules/filesystem/file_system_dispatcher.h"
6 
7 #include <utility>
8 
9 #include "build/build_config.h"
10 #include "mojo/public/cpp/bindings/pending_receiver.h"
11 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
12 #include "third_party/blink/public/platform/file_path_conversion.h"
13 #include "third_party/blink/public/platform/platform.h"
14 #include "third_party/blink/public/platform/task_type.h"
15 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
16 #include "third_party/blink/renderer/platform/wtf/functional.h"
17 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
18 
19 namespace blink {
20 
21 class FileSystemDispatcher::WriteListener
22     : public mojom::blink::FileSystemOperationListener {
23  public:
WriteListener(const WriteCallback & success_callback,StatusCallback error_callback)24   WriteListener(const WriteCallback& success_callback,
25                 StatusCallback error_callback)
26       : error_callback_(std::move(error_callback)),
27         write_callback_(success_callback) {}
28 
ResultsRetrieved(Vector<filesystem::mojom::blink::DirectoryEntryPtr> entries,bool has_more)29   void ResultsRetrieved(
30       Vector<filesystem::mojom::blink::DirectoryEntryPtr> entries,
31       bool has_more) override {
32     NOTREACHED();
33   }
34 
ErrorOccurred(base::File::Error error_code)35   void ErrorOccurred(base::File::Error error_code) override {
36     std::move(error_callback_).Run(error_code);
37   }
38 
DidWrite(int64_t byte_count,bool complete)39   void DidWrite(int64_t byte_count, bool complete) override {
40     write_callback_.Run(byte_count, complete);
41   }
42 
43  private:
44   StatusCallback error_callback_;
45   WriteCallback write_callback_;
46 };
47 
48 class FileSystemDispatcher::ReadDirectoryListener
49     : public mojom::blink::FileSystemOperationListener {
50  public:
ReadDirectoryListener(std::unique_ptr<EntriesCallbacks> callbacks)51   explicit ReadDirectoryListener(std::unique_ptr<EntriesCallbacks> callbacks)
52       : callbacks_(std::move(callbacks)) {}
53 
ResultsRetrieved(Vector<filesystem::mojom::blink::DirectoryEntryPtr> entries,bool has_more)54   void ResultsRetrieved(
55       Vector<filesystem::mojom::blink::DirectoryEntryPtr> entries,
56       bool has_more) override {
57     for (const auto& entry : entries) {
58       callbacks_->DidReadDirectoryEntry(
59           FilePathToWebString(entry->name),
60           entry->type == filesystem::mojom::blink::FsFileType::DIRECTORY);
61     }
62     callbacks_->DidReadDirectoryEntries(has_more);
63   }
64 
ErrorOccurred(base::File::Error error_code)65   void ErrorOccurred(base::File::Error error_code) override {
66     callbacks_->DidFail(error_code);
67   }
68 
DidWrite(int64_t byte_count,bool complete)69   void DidWrite(int64_t byte_count, bool complete) override { NOTREACHED(); }
70 
71  private:
72   std::unique_ptr<EntriesCallbacks> callbacks_;
73 };
74 
FileSystemDispatcher(ExecutionContext & context)75 FileSystemDispatcher::FileSystemDispatcher(ExecutionContext& context)
76     : Supplement<ExecutionContext>(context),
77       file_system_manager_(&context),
78       next_operation_id_(1),
79       op_listeners_(&context) {}
80 
81 // static
82 const char FileSystemDispatcher::kSupplementName[] = "FileSystemDispatcher";
83 
84 // static
From(ExecutionContext * context)85 FileSystemDispatcher& FileSystemDispatcher::From(ExecutionContext* context) {
86   DCHECK(context);
87   FileSystemDispatcher* dispatcher =
88       Supplement<ExecutionContext>::From<FileSystemDispatcher>(context);
89   if (!dispatcher) {
90     dispatcher = MakeGarbageCollected<FileSystemDispatcher>(*context);
91     Supplement<ExecutionContext>::ProvideTo(*context, dispatcher);
92   }
93   return *dispatcher;
94 }
95 
96 FileSystemDispatcher::~FileSystemDispatcher() = default;
97 
GetFileSystemManager()98 mojom::blink::FileSystemManager& FileSystemDispatcher::GetFileSystemManager() {
99   if (!file_system_manager_.is_bound()) {
100     // See https://bit.ly/2S0zRAS for task types
101     mojo::PendingReceiver<mojom::blink::FileSystemManager> receiver =
102         file_system_manager_.BindNewPipeAndPassReceiver(
103             GetSupplementable()->GetTaskRunner(
104                 blink::TaskType::kMiscPlatformAPI));
105 
106     GetSupplementable()->GetBrowserInterfaceBroker().GetInterface(
107         std::move(receiver));
108   }
109   DCHECK(file_system_manager_.is_bound());
110   return *file_system_manager_.get();
111 }
112 
OpenFileSystem(const SecurityOrigin * origin,mojom::blink::FileSystemType type,std::unique_ptr<FileSystemCallbacks> callbacks)113 void FileSystemDispatcher::OpenFileSystem(
114     const SecurityOrigin* origin,
115     mojom::blink::FileSystemType type,
116     std::unique_ptr<FileSystemCallbacks> callbacks) {
117   GetFileSystemManager().Open(
118       origin, type,
119       WTF::Bind(&FileSystemDispatcher::DidOpenFileSystem,
120                 WrapWeakPersistent(this), std::move(callbacks)));
121 }
122 
OpenFileSystemSync(const SecurityOrigin * origin,mojom::blink::FileSystemType type,std::unique_ptr<FileSystemCallbacks> callbacks)123 void FileSystemDispatcher::OpenFileSystemSync(
124     const SecurityOrigin* origin,
125     mojom::blink::FileSystemType type,
126     std::unique_ptr<FileSystemCallbacks> callbacks) {
127   String name;
128   KURL root_url;
129   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
130   GetFileSystemManager().Open(origin, type, &name, &root_url, &error_code);
131   DidOpenFileSystem(std::move(callbacks), std::move(name), root_url,
132                     error_code);
133 }
134 
ResolveURL(const KURL & filesystem_url,std::unique_ptr<ResolveURICallbacks> callbacks)135 void FileSystemDispatcher::ResolveURL(
136     const KURL& filesystem_url,
137     std::unique_ptr<ResolveURICallbacks> callbacks) {
138   GetFileSystemManager().ResolveURL(
139       filesystem_url,
140       WTF::Bind(&FileSystemDispatcher::DidResolveURL, WrapWeakPersistent(this),
141                 std::move(callbacks)));
142 }
143 
ResolveURLSync(const KURL & filesystem_url,std::unique_ptr<ResolveURICallbacks> callbacks)144 void FileSystemDispatcher::ResolveURLSync(
145     const KURL& filesystem_url,
146     std::unique_ptr<ResolveURICallbacks> callbacks) {
147   mojom::blink::FileSystemInfoPtr info;
148   base::FilePath file_path;
149   bool is_directory;
150   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
151   GetFileSystemManager().ResolveURL(filesystem_url, &info, &file_path,
152                                     &is_directory, &error_code);
153   DidResolveURL(std::move(callbacks), std::move(info), std::move(file_path),
154                 is_directory, error_code);
155 }
156 
Move(const KURL & src_path,const KURL & dest_path,std::unique_ptr<EntryCallbacks> callbacks)157 void FileSystemDispatcher::Move(const KURL& src_path,
158                                 const KURL& dest_path,
159                                 std::unique_ptr<EntryCallbacks> callbacks) {
160   GetFileSystemManager().Move(
161       src_path, dest_path,
162       WTF::Bind(&FileSystemDispatcher::DidFinish, WrapWeakPersistent(this),
163                 std::move(callbacks)));
164 }
165 
MoveSync(const KURL & src_path,const KURL & dest_path,std::unique_ptr<EntryCallbacks> callbacks)166 void FileSystemDispatcher::MoveSync(const KURL& src_path,
167                                     const KURL& dest_path,
168                                     std::unique_ptr<EntryCallbacks> callbacks) {
169   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
170   GetFileSystemManager().Move(src_path, dest_path, &error_code);
171   DidFinish(std::move(callbacks), error_code);
172 }
173 
Copy(const KURL & src_path,const KURL & dest_path,std::unique_ptr<EntryCallbacks> callbacks)174 void FileSystemDispatcher::Copy(const KURL& src_path,
175                                 const KURL& dest_path,
176                                 std::unique_ptr<EntryCallbacks> callbacks) {
177   GetFileSystemManager().Copy(
178       src_path, dest_path,
179       WTF::Bind(&FileSystemDispatcher::DidFinish, WrapWeakPersistent(this),
180                 std::move(callbacks)));
181 }
182 
CopySync(const KURL & src_path,const KURL & dest_path,std::unique_ptr<EntryCallbacks> callbacks)183 void FileSystemDispatcher::CopySync(const KURL& src_path,
184                                     const KURL& dest_path,
185                                     std::unique_ptr<EntryCallbacks> callbacks) {
186   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
187   GetFileSystemManager().Copy(src_path, dest_path, &error_code);
188   DidFinish(std::move(callbacks), error_code);
189 }
190 
Remove(const KURL & path,bool recursive,std::unique_ptr<VoidCallbacks> callbacks)191 void FileSystemDispatcher::Remove(const KURL& path,
192                                   bool recursive,
193                                   std::unique_ptr<VoidCallbacks> callbacks) {
194   GetFileSystemManager().Remove(
195       path, recursive,
196       WTF::Bind(&FileSystemDispatcher::DidRemove, WrapWeakPersistent(this),
197                 std::move(callbacks)));
198 }
199 
RemoveSync(const KURL & path,bool recursive,std::unique_ptr<VoidCallbacks> callbacks)200 void FileSystemDispatcher::RemoveSync(
201     const KURL& path,
202     bool recursive,
203     std::unique_ptr<VoidCallbacks> callbacks) {
204   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
205   GetFileSystemManager().Remove(path, recursive, &error_code);
206   DidRemove(std::move(callbacks), error_code);
207 }
208 
ReadMetadata(const KURL & path,std::unique_ptr<MetadataCallbacks> callbacks)209 void FileSystemDispatcher::ReadMetadata(
210     const KURL& path,
211     std::unique_ptr<MetadataCallbacks> callbacks) {
212   GetFileSystemManager().ReadMetadata(
213       path, WTF::Bind(&FileSystemDispatcher::DidReadMetadata,
214                       WrapWeakPersistent(this), std::move(callbacks)));
215 }
216 
ReadMetadataSync(const KURL & path,std::unique_ptr<MetadataCallbacks> callbacks)217 void FileSystemDispatcher::ReadMetadataSync(
218     const KURL& path,
219     std::unique_ptr<MetadataCallbacks> callbacks) {
220   base::File::Info file_info;
221   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
222   GetFileSystemManager().ReadMetadata(path, &file_info, &error_code);
223   DidReadMetadata(std::move(callbacks), std::move(file_info), error_code);
224 }
225 
CreateFile(const KURL & path,bool exclusive,std::unique_ptr<EntryCallbacks> callbacks)226 void FileSystemDispatcher::CreateFile(
227     const KURL& path,
228     bool exclusive,
229     std::unique_ptr<EntryCallbacks> callbacks) {
230   GetFileSystemManager().Create(
231       path, exclusive, /*is_directory=*/false, /*is_recursive=*/false,
232       WTF::Bind(&FileSystemDispatcher::DidFinish, WrapWeakPersistent(this),
233                 std::move(callbacks)));
234 }
235 
CreateFileSync(const KURL & path,bool exclusive,std::unique_ptr<EntryCallbacks> callbacks)236 void FileSystemDispatcher::CreateFileSync(
237     const KURL& path,
238     bool exclusive,
239     std::unique_ptr<EntryCallbacks> callbacks) {
240   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
241   GetFileSystemManager().Create(path, exclusive, /*is_directory=*/false,
242                                 /*is_recursive=*/false, &error_code);
243   DidFinish(std::move(callbacks), error_code);
244 }
245 
CreateDirectory(const KURL & path,bool exclusive,bool recursive,std::unique_ptr<EntryCallbacks> callbacks)246 void FileSystemDispatcher::CreateDirectory(
247     const KURL& path,
248     bool exclusive,
249     bool recursive,
250     std::unique_ptr<EntryCallbacks> callbacks) {
251   GetFileSystemManager().Create(
252       path, exclusive, /*is_directory=*/true, recursive,
253       WTF::Bind(&FileSystemDispatcher::DidFinish, WrapWeakPersistent(this),
254                 std::move(callbacks)));
255 }
256 
CreateDirectorySync(const KURL & path,bool exclusive,bool recursive,std::unique_ptr<EntryCallbacks> callbacks)257 void FileSystemDispatcher::CreateDirectorySync(
258     const KURL& path,
259     bool exclusive,
260     bool recursive,
261     std::unique_ptr<EntryCallbacks> callbacks) {
262   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
263   GetFileSystemManager().Create(path, exclusive, /*is_directory=*/true,
264                                 recursive, &error_code);
265   DidFinish(std::move(callbacks), error_code);
266 }
267 
Exists(const KURL & path,bool is_directory,std::unique_ptr<EntryCallbacks> callbacks)268 void FileSystemDispatcher::Exists(const KURL& path,
269                                   bool is_directory,
270                                   std::unique_ptr<EntryCallbacks> callbacks) {
271   GetFileSystemManager().Exists(
272       path, is_directory,
273       WTF::Bind(&FileSystemDispatcher::DidFinish, WrapWeakPersistent(this),
274                 std::move(callbacks)));
275 }
276 
ExistsSync(const KURL & path,bool is_directory,std::unique_ptr<EntryCallbacks> callbacks)277 void FileSystemDispatcher::ExistsSync(
278     const KURL& path,
279     bool is_directory,
280     std::unique_ptr<EntryCallbacks> callbacks) {
281   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
282   GetFileSystemManager().Exists(path, is_directory, &error_code);
283   DidFinish(std::move(callbacks), error_code);
284 }
285 
ReadDirectory(const KURL & path,std::unique_ptr<EntriesCallbacks> callbacks)286 void FileSystemDispatcher::ReadDirectory(
287     const KURL& path,
288     std::unique_ptr<EntriesCallbacks> callbacks) {
289   mojo::PendingRemote<mojom::blink::FileSystemOperationListener> listener;
290   mojo::PendingReceiver<mojom::blink::FileSystemOperationListener> receiver =
291       listener.InitWithNewPipeAndPassReceiver();
292   op_listeners_.Add(
293       std::make_unique<ReadDirectoryListener>(std::move(callbacks)),
294       std::move(receiver),
295       // See https://bit.ly/2S0zRAS for task types
296       GetSupplementable()->GetTaskRunner(blink::TaskType::kMiscPlatformAPI));
297   GetFileSystemManager().ReadDirectory(path, std::move(listener));
298 }
299 
ReadDirectorySync(const KURL & path,std::unique_ptr<EntriesCallbacks> callbacks)300 void FileSystemDispatcher::ReadDirectorySync(
301     const KURL& path,
302     std::unique_ptr<EntriesCallbacks> callbacks) {
303   Vector<filesystem::mojom::blink::DirectoryEntryPtr> entries;
304   base::File::Error result = base::File::FILE_ERROR_FAILED;
305   GetFileSystemManager().ReadDirectorySync(path, &entries, &result);
306   if (result == base::File::FILE_OK) {
307     DidReadDirectory(std::move(callbacks), std::move(entries),
308                      std::move(result));
309   }
310 }
311 
InitializeFileWriter(const KURL & path,std::unique_ptr<FileWriterCallbacks> callbacks)312 void FileSystemDispatcher::InitializeFileWriter(
313     const KURL& path,
314     std::unique_ptr<FileWriterCallbacks> callbacks) {
315   GetFileSystemManager().ReadMetadata(
316       path, WTF::Bind(&FileSystemDispatcher::InitializeFileWriterCallback,
317                       WrapWeakPersistent(this), path, std::move(callbacks)));
318 }
319 
InitializeFileWriterSync(const KURL & path,std::unique_ptr<FileWriterCallbacks> callbacks)320 void FileSystemDispatcher::InitializeFileWriterSync(
321     const KURL& path,
322     std::unique_ptr<FileWriterCallbacks> callbacks) {
323   base::File::Info file_info;
324   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
325   GetFileSystemManager().ReadMetadata(path, &file_info, &error_code);
326   InitializeFileWriterCallback(path, std::move(callbacks), file_info,
327                                error_code);
328 }
329 
Truncate(const KURL & path,int64_t offset,int * request_id_out,StatusCallback callback)330 void FileSystemDispatcher::Truncate(const KURL& path,
331                                     int64_t offset,
332                                     int* request_id_out,
333                                     StatusCallback callback) {
334   HeapMojoRemote<mojom::blink::FileSystemCancellableOperation> op_remote(
335       GetSupplementable());
336   // See https://bit.ly/2S0zRAS for task types
337   mojo::PendingReceiver<mojom::blink::FileSystemCancellableOperation>
338       op_receiver = op_remote.BindNewPipeAndPassReceiver(
339           GetSupplementable()->GetTaskRunner(
340               blink::TaskType::kMiscPlatformAPI));
341   int operation_id = next_operation_id_++;
342   op_remote.set_disconnect_handler(
343       WTF::Bind(&FileSystemDispatcher::RemoveOperationRemote,
344                 WrapWeakPersistent(this), operation_id));
345   cancellable_operations_.insert(operation_id,
346                                  WrapDisallowNew(std::move(op_remote)));
347   GetFileSystemManager().Truncate(
348       path, offset, std::move(op_receiver),
349       WTF::Bind(&FileSystemDispatcher::DidTruncate, WrapWeakPersistent(this),
350                 operation_id, std::move(callback)));
351 
352   if (request_id_out)
353     *request_id_out = operation_id;
354 }
355 
TruncateSync(const KURL & path,int64_t offset,StatusCallback callback)356 void FileSystemDispatcher::TruncateSync(const KURL& path,
357                                         int64_t offset,
358                                         StatusCallback callback) {
359   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
360   GetFileSystemManager().TruncateSync(path, offset, &error_code);
361   std::move(callback).Run(error_code);
362 }
363 
Write(const KURL & path,const String & blob_id,int64_t offset,int * request_id_out,const WriteCallback & success_callback,StatusCallback error_callback)364 void FileSystemDispatcher::Write(const KURL& path,
365                                  const String& blob_id,
366                                  int64_t offset,
367                                  int* request_id_out,
368                                  const WriteCallback& success_callback,
369                                  StatusCallback error_callback) {
370   HeapMojoRemote<mojom::blink::FileSystemCancellableOperation> op_remote(
371       GetSupplementable());
372   // See https://bit.ly/2S0zRAS for task types
373   scoped_refptr<base::SequencedTaskRunner> task_runner =
374       GetSupplementable()->GetTaskRunner(blink::TaskType::kMiscPlatformAPI);
375   mojo::PendingReceiver<mojom::blink::FileSystemCancellableOperation>
376       op_receiver = op_remote.BindNewPipeAndPassReceiver(task_runner);
377   int operation_id = next_operation_id_++;
378   op_remote.set_disconnect_handler(
379       WTF::Bind(&FileSystemDispatcher::RemoveOperationRemote,
380                 WrapWeakPersistent(this), operation_id));
381   cancellable_operations_.insert(operation_id,
382                                  WrapDisallowNew(std::move(op_remote)));
383 
384   mojo::PendingRemote<mojom::blink::FileSystemOperationListener> listener;
385   mojo::PendingReceiver<mojom::blink::FileSystemOperationListener> receiver =
386       listener.InitWithNewPipeAndPassReceiver();
387   op_listeners_.Add(std::make_unique<WriteListener>(
388                         WTF::BindRepeating(&FileSystemDispatcher::DidWrite,
389                                            WrapWeakPersistent(this),
390                                            success_callback, operation_id),
391                         WTF::Bind(&FileSystemDispatcher::WriteErrorCallback,
392                                   WrapWeakPersistent(this),
393                                   std::move(error_callback), operation_id)),
394                     std::move(receiver), task_runner);
395 
396   GetFileSystemManager().Write(path, blob_id, offset, std::move(op_receiver),
397                                std::move(listener));
398 
399   if (request_id_out)
400     *request_id_out = operation_id;
401 }
402 
WriteSync(const KURL & path,const String & blob_id,int64_t offset,const WriteCallback & success_callback,StatusCallback error_callback)403 void FileSystemDispatcher::WriteSync(const KURL& path,
404                                      const String& blob_id,
405                                      int64_t offset,
406                                      const WriteCallback& success_callback,
407                                      StatusCallback error_callback) {
408   int64_t byte_count;
409   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
410   GetFileSystemManager().WriteSync(path, blob_id, offset, &byte_count,
411                                    &error_code);
412   if (error_code == base::File::FILE_OK)
413     std::move(success_callback).Run(byte_count, /*complete=*/true);
414   else
415     std::move(error_callback).Run(error_code);
416 }
417 
Cancel(int request_id_to_cancel,StatusCallback callback)418 void FileSystemDispatcher::Cancel(int request_id_to_cancel,
419                                   StatusCallback callback) {
420   if (cancellable_operations_.find(request_id_to_cancel) ==
421       cancellable_operations_.end()) {
422     std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
423     return;
424   }
425   auto& remote =
426       cancellable_operations_.find(request_id_to_cancel)->value->Value();
427   if (!remote.is_bound()) {
428     RemoveOperationRemote(request_id_to_cancel);
429     std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
430     return;
431   }
432   remote->Cancel(WTF::Bind(&FileSystemDispatcher::DidCancel,
433                            WrapWeakPersistent(this), std::move(callback),
434                            request_id_to_cancel));
435 }
436 
CreateSnapshotFile(const KURL & file_path,std::unique_ptr<SnapshotFileCallbackBase> callbacks)437 void FileSystemDispatcher::CreateSnapshotFile(
438     const KURL& file_path,
439     std::unique_ptr<SnapshotFileCallbackBase> callbacks) {
440   GetFileSystemManager().CreateSnapshotFile(
441       file_path, WTF::Bind(&FileSystemDispatcher::DidCreateSnapshotFile,
442                            WrapWeakPersistent(this), std::move(callbacks)));
443 }
444 
CreateSnapshotFileSync(const KURL & file_path,std::unique_ptr<SnapshotFileCallbackBase> callbacks)445 void FileSystemDispatcher::CreateSnapshotFileSync(
446     const KURL& file_path,
447     std::unique_ptr<SnapshotFileCallbackBase> callbacks) {
448   base::File::Info file_info;
449   base::FilePath platform_path;
450   base::File::Error error_code = base::File::FILE_ERROR_FAILED;
451   mojo::PendingRemote<mojom::blink::ReceivedSnapshotListener> listener;
452   GetFileSystemManager().CreateSnapshotFile(
453       file_path, &file_info, &platform_path, &error_code, &listener);
454   DidCreateSnapshotFile(std::move(callbacks), std::move(file_info),
455                         std::move(platform_path), error_code,
456                         std::move(listener));
457 }
458 
Trace(Visitor * visitor) const459 void FileSystemDispatcher::Trace(Visitor* visitor) const {
460   visitor->Trace(file_system_manager_);
461   visitor->Trace(cancellable_operations_);
462   visitor->Trace(op_listeners_);
463   Supplement<ExecutionContext>::Trace(visitor);
464 }
465 
DidOpenFileSystem(std::unique_ptr<FileSystemCallbacks> callbacks,const String & name,const KURL & root,base::File::Error error_code)466 void FileSystemDispatcher::DidOpenFileSystem(
467     std::unique_ptr<FileSystemCallbacks> callbacks,
468     const String& name,
469     const KURL& root,
470     base::File::Error error_code) {
471   if (error_code == base::File::Error::FILE_OK) {
472     callbacks->DidOpenFileSystem(name, root);
473   } else {
474     callbacks->DidFail(error_code);
475   }
476 }
477 
DidResolveURL(std::unique_ptr<ResolveURICallbacks> callbacks,mojom::blink::FileSystemInfoPtr info,const base::FilePath & file_path,bool is_directory,base::File::Error error_code)478 void FileSystemDispatcher::DidResolveURL(
479     std::unique_ptr<ResolveURICallbacks> callbacks,
480     mojom::blink::FileSystemInfoPtr info,
481     const base::FilePath& file_path,
482     bool is_directory,
483     base::File::Error error_code) {
484   if (error_code == base::File::Error::FILE_OK) {
485     DCHECK(info->root_url.IsValid());
486     callbacks->DidResolveURL(info->name, info->root_url, info->mount_type,
487                              FilePathToWebString(file_path), is_directory);
488   } else {
489     callbacks->DidFail(error_code);
490   }
491 }
492 
DidRemove(std::unique_ptr<VoidCallbacks> callbacks,base::File::Error error_code)493 void FileSystemDispatcher::DidRemove(std::unique_ptr<VoidCallbacks> callbacks,
494                                      base::File::Error error_code) {
495   if (error_code == base::File::Error::FILE_OK)
496     callbacks->DidSucceed();
497   else
498     callbacks->DidFail(error_code);
499 }
500 
DidFinish(std::unique_ptr<EntryCallbacks> callbacks,base::File::Error error_code)501 void FileSystemDispatcher::DidFinish(std::unique_ptr<EntryCallbacks> callbacks,
502                                      base::File::Error error_code) {
503   if (error_code == base::File::Error::FILE_OK)
504     callbacks->DidSucceed();
505   else
506     callbacks->DidFail(error_code);
507 }
508 
DidReadMetadata(std::unique_ptr<MetadataCallbacks> callbacks,const base::File::Info & file_info,base::File::Error error_code)509 void FileSystemDispatcher::DidReadMetadata(
510     std::unique_ptr<MetadataCallbacks> callbacks,
511     const base::File::Info& file_info,
512     base::File::Error error_code) {
513   if (error_code == base::File::Error::FILE_OK) {
514     callbacks->DidReadMetadata(FileMetadata::From(file_info));
515   } else {
516     callbacks->DidFail(error_code);
517   }
518 }
519 
DidReadDirectory(std::unique_ptr<EntriesCallbacks> callbacks,Vector<filesystem::mojom::blink::DirectoryEntryPtr> entries,base::File::Error error_code)520 void FileSystemDispatcher::DidReadDirectory(
521     std::unique_ptr<EntriesCallbacks> callbacks,
522     Vector<filesystem::mojom::blink::DirectoryEntryPtr> entries,
523     base::File::Error error_code) {
524   if (error_code == base::File::Error::FILE_OK) {
525     for (const auto& entry : entries) {
526       callbacks->DidReadDirectoryEntry(
527           FilePathToWebString(entry->name),
528           entry->type == filesystem::mojom::blink::FsFileType::DIRECTORY);
529     }
530     callbacks->DidReadDirectoryEntries(false);
531   } else {
532     callbacks->DidFail(error_code);
533   }
534 }
535 
InitializeFileWriterCallback(const KURL & path,std::unique_ptr<FileWriterCallbacks> callbacks,const base::File::Info & file_info,base::File::Error error_code)536 void FileSystemDispatcher::InitializeFileWriterCallback(
537     const KURL& path,
538     std::unique_ptr<FileWriterCallbacks> callbacks,
539     const base::File::Info& file_info,
540     base::File::Error error_code) {
541   if (error_code == base::File::Error::FILE_OK) {
542     if (file_info.is_directory || file_info.size < 0) {
543       callbacks->DidFail(base::File::FILE_ERROR_FAILED);
544       return;
545     }
546     callbacks->DidCreateFileWriter(path, file_info.size);
547   } else {
548     callbacks->DidFail(error_code);
549   }
550 }
551 
DidTruncate(int operation_id,StatusCallback callback,base::File::Error error_code)552 void FileSystemDispatcher::DidTruncate(int operation_id,
553                                        StatusCallback callback,
554                                        base::File::Error error_code) {
555   if (error_code != base::File::FILE_ERROR_ABORT)
556     RemoveOperationRemote(operation_id);
557   std::move(callback).Run(error_code);
558 }
559 
DidWrite(const WriteCallback & callback,int operation_id,int64_t bytes,bool complete)560 void FileSystemDispatcher::DidWrite(const WriteCallback& callback,
561                                     int operation_id,
562                                     int64_t bytes,
563                                     bool complete) {
564   callback.Run(bytes, complete);
565   if (complete)
566     RemoveOperationRemote(operation_id);
567 }
568 
WriteErrorCallback(StatusCallback callback,int operation_id,base::File::Error error)569 void FileSystemDispatcher::WriteErrorCallback(StatusCallback callback,
570                                               int operation_id,
571                                               base::File::Error error) {
572   std::move(callback).Run(error);
573   if (error != base::File::FILE_ERROR_ABORT)
574     RemoveOperationRemote(operation_id);
575 }
576 
DidCancel(StatusCallback callback,int cancelled_operation_id,base::File::Error error_code)577 void FileSystemDispatcher::DidCancel(StatusCallback callback,
578                                      int cancelled_operation_id,
579                                      base::File::Error error_code) {
580   if (error_code == base::File::FILE_OK)
581     RemoveOperationRemote(cancelled_operation_id);
582   std::move(callback).Run(error_code);
583 }
584 
DidCreateSnapshotFile(std::unique_ptr<SnapshotFileCallbackBase> callbacks,const base::File::Info & file_info,const base::FilePath & platform_path,base::File::Error error_code,mojo::PendingRemote<mojom::blink::ReceivedSnapshotListener> listener)585 void FileSystemDispatcher::DidCreateSnapshotFile(
586     std::unique_ptr<SnapshotFileCallbackBase> callbacks,
587     const base::File::Info& file_info,
588     const base::FilePath& platform_path,
589     base::File::Error error_code,
590     mojo::PendingRemote<mojom::blink::ReceivedSnapshotListener> listener) {
591   if (error_code == base::File::FILE_OK) {
592     FileMetadata file_metadata = FileMetadata::From(file_info);
593     file_metadata.platform_path = FilePathToWebString(platform_path);
594 
595     callbacks->DidCreateSnapshotFile(file_metadata);
596 
597     if (listener) {
598       mojo::Remote<mojom::blink::ReceivedSnapshotListener>(std::move(listener))
599           ->DidReceiveSnapshotFile();
600     }
601   } else {
602     callbacks->DidFail(error_code);
603   }
604 }
605 
RemoveOperationRemote(int operation_id)606 void FileSystemDispatcher::RemoveOperationRemote(int operation_id) {
607   auto it = cancellable_operations_.find(operation_id);
608   if (it == cancellable_operations_.end())
609     return;
610   cancellable_operations_.erase(it);
611 }
612 
613 }  // namespace blink
614