зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1202006 - Memory Blob to Temporary File - part 1 - MutableBlobStorage for XHR, r=smaug
--HG-- rename : dom/base/BlobSet.cpp => dom/base/MutableBlobStorage.cpp rename : dom/base/BlobSet.h => dom/base/MutableBlobStorage.h
This commit is contained in:
Родитель
b0c2b695f5
Коммит
6420171857
|
@ -0,0 +1,101 @@
|
|||
/* -*- 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/MutableBlobStorage.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "MultipartBlobImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
already_AddRefed<Blob>
|
||||
MutableBlobStorage::GetBlob(nsISupports* aParent,
|
||||
const nsACString& aContentType,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Flush();
|
||||
|
||||
nsTArray<RefPtr<BlobImpl>> blobImpls(mBlobImpls);
|
||||
RefPtr<BlobImpl> blobImpl =
|
||||
MultipartBlobImpl::Create(Move(blobImpls),
|
||||
NS_ConvertASCIItoUTF16(aContentType),
|
||||
aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<Blob> blob = Blob::Create(aParent, blobImpl);
|
||||
return blob.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
MutableBlobStorage::Append(const void* aData, uint32_t aLength)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aData);
|
||||
if (!aLength) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint64_t offset = mDataLen;
|
||||
|
||||
if (!ExpandBufferSize(aLength)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy((char*)mData + offset, aData, aLength);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
MutableBlobStorage::ExpandBufferSize(uint64_t aSize)
|
||||
{
|
||||
if (mDataBufferLen >= mDataLen + aSize) {
|
||||
mDataLen += aSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Start at 1 or we'll loop forever.
|
||||
CheckedUint32 bufferLen =
|
||||
std::max<uint32_t>(static_cast<uint32_t>(mDataBufferLen), 1);
|
||||
while (bufferLen.isValid() && bufferLen.value() < mDataLen + aSize) {
|
||||
bufferLen *= 2;
|
||||
}
|
||||
|
||||
if (!bufferLen.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void* data = realloc(mData, bufferLen.value());
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mData = data;
|
||||
mDataBufferLen = bufferLen.value();
|
||||
mDataLen += aSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MutableBlobStorage::Flush()
|
||||
{
|
||||
if (mData) {
|
||||
// If we have some data, create a blob for it
|
||||
// and put it on the stack
|
||||
|
||||
RefPtr<BlobImpl> blobImpl =
|
||||
new BlobImplMemory(mData, mDataLen, EmptyString());
|
||||
mBlobImpls.AppendElement(blobImpl);
|
||||
|
||||
mData = nullptr; // The nsDOMMemoryFile takes ownership of the buffer
|
||||
mDataLen = 0;
|
||||
mDataBufferLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
|
@ -0,0 +1,53 @@
|
|||
/* -*- 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_MutableBlobStorage_h
|
||||
#define mozilla_dom_MutableBlobStorage_h
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Blob;
|
||||
class BlobImpl;
|
||||
|
||||
class MutableBlobStorage final
|
||||
{
|
||||
public:
|
||||
MutableBlobStorage()
|
||||
: mData(nullptr)
|
||||
, mDataLen(0)
|
||||
, mDataBufferLen(0)
|
||||
{}
|
||||
|
||||
~MutableBlobStorage()
|
||||
{
|
||||
free(mData);
|
||||
}
|
||||
|
||||
nsresult Append(const void* aData, uint32_t aLength);
|
||||
|
||||
already_AddRefed<Blob> GetBlob(nsISupports* aParent,
|
||||
const nsACString& aContentType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
bool ExpandBufferSize(uint64_t aSize);
|
||||
|
||||
void Flush();
|
||||
|
||||
nsTArray<RefPtr<BlobImpl>> mBlobImpls;
|
||||
|
||||
void* mData;
|
||||
uint64_t mDataLen;
|
||||
uint64_t mDataBufferLen;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_MutableBlobStorage_h
|
|
@ -186,6 +186,7 @@ EXPORTS.mozilla.dom += [
|
|||
'ImportManager.h',
|
||||
'Link.h',
|
||||
'Location.h',
|
||||
'MutableBlobStorage.h',
|
||||
'NameSpaceConstants.h',
|
||||
'Navigator.h',
|
||||
'NodeInfo.h',
|
||||
|
@ -247,6 +248,7 @@ UNIFIED_SOURCES += [
|
|||
'Link.cpp',
|
||||
'Location.cpp',
|
||||
'MultipartBlobImpl.cpp',
|
||||
'MutableBlobStorage.cpp',
|
||||
'Navigator.cpp',
|
||||
'NodeInfo.cpp',
|
||||
'NodeIterator.cpp',
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
#endif
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/dom/BlobSet.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FetchUtil.h"
|
||||
#include "mozilla/dom/FormData.h"
|
||||
#include "mozilla/dom/MutableBlobStorage.h"
|
||||
#include "mozilla/dom/XMLDocument.h"
|
||||
#include "mozilla/dom/URLSearchParams.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
|
@ -291,7 +291,7 @@ XMLHttpRequestMainThread::ResetResponse()
|
|||
TruncateResponseText();
|
||||
mResponseBlob = nullptr;
|
||||
mDOMBlob = nullptr;
|
||||
mBlobSet = nullptr;
|
||||
mBlobStorage = nullptr;
|
||||
mResultArrayBuffer = nullptr;
|
||||
mArrayBufferBuilder.reset();
|
||||
mResultJSON.setUndefined();
|
||||
|
@ -677,8 +677,8 @@ XMLHttpRequestMainThread::CreatePartialBlob(ErrorResult& aRv)
|
|||
return;
|
||||
}
|
||||
|
||||
// mBlobSet can be null if the request has been canceled
|
||||
if (!mBlobSet) {
|
||||
// mBlobStorage can be null if the request has been canceled
|
||||
if (!mBlobStorage) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -687,7 +687,7 @@ XMLHttpRequestMainThread::CreatePartialBlob(ErrorResult& aRv)
|
|||
mChannel->GetContentType(contentType);
|
||||
}
|
||||
|
||||
mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType, aRv);
|
||||
mResponseBlob = mBlobStorage->GetBlob(GetOwner(), contentType, aRv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP XMLHttpRequestMainThread::GetResponseType(nsAString& aResponseType)
|
||||
|
@ -1584,10 +1584,10 @@ XMLHttpRequestMainThread::StreamReaderFunc(nsIInputStream* in,
|
|||
if (xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Blob ||
|
||||
xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Moz_blob) {
|
||||
if (!xmlHttpRequest->mDOMBlob) {
|
||||
if (!xmlHttpRequest->mBlobSet) {
|
||||
xmlHttpRequest->mBlobSet = new BlobSet();
|
||||
if (!xmlHttpRequest->mBlobStorage) {
|
||||
xmlHttpRequest->mBlobStorage = new MutableBlobStorage();
|
||||
}
|
||||
rv = xmlHttpRequest->mBlobSet->AppendVoidPtr(fromRawSegment, count);
|
||||
rv = xmlHttpRequest->mBlobStorage->Append(fromRawSegment, count);
|
||||
}
|
||||
// Clear the cache so that the blob size is updated.
|
||||
if (xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Moz_blob) {
|
||||
|
@ -1668,7 +1668,7 @@ bool XMLHttpRequestMainThread::CreateDOMBlob(nsIRequest *request)
|
|||
mDOMBlob = File::CreateFromFile(GetOwner(), file, EmptyString(),
|
||||
NS_ConvertASCIItoUTF16(contentType));
|
||||
|
||||
mBlobSet = nullptr;
|
||||
mBlobStorage = nullptr;
|
||||
NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty");
|
||||
return true;
|
||||
}
|
||||
|
@ -2038,18 +2038,18 @@ XMLHttpRequestMainThread::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
|
|||
mResponseBlob = mDOMBlob;
|
||||
mDOMBlob = nullptr;
|
||||
} else {
|
||||
// mBlobSet can be null if the channel is non-file non-cacheable
|
||||
// mBlobStorage can be null if the channel is non-file non-cacheable
|
||||
// and if the response length is zero.
|
||||
if (!mBlobSet) {
|
||||
mBlobSet = new BlobSet();
|
||||
if (!mBlobStorage) {
|
||||
mBlobStorage = new MutableBlobStorage();
|
||||
}
|
||||
// Smaller files may be written in cache map instead of separate files.
|
||||
// Also, no-store response cannot be written in persistent cache.
|
||||
nsAutoCString contentType;
|
||||
mChannel->GetContentType(contentType);
|
||||
|
||||
mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType, rv);
|
||||
mBlobSet = nullptr;
|
||||
mResponseBlob = mBlobStorage->GetBlob(GetOwner(), contentType, rv);
|
||||
mBlobStorage = nullptr;
|
||||
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
|
|
|
@ -55,8 +55,8 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
|
||||
class Blob;
|
||||
class BlobSet;
|
||||
class FormData;
|
||||
class MutableBlobStorage;
|
||||
class URLSearchParams;
|
||||
class XMLHttpRequestUpload;
|
||||
struct OriginAttributesDictionary;
|
||||
|
@ -644,9 +644,9 @@ protected:
|
|||
// Non-null only when we are able to get a os-file representation of the
|
||||
// response, i.e. when loading from a file.
|
||||
RefPtr<Blob> mDOMBlob;
|
||||
// We stream data to mBlobSet when response type is "blob" or "moz-blob"
|
||||
// We stream data to mBlobStorage when response type is "blob" or "moz-blob"
|
||||
// and mDOMBlob is null.
|
||||
nsAutoPtr<BlobSet> mBlobSet;
|
||||
nsAutoPtr<MutableBlobStorage> mBlobStorage;
|
||||
|
||||
nsString mOverrideMimeType;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче