Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/filesystem/FileSystemRequestParent.cpp
Line
Count
Source (jump to first uncovered line)
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
FileSystemRequestParent::FileSystemRequestParent()
26
  : mDestroyed(false)
27
0
{
28
0
  AssertIsOnBackgroundThread();
29
0
}
30
31
FileSystemRequestParent::~FileSystemRequestParent()
32
0
{
33
0
  AssertIsOnBackgroundThread();
34
0
}
35
36
#define FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(name)                         \
37
0
    case FileSystemParams::TFileSystem##name##Params: {                        \
38
0
      const FileSystem##name##Params& p = aParams;                             \
39
0
      mFileSystem = new OSFileSystemParent(p.filesystem());                    \
40
0
      MOZ_ASSERT(mFileSystem);                                                 \
41
0
      mTask = name##TaskParent::Create(mFileSystem, p, this, rv);              \
42
0
      if (NS_WARN_IF(rv.Failed())) {                                           \
43
0
        rv.SuppressException();                                                \
44
0
        return false;                                                          \
45
0
      }                                                                        \
46
0
      break;                                                                   \
47
0
    }
48
49
bool
50
FileSystemRequestParent::Initialize(const FileSystemParams& aParams)
51
0
{
52
0
  AssertIsOnBackgroundThread();
53
0
54
0
  ErrorResult rv;
55
0
56
0
  switch (aParams.type()) {
57
0
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
0
62
0
    default: {
63
0
      MOZ_CRASH("not reached");
64
0
      break;
65
0
    }
66
0
  }
67
0
68
0
  if (NS_WARN_IF(!mTask || !mFileSystem)) {
69
0
    // Should never reach here.
70
0
    return false;
71
0
  }
72
0
73
0
  return true;
74
0
}
75
76
namespace {
77
78
class CheckPermissionRunnable final : public Runnable
79
{
80
public:
81
  CheckPermissionRunnable(already_AddRefed<ContentParent> aParent,
82
                          FileSystemRequestParent* aActor,
83
                          FileSystemTaskParentBase* aTask,
84
                          const nsAString& aPath)
85
    : Runnable("dom::CheckPermissionRunnable")
86
    , mContentParent(aParent)
87
    , mActor(aActor)
88
    , mTask(aTask)
89
    , mPath(aPath)
90
    , mBackgroundEventTarget(GetCurrentThreadEventTarget())
91
0
  {
92
0
    AssertIsInMainProcess();
93
0
    AssertIsOnBackgroundThread();
94
0
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
  Run() override
103
0
  {
104
0
    if (NS_IsMainThread()) {
105
0
      auto raii = mozilla::MakeScopeExit([&] { mContentParent = nullptr; });
106
0
107
0
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
0
                       !fss->ContentProcessHasAccessTo(mContentParent->ChildID(),
112
0
                                                       mPath))) {
113
0
          mContentParent->KillHard("This path is not allowed.");
114
0
          return NS_OK;
115
0
        }
116
0
      }
117
0
118
0
      return mBackgroundEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
119
0
    }
120
0
121
0
    AssertIsOnBackgroundThread();
122
0
123
0
    // It can happen that this actor has been destroyed in the meantime we were
124
0
    // on the main-thread.
125
0
    if (!mActor->Destroyed()) {
126
0
      mTask->Start();
127
0
    }
128
0
129
0
    return NS_OK;
130
0
  }
131
132
private:
133
  ~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
FileSystemRequestParent::Start()
151
0
{
152
0
  AssertIsInMainProcess();
153
0
  AssertIsOnBackgroundThread();
154
0
155
0
  MOZ_ASSERT(!mDestroyed);
156
0
  MOZ_ASSERT(mFileSystem);
157
0
  MOZ_ASSERT(mTask);
158
0
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
0
  }
164
0
165
0
  RefPtr<ContentParent> parent = BackgroundParent::GetContentParent(Manager());
166
0
167
0
  // 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
0
  }
172
0
173
0
  RefPtr<Runnable> runnable =
174
0
    new CheckPermissionRunnable(parent.forget(), this, mTask, path);
175
0
  NS_DispatchToMainThread(runnable);
176
0
}
177
178
void
179
FileSystemRequestParent::ActorDestroy(ActorDestroyReason aWhy)
180
0
{
181
0
  AssertIsOnBackgroundThread();
182
0
  MOZ_ASSERT(!mDestroyed);
183
0
184
0
  if (!mFileSystem) {
185
0
    return;
186
0
  }
187
0
188
0
  mFileSystem->Shutdown();
189
0
  mFileSystem = nullptr;
190
0
  mTask = nullptr;
191
0
  mDestroyed = true;
192
0
}
193
194
} // namespace dom
195
} // namespace mozilla