tor-browser

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

CallbackRunnables.cpp (8113B)


      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 "CallbackRunnables.h"
      8 
      9 #include "../GetFileOrDirectoryTask.h"
     10 #include "mozilla/dom/DOMException.h"
     11 #include "mozilla/dom/Directory.h"
     12 #include "mozilla/dom/DirectoryBinding.h"
     13 #include "mozilla/dom/File.h"
     14 #include "mozilla/dom/FileBinding.h"
     15 #include "mozilla/dom/FileSystem.h"
     16 #include "mozilla/dom/FileSystemDirectoryReaderBinding.h"
     17 #include "mozilla/dom/FileSystemFileEntry.h"
     18 #include "mozilla/dom/FileSystemUtils.h"
     19 #include "mozilla/dom/Promise.h"
     20 #include "nsIFile.h"
     21 #include "nsIGlobalObject.h"
     22 #include "nsPIDOMWindow.h"
     23 
     24 namespace mozilla::dom {
     25 
     26 EntryCallbackRunnable::EntryCallbackRunnable(FileSystemEntryCallback* aCallback,
     27                                             FileSystemEntry* aEntry)
     28    : Runnable("EntryCallbackRunnable"), mCallback(aCallback), mEntry(aEntry) {
     29  MOZ_ASSERT(aCallback);
     30  MOZ_ASSERT(aEntry);
     31 }
     32 
     33 NS_IMETHODIMP
     34 EntryCallbackRunnable::Run() {
     35  mCallback->Call(*mEntry);
     36  return NS_OK;
     37 }
     38 
     39 ErrorCallbackRunnable::ErrorCallbackRunnable(nsIGlobalObject* aGlobalObject,
     40                                             ErrorCallback* aCallback,
     41                                             nsresult aError)
     42    : Runnable("ErrorCallbackRunnable"),
     43      mGlobal(aGlobalObject),
     44      mCallback(aCallback),
     45      mError(aError) {
     46  MOZ_ASSERT(aGlobalObject);
     47  MOZ_ASSERT(aCallback);
     48  MOZ_ASSERT(NS_FAILED(aError));
     49 }
     50 
     51 NS_IMETHODIMP
     52 ErrorCallbackRunnable::Run() {
     53  RefPtr<DOMException> exception = DOMException::Create(mError);
     54  mCallback->Call(*exception);
     55  return NS_OK;
     56 }
     57 
     58 EmptyEntriesCallbackRunnable::EmptyEntriesCallbackRunnable(
     59    FileSystemEntriesCallback* aCallback)
     60    : Runnable("EmptyEntriesCallbackRunnable"), mCallback(aCallback) {
     61  MOZ_ASSERT(aCallback);
     62 }
     63 
     64 NS_IMETHODIMP
     65 EmptyEntriesCallbackRunnable::Run() {
     66  Sequence<OwningNonNull<FileSystemEntry>> sequence;
     67  mCallback->Call(sequence);
     68  return NS_OK;
     69 }
     70 
     71 GetEntryHelper::GetEntryHelper(FileSystemDirectoryEntry* aParentEntry,
     72                               Directory* aDirectory,
     73                               nsTArray<nsString>& aParts,
     74                               FileSystem* aFileSystem,
     75                               FileSystemEntryCallback* aSuccessCallback,
     76                               ErrorCallback* aErrorCallback,
     77                               FileSystemDirectoryEntry::GetInternalType aType)
     78    : mParentEntry(aParentEntry),
     79      mDirectory(aDirectory),
     80      mParts(aParts.Clone()),
     81      mFileSystem(aFileSystem),
     82      mSuccessCallback(aSuccessCallback),
     83      mErrorCallback(aErrorCallback),
     84      mType(aType) {
     85  MOZ_ASSERT(aParentEntry);
     86  MOZ_ASSERT(aDirectory);
     87  MOZ_ASSERT(!aParts.IsEmpty());
     88  MOZ_ASSERT(aFileSystem);
     89  MOZ_ASSERT(aSuccessCallback || aErrorCallback);
     90 }
     91 
     92 GetEntryHelper::~GetEntryHelper() = default;
     93 
     94 namespace {
     95 
     96 nsresult DOMPathToRealPath(Directory* aDirectory, const nsAString& aPath,
     97                           nsIFile** aFile) {
     98  nsString relativePath;
     99  relativePath = aPath;
    100 
    101  // Trim white spaces.
    102  static const char kWhitespace[] = "\b\t\r\n ";
    103  relativePath.Trim(kWhitespace);
    104 
    105  nsTArray<nsString> parts;
    106  if (!FileSystemUtils::IsValidRelativeDOMPath(relativePath, parts)) {
    107    return NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
    108  }
    109 
    110  nsCOMPtr<nsIFile> file;
    111  nsresult rv = aDirectory->GetInternalNsIFile()->Clone(getter_AddRefs(file));
    112  if (NS_WARN_IF(NS_FAILED(rv))) {
    113    return rv;
    114  }
    115 
    116  for (uint32_t i = 0; i < parts.Length(); ++i) {
    117    rv = file->AppendRelativePath(parts[i]);
    118    if (NS_WARN_IF(NS_FAILED(rv))) {
    119      return rv;
    120    }
    121  }
    122 
    123  file.forget(aFile);
    124  return NS_OK;
    125 }
    126 
    127 }  // namespace
    128 
    129 void GetEntryHelper::Run() {
    130  MOZ_ASSERT(!mParts.IsEmpty());
    131 
    132  nsCOMPtr<nsIFile> realPath;
    133  nsresult error =
    134      DOMPathToRealPath(mDirectory, mParts[0], getter_AddRefs(realPath));
    135 
    136  ErrorResult rv;
    137  RefPtr<FileSystemBase> fs = mDirectory->GetFileSystem(rv);
    138  if (NS_WARN_IF(rv.Failed())) {
    139    rv.SuppressException();
    140    Error(NS_ERROR_DOM_INVALID_STATE_ERR);
    141    return;
    142  }
    143 
    144  RefPtr<GetFileOrDirectoryTaskChild> task =
    145      GetFileOrDirectoryTaskChild::Create(fs, realPath, rv);
    146  if (NS_WARN_IF(rv.Failed())) {
    147    rv.SuppressException();
    148    Error(NS_ERROR_DOM_INVALID_STATE_ERR);
    149    return;
    150  }
    151 
    152  task->SetError(error);
    153  task->Start();
    154 
    155  RefPtr<Promise> promise = task->GetPromise();
    156 
    157  mParts.RemoveElementAt(0);
    158  promise->AppendNativeHandler(this);
    159 }
    160 
    161 void GetEntryHelper::ResolvedCallback(JSContext* aCx,
    162                                      JS::Handle<JS::Value> aValue,
    163                                      ErrorResult& aRv) {
    164  if (NS_WARN_IF(!aValue.isObject())) {
    165    return;
    166  }
    167 
    168  JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
    169 
    170  // This is not the last part of the path.
    171  if (!mParts.IsEmpty()) {
    172    ContinueRunning(obj);
    173    return;
    174  }
    175 
    176  CompleteOperation(obj);
    177 }
    178 
    179 void GetEntryHelper::CompleteOperation(JSObject* aObj) {
    180  MOZ_ASSERT(mParts.IsEmpty());
    181 
    182  if (mType == FileSystemDirectoryEntry::eGetFile) {
    183    RefPtr<File> file;
    184    if (NS_FAILED(UNWRAP_OBJECT(File, aObj, file))) {
    185      Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
    186      return;
    187    }
    188 
    189    RefPtr<FileSystemFileEntry> entry = new FileSystemFileEntry(
    190        mParentEntry->GetParentObject(), file, mParentEntry, mFileSystem);
    191    mSuccessCallback->Call(*entry);
    192    return;
    193  }
    194 
    195  MOZ_ASSERT(mType == FileSystemDirectoryEntry::eGetDirectory);
    196 
    197  RefPtr<Directory> directory;
    198  if (NS_FAILED(UNWRAP_OBJECT(Directory, aObj, directory))) {
    199    Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
    200    return;
    201  }
    202 
    203  RefPtr<FileSystemDirectoryEntry> entry = new FileSystemDirectoryEntry(
    204      mParentEntry->GetParentObject(), directory, mParentEntry, mFileSystem);
    205  mSuccessCallback->Call(*entry);
    206 }
    207 
    208 void GetEntryHelper::ContinueRunning(JSObject* aObj) {
    209  MOZ_ASSERT(!mParts.IsEmpty());
    210 
    211  RefPtr<Directory> directory;
    212  if (NS_FAILED(UNWRAP_OBJECT(Directory, aObj, directory))) {
    213    Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
    214    return;
    215  }
    216 
    217  RefPtr<FileSystemDirectoryEntry> entry = new FileSystemDirectoryEntry(
    218      mParentEntry->GetParentObject(), directory, mParentEntry, mFileSystem);
    219 
    220  // Update the internal values.
    221  mParentEntry = entry;
    222  mDirectory = directory;
    223 
    224  Run();
    225 }
    226 
    227 void GetEntryHelper::RejectedCallback(JSContext* aCx,
    228                                      JS::Handle<JS::Value> aValue,
    229                                      ErrorResult& aRv) {
    230  Error(NS_ERROR_DOM_NOT_FOUND_ERR);
    231 }
    232 
    233 void GetEntryHelper::Error(nsresult aError) {
    234  MOZ_ASSERT(NS_FAILED(aError));
    235 
    236  if (mErrorCallback) {
    237    RefPtr<ErrorCallbackRunnable> runnable = new ErrorCallbackRunnable(
    238        mParentEntry->GetParentObject(), mErrorCallback, aError);
    239 
    240    FileSystemUtils::DispatchRunnable(mParentEntry->GetParentObject(),
    241                                      runnable.forget());
    242  }
    243 }
    244 
    245 NS_IMPL_ISUPPORTS0(GetEntryHelper);
    246 
    247 /* static */
    248 void FileSystemEntryCallbackHelper::Call(
    249    nsIGlobalObject* aGlobalObject,
    250    const Optional<OwningNonNull<FileSystemEntryCallback>>& aEntryCallback,
    251    FileSystemEntry* aEntry) {
    252  MOZ_ASSERT(aGlobalObject);
    253  MOZ_ASSERT(aEntry);
    254 
    255  if (aEntryCallback.WasPassed()) {
    256    RefPtr<EntryCallbackRunnable> runnable =
    257        new EntryCallbackRunnable(&aEntryCallback.Value(), aEntry);
    258 
    259    FileSystemUtils::DispatchRunnable(aGlobalObject, runnable.forget());
    260  }
    261 }
    262 
    263 /* static */
    264 void ErrorCallbackHelper::Call(
    265    nsIGlobalObject* aGlobal,
    266    const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
    267    nsresult aError) {
    268  MOZ_ASSERT(aGlobal);
    269  MOZ_ASSERT(NS_FAILED(aError));
    270 
    271  if (aErrorCallback.WasPassed()) {
    272    RefPtr<ErrorCallbackRunnable> runnable =
    273        new ErrorCallbackRunnable(aGlobal, &aErrorCallback.Value(), aError);
    274 
    275    FileSystemUtils::DispatchRunnable(aGlobal, runnable.forget());
    276  }
    277 }
    278 
    279 }  // namespace mozilla::dom