summaryrefslogtreecommitdiff
path: root/dom/filehandle/ActorsChild.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/filehandle/ActorsChild.cpp')
-rw-r--r--dom/filehandle/ActorsChild.cpp743
1 files changed, 743 insertions, 0 deletions
diff --git a/dom/filehandle/ActorsChild.cpp b/dom/filehandle/ActorsChild.cpp
new file mode 100644
index 0000000000..7a0b622f8f
--- /dev/null
+++ b/dom/filehandle/ActorsChild.cpp
@@ -0,0 +1,743 @@
+/* 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 "ActorsChild.h"
+
+#include "BackgroundChildImpl.h"
+#include "FileHandleBase.h"
+#include "FileRequestBase.h"
+#include "js/Date.h"
+#include "mozilla/dom/EncodingUtils.h"
+#include "mozilla/dom/File.h"
+#include "mozilla/dom/ipc/BlobChild.h"
+#include "MutableFileBase.h"
+#include "nsCOMPtr.h"
+#include "nsContentUtils.h"
+#include "nsString.h"
+#include "xpcpublic.h"
+#include "mozilla/dom/BindingUtils.h"
+
+namespace mozilla {
+namespace dom {
+
+/*******************************************************************************
+ * Helpers
+ ******************************************************************************/
+
+namespace {
+
+class MOZ_STACK_CLASS AutoSetCurrentFileHandle final
+{
+ typedef mozilla::ipc::BackgroundChildImpl BackgroundChildImpl;
+
+ FileHandleBase* const mFileHandle;
+ FileHandleBase* mPreviousFileHandle;
+ FileHandleBase** mThreadLocalSlot;
+
+public:
+ explicit AutoSetCurrentFileHandle(FileHandleBase* aFileHandle)
+ : mFileHandle(aFileHandle)
+ , mPreviousFileHandle(nullptr)
+ , mThreadLocalSlot(nullptr)
+ {
+ if (aFileHandle) {
+ BackgroundChildImpl::ThreadLocal* threadLocal =
+ BackgroundChildImpl::GetThreadLocalForCurrentThread();
+ MOZ_ASSERT(threadLocal);
+
+ // Hang onto this location for resetting later.
+ mThreadLocalSlot = &threadLocal->mCurrentFileHandle;
+
+ // Save the current value.
+ mPreviousFileHandle = *mThreadLocalSlot;
+
+ // Set the new value.
+ *mThreadLocalSlot = aFileHandle;
+ }
+ }
+
+ ~AutoSetCurrentFileHandle()
+ {
+ MOZ_ASSERT_IF(mThreadLocalSlot, mFileHandle);
+ MOZ_ASSERT_IF(mThreadLocalSlot, *mThreadLocalSlot == mFileHandle);
+
+ if (mThreadLocalSlot) {
+ // Reset old value.
+ *mThreadLocalSlot = mPreviousFileHandle;
+ }
+ }
+
+ FileHandleBase*
+ FileHandle() const
+ {
+ return mFileHandle;
+ }
+};
+
+class MOZ_STACK_CLASS ResultHelper final
+ : public FileRequestBase::ResultCallback
+{
+ FileRequestBase* mFileRequest;
+ AutoSetCurrentFileHandle mAutoFileHandle;
+
+ union
+ {
+ File* mFile;
+ const nsCString* mString;
+ const FileRequestMetadata* mMetadata;
+ const JS::Handle<JS::Value>* mJSValHandle;
+ } mResult;
+
+ enum
+ {
+ ResultTypeFile,
+ ResultTypeString,
+ ResultTypeMetadata,
+ ResultTypeJSValHandle,
+ } mResultType;
+
+public:
+ ResultHelper(FileRequestBase* aFileRequest,
+ FileHandleBase* aFileHandle,
+ File* aResult)
+ : mFileRequest(aFileRequest)
+ , mAutoFileHandle(aFileHandle)
+ , mResultType(ResultTypeFile)
+ {
+ MOZ_ASSERT(aFileRequest);
+ MOZ_ASSERT(aFileHandle);
+ MOZ_ASSERT(aResult);
+
+ mResult.mFile = aResult;
+ }
+
+ ResultHelper(FileRequestBase* aFileRequest,
+ FileHandleBase* aFileHandle,
+ const nsCString* aResult)
+ : mFileRequest(aFileRequest)
+ , mAutoFileHandle(aFileHandle)
+ , mResultType(ResultTypeString)
+ {
+ MOZ_ASSERT(aFileRequest);
+ MOZ_ASSERT(aFileHandle);
+ MOZ_ASSERT(aResult);
+
+ mResult.mString = aResult;
+ }
+
+ ResultHelper(FileRequestBase* aFileRequest,
+ FileHandleBase* aFileHandle,
+ const FileRequestMetadata* aResult)
+ : mFileRequest(aFileRequest)
+ , mAutoFileHandle(aFileHandle)
+ , mResultType(ResultTypeMetadata)
+ {
+ MOZ_ASSERT(aFileRequest);
+ MOZ_ASSERT(aFileHandle);
+ MOZ_ASSERT(aResult);
+
+ mResult.mMetadata = aResult;
+ }
+
+
+ ResultHelper(FileRequestBase* aFileRequest,
+ FileHandleBase* aFileHandle,
+ const JS::Handle<JS::Value>* aResult)
+ : mFileRequest(aFileRequest)
+ , mAutoFileHandle(aFileHandle)
+ , mResultType(ResultTypeJSValHandle)
+ {
+ MOZ_ASSERT(aFileRequest);
+ MOZ_ASSERT(aFileHandle);
+ MOZ_ASSERT(aResult);
+
+ mResult.mJSValHandle = aResult;
+ }
+
+ FileRequestBase*
+ FileRequest() const
+ {
+ return mFileRequest;
+ }
+
+ FileHandleBase*
+ FileHandle() const
+ {
+ return mAutoFileHandle.FileHandle();
+ }
+
+ virtual nsresult
+ GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult) override
+ {
+ MOZ_ASSERT(aCx);
+ MOZ_ASSERT(mFileRequest);
+
+ switch (mResultType) {
+ case ResultTypeFile:
+ return GetResult(aCx, mResult.mFile, aResult);
+
+ case ResultTypeString:
+ return GetResult(aCx, mResult.mString, aResult);
+
+ case ResultTypeMetadata:
+ return GetResult(aCx, mResult.mMetadata, aResult);
+
+ case ResultTypeJSValHandle:
+ aResult.set(*mResult.mJSValHandle);
+ return NS_OK;
+
+ default:
+ MOZ_CRASH("Unknown result type!");
+ }
+
+ MOZ_CRASH("Should never get here!");
+ }
+
+private:
+ nsresult
+ GetResult(JSContext* aCx,
+ File* aFile,
+ JS::MutableHandle<JS::Value> aResult)
+ {
+ bool ok = GetOrCreateDOMReflector(aCx, aFile, aResult);
+ if (NS_WARN_IF(!ok)) {
+ return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
+ }
+
+ return NS_OK;
+ }
+
+ nsresult
+ GetResult(JSContext* aCx,
+ const nsCString* aString,
+ JS::MutableHandle<JS::Value> aResult)
+ {
+ const nsCString& data = *aString;
+
+ nsresult rv;
+
+ if (!mFileRequest->HasEncoding()) {
+ JS::Rooted<JSObject*> arrayBuffer(aCx);
+ rv = nsContentUtils::CreateArrayBuffer(aCx, data, arrayBuffer.address());
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
+ }
+
+ aResult.setObject(*arrayBuffer);
+ return NS_OK;
+ }
+
+ nsAutoCString encoding;
+ // The BOM sniffing is baked into the "decode" part of the Encoding
+ // Standard, which the File API references.
+ if (!nsContentUtils::CheckForBOM(
+ reinterpret_cast<const unsigned char *>(data.get()),
+ data.Length(),
+ encoding)) {
+ // BOM sniffing failed. Try the API argument.
+ if (!EncodingUtils::FindEncodingForLabel(mFileRequest->GetEncoding(),
+ encoding)) {
+ // API argument failed. Since we are dealing with a file system file,
+ // we don't have a meaningful type attribute for the blob available,
+ // so proceeding to the next step, which is defaulting to UTF-8.
+ encoding.AssignLiteral("UTF-8");
+ }
+ }
+
+ nsString tmpString;
+ rv = nsContentUtils::ConvertStringFromEncoding(encoding, data, tmpString);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
+ }
+
+ if (NS_WARN_IF(!xpc::StringToJsval(aCx, tmpString, aResult))) {
+ return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
+ }
+
+ return NS_OK;
+ }
+
+ nsresult
+ GetResult(JSContext* aCx,
+ const FileRequestMetadata* aMetadata,
+ JS::MutableHandle<JS::Value> aResult)
+ {
+ JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
+ if (NS_WARN_IF(!obj)) {
+ return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
+ }
+
+ const FileRequestSize& size = aMetadata->size();
+ if (size.type() != FileRequestSize::Tvoid_t) {
+ MOZ_ASSERT(size.type() == FileRequestSize::Tuint64_t);
+
+ JS::Rooted<JS::Value> number(aCx, JS_NumberValue(size.get_uint64_t()));
+
+ if (NS_WARN_IF(!JS_DefineProperty(aCx, obj, "size", number, 0))) {
+ return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
+ }
+ }
+
+ const FileRequestLastModified& lastModified = aMetadata->lastModified();
+ if (lastModified.type() != FileRequestLastModified::Tvoid_t) {
+ MOZ_ASSERT(lastModified.type() == FileRequestLastModified::Tint64_t);
+
+ JS::Rooted<JSObject*> date(aCx,
+ JS::NewDateObject(aCx, JS::TimeClip(lastModified.get_int64_t())));
+ if (NS_WARN_IF(!date)) {
+ return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
+ }
+
+ if (NS_WARN_IF(!JS_DefineProperty(aCx, obj, "lastModified", date, 0))) {
+ return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
+ }
+ }
+
+ aResult.setObject(*obj);
+ return NS_OK;
+ }
+};
+
+already_AddRefed<File>
+ConvertActorToFile(FileHandleBase* aFileHandle,
+ const FileRequestGetFileResponse& aResponse)
+{
+ auto* actor = static_cast<BlobChild*>(aResponse.fileChild());
+
+ MutableFileBase* mutableFile = aFileHandle->MutableFile();
+ MOZ_ASSERT(mutableFile);
+
+ const FileRequestMetadata& metadata = aResponse.metadata();
+
+ const FileRequestSize& size = metadata.size();
+ MOZ_ASSERT(size.type() == FileRequestSize::Tuint64_t);
+
+ const FileRequestLastModified& lastModified = metadata.lastModified();
+ MOZ_ASSERT(lastModified.type() == FileRequestLastModified::Tint64_t);
+
+ actor->SetMysteryBlobInfo(mutableFile->Name(),
+ mutableFile->Type(),
+ size.get_uint64_t(),
+ lastModified.get_int64_t());
+
+ RefPtr<BlobImpl> blobImpl = actor->GetBlobImpl();
+ MOZ_ASSERT(blobImpl);
+
+ RefPtr<File> file = mutableFile->CreateFileFor(blobImpl, aFileHandle);
+ return file.forget();
+}
+
+void
+HandleSuccess(ResultHelper* aResultHelper)
+{
+ MOZ_ASSERT(aResultHelper);
+
+ RefPtr<FileRequestBase> fileRequest = aResultHelper->FileRequest();
+ MOZ_ASSERT(fileRequest);
+ fileRequest->AssertIsOnOwningThread();
+
+ RefPtr<FileHandleBase> fileHandle = aResultHelper->FileHandle();
+ MOZ_ASSERT(fileHandle);
+
+ if (fileHandle->IsAborted()) {
+ fileRequest->SetError(NS_ERROR_DOM_FILEHANDLE_ABORT_ERR);
+ return;
+ }
+
+ MOZ_ASSERT(fileHandle->IsOpen());
+
+ fileRequest->SetResultCallback(aResultHelper);
+
+ MOZ_ASSERT(fileHandle->IsOpen() || fileHandle->IsAborted());
+}
+
+void
+HandleError(FileRequestBase* aFileRequest,
+ nsresult aErrorCode,
+ FileHandleBase* aFileHandle)
+{
+ MOZ_ASSERT(aFileRequest);
+ aFileRequest->AssertIsOnOwningThread();
+ MOZ_ASSERT(NS_FAILED(aErrorCode));
+ MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_FILEHANDLE);
+ MOZ_ASSERT(aFileHandle);
+
+ RefPtr<FileRequestBase> fileRequest = aFileRequest;
+ RefPtr<FileHandleBase> fileHandle = aFileHandle;
+
+ AutoSetCurrentFileHandle ascfh(aFileHandle);
+
+ fileRequest->SetError(aErrorCode);
+
+ MOZ_ASSERT(fileHandle->IsOpen() || fileHandle->IsAborted());
+}
+
+} // anonymous namespace
+
+/*******************************************************************************
+ * BackgroundMutableFileChildBase
+ ******************************************************************************/
+
+BackgroundMutableFileChildBase::BackgroundMutableFileChildBase(
+ DEBUGONLY(PRThread* aOwningThread))
+ : ThreadObject(DEBUGONLY(aOwningThread))
+ , mMutableFile(nullptr)
+{
+ AssertIsOnOwningThread();
+
+ MOZ_COUNT_CTOR(BackgroundMutableFileChildBase);
+}
+
+BackgroundMutableFileChildBase::~BackgroundMutableFileChildBase()
+{
+ AssertIsOnOwningThread();
+
+ MOZ_COUNT_DTOR(BackgroundMutableFileChildBase);
+}
+
+void
+BackgroundMutableFileChildBase::EnsureDOMObject()
+{
+ AssertIsOnOwningThread();
+
+ if (mTemporaryStrongMutableFile) {
+ return;
+ }
+
+ mTemporaryStrongMutableFile = CreateMutableFile();
+
+ MOZ_ASSERT(mTemporaryStrongMutableFile);
+ mTemporaryStrongMutableFile->AssertIsOnOwningThread();
+
+ mMutableFile = mTemporaryStrongMutableFile;
+}
+
+void
+BackgroundMutableFileChildBase::ReleaseDOMObject()
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(mTemporaryStrongMutableFile);
+ mTemporaryStrongMutableFile->AssertIsOnOwningThread();
+ MOZ_ASSERT(mMutableFile == mTemporaryStrongMutableFile);
+
+ mTemporaryStrongMutableFile = nullptr;
+}
+
+void
+BackgroundMutableFileChildBase::SendDeleteMeInternal()
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(!mTemporaryStrongMutableFile);
+
+ if (mMutableFile) {
+ mMutableFile->ClearBackgroundActor();
+ mMutableFile = nullptr;
+
+ MOZ_ALWAYS_TRUE(PBackgroundMutableFileChild::SendDeleteMe());
+ }
+}
+
+void
+BackgroundMutableFileChildBase::ActorDestroy(ActorDestroyReason aWhy)
+{
+ AssertIsOnOwningThread();
+
+ if (mMutableFile) {
+ mMutableFile->ClearBackgroundActor();
+ DEBUGONLY(mMutableFile = nullptr;)
+ }
+}
+
+PBackgroundFileHandleChild*
+BackgroundMutableFileChildBase::AllocPBackgroundFileHandleChild(
+ const FileMode& aMode)
+{
+ MOZ_CRASH("PBackgroundFileHandleChild actors should be manually "
+ "constructed!");
+}
+
+bool
+BackgroundMutableFileChildBase::DeallocPBackgroundFileHandleChild(
+ PBackgroundFileHandleChild* aActor)
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(aActor);
+
+ delete static_cast<BackgroundFileHandleChild*>(aActor);
+ return true;
+}
+
+/*******************************************************************************
+ * BackgroundFileHandleChild
+ ******************************************************************************/
+
+BackgroundFileHandleChild::BackgroundFileHandleChild(
+ DEBUGONLY(PRThread* aOwningThread,)
+ FileHandleBase* aFileHandle)
+ : ThreadObject(DEBUGONLY(aOwningThread))
+ , mTemporaryStrongFileHandle(aFileHandle)
+ , mFileHandle(aFileHandle)
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(aFileHandle);
+ aFileHandle->AssertIsOnOwningThread();
+
+ MOZ_COUNT_CTOR(BackgroundFileHandleChild);
+}
+
+BackgroundFileHandleChild::~BackgroundFileHandleChild()
+{
+ AssertIsOnOwningThread();
+
+ MOZ_COUNT_DTOR(BackgroundFileHandleChild);
+}
+
+void
+BackgroundFileHandleChild::SendDeleteMeInternal()
+{
+ AssertIsOnOwningThread();
+
+ if (mFileHandle) {
+ NoteActorDestroyed();
+
+ MOZ_ALWAYS_TRUE(PBackgroundFileHandleChild::SendDeleteMe());
+ }
+}
+
+void
+BackgroundFileHandleChild::NoteActorDestroyed()
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT_IF(mTemporaryStrongFileHandle, mFileHandle);
+
+ if (mFileHandle) {
+ mFileHandle->ClearBackgroundActor();
+
+ // Normally this would be DEBUG-only but NoteActorDestroyed is also called
+ // from SendDeleteMeInternal. In that case we're going to receive an actual
+ // ActorDestroy call later and we don't want to touch a dead object.
+ mTemporaryStrongFileHandle = nullptr;
+ mFileHandle = nullptr;
+ }
+}
+
+void
+BackgroundFileHandleChild::NoteComplete()
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT_IF(mFileHandle, mTemporaryStrongFileHandle);
+
+ mTemporaryStrongFileHandle = nullptr;
+}
+
+void
+BackgroundFileHandleChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+ AssertIsOnOwningThread();
+
+ NoteActorDestroyed();
+}
+
+bool
+BackgroundFileHandleChild::RecvComplete(const bool& aAborted)
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(mFileHandle);
+
+ mFileHandle->HandleCompleteOrAbort(aAborted);
+
+ NoteComplete();
+ return true;
+}
+
+PBackgroundFileRequestChild*
+BackgroundFileHandleChild::AllocPBackgroundFileRequestChild(
+ const FileRequestParams& aParams)
+{
+ MOZ_CRASH("PBackgroundFileRequestChild actors should be manually "
+ "constructed!");
+}
+
+bool
+BackgroundFileHandleChild::DeallocPBackgroundFileRequestChild(
+ PBackgroundFileRequestChild* aActor)
+{
+ MOZ_ASSERT(aActor);
+
+ delete static_cast<BackgroundFileRequestChild*>(aActor);
+ return true;
+}
+
+/*******************************************************************************
+ * BackgroundFileRequestChild
+ ******************************************************************************/
+
+BackgroundFileRequestChild::BackgroundFileRequestChild(
+ DEBUGONLY(PRThread* aOwningThread,)
+ FileRequestBase* aFileRequest)
+ : ThreadObject(DEBUGONLY(aOwningThread))
+ , mFileRequest(aFileRequest)
+ , mFileHandle(aFileRequest->FileHandle())
+ , mActorDestroyed(false)
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(aFileRequest);
+ aFileRequest->AssertIsOnOwningThread();
+ MOZ_ASSERT(mFileHandle);
+ mFileHandle->AssertIsOnOwningThread();
+
+ MOZ_COUNT_CTOR(BackgroundFileRequestChild);
+}
+
+BackgroundFileRequestChild::~BackgroundFileRequestChild()
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(!mFileHandle);
+
+ MOZ_COUNT_DTOR(BackgroundFileRequestChild);
+}
+
+void
+BackgroundFileRequestChild::HandleResponse(nsresult aResponse)
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(NS_FAILED(aResponse));
+ MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_FILEHANDLE);
+ MOZ_ASSERT(mFileHandle);
+
+ HandleError(mFileRequest, aResponse, mFileHandle);
+}
+
+void
+BackgroundFileRequestChild::HandleResponse(
+ const FileRequestGetFileResponse& aResponse)
+{
+ AssertIsOnOwningThread();
+
+ RefPtr<File> file = ConvertActorToFile(mFileHandle, aResponse);
+
+ ResultHelper helper(mFileRequest, mFileHandle, file);
+
+ HandleSuccess(&helper);
+}
+
+void
+BackgroundFileRequestChild::HandleResponse(const nsCString& aResponse)
+{
+ AssertIsOnOwningThread();
+
+ ResultHelper helper(mFileRequest, mFileHandle, &aResponse);
+
+ HandleSuccess(&helper);
+}
+
+void
+BackgroundFileRequestChild::HandleResponse(const FileRequestMetadata& aResponse)
+{
+ AssertIsOnOwningThread();
+
+ ResultHelper helper(mFileRequest, mFileHandle, &aResponse);
+
+ HandleSuccess(&helper);
+}
+
+void
+BackgroundFileRequestChild::HandleResponse(JS::Handle<JS::Value> aResponse)
+{
+ AssertIsOnOwningThread();
+
+ ResultHelper helper(mFileRequest, mFileHandle, &aResponse);
+
+ HandleSuccess(&helper);
+}
+
+void
+BackgroundFileRequestChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+ AssertIsOnOwningThread();
+
+ MOZ_ASSERT(!mActorDestroyed);
+
+ mActorDestroyed = true;
+
+ if (mFileHandle) {
+ mFileHandle->AssertIsOnOwningThread();
+
+ mFileHandle->OnRequestFinished(/* aActorDestroyedNormally */
+ aWhy == Deletion);
+
+ DEBUGONLY(mFileHandle = nullptr;)
+ }
+}
+
+bool
+BackgroundFileRequestChild::Recv__delete__(const FileRequestResponse& aResponse)
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(mFileRequest);
+ MOZ_ASSERT(mFileHandle);
+
+ if (mFileHandle->IsAborted()) {
+ // Always handle an "error" with ABORT_ERR if the file handle was aborted,
+ // even if the request succeeded or failed with another error.
+ HandleResponse(NS_ERROR_DOM_FILEHANDLE_ABORT_ERR);
+ } else {
+ switch (aResponse.type()) {
+ case FileRequestResponse::Tnsresult:
+ HandleResponse(aResponse.get_nsresult());
+ break;
+
+ case FileRequestResponse::TFileRequestGetFileResponse:
+ HandleResponse(aResponse.get_FileRequestGetFileResponse());
+ break;
+
+ case FileRequestResponse::TFileRequestReadResponse:
+ HandleResponse(aResponse.get_FileRequestReadResponse().data());
+ break;
+
+ case FileRequestResponse::TFileRequestWriteResponse:
+ HandleResponse(JS::UndefinedHandleValue);
+ break;
+
+ case FileRequestResponse::TFileRequestTruncateResponse:
+ HandleResponse(JS::UndefinedHandleValue);
+ break;
+
+ case FileRequestResponse::TFileRequestFlushResponse:
+ HandleResponse(JS::UndefinedHandleValue);
+ break;
+
+ case FileRequestResponse::TFileRequestGetMetadataResponse:
+ HandleResponse(aResponse.get_FileRequestGetMetadataResponse()
+ .metadata());
+ break;
+
+ default:
+ MOZ_CRASH("Unknown response type!");
+ }
+ }
+
+ mFileHandle->OnRequestFinished(/* aActorDestroyedNormally */ true);
+
+ // Null this out so that we don't try to call OnRequestFinished() again in
+ // ActorDestroy.
+ mFileHandle = nullptr;
+
+ return true;
+}
+
+bool
+BackgroundFileRequestChild::RecvProgress(const uint64_t& aProgress,
+ const uint64_t& aProgressMax)
+{
+ AssertIsOnOwningThread();
+ MOZ_ASSERT(mFileRequest);
+
+ mFileRequest->OnProgress(aProgress, aProgressMax);
+
+ return true;
+}
+
+} // namespace dom
+} // namespace mozilla