зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1534712 - Port FileCreatorHelper to PBackground, r=smaug
FileCreatorHelper creates a FileBlobImpl on the main-thread and, because of this, we end up executing I/O operations on that thread, slowing down other components. With this patch, FileCreatorHelper logic is moved to PBackground. That the 'type' getter is still called on the main-thread because FileBlobImpl uses nsIMIMEService which is a non thread-safe component. Differential Revision: https://phabricator.services.mozilla.com/D27641 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
72d6086fa4
Коммит
35bde55efd
|
@ -28,14 +28,14 @@ void BaseBlobImpl::SetDOMPath(const nsAString& aPath) {
|
|||
|
||||
void BaseBlobImpl::GetMozFullPath(nsAString& aFileName,
|
||||
SystemCallerGuarantee /* unused */,
|
||||
ErrorResult& aRv) const {
|
||||
ErrorResult& aRv) {
|
||||
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
||||
|
||||
GetMozFullPathInternal(aFileName, aRv);
|
||||
}
|
||||
|
||||
void BaseBlobImpl::GetMozFullPathInternal(nsAString& aFileName,
|
||||
ErrorResult& aRv) const {
|
||||
ErrorResult& aRv) {
|
||||
if (!mIsFile) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
|
|
|
@ -86,10 +86,10 @@ class BaseBlobImpl : public BlobImpl {
|
|||
|
||||
virtual void GetMozFullPath(nsAString& aName,
|
||||
SystemCallerGuarantee /* unused */,
|
||||
ErrorResult& aRv) const override;
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
virtual void GetMozFullPathInternal(nsAString& aFileName,
|
||||
ErrorResult& aRv) const override;
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
virtual uint64_t GetSize(ErrorResult& aRv) override { return mLength; }
|
||||
|
||||
|
|
|
@ -45,10 +45,10 @@ class BlobImpl : public nsISupports {
|
|||
|
||||
virtual void GetMozFullPath(nsAString& aName,
|
||||
SystemCallerGuarantee /* unused */,
|
||||
ErrorResult& aRv) const = 0;
|
||||
ErrorResult& aRv) = 0;
|
||||
|
||||
virtual void GetMozFullPathInternal(nsAString& aFileName,
|
||||
ErrorResult& aRv) const = 0;
|
||||
ErrorResult& aRv) = 0;
|
||||
|
||||
virtual uint64_t GetSize(ErrorResult& aRv) = 0;
|
||||
|
||||
|
|
|
@ -100,13 +100,11 @@ int64_t File::GetLastModified(ErrorResult& aRv) {
|
|||
}
|
||||
|
||||
void File::GetMozFullPath(nsAString& aFilename,
|
||||
SystemCallerGuarantee aGuarantee,
|
||||
ErrorResult& aRv) const {
|
||||
SystemCallerGuarantee aGuarantee, ErrorResult& aRv) {
|
||||
mImpl->GetMozFullPath(aFilename, aGuarantee, aRv);
|
||||
}
|
||||
|
||||
void File::GetMozFullPathInternal(nsAString& aFileName,
|
||||
ErrorResult& aRv) const {
|
||||
void File::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) {
|
||||
mImpl->GetMozFullPathInternal(aFileName, aRv);
|
||||
}
|
||||
|
||||
|
|
|
@ -88,9 +88,9 @@ class File final : public Blob {
|
|||
void GetRelativePath(nsAString& aPath) const;
|
||||
|
||||
void GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee,
|
||||
ErrorResult& aRv) const;
|
||||
ErrorResult& aRv);
|
||||
|
||||
void GetMozFullPathInternal(nsAString& aName, ErrorResult& aRv) const;
|
||||
void GetMozFullPathInternal(nsAString& aName, ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
virtual bool HasFileInterface() const override { return true; }
|
||||
|
|
|
@ -22,12 +22,13 @@ FileBlobImpl::FileBlobImpl(nsIFile* aFile)
|
|||
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), EmptyString(),
|
||||
EmptyString(), UINT64_MAX, INT64_MAX),
|
||||
mFile(aFile),
|
||||
mWholeFile(true),
|
||||
mFileId(-1) {
|
||||
mFileId(-1),
|
||||
mWholeFile(true) {
|
||||
MOZ_ASSERT(mFile, "must have file");
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
// Lazily get the content type and size
|
||||
mContentType.SetIsVoid(true);
|
||||
mMozFullPath.SetIsVoid(true);
|
||||
mFile->GetLeafName(mName);
|
||||
}
|
||||
|
||||
|
@ -37,10 +38,11 @@ FileBlobImpl::FileBlobImpl(const nsAString& aName,
|
|||
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType,
|
||||
aLength, UINT64_MAX),
|
||||
mFile(aFile),
|
||||
mWholeFile(true),
|
||||
mFileId(-1) {
|
||||
mFileId(-1),
|
||||
mWholeFile(true) {
|
||||
MOZ_ASSERT(mFile, "must have file");
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
mMozFullPath.SetIsVoid(true);
|
||||
}
|
||||
|
||||
FileBlobImpl::FileBlobImpl(const nsAString& aName,
|
||||
|
@ -49,10 +51,11 @@ FileBlobImpl::FileBlobImpl(const nsAString& aName,
|
|||
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType,
|
||||
aLength, aLastModificationDate),
|
||||
mFile(aFile),
|
||||
mWholeFile(true),
|
||||
mFileId(-1) {
|
||||
mFileId(-1),
|
||||
mWholeFile(true) {
|
||||
MOZ_ASSERT(mFile, "must have file");
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
mMozFullPath.SetIsVoid(true);
|
||||
}
|
||||
|
||||
FileBlobImpl::FileBlobImpl(nsIFile* aFile, const nsAString& aName,
|
||||
|
@ -60,14 +63,16 @@ FileBlobImpl::FileBlobImpl(nsIFile* aFile, const nsAString& aName,
|
|||
const nsAString& aBlobImplType)
|
||||
: BaseBlobImpl(aBlobImplType, aName, aContentType, UINT64_MAX, INT64_MAX),
|
||||
mFile(aFile),
|
||||
mWholeFile(true),
|
||||
mFileId(-1) {
|
||||
mFileId(-1),
|
||||
mWholeFile(true) {
|
||||
MOZ_ASSERT(mFile, "must have file");
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
if (aContentType.IsEmpty()) {
|
||||
// Lazily get the content type and size
|
||||
mContentType.SetIsVoid(true);
|
||||
}
|
||||
|
||||
mMozFullPath.SetIsVoid(true);
|
||||
}
|
||||
|
||||
FileBlobImpl::FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart,
|
||||
|
@ -75,24 +80,37 @@ FileBlobImpl::FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart,
|
|||
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aContentType,
|
||||
aOther->mStart + aStart, aLength),
|
||||
mFile(aOther->mFile),
|
||||
mWholeFile(false),
|
||||
mFileId(-1) {
|
||||
mFileId(-1),
|
||||
mWholeFile(false) {
|
||||
MOZ_ASSERT(mFile, "must have file");
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
mImmutable = aOther->mImmutable;
|
||||
mMozFullPath = aOther->mMozFullPath;
|
||||
}
|
||||
|
||||
already_AddRefed<BlobImpl> FileBlobImpl::CreateSlice(
|
||||
uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
|
||||
ErrorResult& aRv) {
|
||||
RefPtr<BlobImpl> impl = new FileBlobImpl(this, aStart, aLength, aContentType);
|
||||
RefPtr<FileBlobImpl> impl =
|
||||
new FileBlobImpl(this, aStart, aLength, aContentType);
|
||||
return impl.forget();
|
||||
}
|
||||
|
||||
void FileBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
|
||||
ErrorResult& aRv) const {
|
||||
ErrorResult& aRv) {
|
||||
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
||||
|
||||
if (!mMozFullPath.IsVoid()) {
|
||||
aFilename = mMozFullPath;
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mFile->GetPath(aFilename);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
mMozFullPath = aFilename;
|
||||
}
|
||||
|
||||
uint64_t FileBlobImpl::GetSize(ErrorResult& aRv) {
|
||||
|
@ -205,10 +223,6 @@ int64_t FileBlobImpl::GetLastModified(ErrorResult& aRv) {
|
|||
return mLastModificationDate;
|
||||
}
|
||||
|
||||
void FileBlobImpl::SetLastModified(int64_t aLastModified) {
|
||||
MOZ_CRASH("SetLastModified of a real file is not allowed!");
|
||||
}
|
||||
|
||||
const uint32_t sFileStreamFlags =
|
||||
nsIFileInputStream::CLOSE_ON_EOF | nsIFileInputStream::REOPEN_ON_REWIND |
|
||||
nsIFileInputStream::DEFER_OPEN | nsIFileInputStream::SHARE_DELETE;
|
||||
|
|
|
@ -37,9 +37,8 @@ class FileBlobImpl : public BaseBlobImpl {
|
|||
virtual uint64_t GetSize(ErrorResult& aRv) override;
|
||||
virtual void GetType(nsAString& aType) override;
|
||||
virtual int64_t GetLastModified(ErrorResult& aRv) override;
|
||||
virtual void SetLastModified(int64_t aLastModified) override;
|
||||
virtual void GetMozFullPathInternal(nsAString& aFullPath,
|
||||
ErrorResult& aRv) const override;
|
||||
ErrorResult& aRv) override;
|
||||
virtual void CreateInputStream(nsIInputStream** aInputStream,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
|
@ -57,6 +56,10 @@ class FileBlobImpl : public BaseBlobImpl {
|
|||
|
||||
void SetFileId(int64_t aFileId) { mFileId = aFileId; }
|
||||
|
||||
void SetEmptySize() { mLength = 0; }
|
||||
|
||||
void SetMozFullPath(const nsAString& aPath) { mMozFullPath = aPath; }
|
||||
|
||||
protected:
|
||||
virtual ~FileBlobImpl() = default;
|
||||
|
||||
|
@ -70,8 +73,9 @@ class FileBlobImpl : public BaseBlobImpl {
|
|||
ErrorResult& aRv) override;
|
||||
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
bool mWholeFile;
|
||||
nsString mMozFullPath;
|
||||
int64_t mFileId;
|
||||
bool mWholeFile;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -7,13 +7,16 @@
|
|||
#include "FileCreatorHelper.h"
|
||||
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/FileBinding.h"
|
||||
#include "mozilla/dom/ipc/FileCreatorChild.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
// Undefine the macro of CreateFile to avoid FileCreatorHelper#CreateFile being
|
||||
|
@ -36,167 +39,32 @@ already_AddRefed<Promise> FileCreatorHelper::CreateFile(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobalObject);
|
||||
|
||||
// Parent process
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
RefPtr<File> file =
|
||||
CreateFileInternal(window, aFile, aBag, aIsFromNsIFile, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
promise->MaybeResolve(file);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Content process.
|
||||
|
||||
ContentChild* cc = ContentChild::GetSingleton();
|
||||
if (!cc) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
if (!cc->GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE) &&
|
||||
!Preferences::GetBool("dom.file.createInChild", false)) {
|
||||
// If this pref is not set and the request is received by the parent
|
||||
// process, this child is killed for security reason.
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
RefPtr<FileCreatorHelper> helper = new FileCreatorHelper(promise, window);
|
||||
|
||||
// The request is sent to the parent process and it's kept alive by
|
||||
// ContentChild.
|
||||
helper->SendRequest(aFile, aBag, aIsFromNsIFile, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<File> FileCreatorHelper::CreateFileInternal(
|
||||
nsPIDOMWindowInner* aWindow, nsIFile* aFile,
|
||||
const ChromeFilePropertyBag& aBag, bool aIsFromNsIFile, ErrorResult& aRv) {
|
||||
bool lastModifiedPassed = false;
|
||||
int64_t lastModified = 0;
|
||||
if (aBag.mLastModified.WasPassed()) {
|
||||
lastModifiedPassed = true;
|
||||
lastModified = aBag.mLastModified.Value();
|
||||
}
|
||||
|
||||
RefPtr<BlobImpl> blobImpl;
|
||||
aRv = CreateBlobImpl(aFile, aBag.mType, aBag.mName, lastModifiedPassed,
|
||||
lastModified, aBag.mExistenceCheck, aIsFromNsIFile,
|
||||
getter_AddRefs(blobImpl));
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<File> file = File::Create(aWindow, blobImpl);
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
FileCreatorHelper::FileCreatorHelper(Promise* aPromise,
|
||||
nsPIDOMWindowInner* aWindow)
|
||||
: mPromise(aPromise), mWindow(aWindow) {
|
||||
MOZ_ASSERT(aPromise);
|
||||
}
|
||||
|
||||
FileCreatorHelper::~FileCreatorHelper() {}
|
||||
|
||||
void FileCreatorHelper::SendRequest(nsIFile* aFile,
|
||||
const ChromeFilePropertyBag& aBag,
|
||||
bool aIsFromNsIFile, ErrorResult& aRv) {
|
||||
MOZ_ASSERT(aFile);
|
||||
|
||||
ContentChild* cc = ContentChild::GetSingleton();
|
||||
if (NS_WARN_IF(!cc)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
nsID uuid;
|
||||
aRv = nsContentUtils::GenerateUUIDInPlace(uuid);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString path;
|
||||
aRv = aFile->GetPath(path);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cc->FileCreationRequest(uuid, this, path, aBag.mType, aBag.mName,
|
||||
aBag.mLastModified, aBag.mExistenceCheck,
|
||||
aIsFromNsIFile);
|
||||
}
|
||||
|
||||
void FileCreatorHelper::ResponseReceived(BlobImpl* aBlobImpl, nsresult aRv) {
|
||||
if (NS_FAILED(aRv)) {
|
||||
mPromise->MaybeReject(aRv);
|
||||
return;
|
||||
// Register this component to PBackground.
|
||||
mozilla::ipc::PBackgroundChild* actorChild =
|
||||
mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
|
||||
if (NS_WARN_IF(!actorChild)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<File> file = File::Create(mWindow, aBlobImpl);
|
||||
mPromise->MaybeResolve(file);
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult FileCreatorHelper::CreateBlobImplForIPC(
|
||||
const nsAString& aPath, const nsAString& aType, const nsAString& aName,
|
||||
bool aLastModifiedPassed, int64_t aLastModified, bool aExistenceCheck,
|
||||
bool aIsFromNsIFile, BlobImpl** aBlobImpl) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = NS_NewLocalFile(aPath, true, getter_AddRefs(file));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
Maybe<int64_t> lastModified;
|
||||
if (aBag.mLastModified.WasPassed()) {
|
||||
lastModified.emplace(aBag.mLastModified.Value());
|
||||
}
|
||||
|
||||
return CreateBlobImpl(file, aType, aName, aLastModifiedPassed, aLastModified,
|
||||
aExistenceCheck, aIsFromNsIFile, aBlobImpl);
|
||||
}
|
||||
mozilla::ipc::PFileCreatorChild* actor =
|
||||
actorChild->SendPFileCreatorConstructor(
|
||||
path, aBag.mType, aBag.mName, lastModified, aBag.mExistenceCheck,
|
||||
aIsFromNsIFile);
|
||||
|
||||
/* static */
|
||||
nsresult FileCreatorHelper::CreateBlobImpl(
|
||||
nsIFile* aFile, const nsAString& aType, const nsAString& aName,
|
||||
bool aLastModifiedPassed, int64_t aLastModified, bool aExistenceCheck,
|
||||
bool aIsFromNsIFile, BlobImpl** aBlobImpl) {
|
||||
if (!aExistenceCheck) {
|
||||
RefPtr<FileBlobImpl> impl = new FileBlobImpl(aFile);
|
||||
|
||||
if (!aName.IsEmpty()) {
|
||||
impl->SetName(aName);
|
||||
}
|
||||
|
||||
if (!aType.IsEmpty()) {
|
||||
impl->SetType(aType);
|
||||
}
|
||||
|
||||
if (aLastModifiedPassed) {
|
||||
impl->SetLastModified(aLastModified);
|
||||
}
|
||||
|
||||
impl.forget(aBlobImpl);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
|
||||
nsresult rv = impl->InitializeChromeFile(
|
||||
aFile, aType, aName, aLastModifiedPassed, aLastModified, aIsFromNsIFile);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(impl->IsFile());
|
||||
|
||||
impl.forget(aBlobImpl);
|
||||
return NS_OK;
|
||||
static_cast<FileCreatorChild*>(actor)->SetPromise(promise);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -20,52 +20,20 @@
|
|||
|
||||
class nsIFile;
|
||||
class nsIGlobalObject;
|
||||
class nsPIDOMWindowInner;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct ChromeFilePropertyBag;
|
||||
class Promise;
|
||||
class File;
|
||||
|
||||
class FileCreatorHelper final {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(FileCreatorHelper);
|
||||
|
||||
static already_AddRefed<Promise> CreateFile(nsIGlobalObject* aGlobalObject,
|
||||
nsIFile* aFile,
|
||||
const ChromeFilePropertyBag& aBag,
|
||||
bool aIsFromNsIFile,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void ResponseReceived(BlobImpl* aBlobImpl, nsresult aRv);
|
||||
|
||||
// For IPC only
|
||||
static nsresult CreateBlobImplForIPC(
|
||||
const nsAString& aPath, const nsAString& aType, const nsAString& aName,
|
||||
bool aLastModifiedPassed, int64_t aLastModified, bool aExistenceCheck,
|
||||
bool aIsFromNsIFile, BlobImpl** aBlobImpl);
|
||||
|
||||
private:
|
||||
static already_AddRefed<File> CreateFileInternal(
|
||||
nsPIDOMWindowInner* aWindow, nsIFile* aFile,
|
||||
const ChromeFilePropertyBag& aBag, bool aIsFromNsIFile, ErrorResult& aRv);
|
||||
|
||||
static nsresult CreateBlobImpl(nsIFile* aFile, const nsAString& aType,
|
||||
const nsAString& aName,
|
||||
bool aLastModifiedPassed,
|
||||
int64_t aLastModified, bool aExistenceCheck,
|
||||
bool aIsFromNsIFile, BlobImpl** aBlobImpl);
|
||||
|
||||
FileCreatorHelper(Promise* aPromise, nsPIDOMWindowInner* aWindow);
|
||||
~FileCreatorHelper();
|
||||
|
||||
void SendRequest(nsIFile* aFile, const ChromeFilePropertyBag& aBag,
|
||||
bool aIsFromNsIFile, ErrorResult& aRv);
|
||||
|
||||
RefPtr<Promise> mPromise;
|
||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -274,22 +274,6 @@ void MultipartBlobImpl::SetLengthAndModifiedDate(ErrorResult& aRv) {
|
|||
}
|
||||
}
|
||||
|
||||
void MultipartBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
|
||||
ErrorResult& aRv) const {
|
||||
if (!mIsFromNsIFile || mBlobImpls.Length() == 0) {
|
||||
BaseBlobImpl::GetMozFullPathInternal(aFilename, aRv);
|
||||
return;
|
||||
}
|
||||
|
||||
BlobImpl* blobImpl = mBlobImpls.ElementAt(0).get();
|
||||
if (!blobImpl) {
|
||||
BaseBlobImpl::GetMozFullPathInternal(aFilename, aRv);
|
||||
return;
|
||||
}
|
||||
|
||||
blobImpl->GetMozFullPathInternal(aFilename, aRv);
|
||||
}
|
||||
|
||||
nsresult MultipartBlobImpl::SetMutable(bool aMutable) {
|
||||
nsresult rv;
|
||||
|
||||
|
@ -317,82 +301,6 @@ nsresult MultipartBlobImpl::SetMutable(bool aMutable) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult MultipartBlobImpl::InitializeChromeFile(
|
||||
nsIFile* aFile, const nsAString& aType, const nsAString& aName,
|
||||
bool aLastModifiedPassed, int64_t aLastModified, bool aIsFromNsIFile) {
|
||||
MOZ_ASSERT(!mImmutable, "Something went wrong ...");
|
||||
if (mImmutable) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
mName = aName;
|
||||
mContentType = aType;
|
||||
mIsFromNsIFile = aIsFromNsIFile;
|
||||
|
||||
bool exists;
|
||||
nsresult rv = aFile->Exists(&exists);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
bool isDir;
|
||||
rv = aFile->IsDirectory(&isDir);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (isDir) {
|
||||
return NS_ERROR_FILE_IS_DIRECTORY;
|
||||
}
|
||||
|
||||
if (mName.IsEmpty()) {
|
||||
aFile->GetLeafName(mName);
|
||||
}
|
||||
|
||||
RefPtr<File> blob = File::CreateFromFile(nullptr, aFile);
|
||||
|
||||
// Pre-cache size.
|
||||
ErrorResult error;
|
||||
blob->GetSize(error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
// Pre-cache modified date.
|
||||
blob->GetLastModified(error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
// XXXkhuey this is terrible
|
||||
if (mContentType.IsEmpty()) {
|
||||
blob->GetType(mContentType);
|
||||
}
|
||||
|
||||
BlobSet blobSet;
|
||||
rv = blobSet.AppendBlobImpl(static_cast<File*>(blob.get())->Impl());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mBlobImpls = blobSet.GetBlobImpls();
|
||||
|
||||
SetLengthAndModifiedDate(error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
if (aLastModifiedPassed) {
|
||||
SetLastModified(aLastModified);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool MultipartBlobImpl::MayBeClonedToOtherThreads() const {
|
||||
for (uint32_t i = 0; i < mBlobImpls.Length(); ++i) {
|
||||
if (!mBlobImpls[i]->MayBeClonedToOtherThreads()) {
|
||||
|
|
|
@ -32,14 +32,12 @@ class MultipartBlobImpl final : public BaseBlobImpl {
|
|||
// Create as a file to be later initialized
|
||||
explicit MultipartBlobImpl(const nsAString& aName)
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aName,
|
||||
EmptyString(), UINT64_MAX),
|
||||
mIsFromNsIFile(false) {}
|
||||
EmptyString(), UINT64_MAX) {}
|
||||
|
||||
// Create as a blob to be later initialized
|
||||
MultipartBlobImpl()
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), EmptyString(),
|
||||
UINT64_MAX),
|
||||
mIsFromNsIFile(false) {}
|
||||
UINT64_MAX) {}
|
||||
|
||||
void InitializeBlob(ErrorResult& aRv);
|
||||
|
||||
|
@ -47,11 +45,6 @@ class MultipartBlobImpl final : public BaseBlobImpl {
|
|||
const nsAString& aContentType, bool aNativeEOL,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsresult InitializeChromeFile(nsIFile* aData, const nsAString& aType,
|
||||
const nsAString& aName,
|
||||
bool aLastModifiedPassed, int64_t aLastModified,
|
||||
bool aIsFromNsIFile);
|
||||
|
||||
virtual already_AddRefed<BlobImpl> CreateSlice(uint64_t aStart,
|
||||
uint64_t aLength,
|
||||
const nsAString& aContentType,
|
||||
|
@ -66,9 +59,6 @@ class MultipartBlobImpl final : public BaseBlobImpl {
|
|||
return mBlobImpls.Length() ? &mBlobImpls : nullptr;
|
||||
}
|
||||
|
||||
virtual void GetMozFullPathInternal(nsAString& aFullPath,
|
||||
ErrorResult& aRv) const override;
|
||||
|
||||
virtual nsresult SetMutable(bool aMutable) override;
|
||||
|
||||
void SetName(const nsAString& aName) { mName = aName; }
|
||||
|
@ -86,22 +76,19 @@ class MultipartBlobImpl final : public BaseBlobImpl {
|
|||
const nsAString& aName, const nsAString& aContentType)
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aName,
|
||||
aContentType, UINT64_MAX),
|
||||
mBlobImpls(std::move(aBlobImpls)),
|
||||
mIsFromNsIFile(false) {}
|
||||
mBlobImpls(std::move(aBlobImpls)) {}
|
||||
|
||||
MultipartBlobImpl(nsTArray<RefPtr<BlobImpl>>&& aBlobImpls,
|
||||
const nsAString& aContentType)
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aContentType,
|
||||
UINT64_MAX),
|
||||
mBlobImpls(std::move(aBlobImpls)),
|
||||
mIsFromNsIFile(false) {}
|
||||
mBlobImpls(std::move(aBlobImpls)) {}
|
||||
|
||||
virtual ~MultipartBlobImpl() {}
|
||||
|
||||
void SetLengthAndModifiedDate(ErrorResult& aRv);
|
||||
|
||||
nsTArray<RefPtr<BlobImpl>> mBlobImpls;
|
||||
bool mIsFromNsIFile;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -46,8 +46,7 @@ class StreamBlobImpl final : public BaseBlobImpl, public nsIMemoryReporter {
|
|||
|
||||
void SetFullPath(const nsAString& aFullPath) { mFullPath = aFullPath; }
|
||||
|
||||
void GetMozFullPathInternal(nsAString& aFullPath,
|
||||
ErrorResult& aRv) const override {
|
||||
void GetMozFullPathInternal(nsAString& aFullPath, ErrorResult& aRv) override {
|
||||
aFullPath = mFullPath;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FileCreatorChild.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/IPCBlobUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
FileCreatorChild::FileCreatorChild() = default;
|
||||
|
||||
FileCreatorChild::~FileCreatorChild() { MOZ_ASSERT(!mPromise); }
|
||||
|
||||
void FileCreatorChild::SetPromise(Promise* aPromise) {
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_ASSERT(!mPromise);
|
||||
|
||||
mPromise = aPromise;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult FileCreatorChild::Recv__delete__(
|
||||
const FileCreationResult& aResult) {
|
||||
MOZ_ASSERT(mPromise);
|
||||
|
||||
RefPtr<Promise> promise;
|
||||
promise.swap(mPromise);
|
||||
|
||||
if (aResult.type() == FileCreationResult::TFileCreationErrorResult) {
|
||||
promise->MaybeReject(aResult.get_FileCreationErrorResult().errorCode());
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aResult.type() == FileCreationResult::TFileCreationSuccessResult);
|
||||
|
||||
RefPtr<dom::BlobImpl> impl = dom::IPCBlobUtils::Deserialize(
|
||||
aResult.get_FileCreationSuccessResult().blob());
|
||||
|
||||
RefPtr<File> file = File::Create(promise->GetParentObject(), impl);
|
||||
promise->MaybeResolve(file);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void FileCreatorChild::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
if (mPromise) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
mPromise = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,36 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_ipc_FileCreatorChild_h
|
||||
#define mozilla_dom_ipc_FileCreatorChild_h
|
||||
|
||||
#include "mozilla/ipc/PFileCreatorChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FileCreatorChild final : public mozilla::ipc::PFileCreatorChild {
|
||||
friend class mozilla::ipc::PFileCreatorChild;
|
||||
|
||||
public:
|
||||
FileCreatorChild();
|
||||
~FileCreatorChild();
|
||||
|
||||
void SetPromise(Promise* aPromise);
|
||||
|
||||
private:
|
||||
mozilla::ipc::IPCResult Recv__delete__(
|
||||
const FileCreationResult& aResult) override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
RefPtr<Promise> mPromise;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ipc_FileCreatorChild_h
|
|
@ -0,0 +1,136 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FileCreatorParent.h"
|
||||
#include "mozilla/dom/FileBlobImpl.h"
|
||||
#include "mozilla/dom/IPCBlobUtils.h"
|
||||
#include "mozilla/dom/MultipartBlobImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
FileCreatorParent::FileCreatorParent()
|
||||
: mBackgroundEventTarget(GetCurrentThreadEventTarget()), mIPCActive(true) {}
|
||||
|
||||
FileCreatorParent::~FileCreatorParent() = default;
|
||||
|
||||
mozilla::ipc::IPCResult FileCreatorParent::CreateAndShareFile(
|
||||
const nsString& aFullPath, const nsString& aType, const nsString& aName,
|
||||
const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
|
||||
const bool& aIsFromNsIFile) {
|
||||
RefPtr<dom::BlobImpl> blobImpl;
|
||||
nsresult rv =
|
||||
CreateBlobImpl(aFullPath, aType, aName, aLastModified.isSome(),
|
||||
aLastModified.isSome() ? aLastModified.value() : 0,
|
||||
aExistenceCheck, aIsFromNsIFile, getter_AddRefs(blobImpl));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
Unused << Send__delete__(this, FileCreationErrorResult(rv));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(blobImpl);
|
||||
|
||||
// FileBlobImpl is unable to return the correct type on this thread because
|
||||
// nsIMIMEService is not thread-safe. We must exec the 'type' getter on
|
||||
// main-thread before send the blob to the child actor.
|
||||
|
||||
RefPtr<FileCreatorParent> self = this;
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"FileCreatorParent::CreateAndShareFile", [self, blobImpl]() {
|
||||
nsAutoString type;
|
||||
blobImpl->GetType(type);
|
||||
|
||||
self->mBackgroundEventTarget->Dispatch(NS_NewRunnableFunction(
|
||||
"FileCreatorParent::CreateAndShareFile return", [self, blobImpl]() {
|
||||
if (self->mIPCActive) {
|
||||
IPCBlob ipcBlob;
|
||||
nsresult rv = dom::IPCBlobUtils::Serialize(
|
||||
blobImpl, self->Manager(), ipcBlob);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
Unused << Send__delete__(self, FileCreationErrorResult(rv));
|
||||
return;
|
||||
}
|
||||
|
||||
Unused << Send__delete__(self,
|
||||
FileCreationSuccessResult(ipcBlob));
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void FileCreatorParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
mIPCActive = false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult FileCreatorParent::CreateBlobImpl(
|
||||
const nsAString& aPath, const nsAString& aType, const nsAString& aName,
|
||||
bool aLastModifiedPassed, int64_t aLastModified, bool aExistenceCheck,
|
||||
bool aIsFromNsIFile, BlobImpl** aBlobImpl) {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = NS_NewLocalFile(aPath, true, getter_AddRefs(file));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (aExistenceCheck) {
|
||||
bool exists;
|
||||
nsresult rv = file->Exists(&exists);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
bool isDir;
|
||||
rv = file->IsDirectory(&isDir);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (isDir) {
|
||||
return NS_ERROR_FILE_IS_DIRECTORY;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<FileBlobImpl> impl = new FileBlobImpl(file);
|
||||
|
||||
// If the file doesn't exist, we cannot have its path, its size and so on.
|
||||
// Let's set them now.
|
||||
if (!aExistenceCheck) {
|
||||
impl->SetMozFullPath(aPath);
|
||||
impl->SetLastModified(0);
|
||||
impl->SetEmptySize();
|
||||
}
|
||||
|
||||
if (!aName.IsEmpty()) {
|
||||
impl->SetName(aName);
|
||||
}
|
||||
|
||||
if (!aType.IsEmpty()) {
|
||||
impl->SetType(aType);
|
||||
}
|
||||
|
||||
if (aLastModifiedPassed) {
|
||||
impl->SetLastModified(aLastModified);
|
||||
}
|
||||
|
||||
if (!aIsFromNsIFile) {
|
||||
impl->SetMozFullPath(EmptyString());
|
||||
}
|
||||
|
||||
impl.forget(aBlobImpl);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,47 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_ipc_FileCreatorParent_h
|
||||
#define mozilla_dom_ipc_FileCreatorParent_h
|
||||
|
||||
#include "mozilla/ipc/PFileCreatorParent.h"
|
||||
|
||||
class nsIFile;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class BlobImpl;
|
||||
|
||||
class FileCreatorParent final : public mozilla::ipc::PFileCreatorParent {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FileCreatorParent)
|
||||
|
||||
FileCreatorParent();
|
||||
|
||||
mozilla::ipc::IPCResult CreateAndShareFile(
|
||||
const nsString& aFullPath, const nsString& aType, const nsString& aName,
|
||||
const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
|
||||
const bool& aIsFromNsIFile);
|
||||
|
||||
private:
|
||||
~FileCreatorParent();
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
nsresult CreateBlobImpl(const nsAString& aPath, const nsAString& aType,
|
||||
const nsAString& aName, bool aLastModifiedPassed,
|
||||
int64_t aLastModified, bool aExistenceCheck,
|
||||
bool aIsFromNsIFile, BlobImpl** aBlobImpl);
|
||||
|
||||
nsCOMPtr<nsIEventTarget> mBackgroundEventTarget;
|
||||
bool mIPCActive;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ipc_FileCreatorParent_h
|
|
@ -0,0 +1,41 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PBackground;
|
||||
include protocol PChildToParentStream;
|
||||
include protocol PFileDescriptorSet;
|
||||
include protocol PIPCBlobInputStream;
|
||||
include protocol PParentToChildStream;
|
||||
|
||||
include IPCBlob;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
struct FileCreationSuccessResult
|
||||
{
|
||||
IPCBlob blob;
|
||||
};
|
||||
|
||||
struct FileCreationErrorResult
|
||||
{
|
||||
nsresult errorCode;
|
||||
};
|
||||
|
||||
union FileCreationResult
|
||||
{
|
||||
FileCreationSuccessResult;
|
||||
FileCreationErrorResult;
|
||||
};
|
||||
|
||||
protocol PFileCreator
|
||||
{
|
||||
manager PBackground;
|
||||
|
||||
child:
|
||||
async __delete__(FileCreationResult aResult);
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
|
@ -39,5 +39,5 @@ parent:
|
|||
async OperationDone(nsCString aContentType, FileDescriptor aFD);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -8,6 +8,8 @@ with Files("**"):
|
|||
BUG_COMPONENT = ("Core", "DOM: File")
|
||||
|
||||
EXPORTS.mozilla.dom.ipc += [
|
||||
'FileCreatorChild.h',
|
||||
'FileCreatorParent.h',
|
||||
'IPCBlobInputStream.h',
|
||||
'IPCBlobInputStreamChild.h',
|
||||
'IPCBlobInputStreamParent.h',
|
||||
|
@ -23,6 +25,8 @@ EXPORTS.mozilla.dom += [
|
|||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'FileCreatorChild.cpp',
|
||||
'FileCreatorParent.cpp',
|
||||
'IPCBlobInputStream.cpp',
|
||||
'IPCBlobInputStreamChild.cpp',
|
||||
'IPCBlobInputStreamParent.cpp',
|
||||
|
@ -38,6 +42,7 @@ UNIFIED_SOURCES += [
|
|||
IPDL_SOURCES += [
|
||||
'BlobTypes.ipdlh',
|
||||
'IPCBlob.ipdlh',
|
||||
'PFileCreator.ipdl',
|
||||
'PIPCBlobInputStream.ipdl',
|
||||
'PPendingIPCBlob.ipdl',
|
||||
'PTemporaryIPCBlob.ipdl',
|
||||
|
|
|
@ -72,12 +72,12 @@ class BlobImplSnapshot final : public BlobImpl, public PIBlobImplSnapshot {
|
|||
|
||||
virtual void GetMozFullPath(nsAString& aName,
|
||||
SystemCallerGuarantee aGuarantee,
|
||||
ErrorResult& aRv) const override {
|
||||
ErrorResult& aRv) override {
|
||||
mBlobImpl->GetMozFullPath(aName, aGuarantee, aRv);
|
||||
}
|
||||
|
||||
virtual void GetMozFullPathInternal(nsAString& aFileName,
|
||||
ErrorResult& aRv) const override {
|
||||
ErrorResult& aRv) override {
|
||||
mBlobImpl->GetMozFullPathInternal(aFileName, aRv);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include "mozilla/dom/DataTransfer.h"
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
#include "mozilla/dom/ExternalHelperAppChild.h"
|
||||
#include "mozilla/dom/FileCreatorHelper.h"
|
||||
#include "mozilla/dom/GetFilesHelper.h"
|
||||
#include "mozilla/dom/IPCBlobUtils.h"
|
||||
#include "mozilla/dom/JSWindowActorService.h"
|
||||
|
@ -3394,51 +3393,6 @@ bool ContentChild::DeallocPSessionStorageObserverChild(
|
|||
return true;
|
||||
}
|
||||
|
||||
void ContentChild::FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
|
||||
const nsAString& aFullPath,
|
||||
const nsAString& aType,
|
||||
const nsAString& aName,
|
||||
const Optional<int64_t>& aLastModified,
|
||||
bool aExistenceCheck,
|
||||
bool aIsFromNsIFile) {
|
||||
MOZ_ASSERT(aHelper);
|
||||
|
||||
bool lastModifiedPassed = false;
|
||||
int64_t lastModified = 0;
|
||||
if (aLastModified.WasPassed()) {
|
||||
lastModifiedPassed = true;
|
||||
lastModified = aLastModified.Value();
|
||||
}
|
||||
|
||||
Unused << SendFileCreationRequest(
|
||||
aUUID, nsString(aFullPath), nsString(aType), nsString(aName),
|
||||
lastModifiedPassed, lastModified, aExistenceCheck, aIsFromNsIFile);
|
||||
mFileCreationPending.Put(aUUID, aHelper);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvFileCreationResponse(
|
||||
const nsID& aUUID, const FileCreationResult& aResult) {
|
||||
FileCreatorHelper* helper = mFileCreationPending.GetWeak(aUUID);
|
||||
if (!helper) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
if (aResult.type() == FileCreationResult::TFileCreationErrorResult) {
|
||||
helper->ResponseReceived(nullptr,
|
||||
aResult.get_FileCreationErrorResult().errorCode());
|
||||
} else {
|
||||
MOZ_ASSERT(aResult.type() ==
|
||||
FileCreationResult::TFileCreationSuccessResult);
|
||||
|
||||
RefPtr<BlobImpl> impl = IPCBlobUtils::Deserialize(
|
||||
aResult.get_FileCreationSuccessResult().blob());
|
||||
helper->ResponseReceived(impl, NS_OK);
|
||||
}
|
||||
|
||||
mFileCreationPending.Remove(aUUID);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvActivate(PBrowserChild* aTab) {
|
||||
BrowserChild* tab = static_cast<BrowserChild*>(aTab);
|
||||
return tab->RecvActivate();
|
||||
|
|
|
@ -77,7 +77,6 @@ class ConsoleListener;
|
|||
class ClonedMessageData;
|
||||
class BrowserChild;
|
||||
class GetFilesHelperChild;
|
||||
class FileCreatorHelper;
|
||||
|
||||
class ContentChild final : public PContentChild,
|
||||
public nsIWindowProvider,
|
||||
|
@ -562,9 +561,6 @@ class ContentChild final : public PContentChild,
|
|||
|
||||
mozilla::ipc::IPCResult RecvBlobURLUnregistration(const nsCString& aURI);
|
||||
|
||||
mozilla::ipc::IPCResult RecvFileCreationResponse(
|
||||
const nsID& aUUID, const FileCreationResult& aResult);
|
||||
|
||||
mozilla::ipc::IPCResult RecvRequestMemoryReport(
|
||||
const uint32_t& generation, const bool& anonymize,
|
||||
const bool& minimizeMemoryUsage, const Maybe<FileDescriptor>& DMDFile);
|
||||
|
@ -643,13 +639,6 @@ class ContentChild final : public PContentChild,
|
|||
static void FatalErrorIfNotUsingGPUProcess(const char* const aErrorMsg,
|
||||
base::ProcessId aOtherPid);
|
||||
|
||||
// This method is used by FileCreatorHelper for the creation of a BlobImpl.
|
||||
void FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
|
||||
const nsAString& aFullPath, const nsAString& aType,
|
||||
const nsAString& aName,
|
||||
const Optional<int64_t>& aLastModified,
|
||||
bool aExistenceCheck, bool aIsFromNsIFile);
|
||||
|
||||
typedef std::function<void(PRFileDesc*)> AnonymousTemporaryFileCallback;
|
||||
nsresult AsyncOpenAnonymousTemporaryFile(
|
||||
const AnonymousTemporaryFileCallback& aCallback);
|
||||
|
@ -802,10 +791,6 @@ class ContentChild final : public PContentChild,
|
|||
// received.
|
||||
nsRefPtrHashtable<nsIDHashKey, GetFilesHelperChild> mGetFilesPendingRequests;
|
||||
|
||||
// Hashtable to keep track of the pending file creation.
|
||||
// These items are removed when RecvFileCreationResponse is received.
|
||||
nsRefPtrHashtable<nsIDHashKey, FileCreatorHelper> mFileCreationPending;
|
||||
|
||||
nsClassHashtable<nsUint64HashKey, AnonymousTemporaryFileCallback>
|
||||
mPendingAnonymousTemporaryFiles;
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include "mozilla/dom/DataTransfer.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FileCreatorHelper.h"
|
||||
#include "mozilla/dom/FileSystemSecurity.h"
|
||||
#include "mozilla/dom/IPCBlobUtils.h"
|
||||
#include "mozilla/dom/ExternalHelperAppParent.h"
|
||||
|
@ -5533,49 +5532,6 @@ bool ContentParent::DeallocPSessionStorageObserverParent(
|
|||
return mozilla::dom::DeallocPSessionStorageObserverParent(aActor);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvFileCreationRequest(
|
||||
const nsID& aID, const nsString& aFullPath, const nsString& aType,
|
||||
const nsString& aName, const bool& aLastModifiedPassed,
|
||||
const int64_t& aLastModified, const bool& aExistenceCheck,
|
||||
const bool& aIsFromNsIFile) {
|
||||
// We allow the creation of File via this IPC call only for the 'file' process
|
||||
// or for testing.
|
||||
if (!mRemoteType.EqualsLiteral(FILE_REMOTE_TYPE) &&
|
||||
!Preferences::GetBool("dom.file.createInChild", false)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
RefPtr<BlobImpl> blobImpl;
|
||||
nsresult rv = FileCreatorHelper::CreateBlobImplForIPC(
|
||||
aFullPath, aType, aName, aLastModifiedPassed, aLastModified,
|
||||
aExistenceCheck, aIsFromNsIFile, getter_AddRefs(blobImpl));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (!SendFileCreationResponse(aID, FileCreationErrorResult(rv))) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(blobImpl);
|
||||
|
||||
IPCBlob ipcBlob;
|
||||
rv = IPCBlobUtils::Serialize(blobImpl, this, ipcBlob);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (!SendFileCreationResponse(aID, FileCreationErrorResult(rv))) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
if (!SendFileCreationResponse(aID, FileCreationSuccessResult(ipcBlob))) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
nsresult ContentParent::SaveRecording(nsIFile* aFile, bool* aRetval) {
|
||||
if (mRecordReplayState != eRecording) {
|
||||
*aRetval = false;
|
||||
|
|
|
@ -1128,12 +1128,6 @@ class ContentParent final : public PContentParent,
|
|||
|
||||
mozilla::ipc::IPCResult RecvDeleteGetFilesRequest(const nsID& aID);
|
||||
|
||||
mozilla::ipc::IPCResult RecvFileCreationRequest(
|
||||
const nsID& aID, const nsString& aFullPath, const nsString& aType,
|
||||
const nsString& aName, const bool& aLastModifiedPassed,
|
||||
const int64_t& aLastModified, const bool& aExistenceCheck,
|
||||
const bool& aIsFromNsIFile);
|
||||
|
||||
mozilla::ipc::IPCResult RecvAccumulateChildHistograms(
|
||||
InfallibleTArray<HistogramAccumulation>&& aAccumulations);
|
||||
mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistograms(
|
||||
|
|
|
@ -203,22 +203,6 @@ union GetFilesResponseResult
|
|||
GetFilesResponseFailure;
|
||||
};
|
||||
|
||||
struct FileCreationSuccessResult
|
||||
{
|
||||
IPCBlob blob;
|
||||
};
|
||||
|
||||
struct FileCreationErrorResult
|
||||
{
|
||||
nsresult errorCode;
|
||||
};
|
||||
|
||||
union FileCreationResult
|
||||
{
|
||||
FileCreationSuccessResult;
|
||||
FileCreationErrorResult;
|
||||
};
|
||||
|
||||
struct BlobURLRegistrationData
|
||||
{
|
||||
nsCString url;
|
||||
|
@ -670,8 +654,6 @@ child:
|
|||
async GMPsChanged(GMPCapabilityData[] capabilities);
|
||||
|
||||
|
||||
async FileCreationResponse(nsID aID, FileCreationResult aResult);
|
||||
|
||||
/**
|
||||
* Sending an activate message moves focus to the child.
|
||||
*/
|
||||
|
@ -1206,11 +1188,6 @@ parent:
|
|||
async GetFilesRequest(nsID aID, nsString aDirectory, bool aRecursiveFlag);
|
||||
async DeleteGetFilesRequest(nsID aID);
|
||||
|
||||
async FileCreationRequest(nsID aID, nsString aFullPath, nsString aType,
|
||||
nsString aName, bool lastModifiedPassed,
|
||||
int64_t lastModified, bool aExistenceCheck,
|
||||
bool aIsFromNsIFile);
|
||||
|
||||
async StoreAndBroadcastBlobURLRegistration(nsCString url, IPCBlob blob,
|
||||
Principal principal);
|
||||
|
||||
|
|
|
@ -27,9 +27,11 @@
|
|||
#include "mozilla/dom/cache/ActorUtils.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIndexedDBUtilsChild.h"
|
||||
#include "mozilla/dom/ipc/FileCreatorChild.h"
|
||||
#include "mozilla/dom/ipc/IPCBlobInputStreamChild.h"
|
||||
#include "mozilla/dom/ipc/PendingIPCBlobChild.h"
|
||||
#include "mozilla/dom/ipc/TemporaryIPCBlobChild.h"
|
||||
#include "mozilla/dom/IPCBlobUtils.h"
|
||||
#include "mozilla/dom/quota/PQuotaChild.h"
|
||||
#include "mozilla/dom/RemoteWorkerChild.h"
|
||||
#include "mozilla/dom/RemoteWorkerServiceChild.h"
|
||||
|
@ -379,6 +381,18 @@ bool BackgroundChildImpl::DeallocPTemporaryIPCBlobChild(
|
|||
return true;
|
||||
}
|
||||
|
||||
PFileCreatorChild* BackgroundChildImpl::AllocPFileCreatorChild(
|
||||
const nsString& aFullPath, const nsString& aType, const nsString& aName,
|
||||
const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
|
||||
const bool& aIsFromNsIFile) {
|
||||
return new mozilla::dom::FileCreatorChild();
|
||||
}
|
||||
|
||||
bool BackgroundChildImpl::DeallocPFileCreatorChild(PFileCreatorChild* aActor) {
|
||||
delete static_cast<mozilla::dom::FileCreatorChild*>(aActor);
|
||||
return true;
|
||||
}
|
||||
|
||||
PIPCBlobInputStreamChild* BackgroundChildImpl::AllocPIPCBlobInputStreamChild(
|
||||
const nsID& aID, const uint64_t& aSize) {
|
||||
// IPCBlobInputStreamChild is refcounted. Here it's created and in
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -126,6 +127,13 @@ class BackgroundChildImpl : public PBackgroundChild {
|
|||
virtual bool DeallocPTemporaryIPCBlobChild(
|
||||
PTemporaryIPCBlobChild* aActor) override;
|
||||
|
||||
virtual PFileCreatorChild* AllocPFileCreatorChild(
|
||||
const nsString& aFullPath, const nsString& aType, const nsString& aName,
|
||||
const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
|
||||
const bool& aIsFromNsIFile) override;
|
||||
|
||||
virtual bool DeallocPFileCreatorChild(PFileCreatorChild* aActor) override;
|
||||
|
||||
virtual mozilla::dom::PRemoteWorkerChild* AllocPRemoteWorkerChild(
|
||||
const RemoteWorkerData& aData) override;
|
||||
|
||||
|
|
|
@ -30,9 +30,11 @@
|
|||
#include "mozilla/dom/StorageActivityService.h"
|
||||
#include "mozilla/dom/cache/ActorUtils.h"
|
||||
#include "mozilla/dom/indexedDB/ActorsParent.h"
|
||||
#include "mozilla/dom/ipc/FileCreatorParent.h"
|
||||
#include "mozilla/dom/ipc/IPCBlobInputStreamParent.h"
|
||||
#include "mozilla/dom/ipc/PendingIPCBlobParent.h"
|
||||
#include "mozilla/dom/ipc/TemporaryIPCBlobParent.h"
|
||||
#include "mozilla/dom/IPCBlobUtils.h"
|
||||
#include "mozilla/dom/localstorage/ActorsParent.h"
|
||||
#include "mozilla/dom/quota/ActorsParent.h"
|
||||
#include "mozilla/dom/simpledb/ActorsParent.h"
|
||||
|
@ -56,6 +58,7 @@
|
|||
#include "mozilla/dom/network/UDPSocketParent.h"
|
||||
#include "mozilla/dom/WebAuthnTransactionParent.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
@ -538,6 +541,53 @@ bool BackgroundParentImpl::DeallocPSharedWorkerParent(
|
|||
return true;
|
||||
}
|
||||
|
||||
PFileCreatorParent* BackgroundParentImpl::AllocPFileCreatorParent(
|
||||
const nsString& aFullPath, const nsString& aType, const nsString& aName,
|
||||
const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
|
||||
const bool& aIsFromNsIFile) {
|
||||
RefPtr<mozilla::dom::FileCreatorParent> actor =
|
||||
new mozilla::dom::FileCreatorParent();
|
||||
return actor.forget().take();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BackgroundParentImpl::RecvPFileCreatorConstructor(
|
||||
PFileCreatorParent* aActor, const nsString& aFullPath,
|
||||
const nsString& aType, const nsString& aName,
|
||||
const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
|
||||
const bool& aIsFromNsIFile) {
|
||||
bool isFileRemoteType = false;
|
||||
|
||||
// If the ContentParent is null we are dealing with a same-process actor.
|
||||
RefPtr<ContentParent> parent = BackgroundParent::GetContentParent(this);
|
||||
if (!parent) {
|
||||
isFileRemoteType = true;
|
||||
} else {
|
||||
isFileRemoteType = parent->GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE);
|
||||
NS_ReleaseOnMainThreadSystemGroup("ContentParent release", parent.forget());
|
||||
}
|
||||
|
||||
mozilla::dom::FileCreatorParent* actor =
|
||||
static_cast<mozilla::dom::FileCreatorParent*>(aActor);
|
||||
|
||||
// We allow the creation of File via this IPC call only for the 'file' process
|
||||
// or for testing.
|
||||
if (!isFileRemoteType && !StaticPrefs::dom_file_createInChild()) {
|
||||
Unused << mozilla::dom::FileCreatorParent::Send__delete__(
|
||||
actor, FileCreationErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
return actor->CreateAndShareFile(aFullPath, aType, aName, aLastModified,
|
||||
aExistenceCheck, aIsFromNsIFile);
|
||||
}
|
||||
|
||||
bool BackgroundParentImpl::DeallocPFileCreatorParent(
|
||||
PFileCreatorParent* aActor) {
|
||||
RefPtr<mozilla::dom::FileCreatorParent> actor =
|
||||
dont_AddRef(static_cast<mozilla::dom::FileCreatorParent*>(aActor));
|
||||
return true;
|
||||
}
|
||||
|
||||
PTemporaryIPCBlobParent* BackgroundParentImpl::AllocPTemporaryIPCBlobParent() {
|
||||
return new mozilla::dom::TemporaryIPCBlobParent();
|
||||
}
|
||||
|
|
|
@ -155,6 +155,19 @@ class BackgroundParentImpl : public PBackgroundParent {
|
|||
virtual bool DeallocPTemporaryIPCBlobParent(
|
||||
PTemporaryIPCBlobParent* aActor) override;
|
||||
|
||||
virtual PFileCreatorParent* AllocPFileCreatorParent(
|
||||
const nsString& aFullPath, const nsString& aType, const nsString& aName,
|
||||
const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
|
||||
const bool& aIsFromNsIFile) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvPFileCreatorConstructor(
|
||||
PFileCreatorParent* actor, const nsString& aFullPath,
|
||||
const nsString& aType, const nsString& aName,
|
||||
const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
|
||||
const bool& aIsFromNsIFile) override;
|
||||
|
||||
virtual bool DeallocPFileCreatorParent(PFileCreatorParent* aActor) override;
|
||||
|
||||
virtual mozilla::dom::PRemoteWorkerParent* AllocPRemoteWorkerParent(
|
||||
const RemoteWorkerData& aData) override;
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ include protocol PRemoteWorker;
|
|||
include protocol PRemoteWorkerService;
|
||||
include protocol PSharedWorker;
|
||||
include protocol PTemporaryIPCBlob;
|
||||
include protocol PFileCreator;
|
||||
include protocol PMessagePort;
|
||||
include protocol PCameras;
|
||||
include protocol PMIDIManager;
|
||||
|
@ -94,6 +95,7 @@ sync protocol PBackground
|
|||
manages PRemoteWorkerService;
|
||||
manages PSharedWorker;
|
||||
manages PTemporaryIPCBlob;
|
||||
manages PFileCreator;
|
||||
manages PMessagePort;
|
||||
manages PCameras;
|
||||
manages PMIDIManager;
|
||||
|
@ -197,6 +199,10 @@ parent:
|
|||
|
||||
async PTemporaryIPCBlob();
|
||||
|
||||
async PFileCreator(nsString aFullPath, nsString aType, nsString aName,
|
||||
int64_t? lastModified, bool aExistenceCheck,
|
||||
bool aIsFromNsIFile);
|
||||
|
||||
async PClientManager();
|
||||
|
||||
async PMIDIManager();
|
||||
|
@ -228,6 +234,7 @@ child:
|
|||
async PPendingIPCBlob(IPCBlob blob);
|
||||
|
||||
async PRemoteWorker(RemoteWorkerData data);
|
||||
|
||||
both:
|
||||
// PIPCBlobInputStream is created on the parent side only if the child starts
|
||||
// a migration.
|
||||
|
|
|
@ -29,6 +29,13 @@ DIRECT_CALL_OVERRIDES = {
|
|||
"RemotePermissionRequest", "nsContentPermissionHelper.h"
|
||||
),
|
||||
|
||||
("PFileCreator", "child"): (
|
||||
"mozilla::dom::FileCreatorChild", "mozilla/dom/ipc/FileCreatorChild.h"
|
||||
),
|
||||
("PFileCreator", "parent"): (
|
||||
"mozilla::dom::FileCreatorParent", "mozilla/dom/ipc/FileCreatorParent.h"
|
||||
),
|
||||
|
||||
("PFileSystemRequest", "child"): (
|
||||
"FileSystemTaskChildBase", "mozilla/dom/FileSystemTaskBase.h"
|
||||
),
|
||||
|
|
|
@ -598,6 +598,14 @@ VARCACHE_PREF(
|
|||
)
|
||||
|
||||
|
||||
// Allow the content process to create a File from a path. This is allowed just
|
||||
// on parent process, on 'file' Content process, or for testing.
|
||||
VARCACHE_PREF(
|
||||
"dom.file.createInChild",
|
||||
dom_file_createInChild,
|
||||
RelaxedAtomicBool, false
|
||||
)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Extension prefs
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
Загрузка…
Ссылка в новой задаче