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/. */
7 #include "mozilla/dom/FileSystemRequestParent.h"
8 #include "mozilla/dom/PFileSystemParams.h"
10 #include "GetDirectoryListingTask.h"
11 #include "GetFileOrDirectoryTask.h"
12 #include "GetFilesTask.h"
14 #include "mozilla/dom/BlobImpl.h"
15 #include "mozilla/dom/ContentParent.h"
16 #include "mozilla/dom/FileSystemBase.h"
17 #include "mozilla/dom/FileSystemSecurity.h"
18 #include "mozilla/ipc/BackgroundParent.h"
19 #include "mozilla/dom/OSFileSystem.h"
20 #include "mozilla/Preferences.h"
21 #include "mozilla/ScopeExit.h"
22 #include "mozilla/Unused.h"
23 #include "nsProxyRelease.h"
25 using namespace mozilla::ipc
;
27 namespace mozilla::dom
{
29 FileSystemRequestParent::FileSystemRequestParent() : mDestroyed(false) {
30 AssertIsOnBackgroundThread();
33 FileSystemRequestParent::~FileSystemRequestParent() {
34 AssertIsOnBackgroundThread();
37 #define FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(name) \
38 case FileSystemParams::TFileSystem##name##Params: { \
39 const FileSystem##name##Params& p = aParams; \
40 mFileSystem = new OSFileSystemParent(p.filesystem()); \
41 MOZ_ASSERT(mFileSystem); \
42 mTask = name##TaskParent::Create(mFileSystem, p, this, rv); \
43 if (NS_WARN_IF(rv.Failed())) { \
44 rv.SuppressException(); \
50 bool FileSystemRequestParent::Initialize(const FileSystemParams
& aParams
) {
51 AssertIsOnBackgroundThread();
55 switch (aParams
.type()) {
56 FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetDirectoryListing
)
57 FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetFileOrDirectory
)
58 FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetFiles
)
61 MOZ_CRASH("not reached");
66 if (NS_WARN_IF(!mTask
|| !mFileSystem
)) {
67 // Should never reach here.
76 class CheckPermissionRunnable final
: public Runnable
{
78 CheckPermissionRunnable(
79 already_AddRefed
<ThreadsafeContentParentHandle
> aParent
,
80 FileSystemRequestParent
* aActor
, FileSystemTaskParentBase
* aTask
,
81 const nsAString
& aPath
)
82 : Runnable("dom::CheckPermissionRunnable"),
83 mContentHandle(aParent
),
87 mBackgroundEventTarget(GetCurrentSerialEventTarget()) {
88 AssertIsInMainProcess();
89 AssertIsOnBackgroundThread();
91 MOZ_ASSERT(mContentHandle
);
94 MOZ_ASSERT(mBackgroundEventTarget
);
99 if (NS_IsMainThread()) {
100 if (!mozilla::Preferences::GetBool("dom.filesystem.pathcheck.disabled",
102 RefPtr
<FileSystemSecurity
> fss
= FileSystemSecurity::Get();
103 if (NS_WARN_IF(!fss
|| !fss
->ContentProcessHasAccessTo(
104 mContentHandle
->ChildID(), mPath
))) {
105 AssertIsOnMainThread();
106 if (RefPtr
<ContentParent
> contentParent
=
107 mContentHandle
->GetContentParent()) {
108 contentParent
->KillHard("This path is not allowed.");
114 return mBackgroundEventTarget
->Dispatch(this, NS_DISPATCH_NORMAL
);
117 AssertIsOnBackgroundThread();
119 // It can happen that this actor has been destroyed in the meantime we were
120 // on the main-thread.
121 if (!mActor
->Destroyed()) {
129 ~CheckPermissionRunnable() {
130 NS_ProxyRelease("CheckPermissionRunnable::mActor", mBackgroundEventTarget
,
134 RefPtr
<ThreadsafeContentParentHandle
> mContentHandle
;
135 RefPtr
<FileSystemRequestParent
> mActor
;
136 RefPtr
<FileSystemTaskParentBase
> mTask
;
137 const nsString mPath
;
139 nsCOMPtr
<nsIEventTarget
> mBackgroundEventTarget
;
144 void FileSystemRequestParent::Start() {
145 AssertIsInMainProcess();
146 AssertIsOnBackgroundThread();
148 MOZ_ASSERT(!mDestroyed
);
149 MOZ_ASSERT(mFileSystem
);
153 if (NS_WARN_IF(NS_FAILED(mTask
->GetTargetPath(path
)))) {
154 (void)Send__delete__(this,
155 FileSystemErrorResponse(NS_ERROR_DOM_SECURITY_ERR
));
159 RefPtr
<ThreadsafeContentParentHandle
> parent
=
160 BackgroundParent::GetContentParentHandle(Manager());
162 // If the ThreadsafeContentParentHandle is null we are dealing with a
163 // same-process actor.
169 RefPtr
<Runnable
> runnable
=
170 new CheckPermissionRunnable(parent
.forget(), this, mTask
, path
);
171 NS_DispatchToMainThread(runnable
);
174 void FileSystemRequestParent::ActorDestroy(ActorDestroyReason aWhy
) {
175 AssertIsOnBackgroundThread();
176 MOZ_ASSERT(!mDestroyed
);
182 mFileSystem
->Shutdown();
183 mFileSystem
= nullptr;
188 } // namespace mozilla::dom