tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GetFileOrDirectoryTask.cpp (7418B)


      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "GetFileOrDirectoryTask.h"
      8 
      9 #include "js/Value.h"
     10 #include "mozilla/dom/FileBlobImpl.h"
     11 #include "mozilla/dom/FileSystemBase.h"
     12 #include "mozilla/dom/FileSystemUtils.h"
     13 #include "mozilla/dom/IPCBlobUtils.h"
     14 #include "mozilla/dom/PFileSystemParams.h"
     15 #include "mozilla/dom/Promise.h"
     16 #include "mozilla/ipc/BackgroundParent.h"
     17 #include "nsIFile.h"
     18 #include "nsString.h"
     19 
     20 namespace mozilla::dom {
     21 
     22 /**
     23 * GetFileOrDirectoryTaskChild
     24 */
     25 
     26 /* static */
     27 already_AddRefed<GetFileOrDirectoryTaskChild>
     28 GetFileOrDirectoryTaskChild::Create(FileSystemBase* aFileSystem,
     29                                    nsIFile* aTargetPath, ErrorResult& aRv) {
     30  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
     31  MOZ_ASSERT(aFileSystem);
     32 
     33  nsCOMPtr<nsIGlobalObject> globalObject = aFileSystem->GetParentObject();
     34  if (NS_WARN_IF(!globalObject)) {
     35    aRv.Throw(NS_ERROR_FAILURE);
     36    return nullptr;
     37  }
     38 
     39  RefPtr<GetFileOrDirectoryTaskChild> task =
     40      new GetFileOrDirectoryTaskChild(globalObject, aFileSystem, aTargetPath);
     41 
     42  // aTargetPath can be null. In this case SetError will be called.
     43 
     44  task->mPromise = Promise::Create(globalObject, aRv);
     45  if (NS_WARN_IF(aRv.Failed())) {
     46    return nullptr;
     47  }
     48 
     49  return task.forget();
     50 }
     51 
     52 GetFileOrDirectoryTaskChild::GetFileOrDirectoryTaskChild(
     53    nsIGlobalObject* aGlobalObject, FileSystemBase* aFileSystem,
     54    nsIFile* aTargetPath)
     55    : FileSystemTaskChildBase(aGlobalObject, aFileSystem),
     56      mTargetPath(aTargetPath) {
     57  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
     58  MOZ_ASSERT(aFileSystem);
     59 }
     60 
     61 GetFileOrDirectoryTaskChild::~GetFileOrDirectoryTaskChild() {
     62  MOZ_ASSERT(NS_IsMainThread());
     63 }
     64 
     65 already_AddRefed<Promise> GetFileOrDirectoryTaskChild::GetPromise() {
     66  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
     67  return RefPtr<Promise>(mPromise).forget();
     68 }
     69 
     70 FileSystemParams GetFileOrDirectoryTaskChild::GetRequestParams(
     71    const nsString& aSerializedDOMPath, ErrorResult& aRv) const {
     72  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
     73 
     74  nsAutoString path;
     75  aRv = mTargetPath->GetPath(path);
     76  if (NS_WARN_IF(aRv.Failed())) {
     77    return FileSystemGetFileOrDirectoryParams();
     78  }
     79 
     80  return FileSystemGetFileOrDirectoryParams(aSerializedDOMPath, path);
     81 }
     82 
     83 void GetFileOrDirectoryTaskChild::SetSuccessRequestResult(
     84    const FileSystemResponseValue& aValue, ErrorResult& aRv) {
     85  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
     86  switch (aValue.type()) {
     87    case FileSystemResponseValue::TFileSystemFileResponse: {
     88      FileSystemFileResponse r = aValue;
     89 
     90      RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(r.blob());
     91      MOZ_ASSERT(blobImpl);
     92 
     93      nsCOMPtr<nsIGlobalObject> globalObject = mFileSystem->GetParentObject();
     94      MOZ_ASSERT(globalObject);
     95 
     96      mResultFile = File::Create(globalObject, blobImpl);
     97      if (NS_WARN_IF(!mResultFile)) {
     98        aRv.Throw(NS_ERROR_FAILURE);
     99      }
    100      break;
    101    }
    102    case FileSystemResponseValue::TFileSystemDirectoryResponse: {
    103      FileSystemDirectoryResponse r = aValue;
    104 
    105      nsCOMPtr<nsIFile> file;
    106      aRv = NS_NewLocalFile(r.realPath(), getter_AddRefs(file));
    107      if (NS_WARN_IF(aRv.Failed())) {
    108        return;
    109      }
    110 
    111      mResultDirectory =
    112          Directory::Create(mFileSystem->GetParentObject(), file, mFileSystem);
    113      MOZ_ASSERT(mResultDirectory);
    114      break;
    115    }
    116    default: {
    117      MOZ_CRASH("not reached");
    118      break;
    119    }
    120  }
    121 }
    122 
    123 void GetFileOrDirectoryTaskChild::HandlerCallback() {
    124  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
    125  if (mFileSystem->IsShutdown()) {
    126    mPromise = nullptr;
    127    return;
    128  }
    129 
    130  if (HasError()) {
    131    mPromise->MaybeReject(mErrorValue);
    132    mPromise = nullptr;
    133    return;
    134  }
    135 
    136  if (mResultDirectory) {
    137    mPromise->MaybeResolve(mResultDirectory);
    138    mResultDirectory = nullptr;
    139    mPromise = nullptr;
    140    return;
    141  }
    142 
    143  MOZ_ASSERT(mResultFile);
    144  mPromise->MaybeResolve(mResultFile);
    145  mResultFile = nullptr;
    146  mPromise = nullptr;
    147 }
    148 
    149 /**
    150 * GetFileOrDirectoryTaskParent
    151 */
    152 
    153 /* static */
    154 already_AddRefed<GetFileOrDirectoryTaskParent>
    155 GetFileOrDirectoryTaskParent::Create(
    156    FileSystemBase* aFileSystem,
    157    const FileSystemGetFileOrDirectoryParams& aParam,
    158    FileSystemRequestParent* aParent, ErrorResult& aRv) {
    159  MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
    160  mozilla::ipc::AssertIsOnBackgroundThread();
    161  MOZ_ASSERT(aFileSystem);
    162 
    163  RefPtr<GetFileOrDirectoryTaskParent> task =
    164      new GetFileOrDirectoryTaskParent(aFileSystem, aParam, aParent);
    165 
    166  aRv = NS_NewLocalFile(aParam.realPath(), getter_AddRefs(task->mTargetPath));
    167  if (NS_WARN_IF(aRv.Failed())) {
    168    return nullptr;
    169  }
    170 
    171  return task.forget();
    172 }
    173 
    174 GetFileOrDirectoryTaskParent::GetFileOrDirectoryTaskParent(
    175    FileSystemBase* aFileSystem,
    176    const FileSystemGetFileOrDirectoryParams& aParam,
    177    FileSystemRequestParent* aParent)
    178    : FileSystemTaskParentBase(aFileSystem, aParam, aParent),
    179      mIsDirectory(false) {
    180  MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
    181  mozilla::ipc::AssertIsOnBackgroundThread();
    182  MOZ_ASSERT(aFileSystem);
    183 }
    184 
    185 FileSystemResponseValue GetFileOrDirectoryTaskParent::GetSuccessRequestResult(
    186    ErrorResult& aRv) const {
    187  mozilla::ipc::AssertIsOnBackgroundThread();
    188 
    189  nsAutoString path;
    190  aRv = mTargetPath->GetPath(path);
    191  if (NS_WARN_IF(aRv.Failed())) {
    192    return FileSystemDirectoryResponse();
    193  }
    194 
    195  if (mIsDirectory) {
    196    return FileSystemDirectoryResponse(path);
    197  }
    198 
    199  RefPtr<BlobImpl> blobImpl = new FileBlobImpl(mTargetPath);
    200 
    201  IPCBlob ipcBlob;
    202  aRv = IPCBlobUtils::Serialize(blobImpl, ipcBlob);
    203  if (NS_WARN_IF(aRv.Failed())) {
    204    return FileSystemDirectoryResponse();
    205  }
    206 
    207  return FileSystemFileResponse(ipcBlob);
    208 }
    209 
    210 nsresult GetFileOrDirectoryTaskParent::IOWork() {
    211  MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
    212  MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
    213 
    214  if (mFileSystem->IsShutdown()) {
    215    return NS_ERROR_FAILURE;
    216  }
    217 
    218  // Whether we want to get the root directory.
    219  bool exists;
    220  nsresult rv = mTargetPath->Exists(&exists);
    221  if (NS_WARN_IF(NS_FAILED(rv))) {
    222    return rv;
    223  }
    224 
    225  if (!exists) {
    226    if (!mFileSystem->ShouldCreateDirectory()) {
    227      return NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
    228    }
    229 
    230    rv = mTargetPath->Create(nsIFile::DIRECTORY_TYPE, 0777);
    231    if (NS_WARN_IF(NS_FAILED(rv))) {
    232      return rv;
    233    }
    234  }
    235 
    236  // Get isDirectory.
    237  rv = mTargetPath->IsDirectory(&mIsDirectory);
    238  if (NS_WARN_IF(NS_FAILED(rv))) {
    239    return rv;
    240  }
    241 
    242  if (mIsDirectory) {
    243    return NS_OK;
    244  }
    245 
    246  bool isFile;
    247  // Get isFile
    248  rv = mTargetPath->IsFile(&isFile);
    249  if (NS_WARN_IF(NS_FAILED(rv))) {
    250    return rv;
    251  }
    252 
    253  if (!isFile) {
    254    // Neither directory or file.
    255    return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
    256  }
    257 
    258  if (!mFileSystem->IsSafeFile(mTargetPath)) {
    259    return NS_ERROR_DOM_SECURITY_ERR;
    260  }
    261 
    262  return NS_OK;
    263 }
    264 
    265 nsresult GetFileOrDirectoryTaskParent::GetTargetPath(nsAString& aPath) const {
    266  return mTargetPath->GetPath(aPath);
    267 }
    268 
    269 }  // namespace mozilla::dom