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