зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1371246: Handle serializing Blobs in StructuredCloneHolder instances. r=billm
MozReview-Commit-ID: 2n15NCnLC48 --HG-- extra : rebase_source : b9769b5b79d6d9dd6277a783963d83a0e0ab88eb extra : amend_source : ac9167122891a374b4fd7219feaa7d7afbf6f5f0
This commit is contained in:
Родитель
c2afdb09bd
Коммит
7bb88fc9de
|
@ -99,13 +99,14 @@ StructuredCloneBlob::Deserialize(JSContext* aCx, JS::HandleObject aTargetScope,
|
|||
|
||||
|
||||
/* static */ JSObject*
|
||||
StructuredCloneBlob::ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader)
|
||||
StructuredCloneBlob::ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader,
|
||||
StructuredCloneHolder* aHolder)
|
||||
{
|
||||
JS::RootedObject obj(aCx);
|
||||
{
|
||||
RefPtr<StructuredCloneBlob> holder = new StructuredCloneBlob();
|
||||
|
||||
if (!holder->ReadStructuredCloneInternal(aCx, aReader) ||
|
||||
if (!holder->ReadStructuredCloneInternal(aCx, aReader, aHolder) ||
|
||||
!holder->WrapObject(aCx, nullptr, &obj)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -114,7 +115,8 @@ StructuredCloneBlob::ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader
|
|||
}
|
||||
|
||||
bool
|
||||
StructuredCloneBlob::ReadStructuredCloneInternal(JSContext* aCx, JSStructuredCloneReader* aReader)
|
||||
StructuredCloneBlob::ReadStructuredCloneInternal(JSContext* aCx, JSStructuredCloneReader* aReader,
|
||||
StructuredCloneHolder* aHolder)
|
||||
{
|
||||
uint32_t length;
|
||||
uint32_t version;
|
||||
|
@ -122,6 +124,15 @@ StructuredCloneBlob::ReadStructuredCloneInternal(JSContext* aCx, JSStructuredClo
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t blobOffset;
|
||||
uint32_t blobCount;
|
||||
if (!JS_ReadUint32Pair(aReader, &blobOffset, &blobCount)) {
|
||||
return false;
|
||||
}
|
||||
if (blobCount) {
|
||||
BlobImpls().AppendElements(&aHolder->BlobImpls()[blobOffset], blobCount);
|
||||
}
|
||||
|
||||
JSStructuredCloneData data(length, length, 4096);
|
||||
if (!JS_ReadBytes(aReader, data.Start(), length)) {
|
||||
return false;
|
||||
|
@ -136,14 +147,18 @@ StructuredCloneBlob::ReadStructuredCloneInternal(JSContext* aCx, JSStructuredClo
|
|||
}
|
||||
|
||||
bool
|
||||
StructuredCloneBlob::WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWriter)
|
||||
StructuredCloneBlob::WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWriter,
|
||||
StructuredCloneHolder* aHolder)
|
||||
{
|
||||
auto& data = mBuffer->data();
|
||||
if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_STRUCTURED_CLONE_HOLDER, 0) ||
|
||||
!JS_WriteUint32Pair(aWriter, data.Size(), JS_STRUCTURED_CLONE_VERSION)) {
|
||||
!JS_WriteUint32Pair(aWriter, data.Size(), JS_STRUCTURED_CLONE_VERSION) ||
|
||||
!JS_WriteUint32Pair(aWriter, aHolder->BlobImpls().Length(), BlobImpls().Length())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aHolder->BlobImpls().AppendElements(BlobImpls());
|
||||
|
||||
auto iter = data.Iter();
|
||||
while (!iter.Done()) {
|
||||
if (!JS_WriteBytes(aWriter, iter.Data(), iter.RemainingInSegment())) {
|
||||
|
|
|
@ -26,8 +26,10 @@ public:
|
|||
|
||||
explicit StructuredCloneBlob();
|
||||
|
||||
static JSObject* ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader);
|
||||
bool WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWriter);
|
||||
static JSObject* ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader,
|
||||
StructuredCloneHolder* aHolder);
|
||||
bool WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWriter,
|
||||
StructuredCloneHolder* aHolder);
|
||||
|
||||
static already_AddRefed<StructuredCloneBlob>
|
||||
Constructor(GlobalObject& aGlobal, JS::HandleValue aValue, JS::HandleObject aTargetGlobal, ErrorResult& aRv);
|
||||
|
@ -47,7 +49,8 @@ protected:
|
|||
~StructuredCloneBlob() = default;
|
||||
|
||||
private:
|
||||
bool ReadStructuredCloneInternal(JSContext* aCx, JSStructuredCloneReader* aReader);
|
||||
bool ReadStructuredCloneInternal(JSContext* aCx, JSStructuredCloneReader* aReader,
|
||||
StructuredCloneHolder* aHolder);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -358,10 +358,6 @@ StructuredCloneHolder::ReadFullySerializableObjects(JSContext* aCx,
|
|||
return ReadStructuredCloneImageData(aCx, aReader);
|
||||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_STRUCTURED_CLONE_HOLDER) {
|
||||
return StructuredCloneBlob::ReadStructuredClone(aCx, aReader);
|
||||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_WEBCRYPTO_KEY || aTag == SCTAG_DOM_URLSEARCHPARAMS) {
|
||||
nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
|
||||
if (!global) {
|
||||
|
@ -458,14 +454,6 @@ StructuredCloneHolder::WriteFullySerializableObjects(JSContext* aCx,
|
|||
}
|
||||
}
|
||||
|
||||
// See if this is a StructuredCloneBlob object.
|
||||
{
|
||||
StructuredCloneBlob* holder = nullptr;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(StructuredCloneHolder, aObj, holder))) {
|
||||
return holder->WriteStructuredClone(aCx, aWriter);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle URLSearchParams cloning
|
||||
{
|
||||
URLSearchParams* usp = nullptr;
|
||||
|
@ -999,6 +987,10 @@ StructuredCloneHolder::CustomReadHandler(JSContext* aCx,
|
|||
parent, GetSurfaces(), aIndex);
|
||||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_STRUCTURED_CLONE_HOLDER) {
|
||||
return StructuredCloneBlob::ReadStructuredClone(aCx, aReader, this);
|
||||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_WASM) {
|
||||
return ReadWasmModule(aCx, aIndex, this);
|
||||
}
|
||||
|
@ -1062,6 +1054,14 @@ StructuredCloneHolder::CustomWriteHandler(JSContext* aCx,
|
|||
}
|
||||
}
|
||||
|
||||
// See if this is a StructuredCloneBlob object.
|
||||
{
|
||||
StructuredCloneBlob* holder = nullptr;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(StructuredCloneHolder, aObj, holder))) {
|
||||
return holder->WriteStructuredClone(aCx, aWriter, this);
|
||||
}
|
||||
}
|
||||
|
||||
// See if this is a WasmModule.
|
||||
if ((mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
|
||||
mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread) &&
|
||||
|
|
|
@ -77,3 +77,35 @@ add_task(async function tabsSendMessageReply() {
|
|||
await extension.awaitFinish("sendMessage");
|
||||
await extension.unload();
|
||||
});
|
||||
|
||||
add_task(async function tabsSendMessageBlob() {
|
||||
function background() {
|
||||
browser.runtime.onMessage.addListener(msg => {
|
||||
browser.test.assertTrue(msg.blob instanceof Blob, "Message is a blob");
|
||||
return Promise.resolve(msg);
|
||||
});
|
||||
|
||||
let childFrame = document.createElement("iframe");
|
||||
childFrame.src = "extensionpage.html";
|
||||
document.body.appendChild(childFrame);
|
||||
}
|
||||
|
||||
function senderScript() {
|
||||
browser.runtime.sendMessage({blob: new Blob(["hello"])}).then(response => {
|
||||
browser.test.assertTrue(response.blob instanceof Blob, "Response is a blob");
|
||||
browser.test.notifyPass("sendBlob");
|
||||
});
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
background,
|
||||
files: {
|
||||
"senderScript.js": senderScript,
|
||||
"extensionpage.html": `<!DOCTYPE html><meta charset="utf-8"><script src="senderScript.js"></script>`,
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
await extension.awaitFinish("sendBlob");
|
||||
await extension.unload();
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче