FileSystemManager.cpp (6269B)
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 "mozilla/dom/FileSystemManager.h" 8 9 #include "FileSystemBackgroundRequestHandler.h" 10 #include "fs/FileSystemRequestHandler.h" 11 #include "mozilla/ErrorResult.h" 12 #include "mozilla/dom/FileSystemManagerChild.h" 13 #include "mozilla/dom/Promise.h" 14 #include "mozilla/dom/StorageManager.h" 15 #include "mozilla/dom/fs/ManagedMozPromiseRequestHolder.h" 16 #include "mozilla/dom/quota/QuotaCommon.h" 17 #include "mozilla/dom/quota/ResultExtensions.h" 18 19 namespace mozilla::dom { 20 21 FileSystemManager::FileSystemManager( 22 nsIGlobalObject* aGlobal, RefPtr<StorageManager> aStorageManager, 23 RefPtr<FileSystemBackgroundRequestHandler> aBackgroundRequestHandler) 24 : mGlobal(aGlobal), 25 mStorageManager(std::move(aStorageManager)), 26 mBackgroundRequestHandler(std::move(aBackgroundRequestHandler)), 27 mRequestHandler(new fs::FileSystemRequestHandler()) {} 28 29 FileSystemManager::FileSystemManager(nsIGlobalObject* aGlobal, 30 RefPtr<StorageManager> aStorageManager) 31 : FileSystemManager(aGlobal, std::move(aStorageManager), 32 MakeRefPtr<FileSystemBackgroundRequestHandler>()) {} 33 34 FileSystemManager::~FileSystemManager() { MOZ_ASSERT(mShutdown); } 35 36 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FileSystemManager) 37 NS_INTERFACE_MAP_ENTRY(nsISupports) 38 NS_INTERFACE_MAP_END 39 NS_IMPL_CYCLE_COLLECTING_ADDREF(FileSystemManager); 40 NS_IMPL_CYCLE_COLLECTING_RELEASE(FileSystemManager); 41 NS_IMPL_CYCLE_COLLECTION(FileSystemManager, mGlobal, mStorageManager); 42 43 void FileSystemManager::Shutdown() { 44 mShutdown.Flip(); 45 46 auto shutdownAndDisconnect = [self = RefPtr(this)]() { 47 self->mBackgroundRequestHandler->Shutdown(); 48 49 for (RefPtr<PromiseRequestHolder<FileSystemManagerChild::ActorPromise>> 50 holder : self->mPromiseRequestHolders.ForwardRange()) { 51 holder->DisconnectIfExists(); 52 } 53 }; 54 55 if (NS_IsMainThread()) { 56 if (mBackgroundRequestHandler->FileSystemManagerChildStrongRef()) { 57 mBackgroundRequestHandler->FileSystemManagerChildStrongRef() 58 ->CloseAllWritables( 59 [shutdownAndDisconnect = std::move(shutdownAndDisconnect)]() { 60 shutdownAndDisconnect(); 61 }); 62 } else { 63 shutdownAndDisconnect(); 64 } 65 } else { 66 if (mBackgroundRequestHandler->FileSystemManagerChildStrongRef()) { 67 // FileSystemAccessHandles and FileSystemWritableFileStreams prevent 68 // shutdown until they are full closed, so at this point, they all should 69 // be closed. 70 MOZ_ASSERT(mBackgroundRequestHandler->FileSystemManagerChildStrongRef() 71 ->AllSyncAccessHandlesClosed()); 72 MOZ_ASSERT(mBackgroundRequestHandler->FileSystemManagerChildStrongRef() 73 ->AllWritableFileStreamsClosed()); 74 } 75 76 shutdownAndDisconnect(); 77 } 78 } 79 80 const RefPtr<FileSystemManagerChild>& FileSystemManager::ActorStrongRef() 81 const { 82 return mBackgroundRequestHandler->FileSystemManagerChildStrongRef(); 83 } 84 85 void FileSystemManager::RegisterPromiseRequestHolder( 86 PromiseRequestHolder<FileSystemManagerChild::ActorPromise>* aHolder) { 87 mPromiseRequestHolders.AppendElement(aHolder); 88 } 89 90 void FileSystemManager::UnregisterPromiseRequestHolder( 91 PromiseRequestHolder<FileSystemManagerChild::ActorPromise>* aHolder) { 92 mPromiseRequestHolders.RemoveElement(aHolder); 93 } 94 95 void FileSystemManager::BeginRequest( 96 MoveOnlyFunction<void(RefPtr<FileSystemManagerChild>)>&& aSuccess, 97 MoveOnlyFunction<void(nsresult)>&& aFailure) { 98 MOZ_ASSERT(!mShutdown); 99 100 MOZ_ASSERT(mGlobal); 101 102 nsICookieJarSettings* cookieJarSettings = mGlobal->GetCookieJarSettings(); 103 nsIPrincipal* unpartitionedPrincipal = mGlobal->PrincipalOrNull(); 104 if (NS_WARN_IF(!cookieJarSettings) || NS_WARN_IF(!unpartitionedPrincipal) || 105 NS_WARN_IF(unpartitionedPrincipal->GetIsInPrivateBrowsing())) { 106 // ePartition values can be returned for Private Browsing Mode 107 // for third-party iframes, so we also need to check the private browsing 108 // in that case which means we need to check the principal. 109 aFailure(NS_ERROR_DOM_SECURITY_ERR); 110 return; 111 } 112 113 // Check if we're allowed to use storage. 114 StorageAccess access = mGlobal->GetStorageAccess(); 115 116 // Use allow list to decide the permission. 117 const bool allowed = access == StorageAccess::eAllow || 118 StoragePartitioningEnabled(access, cookieJarSettings); 119 if (NS_WARN_IF(!allowed)) { 120 aFailure(NS_ERROR_DOM_SECURITY_ERR); 121 return; 122 } 123 124 if (mBackgroundRequestHandler->FileSystemManagerChildStrongRef()) { 125 aSuccess(mBackgroundRequestHandler->FileSystemManagerChildStrongRef()); 126 return; 127 } 128 129 auto holder = 130 MakeRefPtr<PromiseRequestHolder<FileSystemManagerChild::ActorPromise>>( 131 this); 132 133 QM_TRY_INSPECT(const auto& principalInfo, mGlobal->GetStorageKey(), QM_VOID, 134 [&aFailure](nsresult rv) { aFailure(rv); }); 135 136 mBackgroundRequestHandler->CreateFileSystemManagerChild(principalInfo) 137 ->Then( 138 GetCurrentSerialEventTarget(), __func__, 139 [self = RefPtr<FileSystemManager>(this), holder, 140 success = std::move(aSuccess), failure = std::move(aFailure)]( 141 const FileSystemManagerChild::ActorPromise::ResolveOrRejectValue& 142 aValue) mutable { 143 holder->Complete(); 144 145 if (aValue.IsResolve()) { 146 success(aValue.ResolveValue()); 147 } else { 148 failure(aValue.RejectValue()); 149 } 150 }) 151 ->Track(*holder); 152 } 153 154 already_AddRefed<Promise> FileSystemManager::GetDirectory(ErrorResult& aError) { 155 MOZ_ASSERT(mGlobal); 156 157 RefPtr<Promise> promise = Promise::Create(mGlobal, aError); 158 if (NS_WARN_IF(aError.Failed())) { 159 return nullptr; 160 } 161 162 MOZ_ASSERT(promise); 163 164 mRequestHandler->GetRootHandle(this, promise, aError); 165 if (NS_WARN_IF(aError.Failed())) { 166 return nullptr; 167 } 168 169 return promise.forget(); 170 } 171 172 } // namespace mozilla::dom