michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "FileHandle.h" michael@0: michael@0: #include "nsContentUtils.h" michael@0: #include "nsDOMClassInfoID.h" michael@0: #include "nsNetUtil.h" michael@0: michael@0: #include "nsIDOMFile.h" michael@0: #include "nsIFileStorage.h" michael@0: michael@0: #include "File.h" michael@0: #include "FileRequest.h" michael@0: #include "FileService.h" michael@0: #include "LockedFile.h" michael@0: #include "MetadataHelper.h" michael@0: #include "mozilla/dom/FileHandleBinding.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::dom; michael@0: USING_FILE_NAMESPACE michael@0: michael@0: namespace { michael@0: michael@0: class GetFileHelper : public MetadataHelper michael@0: { michael@0: public: michael@0: GetFileHelper(LockedFile* aLockedFile, michael@0: FileRequest* aFileRequest, michael@0: MetadataParameters* aParams, michael@0: FileHandle* aFileHandle) michael@0: : MetadataHelper(aLockedFile, aFileRequest, aParams), michael@0: mFileHandle(aFileHandle) michael@0: { } michael@0: michael@0: virtual nsresult michael@0: GetSuccessResult(JSContext* aCx, michael@0: JS::MutableHandle aVal) MOZ_OVERRIDE; michael@0: michael@0: virtual void michael@0: ReleaseObjects() MOZ_OVERRIDE michael@0: { michael@0: mFileHandle = nullptr; michael@0: michael@0: MetadataHelper::ReleaseObjects(); michael@0: } michael@0: michael@0: private: michael@0: nsRefPtr mFileHandle; michael@0: }; michael@0: michael@0: } // anonymous namespace michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_INHERITED(FileHandle, DOMEventTargetHelper, michael@0: mFileStorage) michael@0: michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileHandle) michael@0: NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) michael@0: michael@0: NS_IMPL_ADDREF_INHERITED(FileHandle, DOMEventTargetHelper) michael@0: NS_IMPL_RELEASE_INHERITED(FileHandle, DOMEventTargetHelper) michael@0: michael@0: // static michael@0: already_AddRefed michael@0: FileHandle::Create(nsPIDOMWindow* aWindow, michael@0: nsIFileStorage* aFileStorage, michael@0: nsIFile* aFile) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); michael@0: michael@0: nsRefPtr newFileHandle = new FileHandle(aWindow); michael@0: michael@0: newFileHandle->mFileStorage = aFileStorage; michael@0: nsresult rv = aFile->GetLeafName(newFileHandle->mName); michael@0: if (NS_WARN_IF(NS_FAILED(rv))) { michael@0: return nullptr; michael@0: } michael@0: michael@0: newFileHandle->mFile = aFile; michael@0: newFileHandle->mFileName = newFileHandle->mName; michael@0: michael@0: return newFileHandle.forget(); michael@0: } michael@0: michael@0: // virtual michael@0: already_AddRefed michael@0: FileHandle::CreateStream(nsIFile* aFile, bool aReadOnly) michael@0: { michael@0: nsresult rv; michael@0: michael@0: if (aReadOnly) { michael@0: nsCOMPtr stream; michael@0: rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), aFile, -1, -1, michael@0: nsIFileInputStream::DEFER_OPEN); michael@0: if (NS_WARN_IF(NS_FAILED(rv))) { michael@0: return nullptr; michael@0: } michael@0: return stream.forget(); michael@0: } michael@0: michael@0: nsCOMPtr stream; michael@0: rv = NS_NewLocalFileStream(getter_AddRefs(stream), aFile, -1, -1, michael@0: nsIFileStream::DEFER_OPEN); michael@0: if (NS_WARN_IF(NS_FAILED(rv))) { michael@0: return nullptr; michael@0: } michael@0: return stream.forget(); michael@0: } michael@0: michael@0: // virtual michael@0: already_AddRefed michael@0: FileHandle::CreateFileObject(LockedFile* aLockedFile, uint32_t aFileSize) michael@0: { michael@0: nsCOMPtr file = michael@0: new File(mName, mType, aFileSize, mFile, aLockedFile); michael@0: michael@0: return file.forget(); michael@0: } michael@0: michael@0: // virtual michael@0: JSObject* michael@0: FileHandle::WrapObject(JSContext* aCx) michael@0: { michael@0: return FileHandleBinding::Wrap(aCx, this); michael@0: } michael@0: michael@0: already_AddRefed michael@0: FileHandle::Open(FileMode aMode, ErrorResult& aError) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: if (FileService::IsShuttingDown() || mFileStorage->IsShuttingDown()) { michael@0: aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); michael@0: return nullptr; michael@0: } michael@0: michael@0: nsRefPtr lockedFile = LockedFile::Create(this, aMode); michael@0: if (!lockedFile) { michael@0: aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); michael@0: return nullptr; michael@0: } michael@0: michael@0: return lockedFile.forget(); michael@0: } michael@0: michael@0: already_AddRefed michael@0: FileHandle::GetFile(ErrorResult& aError) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: // Do nothing if the window is closed michael@0: if (!GetOwner()) { michael@0: return nullptr; michael@0: } michael@0: michael@0: nsRefPtr lockedFile = michael@0: LockedFile::Create(this, FileMode::Readonly, LockedFile::PARALLEL); michael@0: if (!lockedFile) { michael@0: aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); michael@0: return nullptr; michael@0: } michael@0: michael@0: nsRefPtr request = michael@0: FileRequest::Create(GetOwner(), lockedFile, /* aWrapAsDOMRequest */ true); michael@0: michael@0: nsRefPtr params = new MetadataParameters(true, false); michael@0: michael@0: nsRefPtr helper = michael@0: new GetFileHelper(lockedFile, request, params, this); michael@0: michael@0: nsresult rv = helper->Enqueue(); michael@0: if (NS_FAILED(rv)) { michael@0: aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); michael@0: return nullptr; michael@0: } michael@0: michael@0: return request.forget(); michael@0: } michael@0: michael@0: nsresult michael@0: GetFileHelper::GetSuccessResult(JSContext* aCx, michael@0: JS::MutableHandle aVal) michael@0: { michael@0: nsCOMPtr domFile = michael@0: mFileHandle->CreateFileObject(mLockedFile, mParams->Size()); michael@0: michael@0: nsresult rv = michael@0: nsContentUtils::WrapNative(aCx, domFile, &NS_GET_IID(nsIDOMFile), aVal); michael@0: NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); michael@0: return NS_OK; michael@0: }