/* -*- 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" #include "nsIFile.h" namespace mozilla::dom { FileCreatorParent::FileCreatorParent() : mBackgroundEventTarget(GetCurrentSerialEventTarget()), mIPCActive(true) {} FileCreatorParent::~FileCreatorParent() = default; mozilla::ipc::IPCResult FileCreatorParent::CreateAndShareFile( const nsAString& aFullPath, const nsAString& aType, const nsAString& aName, const Maybe& aLastModified, const bool& aExistenceCheck, const bool& aIsFromNsIFile) { RefPtr 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))) { (void)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 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, ipcBlob); if (NS_WARN_IF(NS_FAILED(rv))) { (void)Send__delete__(self, FileCreationErrorResult(rv)); return; } (void)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 file; nsresult rv = NS_NewLocalFile(aPath, true, getter_AddRefs(file)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } bool exists; rv = file->Exists(&exists); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (aExistenceCheck) { 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 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 (!exists) { MOZ_ASSERT(!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(u""_ns); } impl.forget(aBlobImpl); return NS_OK; } } // namespace mozilla::dom