Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/filesystem/compat/CallbackRunnables.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 "CallbackRunnables.h"
8
#include "mozilla/dom/Directory.h"
9
#include "mozilla/dom/DirectoryBinding.h"
10
#include "mozilla/dom/DOMException.h"
11
#include "mozilla/dom/File.h"
12
#include "mozilla/dom/FileBinding.h"
13
#include "mozilla/dom/FileSystemDirectoryReaderBinding.h"
14
#include "mozilla/dom/FileSystemFileEntry.h"
15
#include "mozilla/dom/FileSystemUtils.h"
16
#include "mozilla/dom/Promise.h"
17
#include "mozilla/Unused.h"
18
#include "nsIGlobalObject.h"
19
#include "nsIFile.h"
20
#include "nsPIDOMWindow.h"
21
22
#include "../GetFileOrDirectoryTask.h"
23
24
namespace mozilla {
25
namespace dom {
26
27
EntryCallbackRunnable::EntryCallbackRunnable(FileSystemEntryCallback* aCallback,
28
                                             FileSystemEntry* aEntry)
29
  : Runnable("EntryCallbackRunnable")
30
  , mCallback(aCallback)
31
  , mEntry(aEntry)
32
0
{
33
0
  MOZ_ASSERT(aCallback);
34
0
  MOZ_ASSERT(aEntry);
35
0
}
36
37
NS_IMETHODIMP
38
EntryCallbackRunnable::Run()
39
0
{
40
0
  mCallback->HandleEvent(*mEntry);
41
0
  return NS_OK;
42
0
}
43
44
ErrorCallbackRunnable::ErrorCallbackRunnable(nsIGlobalObject* aGlobalObject,
45
                                             ErrorCallback* aCallback,
46
                                             nsresult aError)
47
  : Runnable("ErrorCallbackRunnable")
48
  , mGlobal(aGlobalObject)
49
  , mCallback(aCallback)
50
  , mError(aError)
51
0
{
52
0
  MOZ_ASSERT(aGlobalObject);
53
0
  MOZ_ASSERT(aCallback);
54
0
  MOZ_ASSERT(NS_FAILED(aError));
55
0
}
56
57
NS_IMETHODIMP
58
ErrorCallbackRunnable::Run()
59
0
{
60
0
  RefPtr<DOMException> exception = DOMException::Create(mError);
61
0
  mCallback->HandleEvent(*exception);
62
0
  return NS_OK;
63
0
}
64
65
EmptyEntriesCallbackRunnable::EmptyEntriesCallbackRunnable(FileSystemEntriesCallback* aCallback)
66
  : Runnable("EmptyEntriesCallbackRunnable")
67
  , mCallback(aCallback)
68
0
{
69
0
  MOZ_ASSERT(aCallback);
70
0
}
71
72
NS_IMETHODIMP
73
EmptyEntriesCallbackRunnable::Run()
74
0
{
75
0
  Sequence<OwningNonNull<FileSystemEntry>> sequence;
76
0
  mCallback->HandleEvent(sequence);
77
0
  return NS_OK;
78
0
}
79
80
GetEntryHelper::GetEntryHelper(FileSystemDirectoryEntry* aParentEntry,
81
                               Directory* aDirectory,
82
                               nsTArray<nsString>& aParts,
83
                               FileSystem* aFileSystem,
84
                               FileSystemEntryCallback* aSuccessCallback,
85
                               ErrorCallback* aErrorCallback,
86
                               FileSystemDirectoryEntry::GetInternalType aType)
87
  : mParentEntry(aParentEntry)
88
  , mDirectory(aDirectory)
89
  , mParts(aParts)
90
  , mFileSystem(aFileSystem)
91
  , mSuccessCallback(aSuccessCallback)
92
  , mErrorCallback(aErrorCallback)
93
  , mType(aType)
94
0
{
95
0
  MOZ_ASSERT(aParentEntry);
96
0
  MOZ_ASSERT(aDirectory);
97
0
  MOZ_ASSERT(!aParts.IsEmpty());
98
0
  MOZ_ASSERT(aFileSystem);
99
0
  MOZ_ASSERT(aSuccessCallback || aErrorCallback);
100
0
}
101
102
GetEntryHelper::~GetEntryHelper()
103
0
{}
104
105
namespace {
106
107
nsresult
108
DOMPathToRealPath(Directory* aDirectory, const nsAString& aPath,
109
                  nsIFile** aFile)
110
0
{
111
0
  nsString relativePath;
112
0
  relativePath = aPath;
113
0
114
0
  // Trim white spaces.
115
0
  static const char kWhitespace[] = "\b\t\r\n ";
116
0
  relativePath.Trim(kWhitespace);
117
0
118
0
  nsTArray<nsString> parts;
119
0
  if (!FileSystemUtils::IsValidRelativeDOMPath(relativePath, parts)) {
120
0
    return NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
121
0
  }
122
0
123
0
  nsCOMPtr<nsIFile> file;
124
0
  nsresult rv = aDirectory->GetInternalNsIFile()->Clone(getter_AddRefs(file));
125
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
126
0
    return rv;
127
0
  }
128
0
129
0
  for (uint32_t i = 0; i < parts.Length(); ++i) {
130
0
    rv = file->AppendRelativePath(parts[i]);
131
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
132
0
      return rv;
133
0
    }
134
0
  }
135
0
136
0
  file.forget(aFile);
137
0
  return NS_OK;
138
0
}
139
140
} // anonymous
141
142
void
143
GetEntryHelper::Run()
144
0
{
145
0
  MOZ_ASSERT(!mParts.IsEmpty());
146
0
147
0
  nsCOMPtr<nsIFile> realPath;
148
0
  nsresult error = DOMPathToRealPath(mDirectory, mParts[0],
149
0
                                     getter_AddRefs(realPath));
150
0
151
0
  ErrorResult rv;
152
0
  RefPtr<FileSystemBase> fs = mDirectory->GetFileSystem(rv);
153
0
  if (NS_WARN_IF(rv.Failed())) {
154
0
    rv.SuppressException();
155
0
    Error(NS_ERROR_DOM_INVALID_STATE_ERR);
156
0
    return;
157
0
  }
158
0
159
0
  RefPtr<GetFileOrDirectoryTaskChild> task =
160
0
    GetFileOrDirectoryTaskChild::Create(fs, realPath, rv);
161
0
  if (NS_WARN_IF(rv.Failed())) {
162
0
    rv.SuppressException();
163
0
    Error(NS_ERROR_DOM_INVALID_STATE_ERR);
164
0
    return;
165
0
  }
166
0
167
0
  task->SetError(error);
168
0
  task->Start();
169
0
170
0
  RefPtr<Promise> promise = task->GetPromise();
171
0
172
0
  mParts.RemoveElementAt(0);
173
0
  promise->AppendNativeHandler(this);
174
0
}
175
176
void
177
GetEntryHelper::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
178
0
{
179
0
  if(NS_WARN_IF(!aValue.isObject())) {
180
0
    return;
181
0
  }
182
0
183
0
  JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
184
0
185
0
  // This is not the last part of the path.
186
0
  if (!mParts.IsEmpty()) {
187
0
    ContinueRunning(obj);
188
0
    return;
189
0
  }
190
0
191
0
  CompleteOperation(obj);
192
0
}
193
194
void
195
GetEntryHelper::CompleteOperation(JSObject* aObj)
196
0
{
197
0
  MOZ_ASSERT(mParts.IsEmpty());
198
0
199
0
  if (mType == FileSystemDirectoryEntry::eGetFile) {
200
0
    RefPtr<File> file;
201
0
    if (NS_FAILED(UNWRAP_OBJECT(File, aObj, file))) {
202
0
      Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
203
0
      return;
204
0
    }
205
0
206
0
    RefPtr<FileSystemFileEntry> entry =
207
0
      new FileSystemFileEntry(mParentEntry->GetParentObject(), file,
208
0
                              mParentEntry, mFileSystem);
209
0
    mSuccessCallback->HandleEvent(*entry);
210
0
    return;
211
0
  }
212
0
213
0
  MOZ_ASSERT(mType == FileSystemDirectoryEntry::eGetDirectory);
214
0
215
0
  RefPtr<Directory> directory;
216
0
  if (NS_FAILED(UNWRAP_OBJECT(Directory, aObj, directory))) {
217
0
    Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
218
0
    return;
219
0
  }
220
0
221
0
  RefPtr<FileSystemDirectoryEntry> entry =
222
0
    new FileSystemDirectoryEntry(mParentEntry->GetParentObject(), directory,
223
0
                                 mParentEntry, mFileSystem);
224
0
  mSuccessCallback->HandleEvent(*entry);
225
0
}
226
227
void
228
GetEntryHelper::ContinueRunning(JSObject* aObj)
229
0
{
230
0
  MOZ_ASSERT(!mParts.IsEmpty());
231
0
232
0
  RefPtr<Directory> directory;
233
0
  if (NS_FAILED(UNWRAP_OBJECT(Directory, aObj, directory))) {
234
0
    Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
235
0
    return;
236
0
  }
237
0
238
0
  RefPtr<FileSystemDirectoryEntry> entry =
239
0
    new FileSystemDirectoryEntry(mParentEntry->GetParentObject(), directory,
240
0
                                 mParentEntry, mFileSystem);
241
0
242
0
  // Update the internal values.
243
0
  mParentEntry = entry;
244
0
  mDirectory = directory;
245
0
246
0
  Run();
247
0
}
248
249
void
250
GetEntryHelper::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
251
0
{
252
0
  Error(NS_ERROR_DOM_NOT_FOUND_ERR);
253
0
}
254
255
void
256
GetEntryHelper::Error(nsresult aError)
257
0
{
258
0
  MOZ_ASSERT(NS_FAILED(aError));
259
0
260
0
  if (mErrorCallback) {
261
0
    RefPtr<ErrorCallbackRunnable> runnable =
262
0
      new ErrorCallbackRunnable(mParentEntry->GetParentObject(),
263
0
                                mErrorCallback, aError);
264
0
265
0
    FileSystemUtils::DispatchRunnable(mParentEntry->GetParentObject(),
266
0
                                      runnable.forget());
267
0
  }
268
0
}
269
270
NS_IMPL_ISUPPORTS0(GetEntryHelper);
271
272
/* static */ void
273
FileSystemEntryCallbackHelper::Call(nsIGlobalObject* aGlobalObject,
274
                                    const Optional<OwningNonNull<FileSystemEntryCallback>>& aEntryCallback,
275
                                    FileSystemEntry* aEntry)
276
0
{
277
0
  MOZ_ASSERT(aGlobalObject);
278
0
  MOZ_ASSERT(aEntry);
279
0
280
0
  if (aEntryCallback.WasPassed()) {
281
0
    RefPtr<EntryCallbackRunnable> runnable =
282
0
      new EntryCallbackRunnable(&aEntryCallback.Value(), aEntry);
283
0
284
0
    FileSystemUtils::DispatchRunnable(aGlobalObject, runnable.forget());
285
0
  }
286
0
}
287
288
/* static */ void
289
ErrorCallbackHelper::Call(nsIGlobalObject* aGlobal,
290
                          const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
291
                          nsresult aError)
292
0
{
293
0
  MOZ_ASSERT(aGlobal);
294
0
  MOZ_ASSERT(NS_FAILED(aError));
295
0
296
0
  if (aErrorCallback.WasPassed()) {
297
0
    RefPtr<ErrorCallbackRunnable> runnable =
298
0
      new ErrorCallbackRunnable(aGlobal, &aErrorCallback.Value(), aError);
299
0
300
0
    FileSystemUtils::DispatchRunnable(aGlobal, runnable.forget());
301
0
  }
302
0
}
303
304
} // dom namespace
305
} // mozilla namespace
306