Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/filesystem/GetFileOrDirectoryTask.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 file,
5
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "GetFileOrDirectoryTask.h"
8
9
#include "js/Value.h"
10
#include "mozilla/dom/FileBlobImpl.h"
11
#include "mozilla/dom/FileSystemBase.h"
12
#include "mozilla/dom/FileSystemUtils.h"
13
#include "mozilla/dom/PFileSystemParams.h"
14
#include "mozilla/dom/Promise.h"
15
#include "mozilla/dom/IPCBlobUtils.h"
16
#include "nsIFile.h"
17
#include "nsString.h"
18
19
namespace mozilla {
20
namespace dom {
21
22
/**
23
 * GetFileOrDirectoryTaskChild
24
 */
25
26
/* static */ already_AddRefed<GetFileOrDirectoryTaskChild>
27
GetFileOrDirectoryTaskChild::Create(FileSystemBase* aFileSystem,
28
                                    nsIFile* aTargetPath,
29
                                    ErrorResult& aRv)
30
0
{
31
0
  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
32
0
  MOZ_ASSERT(aFileSystem);
33
0
34
0
  nsCOMPtr<nsIGlobalObject> globalObject =
35
0
    do_QueryInterface(aFileSystem->GetParentObject());
36
0
  if (NS_WARN_IF(!globalObject)) {
37
0
    aRv.Throw(NS_ERROR_FAILURE);
38
0
    return nullptr;
39
0
  }
40
0
41
0
  RefPtr<GetFileOrDirectoryTaskChild> task =
42
0
    new GetFileOrDirectoryTaskChild(globalObject, aFileSystem, aTargetPath);
43
0
44
0
  // aTargetPath can be null. In this case SetError will be called.
45
0
46
0
  task->mPromise = Promise::Create(globalObject, aRv);
47
0
  if (NS_WARN_IF(aRv.Failed())) {
48
0
    return nullptr;
49
0
  }
50
0
51
0
  return task.forget();
52
0
}
53
54
GetFileOrDirectoryTaskChild::GetFileOrDirectoryTaskChild(nsIGlobalObject* aGlobalObject,
55
                                                         FileSystemBase* aFileSystem,
56
                                                         nsIFile* aTargetPath)
57
  : FileSystemTaskChildBase(aGlobalObject, aFileSystem)
58
  , mTargetPath(aTargetPath)
59
0
{
60
0
  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
61
0
  MOZ_ASSERT(aFileSystem);
62
0
}
63
64
GetFileOrDirectoryTaskChild::~GetFileOrDirectoryTaskChild()
65
0
{
66
0
  MOZ_ASSERT(NS_IsMainThread());
67
0
}
68
69
already_AddRefed<Promise>
70
GetFileOrDirectoryTaskChild::GetPromise()
71
0
{
72
0
  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
73
0
  return RefPtr<Promise>(mPromise).forget();
74
0
}
75
76
FileSystemParams
77
GetFileOrDirectoryTaskChild::GetRequestParams(const nsString& aSerializedDOMPath,
78
                                              ErrorResult& aRv) const
79
0
{
80
0
  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
81
0
82
0
  nsAutoString path;
83
0
  aRv = mTargetPath->GetPath(path);
84
0
  if (NS_WARN_IF(aRv.Failed())) {
85
0
    return FileSystemGetFileOrDirectoryParams();
86
0
  }
87
0
88
0
  return FileSystemGetFileOrDirectoryParams(aSerializedDOMPath, path);
89
0
}
90
91
void
92
GetFileOrDirectoryTaskChild::SetSuccessRequestResult(const FileSystemResponseValue& aValue,
93
                                                     ErrorResult& aRv)
94
0
{
95
0
  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
96
0
  switch (aValue.type()) {
97
0
    case FileSystemResponseValue::TFileSystemFileResponse: {
98
0
      FileSystemFileResponse r = aValue;
99
0
100
0
      RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(r.blob());
101
0
      MOZ_ASSERT(blobImpl);
102
0
103
0
      mResultFile = File::Create(mFileSystem->GetParentObject(), blobImpl);
104
0
      MOZ_ASSERT(mResultFile);
105
0
      break;
106
0
    }
107
0
    case FileSystemResponseValue::TFileSystemDirectoryResponse: {
108
0
      FileSystemDirectoryResponse r = aValue;
109
0
110
0
      nsCOMPtr<nsIFile> file;
111
0
      aRv = NS_NewLocalFile(r.realPath(), true, getter_AddRefs(file));
112
0
      if (NS_WARN_IF(aRv.Failed())) {
113
0
        return;
114
0
      }
115
0
116
0
      mResultDirectory = Directory::Create(mFileSystem->GetParentObject(),
117
0
                                           file, mFileSystem);
118
0
      MOZ_ASSERT(mResultDirectory);
119
0
      break;
120
0
    }
121
0
    default: {
122
0
      MOZ_CRASH("not reached");
123
0
      break;
124
0
    }
125
0
  }
126
0
}
127
128
void
129
GetFileOrDirectoryTaskChild::HandlerCallback()
130
0
{
131
0
  MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
132
0
  if (mFileSystem->IsShutdown()) {
133
0
    mPromise = nullptr;
134
0
    return;
135
0
  }
136
0
137
0
  if (HasError()) {
138
0
    mPromise->MaybeReject(mErrorValue);
139
0
    mPromise = nullptr;
140
0
    return;
141
0
  }
142
0
143
0
  if (mResultDirectory) {
144
0
    mPromise->MaybeResolve(mResultDirectory);
145
0
    mResultDirectory = nullptr;
146
0
    mPromise = nullptr;
147
0
    return;
148
0
  }
149
0
150
0
  MOZ_ASSERT(mResultFile);
151
0
  mPromise->MaybeResolve(mResultFile);
152
0
  mResultFile = nullptr;
153
0
  mPromise = nullptr;
154
0
}
155
156
/**
157
 * GetFileOrDirectoryTaskParent
158
 */
159
160
/* static */ already_AddRefed<GetFileOrDirectoryTaskParent>
161
GetFileOrDirectoryTaskParent::Create(FileSystemBase* aFileSystem,
162
                                     const FileSystemGetFileOrDirectoryParams& aParam,
163
                                     FileSystemRequestParent* aParent,
164
                                     ErrorResult& aRv)
165
0
{
166
0
  MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
167
0
  AssertIsOnBackgroundThread();
168
0
  MOZ_ASSERT(aFileSystem);
169
0
170
0
  RefPtr<GetFileOrDirectoryTaskParent> task =
171
0
    new GetFileOrDirectoryTaskParent(aFileSystem, aParam, aParent);
172
0
173
0
  aRv = NS_NewLocalFile(aParam.realPath(), true,
174
0
                        getter_AddRefs(task->mTargetPath));
175
0
  if (NS_WARN_IF(aRv.Failed())) {
176
0
    return nullptr;
177
0
  }
178
0
179
0
  return task.forget();
180
0
}
181
182
GetFileOrDirectoryTaskParent::GetFileOrDirectoryTaskParent(FileSystemBase* aFileSystem,
183
                                                           const FileSystemGetFileOrDirectoryParams& aParam,
184
                                                           FileSystemRequestParent* aParent)
185
  : FileSystemTaskParentBase(aFileSystem, aParam, aParent)
186
  , mIsDirectory(false)
187
0
{
188
0
  MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
189
0
  AssertIsOnBackgroundThread();
190
0
  MOZ_ASSERT(aFileSystem);
191
0
}
192
193
FileSystemResponseValue
194
GetFileOrDirectoryTaskParent::GetSuccessRequestResult(ErrorResult& aRv) const
195
0
{
196
0
  AssertIsOnBackgroundThread();
197
0
198
0
  nsAutoString path;
199
0
  aRv = mTargetPath->GetPath(path);
200
0
  if (NS_WARN_IF(aRv.Failed())) {
201
0
    return FileSystemDirectoryResponse();
202
0
  }
203
0
204
0
  if (mIsDirectory) {
205
0
    return FileSystemDirectoryResponse(path);
206
0
  }
207
0
208
0
  RefPtr<BlobImpl> blobImpl = new FileBlobImpl(mTargetPath);
209
0
210
0
  IPCBlob ipcBlob;
211
0
  aRv = IPCBlobUtils::Serialize(blobImpl, mRequestParent->Manager(), ipcBlob);
212
0
  if (NS_WARN_IF(aRv.Failed())) {
213
0
    return FileSystemDirectoryResponse();
214
0
  }
215
0
216
0
  return FileSystemFileResponse(ipcBlob);
217
0
}
218
219
nsresult
220
GetFileOrDirectoryTaskParent::IOWork()
221
0
{
222
0
  MOZ_ASSERT(XRE_IsParentProcess(),
223
0
             "Only call from parent process!");
224
0
  MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
225
0
226
0
  if (mFileSystem->IsShutdown()) {
227
0
    return NS_ERROR_FAILURE;
228
0
  }
229
0
230
0
  // Whether we want to get the root directory.
231
0
  bool exists;
232
0
  nsresult rv = mTargetPath->Exists(&exists);
233
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
234
0
    return rv;
235
0
  }
236
0
237
0
  if (!exists) {
238
0
    if (!mFileSystem->ShouldCreateDirectory()) {
239
0
      return NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
240
0
    }
241
0
242
0
    rv = mTargetPath->Create(nsIFile::DIRECTORY_TYPE, 0777);
243
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
244
0
      return rv;
245
0
    }
246
0
  }
247
0
248
0
  // Get isDirectory.
249
0
  rv = mTargetPath->IsDirectory(&mIsDirectory);
250
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
251
0
    return rv;
252
0
  }
253
0
254
0
  if (mIsDirectory) {
255
0
    return NS_OK;
256
0
  }
257
0
258
0
  bool isFile;
259
0
  // Get isFile
260
0
  rv = mTargetPath->IsFile(&isFile);
261
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
262
0
    return rv;
263
0
  }
264
0
265
0
  if (!isFile) {
266
0
    // Neither directory or file.
267
0
    return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
268
0
  }
269
0
270
0
  if (!mFileSystem->IsSafeFile(mTargetPath)) {
271
0
    return NS_ERROR_DOM_SECURITY_ERR;
272
0
  }
273
0
274
0
  return NS_OK;
275
0
}
276
277
nsresult
278
GetFileOrDirectoryTaskParent::GetTargetPath(nsAString& aPath) const
279
0
{
280
0
  return mTargetPath->GetPath(aPath);
281
0
}
282
283
} // namespace dom
284
} // namespace mozilla