forked from mirrors/gecko-dev
This only changes the behaviour when called with a TaskQueue or other type using SerialEventTargetGuard on the stack. They are being switched over as the existing GetCurrentEventTarget method is being removed, as it is somewhat confusing, and poorly documented. Callers which need to get the current thread even when on a threadpool or behind a TaskQueue were switched to GetCurrentEventTarget in the previous part. Differential Revision: https://phabricator.services.mozilla.com/D166607
188 lines
5.4 KiB
C++
188 lines
5.4 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/dom/FileSystemRequestParent.h"
|
|
#include "mozilla/dom/PFileSystemParams.h"
|
|
|
|
#include "GetDirectoryListingTask.h"
|
|
#include "GetFileOrDirectoryTask.h"
|
|
#include "GetFilesTask.h"
|
|
|
|
#include "mozilla/dom/BlobImpl.h"
|
|
#include "mozilla/dom/ContentParent.h"
|
|
#include "mozilla/dom/FileSystemBase.h"
|
|
#include "mozilla/dom/FileSystemSecurity.h"
|
|
#include "mozilla/ipc/BackgroundParent.h"
|
|
#include "mozilla/dom/OSFileSystem.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "mozilla/ScopeExit.h"
|
|
#include "mozilla/Unused.h"
|
|
#include "nsProxyRelease.h"
|
|
|
|
using namespace mozilla::ipc;
|
|
|
|
namespace mozilla::dom {
|
|
|
|
FileSystemRequestParent::FileSystemRequestParent() : mDestroyed(false) {
|
|
AssertIsOnBackgroundThread();
|
|
}
|
|
|
|
FileSystemRequestParent::~FileSystemRequestParent() {
|
|
AssertIsOnBackgroundThread();
|
|
}
|
|
|
|
#define FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(name) \
|
|
case FileSystemParams::TFileSystem##name##Params: { \
|
|
const FileSystem##name##Params& p = aParams; \
|
|
mFileSystem = new OSFileSystemParent(p.filesystem()); \
|
|
MOZ_ASSERT(mFileSystem); \
|
|
mTask = name##TaskParent::Create(mFileSystem, p, this, rv); \
|
|
if (NS_WARN_IF(rv.Failed())) { \
|
|
rv.SuppressException(); \
|
|
return false; \
|
|
} \
|
|
break; \
|
|
}
|
|
|
|
bool FileSystemRequestParent::Initialize(const FileSystemParams& aParams) {
|
|
AssertIsOnBackgroundThread();
|
|
|
|
ErrorResult rv;
|
|
|
|
switch (aParams.type()) {
|
|
FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetDirectoryListing)
|
|
FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetFileOrDirectory)
|
|
FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetFiles)
|
|
|
|
default: {
|
|
MOZ_CRASH("not reached");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NS_WARN_IF(!mTask || !mFileSystem)) {
|
|
// Should never reach here.
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
namespace {
|
|
|
|
class CheckPermissionRunnable final : public Runnable {
|
|
public:
|
|
CheckPermissionRunnable(
|
|
already_AddRefed<ThreadsafeContentParentHandle> aParent,
|
|
FileSystemRequestParent* aActor, FileSystemTaskParentBase* aTask,
|
|
const nsAString& aPath)
|
|
: Runnable("dom::CheckPermissionRunnable"),
|
|
mContentHandle(aParent),
|
|
mActor(aActor),
|
|
mTask(aTask),
|
|
mPath(aPath),
|
|
mBackgroundEventTarget(GetCurrentSerialEventTarget()) {
|
|
AssertIsInMainProcess();
|
|
AssertIsOnBackgroundThread();
|
|
|
|
MOZ_ASSERT(mContentHandle);
|
|
MOZ_ASSERT(mActor);
|
|
MOZ_ASSERT(mTask);
|
|
MOZ_ASSERT(mBackgroundEventTarget);
|
|
}
|
|
|
|
NS_IMETHOD
|
|
Run() override {
|
|
if (NS_IsMainThread()) {
|
|
if (!mozilla::Preferences::GetBool("dom.filesystem.pathcheck.disabled",
|
|
false)) {
|
|
RefPtr<FileSystemSecurity> fss = FileSystemSecurity::Get();
|
|
if (NS_WARN_IF(!fss || !fss->ContentProcessHasAccessTo(
|
|
mContentHandle->ChildID(), mPath))) {
|
|
AssertIsOnMainThread();
|
|
if (RefPtr<ContentParent> contentParent =
|
|
mContentHandle->GetContentParent()) {
|
|
contentParent->KillHard("This path is not allowed.");
|
|
}
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
return mBackgroundEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
|
|
}
|
|
|
|
AssertIsOnBackgroundThread();
|
|
|
|
// It can happen that this actor has been destroyed in the meantime we were
|
|
// on the main-thread.
|
|
if (!mActor->Destroyed()) {
|
|
mTask->Start();
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
private:
|
|
~CheckPermissionRunnable() {
|
|
NS_ProxyRelease("CheckPermissionRunnable::mActor", mBackgroundEventTarget,
|
|
mActor.forget());
|
|
}
|
|
|
|
RefPtr<ThreadsafeContentParentHandle> mContentHandle;
|
|
RefPtr<FileSystemRequestParent> mActor;
|
|
RefPtr<FileSystemTaskParentBase> mTask;
|
|
const nsString mPath;
|
|
|
|
nsCOMPtr<nsIEventTarget> mBackgroundEventTarget;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
void FileSystemRequestParent::Start() {
|
|
AssertIsInMainProcess();
|
|
AssertIsOnBackgroundThread();
|
|
|
|
MOZ_ASSERT(!mDestroyed);
|
|
MOZ_ASSERT(mFileSystem);
|
|
MOZ_ASSERT(mTask);
|
|
|
|
nsAutoString path;
|
|
if (NS_WARN_IF(NS_FAILED(mTask->GetTargetPath(path)))) {
|
|
Unused << Send__delete__(
|
|
this, FileSystemErrorResponse(NS_ERROR_DOM_SECURITY_ERR));
|
|
return;
|
|
}
|
|
|
|
RefPtr<ThreadsafeContentParentHandle> parent =
|
|
BackgroundParent::GetContentParentHandle(Manager());
|
|
|
|
// If the ThreadsafeContentParentHandle is null we are dealing with a
|
|
// same-process actor.
|
|
if (!parent) {
|
|
mTask->Start();
|
|
return;
|
|
}
|
|
|
|
RefPtr<Runnable> runnable =
|
|
new CheckPermissionRunnable(parent.forget(), this, mTask, path);
|
|
NS_DispatchToMainThread(runnable);
|
|
}
|
|
|
|
void FileSystemRequestParent::ActorDestroy(ActorDestroyReason aWhy) {
|
|
AssertIsOnBackgroundThread();
|
|
MOZ_ASSERT(!mDestroyed);
|
|
|
|
if (!mFileSystem) {
|
|
return;
|
|
}
|
|
|
|
mFileSystem->Shutdown();
|
|
mFileSystem = nullptr;
|
|
mTask = nullptr;
|
|
mDestroyed = true;
|
|
}
|
|
|
|
} // namespace mozilla::dom
|