зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1288997 - memory blob should not be shared across processes - part 3 - SendStream for memory blobs, r=bkelly
This commit is contained in:
Родитель
d62e084ce0
Коммит
9d38619302
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче