FileSystemManagerChild.cpp (4690B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "FileSystemManagerChild.h" 8 9 #include "FileSystemAccessHandleChild.h" 10 #include "FileSystemBackgroundRequestHandler.h" 11 #include "FileSystemWritableFileStreamChild.h" 12 #include "mozilla/dom/FileSystemSyncAccessHandle.h" 13 #include "mozilla/dom/FileSystemWritableFileStream.h" 14 15 namespace mozilla::dom { 16 17 void FileSystemManagerChild::SetBackgroundRequestHandler( 18 FileSystemBackgroundRequestHandler* aBackgroundRequestHandler) { 19 MOZ_ASSERT(aBackgroundRequestHandler); 20 MOZ_ASSERT(!mBackgroundRequestHandler); 21 22 mBackgroundRequestHandler = aBackgroundRequestHandler; 23 } 24 25 void FileSystemManagerChild::CloseAllWritables( 26 std::function<void()>&& aCallback) { 27 nsTArray<RefPtr<BoolPromise>> promises; 28 CloseAllWritablesImpl(promises); 29 30 // FileSystemManagerChild::CloseAllWritables is sometimes called from 31 // FileSystemManager::Shutdown which can be called late in app shutdown 32 // when GetCurrentSerialEventTarget returns null. At that point there 33 // are no writable file streams. The problem with GetCurrentSerialEventTarget 34 // returning null can be solved by calling the callback directly without 35 // dispatching a new runnable. 36 if (promises.IsEmpty()) { 37 aCallback(); 38 return; 39 } 40 41 BoolPromise::AllSettled(GetCurrentSerialEventTarget(), promises) 42 ->Then(GetCurrentSerialEventTarget(), __func__, 43 [callback = std::move(aCallback)]( 44 const BoolPromise::AllSettledPromiseType::ResolveOrRejectValue& 45 /* aValues */) { callback(); }); 46 } 47 48 #ifdef DEBUG 49 bool FileSystemManagerChild::AllSyncAccessHandlesClosed() const { 50 for (const auto& item : ManagedPFileSystemAccessHandleChild()) { 51 auto* child = static_cast<FileSystemAccessHandleChild*>(item); 52 auto* handle = child->MutableAccessHandlePtr(); 53 54 if (!handle->IsClosed()) { 55 return false; 56 } 57 } 58 59 return true; 60 } 61 62 bool FileSystemManagerChild::AllWritableFileStreamsClosed() const { 63 for (const auto& item : ManagedPFileSystemWritableFileStreamChild()) { 64 auto* const child = static_cast<FileSystemWritableFileStreamChild*>(item); 65 auto* const handle = child->MutableWritableFileStreamPtr(); 66 if (!handle) { 67 continue; 68 } 69 70 if (!handle->IsDone()) { 71 return false; 72 } 73 } 74 75 return true; 76 } 77 78 #endif 79 80 void FileSystemManagerChild::Shutdown() { 81 if (!CanSend()) { 82 return; 83 } 84 85 Close(); 86 } 87 88 already_AddRefed<PFileSystemWritableFileStreamChild> 89 FileSystemManagerChild::AllocPFileSystemWritableFileStreamChild() { 90 return MakeAndAddRef<FileSystemWritableFileStreamChild>(); 91 } 92 93 ::mozilla::ipc::IPCResult FileSystemManagerChild::RecvCloseAll( 94 CloseAllResolver&& aResolver) { 95 mCloseAllReceived = true; 96 97 nsTArray<RefPtr<BoolPromise>> promises; 98 99 // NOTE: getFile() creates blobs that read the data from the child; 100 // we'll need to abort any reads and resolve this call only when all 101 // blobs are closed. 102 103 for (const auto& item : ManagedPFileSystemAccessHandleChild()) { 104 auto* child = static_cast<FileSystemAccessHandleChild*>(item); 105 auto* handle = child->MutableAccessHandlePtr(); 106 107 if (handle->IsOpen()) { 108 promises.AppendElement(handle->BeginClose()); 109 } else if (handle->IsClosing()) { 110 promises.AppendElement(handle->OnClose()); 111 } 112 } 113 114 CloseAllWritablesImpl(promises); 115 116 BoolPromise::AllSettled(GetCurrentSerialEventTarget(), promises) 117 ->Then(GetCurrentSerialEventTarget(), __func__, 118 [resolver = std::move(aResolver)]( 119 const BoolPromise::AllSettledPromiseType::ResolveOrRejectValue& 120 /* aValues */) { resolver(NS_OK); }); 121 122 return IPC_OK(); 123 } 124 125 void FileSystemManagerChild::ActorDestroy(ActorDestroyReason aWhy) { 126 if (mBackgroundRequestHandler) { 127 mBackgroundRequestHandler->ClearActor(); 128 mBackgroundRequestHandler = nullptr; 129 } 130 } 131 132 template <class T> 133 void FileSystemManagerChild::CloseAllWritablesImpl(T& aPromises) { 134 for (const auto& item : ManagedPFileSystemWritableFileStreamChild()) { 135 auto* const child = static_cast<FileSystemWritableFileStreamChild*>(item); 136 auto* const handle = child->MutableWritableFileStreamPtr(); 137 138 if (handle) { 139 if (handle->IsOpen()) { 140 aPromises.AppendElement(handle->BeginAbort()); 141 } else if (handle->IsFinishing()) { 142 aPromises.AppendElement(handle->OnDone()); 143 } 144 } 145 } 146 } 147 148 } // namespace mozilla::dom