FileSystemAccessHandle.cpp (7998B)
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 "FileSystemAccessHandle.h" 8 9 #include "FileSystemDatabaseManager.h" 10 #include "FileSystemParentTypes.h" 11 #include "mozilla/dom/FileSystemDataManager.h" 12 #include "mozilla/dom/FileSystemHelpers.h" 13 #include "mozilla/dom/FileSystemLog.h" 14 #include "mozilla/dom/quota/FileStreams.h" 15 #include "mozilla/dom/quota/QuotaCommon.h" 16 #include "mozilla/dom/quota/RemoteQuotaObjectParent.h" 17 #include "mozilla/dom/quota/ResultExtensions.h" 18 #include "mozilla/ipc/RandomAccessStreamParams.h" 19 #include "mozilla/ipc/RandomAccessStreamUtils.h" 20 #include "nsIFileStreams.h" 21 22 namespace mozilla::dom { 23 24 FileSystemAccessHandle::FileSystemAccessHandle( 25 RefPtr<fs::data::FileSystemDataManager> aDataManager, 26 const fs::EntryId& aEntryId, MovingNotNull<RefPtr<TaskQueue>> aIOTaskQueue) 27 : mEntryId(aEntryId), 28 mDataManager(std::move(aDataManager)), 29 mIOTaskQueue(std::move(aIOTaskQueue)), 30 mActor(nullptr), 31 mControlActor(nullptr), 32 mRegCount(0), 33 mLocked(false), 34 mRegistered(false), 35 mClosed(false) {} 36 37 FileSystemAccessHandle::~FileSystemAccessHandle() { 38 MOZ_DIAGNOSTIC_ASSERT(mClosed); 39 } 40 41 // static 42 RefPtr<FileSystemAccessHandle::CreatePromise> FileSystemAccessHandle::Create( 43 RefPtr<fs::data::FileSystemDataManager> aDataManager, 44 const fs::EntryId& aEntryId) { 45 MOZ_ASSERT(aDataManager); 46 aDataManager->AssertIsOnIOTarget(); 47 48 RefPtr<TaskQueue> ioTaskQueue = TaskQueue::Create( 49 do_AddRef(aDataManager->MutableIOTargetPtr()), "FileSystemAccessHandle"); 50 51 RefPtr<FileSystemAccessHandle> accessHandle = new FileSystemAccessHandle( 52 std::move(aDataManager), aEntryId, WrapMovingNotNull(ioTaskQueue)); 53 54 return accessHandle->BeginInit()->Then( 55 GetCurrentSerialEventTarget(), __func__, 56 [accessHandle = fs::Registered<FileSystemAccessHandle>(accessHandle)]( 57 InitPromise::ResolveOrRejectValue&& value) mutable { 58 if (value.IsReject()) { 59 return CreatePromise::CreateAndReject(value.RejectValue(), __func__); 60 } 61 62 mozilla::ipc::RandomAccessStreamParams streamParams = 63 std::move(value.ResolveValue()); 64 65 return CreatePromise::CreateAndResolve( 66 std::pair(std::move(accessHandle), std::move(streamParams)), 67 __func__); 68 }); 69 } 70 71 NS_IMPL_ISUPPORTS_INHERITED0(FileSystemAccessHandle, FileSystemStreamCallbacks) 72 73 void FileSystemAccessHandle::Register() { ++mRegCount; } 74 75 void FileSystemAccessHandle::Unregister() { 76 MOZ_ASSERT(mRegCount > 0); 77 78 --mRegCount; 79 80 if (IsInactive() && IsOpen()) { 81 BeginClose(); 82 } 83 } 84 85 void FileSystemAccessHandle::RegisterActor( 86 NotNull<FileSystemAccessHandleParent*> aActor) { 87 MOZ_ASSERT(!mActor); 88 89 mActor = aActor; 90 } 91 92 void FileSystemAccessHandle::UnregisterActor( 93 NotNull<FileSystemAccessHandleParent*> aActor) { 94 MOZ_ASSERT(mActor); 95 MOZ_ASSERT(mActor == aActor); 96 97 mActor = nullptr; 98 99 if (IsInactive() && IsOpen()) { 100 BeginClose(); 101 } 102 } 103 104 void FileSystemAccessHandle::RegisterControlActor( 105 NotNull<FileSystemAccessHandleControlParent*> aControlActor) { 106 MOZ_ASSERT(!mControlActor); 107 108 mControlActor = aControlActor; 109 } 110 111 void FileSystemAccessHandle::UnregisterControlActor( 112 NotNull<FileSystemAccessHandleControlParent*> aControlActor) { 113 MOZ_ASSERT(mControlActor); 114 MOZ_ASSERT(mControlActor == aControlActor); 115 116 mControlActor = nullptr; 117 118 if (IsInactive() && IsOpen()) { 119 BeginClose(); 120 } 121 } 122 123 bool FileSystemAccessHandle::IsOpen() const { return !mClosed; } 124 125 RefPtr<BoolPromise> FileSystemAccessHandle::BeginClose() { 126 MOZ_ASSERT(IsOpen()); 127 128 LOG(("Closing AccessHandle")); 129 130 mClosed = true; 131 132 return InvokeAsync(mIOTaskQueue.get(), __func__, 133 [self = RefPtr(this)]() { 134 if (self->mRemoteQuotaObjectParent) { 135 self->mRemoteQuotaObjectParent->Close(); 136 } 137 138 return BoolPromise::CreateAndResolve(true, __func__); 139 }) 140 ->Then(GetCurrentSerialEventTarget(), __func__, 141 [self = RefPtr(this)](const BoolPromise::ResolveOrRejectValue&) { 142 return self->mIOTaskQueue->BeginShutdown(); 143 }) 144 ->Then( 145 GetCurrentSerialEventTarget(), __func__, 146 [self = RefPtr(this)](const ShutdownPromise::ResolveOrRejectValue&) { 147 if (self->mLocked) { 148 self->mDataManager->UnlockExclusive(self->mEntryId); 149 } 150 151 return BoolPromise::CreateAndResolve(true, __func__); 152 }) 153 ->Then(mDataManager->MutableBackgroundTargetPtr(), __func__, 154 [self = RefPtr(this)](const BoolPromise::ResolveOrRejectValue&) { 155 if (self->mRegistered) { 156 self->mDataManager->UnregisterAccessHandle(WrapNotNull(self)); 157 } 158 159 self->mDataManager = nullptr; 160 161 return BoolPromise::CreateAndResolve(true, __func__); 162 }); 163 } 164 165 bool FileSystemAccessHandle::IsInactive() const { 166 return !mRegCount && !mActor && !mControlActor; 167 } 168 169 RefPtr<FileSystemAccessHandle::InitPromise> 170 FileSystemAccessHandle::BeginInit() { 171 QM_TRY_UNWRAP(fs::FileId fileId, mDataManager->LockExclusive(mEntryId), 172 [](const auto& aRv) { 173 return InitPromise::CreateAndReject(ToNSResult(aRv), 174 __func__); 175 }); 176 177 mLocked = true; 178 179 auto CreateAndRejectInitPromise = [](StaticString aFunc, nsresult aRv) { 180 return CreateAndRejectMozPromise<InitPromise>(aFunc, aRv); 181 }; 182 183 fs::ContentType type; 184 fs::TimeStamp lastModifiedMilliSeconds; 185 fs::Path path; 186 nsCOMPtr<nsIFile> file; 187 QM_TRY(MOZ_TO_RESULT(mDataManager->MutableDatabaseManagerPtr()->GetFile( 188 mEntryId, fileId, fs::FileMode::EXCLUSIVE, type, 189 lastModifiedMilliSeconds, path, file)), 190 CreateAndRejectInitPromise); 191 192 if (LOG_ENABLED()) { 193 nsAutoString path; 194 if (NS_SUCCEEDED(file->GetPath(path))) { 195 LOG(("Opening SyncAccessHandle %s", NS_ConvertUTF16toUTF8(path).get())); 196 } 197 } 198 199 return InvokeAsync( 200 mDataManager->MutableBackgroundTargetPtr(), __func__, 201 [self = RefPtr(this)]() { 202 self->mDataManager->RegisterAccessHandle(WrapNotNull(self)); 203 204 self->mRegistered = true; 205 206 return BoolPromise::CreateAndResolve(true, __func__); 207 }) 208 ->Then(mIOTaskQueue.get(), __func__, 209 [self = RefPtr(this), CreateAndRejectInitPromise, 210 file = std::move(file)]( 211 const BoolPromise::ResolveOrRejectValue& value) { 212 if (value.IsReject()) { 213 return InitPromise::CreateAndReject(value.RejectValue(), 214 __func__); 215 } 216 217 QM_TRY_UNWRAP(nsCOMPtr<nsIRandomAccessStream> stream, 218 CreateFileRandomAccessStream( 219 quota::PERSISTENCE_TYPE_DEFAULT, 220 self->mDataManager->OriginMetadataRef(), 221 quota::Client::FILESYSTEM, file, -1, -1, 222 nsIFileRandomAccessStream::DEFER_OPEN), 223 CreateAndRejectInitPromise); 224 225 mozilla::ipc::RandomAccessStreamParams streamParams = 226 mozilla::ipc::SerializeRandomAccessStream( 227 WrapMovingNotNullUnchecked(std::move(stream)), self); 228 229 return InitPromise::CreateAndResolve(std::move(streamParams), 230 __func__); 231 }); 232 } 233 234 } // namespace mozilla::dom