tor-browser

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

FileSystemRequestParent.cpp (5447B)


      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/FileSystemRequestParent.h"
      8 
      9 #include "GetDirectoryListingTask.h"
     10 #include "GetFileOrDirectoryTask.h"
     11 #include "GetFilesTask.h"
     12 #include "mozilla/Preferences.h"
     13 #include "mozilla/dom/BlobImpl.h"
     14 #include "mozilla/dom/ContentParent.h"
     15 #include "mozilla/dom/FileSystemBase.h"
     16 #include "mozilla/dom/FileSystemSecurity.h"
     17 #include "mozilla/dom/OSFileSystem.h"
     18 #include "mozilla/dom/PFileSystemParams.h"
     19 #include "mozilla/ipc/BackgroundParent.h"
     20 #include "nsProxyRelease.h"
     21 
     22 using namespace mozilla::ipc;
     23 
     24 namespace mozilla::dom {
     25 
     26 FileSystemRequestParent::FileSystemRequestParent() : mDestroyed(false) {
     27  AssertIsOnBackgroundThread();
     28 }
     29 
     30 FileSystemRequestParent::~FileSystemRequestParent() {
     31  AssertIsOnBackgroundThread();
     32 }
     33 
     34 #define FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(name)          \
     35  case FileSystemParams::TFileSystem##name##Params: {           \
     36    const FileSystem##name##Params& p = aParams;                \
     37    mFileSystem = new OSFileSystemParent(p.filesystem());       \
     38    MOZ_ASSERT(mFileSystem);                                    \
     39    mTask = name##TaskParent::Create(mFileSystem, p, this, rv); \
     40    if (NS_WARN_IF(rv.Failed())) {                              \
     41      rv.SuppressException();                                   \
     42      return false;                                             \
     43    }                                                           \
     44    break;                                                      \
     45  }
     46 
     47 bool FileSystemRequestParent::Initialize(const FileSystemParams& aParams) {
     48  AssertIsOnBackgroundThread();
     49 
     50  ErrorResult rv;
     51 
     52  switch (aParams.type()) {
     53    FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetDirectoryListing)
     54    FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetFileOrDirectory)
     55    FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetFiles)
     56 
     57    default: {
     58      MOZ_CRASH("not reached");
     59      break;
     60    }
     61  }
     62 
     63  if (NS_WARN_IF(!mTask || !mFileSystem)) {
     64    // Should never reach here.
     65    return false;
     66  }
     67 
     68  return true;
     69 }
     70 
     71 namespace {
     72 
     73 class CheckPermissionRunnable final : public Runnable {
     74 public:
     75  CheckPermissionRunnable(
     76      already_AddRefed<ThreadsafeContentParentHandle> aParent,
     77      FileSystemRequestParent* aActor, FileSystemTaskParentBase* aTask,
     78      const nsAString& aPath)
     79      : Runnable("dom::CheckPermissionRunnable"),
     80        mContentHandle(aParent),
     81        mActor(aActor),
     82        mTask(aTask),
     83        mPath(aPath),
     84        mBackgroundEventTarget(GetCurrentSerialEventTarget()) {
     85    AssertIsInMainProcess();
     86    AssertIsOnBackgroundThread();
     87 
     88    MOZ_ASSERT(mContentHandle);
     89    MOZ_ASSERT(mActor);
     90    MOZ_ASSERT(mTask);
     91    MOZ_ASSERT(mBackgroundEventTarget);
     92  }
     93 
     94  NS_IMETHOD
     95  Run() override {
     96    if (NS_IsMainThread()) {
     97      if (!mozilla::Preferences::GetBool("dom.filesystem.pathcheck.disabled",
     98                                         false)) {
     99        RefPtr<FileSystemSecurity> fss = FileSystemSecurity::Get();
    100        if (NS_WARN_IF(!fss || !fss->ContentProcessHasAccessTo(
    101                                   mContentHandle->ChildID(), mPath))) {
    102          AssertIsOnMainThread();
    103          if (RefPtr<ContentParent> contentParent =
    104                  mContentHandle->GetContentParent()) {
    105            contentParent->KillHard("This path is not allowed.");
    106          }
    107          return NS_OK;
    108        }
    109      }
    110 
    111      return mBackgroundEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
    112    }
    113 
    114    AssertIsOnBackgroundThread();
    115 
    116    // It can happen that this actor has been destroyed in the meantime we were
    117    // on the main-thread.
    118    if (!mActor->Destroyed()) {
    119      mTask->Start();
    120    }
    121 
    122    return NS_OK;
    123  }
    124 
    125 private:
    126  ~CheckPermissionRunnable() {
    127    NS_ProxyRelease("CheckPermissionRunnable::mActor", mBackgroundEventTarget,
    128                    mActor.forget());
    129  }
    130 
    131  RefPtr<ThreadsafeContentParentHandle> mContentHandle;
    132  RefPtr<FileSystemRequestParent> mActor;
    133  RefPtr<FileSystemTaskParentBase> mTask;
    134  const nsString mPath;
    135 
    136  nsCOMPtr<nsIEventTarget> mBackgroundEventTarget;
    137 };
    138 
    139 }  // namespace
    140 
    141 void FileSystemRequestParent::Start() {
    142  AssertIsInMainProcess();
    143  AssertIsOnBackgroundThread();
    144 
    145  MOZ_ASSERT(!mDestroyed);
    146  MOZ_ASSERT(mFileSystem);
    147  MOZ_ASSERT(mTask);
    148 
    149  nsAutoString path;
    150  if (NS_WARN_IF(NS_FAILED(mTask->GetTargetPath(path)))) {
    151    (void)Send__delete__(this,
    152                         FileSystemErrorResponse(NS_ERROR_DOM_SECURITY_ERR));
    153    return;
    154  }
    155 
    156  RefPtr<ThreadsafeContentParentHandle> parent =
    157      BackgroundParent::GetContentParentHandle(Manager());
    158 
    159  // If the ThreadsafeContentParentHandle is null we are dealing with a
    160  // same-process actor.
    161  if (!parent) {
    162    mTask->Start();
    163    return;
    164  }
    165 
    166  RefPtr<Runnable> runnable =
    167      new CheckPermissionRunnable(parent.forget(), this, mTask, path);
    168  NS_DispatchToMainThread(runnable);
    169 }
    170 
    171 void FileSystemRequestParent::ActorDestroy(ActorDestroyReason aWhy) {
    172  AssertIsOnBackgroundThread();
    173  MOZ_ASSERT(!mDestroyed);
    174 
    175  if (!mFileSystem) {
    176    return;
    177  }
    178 
    179  mFileSystem->Shutdown();
    180  mFileSystem = nullptr;
    181  mTask = nullptr;
    182  mDestroyed = true;
    183 }
    184 
    185 }  // namespace mozilla::dom