fune/dom/filesystem/FileSystemTaskBase.cpp
Phil Ringnalda b47ec4d2bd Backed out 8 changesets (bug 1173320) for adding dom/filesystem/tests/test_basic.html without making it work on Android
Backed out changeset 7e3a105b9160 (bug 1173320)
Backed out changeset 094819fbb07f (bug 1173320)
Backed out changeset 23b0e55ff1db (bug 1173320)
Backed out changeset 8bf8e2fcedad (bug 1173320)
Backed out changeset 3de390c6f47f (bug 1173320)
Backed out changeset fb298010e12e (bug 1173320)
Backed out changeset f1a965c2f796 (bug 1173320)
Backed out changeset 176128ba757f (bug 1173320)
2016-03-19 19:44:22 -07:00

267 lines
6.7 KiB
C++

/* -*- 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 "mozilla/dom/FileSystemTaskBase.h"
#include "nsNetCID.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileSystemBase.h"
#include "mozilla/dom/FileSystemRequestParent.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PContent.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/unused.h"
#include "nsProxyRelease.h"
namespace mozilla {
namespace dom {
namespace {
class FileSystemReleaseRunnable : public nsRunnable
{
public:
explicit FileSystemReleaseRunnable(RefPtr<FileSystemBase>& aDoomed)
: mDoomed(nullptr)
{
aDoomed.swap(mDoomed);
}
NS_IMETHOD Run()
{
mDoomed->Release();
return NS_OK;
}
private:
FileSystemBase* MOZ_OWNING_REF mDoomed;
};
} // anonymous namespace
FileSystemTaskBase::FileSystemTaskBase(FileSystemBase* aFileSystem)
: mErrorValue(NS_OK)
, mFileSystem(aFileSystem)
{
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem, "aFileSystem should not be null.");
}
FileSystemTaskBase::FileSystemTaskBase(FileSystemBase* aFileSystem,
const FileSystemParams& aParam,
FileSystemRequestParent* aParent)
: mErrorValue(NS_OK)
, mFileSystem(aFileSystem)
, mRequestParent(aParent)
{
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem, "aFileSystem should not be null.");
}
FileSystemTaskBase::~FileSystemTaskBase()
{
if (!NS_IsMainThread()) {
RefPtr<FileSystemReleaseRunnable> runnable =
new FileSystemReleaseRunnable(mFileSystem);
MOZ_ASSERT(!mFileSystem);
NS_DispatchToMainThread(runnable);
}
}
FileSystemBase*
FileSystemTaskBase::GetFileSystem() const
{
return mFileSystem.get();
}
void
FileSystemTaskBase::Start()
{
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
if (HasError()) {
NS_DispatchToMainThread(this);
return;
}
if (XRE_IsParentProcess()) {
// Run in parent process.
// Start worker thread.
nsCOMPtr<nsIEventTarget> target
= do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
NS_ASSERTION(target, "Must have stream transport service.");
target->Dispatch(this, NS_DISPATCH_NORMAL);
return;
}
// Run in child process.
if (mFileSystem->IsShutdown()) {
return;
}
// Retain a reference so the task object isn't deleted without IPDL's
// knowledge. The reference will be released by
// mozilla::dom::ContentChild::DeallocPFileSystemRequestChild.
NS_ADDREF_THIS();
ContentChild::GetSingleton()->SendPFileSystemRequestConstructor(this,
GetRequestParams(mFileSystem->ToString()));
}
NS_IMETHODIMP
FileSystemTaskBase::Run()
{
if (!NS_IsMainThread()) {
// Run worker thread tasks
nsresult rv = Work();
if (NS_FAILED(rv)) {
SetError(rv);
}
// Dispatch itself to main thread
NS_DispatchToMainThread(this);
return NS_OK;
}
// Run main thread tasks
HandleResult();
return NS_OK;
}
void
FileSystemTaskBase::HandleResult()
{
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
if (mFileSystem->IsShutdown()) {
return;
}
if (mRequestParent && mRequestParent->IsRunning()) {
Unused << mRequestParent->Send__delete__(mRequestParent,
GetRequestResult());
} else {
HandlerCallback();
}
}
FileSystemResponseValue
FileSystemTaskBase::GetRequestResult() const
{
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
if (HasError()) {
return FileSystemErrorResponse(mErrorValue);
} else {
return GetSuccessRequestResult();
}
}
void
FileSystemTaskBase::SetRequestResult(const FileSystemResponseValue& aValue)
{
MOZ_ASSERT(!XRE_IsParentProcess(),
"Only call from child process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
if (aValue.type() == FileSystemResponseValue::TFileSystemErrorResponse) {
FileSystemErrorResponse r = aValue;
mErrorValue = r.error();
} else {
SetSuccessRequestResult(aValue);
}
}
bool
FileSystemTaskBase::Recv__delete__(const FileSystemResponseValue& aValue)
{
SetRequestResult(aValue);
HandlerCallback();
return true;
}
BlobParent*
FileSystemTaskBase::GetBlobParent(BlobImpl* aFile) const
{
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFile);
// Load the lazy dom file data from the parent before sending to the child.
nsString mimeType;
aFile->GetType(mimeType);
// We call GetSize and GetLastModified to prepopulate the value in the
// BlobImpl.
{
ErrorResult rv;
aFile->GetSize(rv);
rv.SuppressException();
}
{
ErrorResult rv;
aFile->GetLastModified(rv);
rv.SuppressException();
}
ContentParent* cp = static_cast<ContentParent*>(mRequestParent->Manager());
return cp->GetOrCreateActorForBlobImpl(aFile);
}
void
FileSystemTaskBase::SetError(const nsresult& aErrorValue)
{
uint16_t module = NS_ERROR_GET_MODULE(aErrorValue);
if (module == NS_ERROR_MODULE_DOM_FILESYSTEM ||
module == NS_ERROR_MODULE_DOM_FILE ||
module == NS_ERROR_MODULE_DOM) {
mErrorValue = aErrorValue;
return;
}
switch (aErrorValue) {
case NS_OK:
mErrorValue = NS_OK;
return;
case NS_ERROR_FILE_INVALID_PATH:
case NS_ERROR_FILE_UNRECOGNIZED_PATH:
mErrorValue = NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
return;
case NS_ERROR_FILE_DESTINATION_NOT_DIR:
mErrorValue = NS_ERROR_DOM_FILESYSTEM_INVALID_MODIFICATION_ERR;
return;
case NS_ERROR_FILE_ACCESS_DENIED:
case NS_ERROR_FILE_DIR_NOT_EMPTY:
mErrorValue = NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR;
return;
case NS_ERROR_FILE_TARGET_DOES_NOT_EXIST:
case NS_ERROR_NOT_AVAILABLE:
mErrorValue = NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
return;
case NS_ERROR_FILE_ALREADY_EXISTS:
mErrorValue = NS_ERROR_DOM_FILESYSTEM_PATH_EXISTS_ERR;
return;
case NS_ERROR_FILE_NOT_DIRECTORY:
mErrorValue = NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
return;
case NS_ERROR_UNEXPECTED:
default:
mErrorValue = NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR;
return;
}
}
} // namespace dom
} // namespace mozilla