|
Packit |
f0b94e |
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
Packit |
f0b94e |
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
Packit |
f0b94e |
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit |
f0b94e |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
Packit |
f0b94e |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include "FileCreatorHelper.h"
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include "mozilla/dom/BindingDeclarations.h"
|
|
Packit |
f0b94e |
#include "mozilla/dom/ContentChild.h"
|
|
Packit |
f0b94e |
#include "mozilla/dom/ContentParent.h"
|
|
Packit |
f0b94e |
#include "mozilla/dom/FileBinding.h"
|
|
Packit |
f0b94e |
#include "mozilla/dom/File.h"
|
|
Packit |
f0b94e |
#include "mozilla/dom/Promise.h"
|
|
Packit |
f0b94e |
#include "nsContentUtils.h"
|
|
Packit |
f0b94e |
#include "nsPIDOMWindow.h"
|
|
Packit |
f0b94e |
#include "nsIFile.h"
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Undefine the macro of CreateFile to avoid FileCreatorHelper#CreateFile being
|
|
Packit |
f0b94e |
// replaced by FileCreatorHelper#CreateFileW.
|
|
Packit |
f0b94e |
#ifdef CreateFile
|
|
Packit |
f0b94e |
#undef CreateFile
|
|
Packit |
f0b94e |
#endif
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
namespace mozilla {
|
|
Packit |
f0b94e |
namespace dom {
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ already_AddRefed<Promise> FileCreatorHelper::CreateFile(
|
|
Packit |
f0b94e |
nsIGlobalObject* aGlobalObject, nsIFile* aFile,
|
|
Packit |
f0b94e |
const ChromeFilePropertyBag& aBag, bool aIsFromNsIFile, ErrorResult& aRv) {
|
|
Packit |
f0b94e |
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
RefPtr<Promise> promise = Promise::Create(aGlobalObject, aRv);
|
|
Packit |
f0b94e |
if (NS_WARN_IF(aRv.Failed())) {
|
|
Packit |
f0b94e |
return nullptr;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobalObject);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Parent process
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (XRE_IsParentProcess()) {
|
|
Packit |
f0b94e |
RefPtr<File> file =
|
|
Packit |
f0b94e |
CreateFileInternal(window, aFile, aBag, aIsFromNsIFile, aRv);
|
|
Packit |
f0b94e |
if (aRv.Failed()) {
|
|
Packit |
f0b94e |
return nullptr;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
promise->MaybeResolve(file);
|
|
Packit |
f0b94e |
return promise.forget();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Content process.
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
ContentChild* cc = ContentChild::GetSingleton();
|
|
Packit |
f0b94e |
if (!cc) {
|
|
Packit |
f0b94e |
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
Packit |
f0b94e |
return promise.forget();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (!cc->GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE) &&
|
|
Packit |
f0b94e |
!Preferences::GetBool("dom.file.createInChild", false)) {
|
|
Packit |
f0b94e |
// If this pref is not set and the request is received by the parent
|
|
Packit |
f0b94e |
// process, this child is killed for security reason.
|
|
Packit |
f0b94e |
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
Packit |
f0b94e |
return promise.forget();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
RefPtr<FileCreatorHelper> helper = new FileCreatorHelper(promise, window);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// The request is sent to the parent process and it's kept alive by
|
|
Packit |
f0b94e |
// ContentChild.
|
|
Packit |
f0b94e |
helper->SendRequest(aFile, aBag, aIsFromNsIFile, aRv);
|
|
Packit |
f0b94e |
if (NS_WARN_IF(aRv.Failed())) {
|
|
Packit |
f0b94e |
return nullptr;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return promise.forget();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ already_AddRefed<File> FileCreatorHelper::CreateFileInternal(
|
|
Packit |
f0b94e |
nsPIDOMWindowInner* aWindow, nsIFile* aFile,
|
|
Packit |
f0b94e |
const ChromeFilePropertyBag& aBag, bool aIsFromNsIFile, ErrorResult& aRv) {
|
|
Packit |
f0b94e |
bool lastModifiedPassed = false;
|
|
Packit |
f0b94e |
int64_t lastModified = 0;
|
|
Packit |
f0b94e |
if (aBag.mLastModified.WasPassed()) {
|
|
Packit |
f0b94e |
lastModifiedPassed = true;
|
|
Packit |
f0b94e |
lastModified = aBag.mLastModified.Value();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
RefPtr<BlobImpl> blobImpl;
|
|
Packit |
f0b94e |
aRv = CreateBlobImpl(aFile, aBag.mType, aBag.mName, lastModifiedPassed,
|
|
Packit |
f0b94e |
lastModified, aBag.mExistenceCheck, aIsFromNsIFile,
|
|
Packit |
f0b94e |
getter_AddRefs(blobImpl));
|
|
Packit |
f0b94e |
if (aRv.Failed()) {
|
|
Packit |
f0b94e |
return nullptr;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
RefPtr<File> file = File::Create(aWindow, blobImpl);
|
|
Packit |
f0b94e |
return file.forget();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
FileCreatorHelper::FileCreatorHelper(Promise* aPromise,
|
|
Packit |
f0b94e |
nsPIDOMWindowInner* aWindow)
|
|
Packit |
f0b94e |
: mPromise(aPromise), mWindow(aWindow) {
|
|
Packit |
f0b94e |
MOZ_ASSERT(aPromise);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
FileCreatorHelper::~FileCreatorHelper() {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FileCreatorHelper::SendRequest(nsIFile* aFile,
|
|
Packit |
f0b94e |
const ChromeFilePropertyBag& aBag,
|
|
Packit |
f0b94e |
bool aIsFromNsIFile, ErrorResult& aRv) {
|
|
Packit |
f0b94e |
MOZ_ASSERT(aFile);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
ContentChild* cc = ContentChild::GetSingleton();
|
|
Packit |
f0b94e |
if (NS_WARN_IF(!cc)) {
|
|
Packit |
f0b94e |
aRv.Throw(NS_ERROR_FAILURE);
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsID uuid;
|
|
Packit |
f0b94e |
aRv = nsContentUtils::GenerateUUIDInPlace(uuid);
|
|
Packit |
f0b94e |
if (NS_WARN_IF(aRv.Failed())) {
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsAutoString path;
|
|
Packit |
f0b94e |
aRv = aFile->GetPath(path);
|
|
Packit |
f0b94e |
if (NS_WARN_IF(aRv.Failed())) {
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
cc->FileCreationRequest(uuid, this, path, aBag.mType, aBag.mName,
|
|
Packit |
f0b94e |
aBag.mLastModified, aBag.mExistenceCheck,
|
|
Packit |
f0b94e |
aIsFromNsIFile);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FileCreatorHelper::ResponseReceived(BlobImpl* aBlobImpl, nsresult aRv) {
|
|
Packit |
f0b94e |
if (NS_FAILED(aRv)) {
|
|
Packit |
f0b94e |
mPromise->MaybeReject(aRv);
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
RefPtr<File> file = File::Create(mWindow, aBlobImpl);
|
|
Packit |
f0b94e |
mPromise->MaybeResolve(file);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ nsresult FileCreatorHelper::CreateBlobImplForIPC(
|
|
Packit |
f0b94e |
const nsAString& aPath, const nsAString& aType, const nsAString& aName,
|
|
Packit |
f0b94e |
bool aLastModifiedPassed, int64_t aLastModified, bool aExistenceCheck,
|
|
Packit |
f0b94e |
bool aIsFromNsIFile, BlobImpl** aBlobImpl) {
|
|
Packit |
f0b94e |
nsCOMPtr<nsIFile> file;
|
|
Packit |
f0b94e |
nsresult rv = NS_NewLocalFile(aPath, true, getter_AddRefs(file));
|
|
Packit |
f0b94e |
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
Packit |
f0b94e |
return rv;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return CreateBlobImpl(file, aType, aName, aLastModifiedPassed, aLastModified,
|
|
Packit |
f0b94e |
aExistenceCheck, aIsFromNsIFile, aBlobImpl);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ nsresult FileCreatorHelper::CreateBlobImpl(
|
|
Packit |
f0b94e |
nsIFile* aFile, const nsAString& aType, const nsAString& aName,
|
|
Packit |
f0b94e |
bool aLastModifiedPassed, int64_t aLastModified, bool aExistenceCheck,
|
|
Packit |
f0b94e |
bool aIsFromNsIFile, BlobImpl** aBlobImpl) {
|
|
Packit |
f0b94e |
if (!aExistenceCheck) {
|
|
Packit |
f0b94e |
RefPtr<FileBlobImpl> impl = new FileBlobImpl(aFile);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (!aName.IsEmpty()) {
|
|
Packit |
f0b94e |
impl->SetName(aName);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (!aType.IsEmpty()) {
|
|
Packit |
f0b94e |
impl->SetType(aType);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (aLastModifiedPassed) {
|
|
Packit |
f0b94e |
impl->SetLastModified(aLastModified);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
impl.forget(aBlobImpl);
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
|
|
Packit |
f0b94e |
nsresult rv = impl->InitializeChromeFile(
|
|
Packit |
f0b94e |
aFile, aType, aName, aLastModifiedPassed, aLastModified, aIsFromNsIFile);
|
|
Packit |
f0b94e |
if (NS_FAILED(rv)) {
|
|
Packit |
f0b94e |
return rv;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
MOZ_ASSERT(impl->IsFile());
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
impl.forget(aBlobImpl);
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
} // namespace dom
|
|
Packit |
f0b94e |
} // namespace mozilla
|