Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/file/FileCreatorHelper.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 "FileCreatorHelper.h"
8
9
#include "mozilla/dom/BindingDeclarations.h"
10
#include "mozilla/dom/ContentChild.h"
11
#include "mozilla/dom/ContentParent.h"
12
#include "mozilla/dom/FileBinding.h"
13
#include "mozilla/dom/File.h"
14
#include "mozilla/dom/Promise.h"
15
#include "nsContentUtils.h"
16
#include "nsPIDOMWindow.h"
17
#include "nsIFile.h"
18
19
// Undefine the macro of CreateFile to avoid FileCreatorHelper#CreateFile being
20
// replaced by FileCreatorHelper#CreateFileW.
21
#ifdef CreateFile
22
#undef CreateFile
23
#endif
24
25
namespace mozilla {
26
namespace dom {
27
28
/* static */ already_AddRefed<Promise>
29
FileCreatorHelper::CreateFile(nsIGlobalObject* aGlobalObject,
30
                              nsIFile* aFile,
31
                              const ChromeFilePropertyBag& aBag,
32
                              bool aIsFromNsIFile,
33
                              ErrorResult& aRv)
34
0
{
35
0
  MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
36
0
37
0
  RefPtr<Promise> promise = Promise::Create(aGlobalObject, aRv);
38
0
  if (NS_WARN_IF(aRv.Failed())) {
39
0
    return nullptr;
40
0
  }
41
0
42
0
  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobalObject);
43
0
44
0
  // Parent process
45
0
46
0
  if (XRE_IsParentProcess()) {
47
0
    RefPtr<File> file =
48
0
      CreateFileInternal(window, aFile, aBag, aIsFromNsIFile, aRv);
49
0
    if (aRv.Failed()) {
50
0
      return nullptr;
51
0
    }
52
0
    promise->MaybeResolve(file);
53
0
    return promise.forget();
54
0
  }
55
0
56
0
  // Content process.
57
0
58
0
  ContentChild* cc = ContentChild::GetSingleton();
59
0
  if (!cc) {
60
0
    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
61
0
    return promise.forget();
62
0
  }
63
0
64
0
  if (!cc->GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE) &&
65
0
      !Preferences::GetBool("dom.file.createInChild", false)) {
66
0
    // If this pref is not set and the request is received by the parent
67
0
    // process, this child is killed for security reason.
68
0
    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
69
0
    return promise.forget();
70
0
  }
71
0
72
0
  RefPtr<FileCreatorHelper> helper = new FileCreatorHelper(promise, window);
73
0
74
0
  // The request is sent to the parent process and it's kept alive by
75
0
  // ContentChild.
76
0
  helper->SendRequest(aFile, aBag, aIsFromNsIFile, aRv);
77
0
  if (NS_WARN_IF(aRv.Failed())) {
78
0
    return nullptr;
79
0
  }
80
0
81
0
  return promise.forget();
82
0
}
83
84
/* static */ already_AddRefed<File>
85
FileCreatorHelper::CreateFileInternal(nsPIDOMWindowInner* aWindow,
86
                                      nsIFile* aFile,
87
                                      const ChromeFilePropertyBag& aBag,
88
                                      bool aIsFromNsIFile,
89
                                      ErrorResult& aRv)
90
0
{
91
0
  bool lastModifiedPassed = false;
92
0
  int64_t lastModified = 0;
93
0
  if (aBag.mLastModified.WasPassed()) {
94
0
    lastModifiedPassed = true;
95
0
    lastModified = aBag.mLastModified.Value();
96
0
  }
97
0
98
0
  RefPtr<BlobImpl> blobImpl;
99
0
  aRv = CreateBlobImpl(aFile, aBag.mType, aBag.mName, lastModifiedPassed,
100
0
                       lastModified, aBag.mExistenceCheck, aIsFromNsIFile,
101
0
                       getter_AddRefs(blobImpl));
102
0
  if (aRv.Failed()) {
103
0
     return nullptr;
104
0
  }
105
0
106
0
  RefPtr<File> file = File::Create(aWindow, blobImpl);
107
0
  return file.forget();
108
0
}
109
110
FileCreatorHelper::FileCreatorHelper(Promise* aPromise,
111
                                     nsPIDOMWindowInner* aWindow)
112
  : mPromise(aPromise)
113
  , mWindow(aWindow)
114
0
{
115
0
  MOZ_ASSERT(aPromise);
116
0
}
117
118
FileCreatorHelper::~FileCreatorHelper()
119
0
{
120
0
}
121
122
void
123
FileCreatorHelper::SendRequest(nsIFile* aFile,
124
                               const ChromeFilePropertyBag& aBag,
125
                               bool aIsFromNsIFile,
126
                               ErrorResult& aRv)
127
0
{
128
0
  MOZ_ASSERT(aFile);
129
0
130
0
  ContentChild* cc = ContentChild::GetSingleton();
131
0
  if (NS_WARN_IF(!cc)) {
132
0
    aRv.Throw(NS_ERROR_FAILURE);
133
0
    return;
134
0
  }
135
0
136
0
  nsID uuid;
137
0
  aRv = nsContentUtils::GenerateUUIDInPlace(uuid);
138
0
  if (NS_WARN_IF(aRv.Failed())) {
139
0
    return;
140
0
  }
141
0
142
0
  nsAutoString path;
143
0
  aRv = aFile->GetPath(path);
144
0
  if (NS_WARN_IF(aRv.Failed())) {
145
0
    return;
146
0
  }
147
0
148
0
  cc->FileCreationRequest(uuid, this, path, aBag.mType, aBag.mName,
149
0
                          aBag.mLastModified, aBag.mExistenceCheck,
150
0
                          aIsFromNsIFile);
151
0
}
152
153
void
154
FileCreatorHelper::ResponseReceived(BlobImpl* aBlobImpl, nsresult aRv)
155
0
{
156
0
  if (NS_FAILED(aRv)) {
157
0
    mPromise->MaybeReject(aRv);
158
0
    return;
159
0
  }
160
0
161
0
  RefPtr<File> file = File::Create(mWindow, aBlobImpl);
162
0
  mPromise->MaybeResolve(file);
163
0
}
164
165
/* static */ nsresult
166
FileCreatorHelper::CreateBlobImplForIPC(const nsAString& aPath,
167
                                        const nsAString& aType,
168
                                        const nsAString& aName,
169
                                        bool aLastModifiedPassed,
170
                                        int64_t aLastModified,
171
                                        bool aExistenceCheck,
172
                                        bool aIsFromNsIFile,
173
                                        BlobImpl** aBlobImpl)
174
0
{
175
0
  nsCOMPtr<nsIFile> file;
176
0
  nsresult rv = NS_NewLocalFile(aPath, true, getter_AddRefs(file));
177
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
178
0
    return rv;
179
0
  }
180
0
181
0
  return CreateBlobImpl(file, aType, aName, aLastModifiedPassed, aLastModified,
182
0
                        aExistenceCheck, aIsFromNsIFile, aBlobImpl);
183
0
}
184
185
/* static */ nsresult
186
FileCreatorHelper::CreateBlobImpl(nsIFile* aFile,
187
                                  const nsAString& aType,
188
                                  const nsAString& aName,
189
                                  bool aLastModifiedPassed,
190
                                  int64_t aLastModified,
191
                                  bool aExistenceCheck,
192
                                  bool aIsFromNsIFile,
193
                                  BlobImpl** aBlobImpl)
194
0
{
195
0
  if (!aExistenceCheck) {
196
0
    RefPtr<FileBlobImpl> impl = new FileBlobImpl(aFile);
197
0
198
0
    if (!aName.IsEmpty()) {
199
0
      impl->SetName(aName);
200
0
    }
201
0
202
0
    if (!aType.IsEmpty()) {
203
0
      impl->SetType(aType);
204
0
    }
205
0
206
0
    if (aLastModifiedPassed) {
207
0
      impl->SetLastModified(aLastModified);
208
0
    }
209
0
210
0
    impl.forget(aBlobImpl);
211
0
    return NS_OK;
212
0
  }
213
0
214
0
  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
215
0
  nsresult rv =
216
0
    impl->InitializeChromeFile(aFile, aType, aName, aLastModifiedPassed,
217
0
                               aLastModified, aIsFromNsIFile);
218
0
  if (NS_FAILED(rv)) {
219
0
    return rv;
220
0
  }
221
0
222
0
  MOZ_ASSERT(impl->IsFile());
223
0
224
0
  impl.forget(aBlobImpl);
225
0
  return NS_OK;
226
0
}
227
228
} // dom namespace
229
} // mozilla namespace