mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +00:00
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 : 3020af12859ce3470bd31e9c3b7f5c919e1b9665
This commit is contained in:
parent
47c200749a
commit
345b497bc6
@ -2573,10 +2573,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();
|
||||
|
@ -406,6 +406,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;
|
||||
@ -216,6 +224,7 @@ SharedMap::Entry::ExtractData(char* aDestPtr, uint32_t aNewOffset)
|
||||
}
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user