/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=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 "FileHandle.h" #include "nsContentUtils.h" #include "nsDOMClassInfoID.h" #include "nsIDOMFile.h" #include "nsIFileStorage.h" #include "FileRequest.h" #include "FileService.h" #include "LockedFile.h" #include "MetadataHelper.h" #include "mozilla/dom/FileHandleBinding.h" using namespace mozilla; using namespace mozilla::dom; USING_FILE_NAMESPACE namespace { class GetFileHelper : public MetadataHelper { public: GetFileHelper(LockedFile* aLockedFile, FileRequest* aFileRequest, MetadataParameters* aParams, FileHandle* aFileHandle) : MetadataHelper(aLockedFile, aFileRequest, aParams), mFileHandle(aFileHandle) { } nsresult GetSuccessResult(JSContext* aCx, JS::MutableHandle aVal) MOZ_OVERRIDE; void ReleaseObjects() { mFileHandle = nullptr; MetadataHelper::ReleaseObjects(); } private: nsRefPtr mFileHandle; }; } // anonymous namespace NS_IMPL_CYCLE_COLLECTION_INHERITED_1(FileHandle, nsDOMEventTargetHelper, mFileStorage) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileHandle) NS_INTERFACE_MAP_ENTRY(nsIDOMFileHandle) NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(FileHandle, nsDOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(FileHandle, nsDOMEventTargetHelper) NS_IMPL_EVENT_HANDLER(FileHandle, abort) NS_IMPL_EVENT_HANDLER(FileHandle, error) NS_IMETHODIMP FileHandle::GetDOMName(nsAString& aName) { aName = mName; return NS_OK; } NS_IMETHODIMP FileHandle::GetDOMType(nsAString& aType) { aType = mType; return NS_OK; } NS_IMETHODIMP FileHandle::Open(const nsAString& aMode, uint8_t aOptionalArgCount, nsIDOMLockedFile** _retval) { FileMode mode; if (aOptionalArgCount) { if (aMode.EqualsLiteral("readwrite")) { mode = FileMode::Readwrite; } else if (aMode.EqualsLiteral("readonly")) { mode = FileMode::Readonly; } else { return NS_ERROR_TYPE_ERR; } } else { mode = FileMode::Readonly; } ErrorResult rv; nsCOMPtr lockedFile = Open(mode, rv); lockedFile.forget(_retval); return rv.ErrorCode(); } already_AddRefed FileHandle::Open(FileMode aMode, ErrorResult& aError) { MOZ_ASSERT(NS_IsMainThread()); if (FileService::IsShuttingDown() || mFileStorage->IsShuttingDown()) { aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); return nullptr; } nsRefPtr lockedFile = LockedFile::Create(this, aMode); if (!lockedFile) { aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); return nullptr; } return lockedFile.forget(); } NS_IMETHODIMP FileHandle::GetFile(nsIDOMDOMRequest** _retval) { ErrorResult rv; nsRefPtr request = GetFile(rv); request.forget(_retval); return rv.ErrorCode(); } already_AddRefed FileHandle::GetFile(ErrorResult& aError) { MOZ_ASSERT(NS_IsMainThread()); // Do nothing if the window is closed if (!GetOwner()) { return nullptr; } nsRefPtr lockedFile = LockedFile::Create(this, FileMode::Readonly, LockedFile::PARALLEL); if (!lockedFile) { aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); return nullptr; } nsRefPtr request = FileRequest::Create(GetOwner(), lockedFile); nsRefPtr params = new MetadataParameters(true, false); nsRefPtr helper = new GetFileHelper(lockedFile, request, params, this); nsresult rv = helper->Enqueue(); if (NS_FAILED(rv)) { aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); return nullptr; } return request.forget(); } NS_IMETHODIMP_(int64_t) FileHandle::GetFileId() { return -1; } NS_IMETHODIMP_(mozilla::dom::indexedDB::FileInfo*) FileHandle::GetFileInfo() { return nullptr; } nsresult GetFileHelper::GetSuccessResult(JSContext* aCx, JS::MutableHandle aVal) { nsCOMPtr domFile = mFileHandle->CreateFileObject(mLockedFile, mParams->Size()); JS::Rooted global(aCx, JS::CurrentGlobalOrNull(aCx)); nsresult rv = nsContentUtils::WrapNative(aCx, global, domFile, &NS_GET_IID(nsIDOMFile), aVal); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); return NS_OK; } /* virtual */ JSObject* FileHandle::WrapObject(JSContext* aCx, JS::Handle aScope) { return FileHandleBinding::Wrap(aCx, aScope, this); }