summaryrefslogtreecommitdiffstats
path: root/dom/filesystem/GetFileOrDirectoryTask.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/filesystem/GetFileOrDirectoryTask.cpp')
-rw-r--r--dom/filesystem/GetFileOrDirectoryTask.cpp280
1 files changed, 280 insertions, 0 deletions
diff --git a/dom/filesystem/GetFileOrDirectoryTask.cpp b/dom/filesystem/GetFileOrDirectoryTask.cpp
new file mode 100644
index 000000000..f71976503
--- /dev/null
+++ b/dom/filesystem/GetFileOrDirectoryTask.cpp
@@ -0,0 +1,280 @@
+/* -*- 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 "GetFileOrDirectoryTask.h"
+
+#include "js/Value.h"
+#include "mozilla/dom/File.h"
+#include "mozilla/dom/FileSystemBase.h"
+#include "mozilla/dom/FileSystemUtils.h"
+#include "mozilla/dom/PFileSystemParams.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/dom/ipc/BlobChild.h"
+#include "mozilla/dom/ipc/BlobParent.h"
+#include "nsIFile.h"
+#include "nsStringGlue.h"
+
+namespace mozilla {
+namespace dom {
+
+/**
+ * GetFileOrDirectoryTaskChild
+ */
+
+/* static */ already_AddRefed<GetFileOrDirectoryTaskChild>
+GetFileOrDirectoryTaskChild::Create(FileSystemBase* aFileSystem,
+ nsIFile* aTargetPath,
+ ErrorResult& aRv)
+{
+ MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
+ MOZ_ASSERT(aFileSystem);
+
+ RefPtr<GetFileOrDirectoryTaskChild> task =
+ new GetFileOrDirectoryTaskChild(aFileSystem, aTargetPath);
+
+ // aTargetPath can be null. In this case SetError will be called.
+
+ nsCOMPtr<nsIGlobalObject> globalObject =
+ do_QueryInterface(aFileSystem->GetParentObject());
+ if (NS_WARN_IF(!globalObject)) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+
+ task->mPromise = Promise::Create(globalObject, aRv);
+ if (NS_WARN_IF(aRv.Failed())) {
+ return nullptr;
+ }
+
+ return task.forget();
+}
+
+GetFileOrDirectoryTaskChild::GetFileOrDirectoryTaskChild(FileSystemBase* aFileSystem,
+ nsIFile* aTargetPath)
+ : FileSystemTaskChildBase(aFileSystem)
+ , mTargetPath(aTargetPath)
+{
+ MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
+ MOZ_ASSERT(aFileSystem);
+}
+
+GetFileOrDirectoryTaskChild::~GetFileOrDirectoryTaskChild()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+}
+
+already_AddRefed<Promise>
+GetFileOrDirectoryTaskChild::GetPromise()
+{
+ MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
+ return RefPtr<Promise>(mPromise).forget();
+}
+
+FileSystemParams
+GetFileOrDirectoryTaskChild::GetRequestParams(const nsString& aSerializedDOMPath,
+ ErrorResult& aRv) const
+{
+ MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
+
+ nsAutoString path;
+ aRv = mTargetPath->GetPath(path);
+ if (NS_WARN_IF(aRv.Failed())) {
+ return FileSystemGetFileOrDirectoryParams();
+ }
+
+ return FileSystemGetFileOrDirectoryParams(aSerializedDOMPath, path);
+}
+
+void
+GetFileOrDirectoryTaskChild::SetSuccessRequestResult(const FileSystemResponseValue& aValue,
+ ErrorResult& aRv)
+{
+ MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
+ switch (aValue.type()) {
+ case FileSystemResponseValue::TFileSystemFileResponse: {
+ FileSystemFileResponse r = aValue;
+
+ RefPtr<BlobImpl> blobImpl =
+ static_cast<BlobChild*>(r.blobChild())->GetBlobImpl();
+ MOZ_ASSERT(blobImpl);
+
+ mResultFile = File::Create(mFileSystem->GetParentObject(), blobImpl);
+ MOZ_ASSERT(mResultFile);
+ break;
+ }
+ case FileSystemResponseValue::TFileSystemDirectoryResponse: {
+ FileSystemDirectoryResponse r = aValue;
+
+ nsCOMPtr<nsIFile> file;
+ aRv = NS_NewLocalFile(r.realPath(), true, getter_AddRefs(file));
+ if (NS_WARN_IF(aRv.Failed())) {
+ return;
+ }
+
+ mResultDirectory = Directory::Create(mFileSystem->GetParentObject(),
+ file, mFileSystem);
+ MOZ_ASSERT(mResultDirectory);
+ break;
+ }
+ default: {
+ NS_RUNTIMEABORT("not reached");
+ break;
+ }
+ }
+}
+
+void
+GetFileOrDirectoryTaskChild::HandlerCallback()
+{
+ MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
+ if (mFileSystem->IsShutdown()) {
+ mPromise = nullptr;
+ return;
+ }
+
+ if (HasError()) {
+ mPromise->MaybeReject(mErrorValue);
+ mPromise = nullptr;
+ return;
+ }
+
+ if (mResultDirectory) {
+ mPromise->MaybeResolve(mResultDirectory);
+ mResultDirectory = nullptr;
+ mPromise = nullptr;
+ return;
+ }
+
+ MOZ_ASSERT(mResultFile);
+ mPromise->MaybeResolve(mResultFile);
+ mResultFile = nullptr;
+ mPromise = nullptr;
+}
+
+/**
+ * GetFileOrDirectoryTaskParent
+ */
+
+/* static */ already_AddRefed<GetFileOrDirectoryTaskParent>
+GetFileOrDirectoryTaskParent::Create(FileSystemBase* aFileSystem,
+ const FileSystemGetFileOrDirectoryParams& aParam,
+ FileSystemRequestParent* aParent,
+ ErrorResult& aRv)
+{
+ MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
+ AssertIsOnBackgroundThread();
+ MOZ_ASSERT(aFileSystem);
+
+ RefPtr<GetFileOrDirectoryTaskParent> task =
+ new GetFileOrDirectoryTaskParent(aFileSystem, aParam, aParent);
+
+ aRv = NS_NewLocalFile(aParam.realPath(), true,
+ getter_AddRefs(task->mTargetPath));
+ if (NS_WARN_IF(aRv.Failed())) {
+ return nullptr;
+ }
+
+ return task.forget();
+}
+
+GetFileOrDirectoryTaskParent::GetFileOrDirectoryTaskParent(FileSystemBase* aFileSystem,
+ const FileSystemGetFileOrDirectoryParams& aParam,
+ FileSystemRequestParent* aParent)
+ : FileSystemTaskParentBase(aFileSystem, aParam, aParent)
+ , mIsDirectory(false)
+{
+ MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
+ AssertIsOnBackgroundThread();
+ MOZ_ASSERT(aFileSystem);
+}
+
+FileSystemResponseValue
+GetFileOrDirectoryTaskParent::GetSuccessRequestResult(ErrorResult& aRv) const
+{
+ AssertIsOnBackgroundThread();
+
+ nsAutoString path;
+ aRv = mTargetPath->GetPath(path);
+ if (NS_WARN_IF(aRv.Failed())) {
+ return FileSystemDirectoryResponse();
+ }
+
+ if (mIsDirectory) {
+ return FileSystemDirectoryResponse(path);
+ }
+
+ RefPtr<BlobImpl> blobImpl = new BlobImplFile(mTargetPath);
+ BlobParent* blobParent =
+ BlobParent::GetOrCreate(mRequestParent->Manager(), blobImpl);
+ return FileSystemFileResponse(blobParent, nullptr);
+}
+
+nsresult
+GetFileOrDirectoryTaskParent::IOWork()
+{
+ MOZ_ASSERT(XRE_IsParentProcess(),
+ "Only call from parent process!");
+ MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
+
+ if (mFileSystem->IsShutdown()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Whether we want to get the root directory.
+ bool exists;
+ nsresult rv = mTargetPath->Exists(&exists);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ if (!exists) {
+ if (!mFileSystem->ShouldCreateDirectory()) {
+ return NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
+ }
+
+ rv = mTargetPath->Create(nsIFile::DIRECTORY_TYPE, 0777);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
+
+ // Get isDirectory.
+ rv = mTargetPath->IsDirectory(&mIsDirectory);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ if (mIsDirectory) {
+ return NS_OK;
+ }
+
+ bool isFile;
+ // Get isFile
+ rv = mTargetPath->IsFile(&isFile);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ if (!isFile) {
+ // Neither directory or file.
+ return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
+ }
+
+ if (!mFileSystem->IsSafeFile(mTargetPath)) {
+ return NS_ERROR_DOM_SECURITY_ERR;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+GetFileOrDirectoryTaskParent::GetTargetPath(nsAString& aPath) const
+{
+ return mTargetPath->GetPath(aPath);
+}
+
+} // namespace dom
+} // namespace mozilla