diff --git a/dom/filehandle/ActorsParent.cpp b/dom/filehandle/ActorsParent.cpp index f25f39bd7902..9e7ffbae8ff0 100644 --- a/dom/filehandle/ActorsParent.cpp +++ b/dom/filehandle/ActorsParent.cpp @@ -17,6 +17,7 @@ #include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseParent.h" #include "mozilla/dom/IPCBlobUtils.h" #include "mozilla/dom/ipc/PendingIPCBlobParent.h" +#include "mozilla/dom/quota/MemoryOutputStream.h" #include "nsAutoPtr.h" #include "nsComponentManagerUtils.h" #include "nsDebug.h" @@ -48,6 +49,7 @@ namespace mozilla { namespace dom { +using namespace mozilla::dom::quota; using namespace mozilla::ipc; namespace { @@ -632,8 +634,6 @@ class ReadOp final { friend class FileHandle; - class MemoryOutputStream; - const FileRequestReadParams mParams; private: @@ -651,34 +651,6 @@ private: GetResponse(FileRequestResponse& aResponse) override; }; -class ReadOp::MemoryOutputStream final - : public nsIOutputStream -{ - nsCString mData; - uint64_t mOffset; - -public: - static already_AddRefed - Create(uint64_t aSize); - - const nsCString& - Data() const - { - return mData; - } - -private: - MemoryOutputStream() - : mOffset(0) - { } - - virtual ~MemoryOutputStream() - { } - - NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSIOUTPUTSTREAM -}; - class WriteOp final : public CopyFileHandleOp { @@ -2404,96 +2376,6 @@ ReadOp::GetResponse(FileRequestResponse& aResponse) aResponse = FileRequestReadResponse(stream->Data()); } -// static -already_AddRefed -ReadOp:: -MemoryOutputStream::Create(uint64_t aSize) -{ - MOZ_ASSERT(aSize, "Passed zero size!"); - - if (NS_WARN_IF(aSize > UINT32_MAX)) { - return nullptr; - } - - RefPtr stream = new MemoryOutputStream(); - - char* dummy; - uint32_t length = stream->mData.GetMutableData(&dummy, aSize, fallible); - if (NS_WARN_IF(length != aSize)) { - return nullptr; - } - - return stream.forget(); -} - -NS_IMPL_ISUPPORTS(ReadOp::MemoryOutputStream, nsIOutputStream) - -NS_IMETHODIMP -ReadOp:: -MemoryOutputStream::Close() -{ - mData.Truncate(mOffset); - return NS_OK; -} - -NS_IMETHODIMP -ReadOp:: -MemoryOutputStream::Write(const char* aBuf, uint32_t aCount, uint32_t* _retval) -{ - return WriteSegments(NS_CopySegmentToBuffer, (char*)aBuf, aCount, _retval); -} - -NS_IMETHODIMP -ReadOp:: -MemoryOutputStream::Flush() -{ - return NS_OK; -} - -NS_IMETHODIMP -ReadOp:: -MemoryOutputStream::WriteFrom(nsIInputStream* aFromStream, uint32_t aCount, - uint32_t* _retval) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -ReadOp:: -MemoryOutputStream::WriteSegments(nsReadSegmentFun aReader, void* aClosure, - uint32_t aCount, uint32_t* _retval) -{ - NS_ASSERTION(mData.Length() >= mOffset, "Bad stream state!"); - - uint32_t maxCount = mData.Length() - mOffset; - if (maxCount == 0) { - *_retval = 0; - return NS_OK; - } - - if (aCount > maxCount) { - aCount = maxCount; - } - - nsresult rv = aReader(this, aClosure, mData.BeginWriting() + mOffset, 0, - aCount, _retval); - if (NS_SUCCEEDED(rv)) { - NS_ASSERTION(*_retval <= aCount, - "Reader should not read more than we asked it to read!"); - mOffset += *_retval; - } - - return NS_OK; -} - -NS_IMETHODIMP -ReadOp:: -MemoryOutputStream::IsNonBlocking(bool* _retval) -{ - *_retval = false; - return NS_OK; -} - WriteOp::WriteOp(FileHandle* aFileHandle, const FileRequestParams& aParams) : CopyFileHandleOp(aFileHandle) diff --git a/dom/quota/MemoryOutputStream.cpp b/dom/quota/MemoryOutputStream.cpp new file mode 100644 index 000000000000..e23d93fcdae3 --- /dev/null +++ b/dom/quota/MemoryOutputStream.cpp @@ -0,0 +1,100 @@ +/* -*- 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 "MemoryOutputStream.h" + +#include "nsStreamUtils.h" + +namespace mozilla { +namespace dom { +namespace quota { + +// static +already_AddRefed +MemoryOutputStream::Create(uint64_t aSize) +{ + MOZ_ASSERT(aSize, "Passed zero size!"); + + if (NS_WARN_IF(aSize > UINT32_MAX)) { + return nullptr; + } + + RefPtr stream = new MemoryOutputStream(); + + char* dummy; + uint32_t length = stream->mData.GetMutableData(&dummy, aSize, fallible); + if (NS_WARN_IF(length != aSize)) { + return nullptr; + } + + return stream.forget(); +} + +NS_IMPL_ISUPPORTS(MemoryOutputStream, nsIOutputStream) + +NS_IMETHODIMP +MemoryOutputStream::Close() +{ + mData.Truncate(mOffset); + return NS_OK; +} + +NS_IMETHODIMP +MemoryOutputStream::Write(const char* aBuf, uint32_t aCount, uint32_t* _retval) +{ + return WriteSegments(NS_CopySegmentToBuffer, (char*)aBuf, aCount, _retval); +} + +NS_IMETHODIMP +MemoryOutputStream::Flush() +{ + return NS_OK; +} + +NS_IMETHODIMP +MemoryOutputStream::WriteFrom(nsIInputStream* aFromStream, uint32_t aCount, + uint32_t* _retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +MemoryOutputStream::WriteSegments(nsReadSegmentFun aReader, void* aClosure, + uint32_t aCount, uint32_t* _retval) +{ + MOZ_ASSERT(mData.Length() >= mOffset, "Bad stream state!"); + + uint32_t maxCount = mData.Length() - mOffset; + if (maxCount == 0) { + *_retval = 0; + return NS_OK; + } + + if (aCount > maxCount) { + aCount = maxCount; + } + + nsresult rv = aReader(this, aClosure, mData.BeginWriting() + mOffset, 0, + aCount, _retval); + if (NS_SUCCEEDED(rv)) { + MOZ_ASSERT(*_retval <= aCount, + "Reader should not read more than we asked it to read!"); + mOffset += *_retval; + } + + return NS_OK; +} + +NS_IMETHODIMP +MemoryOutputStream::IsNonBlocking(bool* _retval) +{ + *_retval = false; + return NS_OK; +} + +} // namespace quota +} // namespace dom +} // namespace mozilla diff --git a/dom/quota/MemoryOutputStream.h b/dom/quota/MemoryOutputStream.h new file mode 100644 index 000000000000..0d4eaac778fb --- /dev/null +++ b/dom/quota/MemoryOutputStream.h @@ -0,0 +1,58 @@ +/* -*- 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/. */ + +#ifndef mozilla_dom_quota_MemoryOutputStream_h +#define mozilla_dom_quota_MemoryOutputStream_h + +#include "nsIOutputStream.h" + +namespace mozilla { +namespace dom { +namespace quota { + +// An output stream so you can read your potentially-async input stream into +// a contiguous buffer in the form of an nsCString using NS_AsyncCopy. +// Back when streams were more synchronous and people didn't know blocking I/O +// was bad, if you wanted to read a stream into a flat buffer, you could use +// NS_ReadInputStreamToString/NS_ReadInputStreamToBuffer. But those don't work +// with async streams. This can be used to replace hand-rolled Read/AsyncWait() +// loops. Because you specify the expected size up front, the nsCString buffer +// is pre-allocated so wasteful reallocations can be avoided. However, +// nsCString currently may over-allocate and this can be problematic on 32-bit +// windows until we're rid of that build configuration. +class MemoryOutputStream final + : public nsIOutputStream +{ + nsCString mData; + uint64_t mOffset; + +public: + static already_AddRefed + Create(uint64_t aSize); + + const nsCString& + Data() const + { + return mData; + } + +private: + MemoryOutputStream() + : mOffset(0) + { } + + virtual ~MemoryOutputStream() + { } + + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIOUTPUTSTREAM +}; + +} // namespace quota +} // namespace dom +} // namespace mozilla + +#endif /* mozilla_dom_quota_MemoryOutputStream_h */ diff --git a/dom/quota/moz.build b/dom/quota/moz.build index f09d88ba6f98..ba91f5bc86ee 100644 --- a/dom/quota/moz.build +++ b/dom/quota/moz.build @@ -32,6 +32,7 @@ EXPORTS.mozilla.dom.quota += [ 'ActorsParent.h', 'Client.h', 'FileStreams.h', + 'MemoryOutputStream.h', 'OriginScope.h', 'PersistenceType.h', 'QuotaCommon.h', @@ -46,6 +47,7 @@ UNIFIED_SOURCES += [ 'ActorsChild.cpp', 'ActorsParent.cpp', 'FileStreams.cpp', + 'MemoryOutputStream.cpp', 'QuotaManagerService.cpp', 'QuotaRequests.cpp', 'QuotaResults.cpp',