зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1463587: Part 4 - Add blob support to SharedMap. r=erahm,baku
I was hoping to avoid supporting blobs here, but some parts of the WebExtensions framework rely on being able to store Blobs in initialProcessData, and can't be migrated without adding blob support. This patch adds an ordered array of BlobImpls for all extant keys, clones them to all child processes when updating the serialized maps, and initializes StructuredCloneData instances with indexes into the combined array. MozReview-Commit-ID: IdSv5FHbPbE --HG-- extra : rebase_source : 90eeb7fad21eac93582ef9244180998d22267373 extra : source : cebf1f055d1dfb505e96cebf7e4284b35a419dd6
This commit is contained in:
Родитель
8316d5a0c0
Коммит
1aa45ee72a
|
@ -2568,10 +2568,18 @@ ContentChild::RecvRegisterStringBundles(nsTArray<mozilla::dom::StringBundleDescr
|
|||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvUpdateSharedData(const FileDescriptor& aMapFile,
|
||||
const uint32_t& aMapSize,
|
||||
nsTArray<IPCBlob>&& aBlobs,
|
||||
nsTArray<nsCString>&& aChangedKeys)
|
||||
{
|
||||
if (mSharedData) {
|
||||
mSharedData->Update(aMapFile, aMapSize, std::move(aChangedKeys));
|
||||
nsTArray<RefPtr<BlobImpl>> blobImpls(aBlobs.Length());
|
||||
for (auto& ipcBlob : aBlobs) {
|
||||
blobImpls.AppendElement(IPCBlobUtils::Deserialize(ipcBlob));
|
||||
}
|
||||
|
||||
mSharedData->Update(aMapFile, aMapSize,
|
||||
std::move(blobImpls),
|
||||
std::move(aChangedKeys));
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
|
|
|
@ -404,6 +404,7 @@ public:
|
|||
|
||||
mozilla::ipc::IPCResult RecvUpdateSharedData(const FileDescriptor& aMapFile,
|
||||
const uint32_t& aMapSize,
|
||||
nsTArray<IPCBlob>&& aBlobs,
|
||||
nsTArray<nsCString>&& aChangedKeys) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition) override;
|
||||
|
|
|
@ -467,6 +467,7 @@ child:
|
|||
async RegisterStringBundles(StringBundleDescriptor[] stringBundles);
|
||||
|
||||
async UpdateSharedData(FileDescriptor mapFile, uint32_t aSize,
|
||||
IPCBlob[] blobs,
|
||||
nsCString[] changedKeys);
|
||||
|
||||
// nsIPermissionManager messages
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "ScriptPreloader-inl.h"
|
||||
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/IPCBlobUtils.h"
|
||||
#include "mozilla/dom/ProcessGlobal.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
||||
|
@ -97,8 +98,11 @@ SharedMap::Entry::Read(JSContext* aCx,
|
|||
StructuredCloneData holder;
|
||||
if (!holder.CopyExternalData(Data(), Size())) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
if (mBlobCount) {
|
||||
holder.BlobImpls().AppendElements(Blobs());
|
||||
}
|
||||
|
||||
holder.Read(aCx, aRetVal, aRv);
|
||||
}
|
||||
|
||||
|
@ -113,6 +117,7 @@ SharedMap::CloneMapFile()
|
|||
|
||||
void
|
||||
SharedMap::Update(const FileDescriptor& aMapFile, size_t aMapSize,
|
||||
nsTArray<RefPtr<BlobImpl>>&& aBlobs,
|
||||
nsTArray<nsCString>&& aChangedKeys)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mWritable);
|
||||
|
@ -127,6 +132,8 @@ SharedMap::Update(const FileDescriptor& aMapFile, size_t aMapSize,
|
|||
mEntries.Clear();
|
||||
mEntryArray.reset();
|
||||
|
||||
mBlobImpls = std::move(aBlobs);
|
||||
|
||||
|
||||
AutoEntryScript aes(GetParentObject(), "SharedMap change event");
|
||||
JSContext* cx = aes.cx();
|
||||
|
@ -198,10 +205,11 @@ SharedMap::Entry::TakeData(StructuredCloneData&& aHolder)
|
|||
mData = AsVariant(std::move(aHolder));
|
||||
|
||||
mSize = Holder().Data().Size();
|
||||
mBlobCount = Holder().BlobImpls().Length();
|
||||
}
|
||||
|
||||
void
|
||||
SharedMap::Entry::ExtractData(char* aDestPtr, uint32_t aNewOffset)
|
||||
SharedMap::Entry::ExtractData(char* aDestPtr, uint32_t aNewOffset, uint16_t aNewBlobOffset)
|
||||
{
|
||||
if (mData.is<StructuredCloneData>()) {
|
||||
char* ptr = aDestPtr;
|
||||
|
@ -210,12 +218,13 @@ SharedMap::Entry::ExtractData(char* aDestPtr, uint32_t aNewOffset)
|
|||
ptr += aSize;
|
||||
return true;
|
||||
});
|
||||
MOZ_ASSERT(ptr - aDestPtr == mSize);
|
||||
MOZ_ASSERT(uint32_t(ptr - aDestPtr) == mSize);
|
||||
} else {
|
||||
memcpy(aDestPtr, Data(), mSize);
|
||||
}
|
||||
|
||||
mData = AsVariant(aNewOffset);
|
||||
mBlobOffset = aNewBlobOffset;
|
||||
}
|
||||
|
||||
Result<Ok, nsresult>
|
||||
|
@ -320,9 +329,11 @@ WritableSharedMap::Serialize()
|
|||
|
||||
size_t dataSize = 0;
|
||||
size_t headerSize = sizeof(count);
|
||||
size_t blobCount = 0;
|
||||
|
||||
for (auto& entry : IterHash(mEntries)) {
|
||||
headerSize += entry->HeaderSize();
|
||||
blobCount += entry->BlobCount();
|
||||
|
||||
dataSize += entry->Size();
|
||||
AlignTo(&dataSize, kStructuredCloneAlign);
|
||||
|
@ -339,18 +350,30 @@ WritableSharedMap::Serialize()
|
|||
|
||||
auto ptr = mem.Get<char>();
|
||||
|
||||
// We need to build the new array of blobs before we overwrite the existing
|
||||
// one, since previously-serialized entries will store their blob references
|
||||
// as indexes into our blobs array.
|
||||
nsTArray<RefPtr<BlobImpl>> blobImpls(blobCount);
|
||||
|
||||
for (auto& entry : IterHash(mEntries)) {
|
||||
AlignTo(&offset, kStructuredCloneAlign);
|
||||
|
||||
entry->ExtractData(&ptr[offset], offset);
|
||||
entry->ExtractData(&ptr[offset], offset, blobImpls.Length());
|
||||
entry->Code(header);
|
||||
|
||||
offset += entry->Size();
|
||||
|
||||
if (entry->BlobCount()) {
|
||||
mBlobImpls.AppendElements(entry->Blobs());
|
||||
}
|
||||
}
|
||||
|
||||
mBlobImpls = std::move(blobImpls);
|
||||
|
||||
// FIXME: We should create a separate OutputBuffer class which can encode to
|
||||
// a static memory region rather than dynamically allocating and then
|
||||
// copying.
|
||||
MOZ_ASSERT(header.cursor() == headerSize);
|
||||
memcpy(ptr.get(), header.Get(), header.cursor());
|
||||
|
||||
// We've already updated offsets at this point. We need this to succeed.
|
||||
|
@ -374,12 +397,24 @@ WritableSharedMap::BroadcastChanges()
|
|||
nsTArray<ContentParent*> parents;
|
||||
ContentParent::GetAll(parents);
|
||||
for (auto& parent : parents) {
|
||||
nsTArray<IPCBlob> blobs(mBlobImpls.Length());
|
||||
|
||||
for (auto& blobImpl : mBlobImpls) {
|
||||
nsresult rv = IPCBlobUtils::Serialize(blobImpl, parent,
|
||||
*blobs.AppendElement());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Unused << parent->SendUpdateSharedData(CloneMapFile(), mMap.size(),
|
||||
mChangedKeys);
|
||||
blobs, mChangedKeys);
|
||||
}
|
||||
|
||||
if (mReadOnly) {
|
||||
nsTArray<RefPtr<BlobImpl>> blobImpls(mBlobImpls);
|
||||
mReadOnly->Update(CloneMapFile(), mMap.size(),
|
||||
std::move(blobImpls),
|
||||
std::move(mChangedKeys));
|
||||
}
|
||||
|
||||
|
@ -407,8 +442,7 @@ WritableSharedMap::Set(JSContext* aCx,
|
|||
return;
|
||||
}
|
||||
|
||||
if (!holder.BlobImpls().IsEmpty() ||
|
||||
!holder.InputStreams().IsEmpty()) {
|
||||
if (!holder.InputStreams().IsEmpty()) {
|
||||
aRv.Throw(NS_ERROR_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@ public:
|
|||
* changed (UTF-8-encoded) keys.
|
||||
*/
|
||||
void Update(const FileDescriptor& aMapFile, size_t aMapSize,
|
||||
nsTArray<RefPtr<BlobImpl>>&& aBlobs,
|
||||
nsTArray<nsCString>&& aChangedKeys);
|
||||
|
||||
|
||||
|
@ -156,6 +157,8 @@ protected:
|
|||
buffer.codeString(mName);
|
||||
buffer.codeUint32(DataOffset());
|
||||
buffer.codeUint32(mSize);
|
||||
buffer.codeUint16(mBlobOffset);
|
||||
buffer.codeUint16(mBlobCount);
|
||||
|
||||
MOZ_ASSERT(buffer.cursor() == startOffset + HeaderSize());
|
||||
}
|
||||
|
@ -168,7 +171,9 @@ protected:
|
|||
{
|
||||
return (sizeof(uint16_t) + mName.Length() +
|
||||
sizeof(DataOffset()) +
|
||||
sizeof(mSize));
|
||||
sizeof(mSize) +
|
||||
sizeof(mBlobOffset) +
|
||||
sizeof(mBlobCount));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,7 +198,7 @@ protected:
|
|||
* snapshot, and must not be accessed again until the SharedMap mMap has been
|
||||
* updated to point to it.
|
||||
*/
|
||||
void ExtractData(char* aDestPtr, uint32_t aNewOffset);
|
||||
void ExtractData(char* aDestPtr, uint32_t aNewOffset, uint16_t aNewBlobOffset);
|
||||
|
||||
// Returns the UTF-8-encoded name of the entry, which is used as its key in
|
||||
// the map.
|
||||
|
@ -228,6 +233,19 @@ protected:
|
|||
return mData.as<uint32_t>();
|
||||
}
|
||||
|
||||
public:
|
||||
uint16_t BlobOffset() const { return mBlobOffset; }
|
||||
uint16_t BlobCount() const { return mBlobCount; }
|
||||
|
||||
Span<const RefPtr<BlobImpl>> Blobs()
|
||||
{
|
||||
if (mData.is<StructuredCloneData>()) {
|
||||
return mData.as<StructuredCloneData>().BlobImpls();
|
||||
}
|
||||
return {&mMap.mBlobImpls[mBlobOffset], BlobCount()};
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns the temporary StructuredCloneData object containing the entry's
|
||||
// value. This is *only* value when mData contains a StructuredCloneDAta
|
||||
// object.
|
||||
|
@ -258,10 +276,15 @@ protected:
|
|||
|
||||
// The size, in bytes, of the entry's structured clone data.
|
||||
uint32_t mSize = 0;
|
||||
|
||||
uint16_t mBlobOffset = 0;
|
||||
uint16_t mBlobCount = 0;
|
||||
};
|
||||
|
||||
const nsTArray<Entry*>& EntryArray() const;
|
||||
|
||||
nsTArray<RefPtr<BlobImpl>> mBlobImpls;
|
||||
|
||||
// Rebuilds the entry hashtable mEntries from the values serialized in the
|
||||
// current snapshot, if necessary. The hashtable is rebuilt lazily after
|
||||
// construction and after every Update() call, so this function must be called
|
||||
|
|
Загрузка…
Ссылка в новой задаче