Bug 1288997 - memory blob should not be shared across processes - part 3 - SendStream for memory blobs, r=bkelly

This commit is contained in:
Andrea Marchesini 2016-09-21 12:27:26 +02:00
Родитель d62e084ce0
Коммит 9d38619302
6 изменённых файлов: 150 добавлений и 60 удалений

Просмотреть файл

@ -4,6 +4,7 @@
* 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 protocol PFileDescriptorSet;
include protocol PBrowser;
using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/COMPtrTypes.h";

Просмотреть файл

@ -40,6 +40,8 @@
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRunnable.h"
#include "nsThreadUtils.h"
#include "nsStreamUtils.h"
#include "SlicedInputStream.h"
namespace mozilla {
namespace dom {
@ -276,7 +278,7 @@ Blob::CreateSlice(uint64_t aStart, uint64_t aLength,
ErrorResult& aRv)
{
RefPtr<BlobImpl> impl = mImpl->CreateSlice(aStart, aLength,
aContentType, aRv);
aContentType, aRv);
if (aRv.Failed()) {
return nullptr;
}
@ -1193,5 +1195,75 @@ BlobImplTemporaryBlob::GetInternalStream(nsIInputStream** aStream,
stream.forget(aStream);
}
////////////////////////////////////////////////////////////////////////////
// BlobImplStream implementation
NS_IMPL_ISUPPORTS_INHERITED0(BlobImplStream, BlobImpl)
BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
const nsAString& aContentType,
uint64_t aLength)
: BlobImplBase(aContentType, aLength)
, mInputStream(aInputStream)
{
mImmutable = true;
}
BlobImplStream::BlobImplStream(BlobImplStream* aOther,
const nsAString& aContentType,
uint64_t aStart, uint64_t aLength)
: BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
, mInputStream(new SlicedInputStream(aOther->mInputStream, aStart, aLength))
{
mImmutable = true;
}
BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
const nsAString& aName,
const nsAString& aContentType,
int64_t aLastModifiedDate,
uint64_t aLength)
: BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
, mInputStream(aInputStream)
{
mImmutable = true;
}
BlobImplStream::~BlobImplStream()
{}
void
BlobImplStream::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
{
nsCOMPtr<nsIInputStream> clonedStream;
nsCOMPtr<nsIInputStream> replacementStream;
aRv = NS_CloneInputStream(mInputStream, getter_AddRefs(clonedStream),
getter_AddRefs(replacementStream));
if (NS_WARN_IF(aRv.Failed())) {
return;
}
if (replacementStream) {
mInputStream = replacementStream.forget();
}
clonedStream.forget(aStream);
}
already_AddRefed<BlobImpl>
BlobImplStream::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv)
{
if (!aLength) {
RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
return impl.forget();
}
RefPtr<BlobImpl> impl =
new BlobImplStream(this, aContentType, aStart, aLength);
return impl.forget();
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -797,6 +797,44 @@ private:
~EmptyBlobImpl() {}
};
class BlobImplStream final : public BlobImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
BlobImplStream(nsIInputStream* aInputStream,
const nsAString& aContentType,
uint64_t aLength);
BlobImplStream(nsIInputStream* aInputStream,
const nsAString& aName,
const nsAString& aContentType,
int64_t aLastModifiedDate,
uint64_t aLength);
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
virtual bool IsMemoryFile() const override
{
return true;
}
private:
BlobImplStream(BlobImplStream* aOther,
const nsAString& aContentType,
uint64_t aStart,
uint64_t aLength);
~BlobImplStream();
nsCOMPtr<nsIInputStream> mInputStream;
};
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -26,6 +26,7 @@
#include "mozilla/dom/indexedDB/FileSnapshot.h"
#include "mozilla/dom/IndexedDatabaseManager.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/ipc/PBackgroundParent.h"
#include "mozilla/ipc/PFileDescriptorSetParent.h"
@ -711,51 +712,38 @@ CreateBlobImpl(const nsID& aKnownBlobIDData,
}
already_AddRefed<BlobImpl>
CreateBlobImpl(const nsTArray<uint8_t>& aMemoryData,
CreateBlobImpl(const IPCStream& aStream,
const CreateBlobImplMetadata& aMetadata)
{
static_assert(sizeof(aMemoryData.Length()) <= sizeof(size_t),
"String length won't fit in size_t!");
static_assert(sizeof(size_t) <= sizeof(uint64_t),
"size_t won't fit in uint64_t!");
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
nsCOMPtr<nsIInputStream> inputStream = DeserializeIPCStream(aStream);
if (!inputStream) {
ASSERT_UNLESS_FUZZING();
return nullptr;
}
uint64_t available;
MOZ_ALWAYS_SUCCEEDS(inputStream->Available(&available));
RefPtr<BlobImpl> blobImpl;
if (auto length = static_cast<size_t>(aMemoryData.Length())) {
static constexpr size_t elementSizeMultiplier =
sizeof(aMemoryData[0]) / sizeof(char);
if (!aMetadata.mHasRecursed &&
NS_WARN_IF(aMetadata.mLength != uint64_t(length))) {
ASSERT_UNLESS_FUZZING();
return nullptr;
}
void* buffer = malloc(length * elementSizeMultiplier);
if (NS_WARN_IF(!buffer)) {
return nullptr;
}
memcpy(buffer, aMemoryData.Elements(), length * elementSizeMultiplier);
if (!aMetadata.mHasRecursed && aMetadata.IsFile()) {
if (!aMetadata.mHasRecursed && aMetadata.IsFile()) {
if (available) {
blobImpl =
new BlobImplMemory(buffer,
uint64_t(length),
new BlobImplStream(inputStream,
aMetadata.mName,
aMetadata.mContentType,
aMetadata.mLastModifiedDate);
aMetadata.mLastModifiedDate,
available);
} else {
blobImpl =
new BlobImplMemory(buffer, uint64_t(length), aMetadata.mContentType);
new EmptyBlobImpl(aMetadata.mName,
aMetadata.mContentType,
aMetadata.mLastModifiedDate);
}
} else if (!aMetadata.mHasRecursed && aMetadata.IsFile()) {
} else if (available) {
blobImpl =
new EmptyBlobImpl(aMetadata.mName,
aMetadata.mContentType,
aMetadata.mLastModifiedDate);
new BlobImplStream(inputStream, aMetadata.mContentType, available);
} else {
blobImpl = new EmptyBlobImpl(aMetadata.mContentType);
}
@ -783,8 +771,8 @@ CreateBlobImplFromBlobData(const BlobData& aBlobData,
break;
}
case BlobData::TArrayOfuint8_t: {
blobImpl = CreateBlobImpl(aBlobData.get_ArrayOfuint8_t(), aMetadata);
case BlobData::TIPCStream: {
blobImpl = CreateBlobImpl(aBlobData.get_IPCStream(), aMetadata);
break;
}
@ -921,8 +909,10 @@ CreateBlobImpl(const ParentBlobConstructorParams& aParams,
return blobImpl.forget();
}
template <class ChildManagerType>
void
BlobDataFromBlobImpl(BlobImpl* aBlobImpl, BlobData& aBlobData)
BlobDataFromBlobImpl(ChildManagerType* aManager, BlobImpl* aBlobImpl,
BlobData& aBlobData)
{
MOZ_ASSERT(gProcessType != GeckoProcessType_Default);
MOZ_ASSERT(aBlobImpl);
@ -940,7 +930,8 @@ BlobDataFromBlobImpl(BlobImpl* aBlobImpl, BlobData& aBlobData)
for (uint32_t count = subBlobs->Length(), index = 0;
index < count;
index++) {
BlobDataFromBlobImpl(subBlobs->ElementAt(index), subBlobDatas[index]);
BlobDataFromBlobImpl(aManager, subBlobs->ElementAt(index),
subBlobDatas[index]);
}
return;
@ -960,26 +951,9 @@ BlobDataFromBlobImpl(BlobImpl* aBlobImpl, BlobData& aBlobData)
aBlobImpl->GetInternalStream(getter_AddRefs(inputStream), rv);
MOZ_ALWAYS_TRUE(!rv.Failed());
DebugOnly<bool> isNonBlocking;
MOZ_ASSERT(NS_SUCCEEDED(inputStream->IsNonBlocking(&isNonBlocking)));
MOZ_ASSERT(isNonBlocking);
uint64_t available;
MOZ_ALWAYS_SUCCEEDS(inputStream->Available(&available));
MOZ_ASSERT(available <= uint64_t(UINT32_MAX));
aBlobData = nsTArray<uint8_t>();
nsTArray<uint8_t>& blobData = aBlobData.get_ArrayOfuint8_t();
blobData.SetLength(size_t(available));
uint32_t readCount;
MOZ_ALWAYS_SUCCEEDS(
inputStream->Read(reinterpret_cast<char*>(blobData.Elements()),
uint32_t(available),
&readCount));
AutoIPCStream autoStream;
autoStream.Serialize(inputStream, aManager);
aBlobData = autoStream.TakeValue();
}
RemoteInputStream::RemoteInputStream(BlobImpl* aBlobImpl,
@ -3375,8 +3349,10 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
blobParams = SameProcessBlobConstructorParams(addRefedBlobImpl);
} else {
// BlobData is going to be populate here and it _must_ be send via IPC in
// order to avoid leaks.
BlobData blobData;
BlobDataFromBlobImpl(aBlobImpl, blobData);
BlobDataFromBlobImpl(aManager, aBlobImpl, blobData);
nsString contentType;
aBlobImpl->GetType(contentType);

Просмотреть файл

@ -5,6 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBlob;
include protocol PSendStream;
include IPCStream;
include ProtocolTypes;
using struct mozilla::void_t
@ -43,7 +45,7 @@ union BlobData
nsID;
// For memory-backed blobs.
uint8_t[];
IPCStream;
// For multiplex blobs.
BlobData[];

Просмотреть файл

@ -7,6 +7,7 @@ include protocol PBlobStream;
include protocol PContent;
include protocol PContentBridge;
include protocol PFileDescriptorSet;
include protocol PSendStream;
include BlobTypes;
include DOMTypes;