mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset f6d29009ae0a (bug 1184557) for crashes in fetch-csp.https.html web platform tests CLOSED TREE
This commit is contained in:
parent
3f571178bb
commit
5419f7038e
@ -23,6 +23,246 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace {
|
||||
|
||||
struct StructuredCloneInfo
|
||||
{
|
||||
PostMessageEvent* event;
|
||||
nsPIDOMWindow* window;
|
||||
|
||||
// This hashtable contains the transferred ports - used to avoid duplicates.
|
||||
nsTArray<nsRefPtr<MessagePortBase>> transferredPorts;
|
||||
|
||||
// This array is populated when the ports are cloned.
|
||||
nsTArray<nsRefPtr<MessagePortBase>> clonedPorts;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
const JSStructuredCloneCallbacks PostMessageEvent::sPostMessageCallbacks = {
|
||||
PostMessageEvent::ReadStructuredClone,
|
||||
PostMessageEvent::WriteStructuredClone,
|
||||
nullptr,
|
||||
PostMessageEvent::ReadTransferStructuredClone,
|
||||
PostMessageEvent::TransferStructuredClone,
|
||||
PostMessageEvent::FreeTransferStructuredClone
|
||||
};
|
||||
|
||||
/* static */ JSObject*
|
||||
PostMessageEvent::ReadStructuredClone(JSContext* cx,
|
||||
JSStructuredCloneReader* reader,
|
||||
uint32_t tag,
|
||||
uint32_t data,
|
||||
void* closure)
|
||||
{
|
||||
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
|
||||
NS_ASSERTION(scInfo, "Must have scInfo!");
|
||||
|
||||
if (tag == SCTAG_DOM_BLOB) {
|
||||
NS_ASSERTION(!data, "Data should be empty");
|
||||
|
||||
// What we get back from the reader is a BlobImpl.
|
||||
// From that we create a new File.
|
||||
BlobImpl* blobImpl;
|
||||
if (JS_ReadBytes(reader, &blobImpl, sizeof(blobImpl))) {
|
||||
MOZ_ASSERT(blobImpl);
|
||||
|
||||
// nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
|
||||
// called because the static analysis thinks dereferencing XPCOM objects
|
||||
// can GC (because in some cases it can!), and a return statement with a
|
||||
// JSObject* type means that JSObject* is on the stack as a raw pointer
|
||||
// while destructors are running.
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
{
|
||||
nsRefPtr<Blob> blob = Blob::Create(scInfo->window, blobImpl);
|
||||
if (!ToJSValue(cx, blob, &val)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return &val.toObject();
|
||||
}
|
||||
}
|
||||
|
||||
if (tag == SCTAG_DOM_FILELIST) {
|
||||
NS_ASSERTION(!data, "Data should be empty");
|
||||
|
||||
// What we get back from the reader is a FileListClonedData.
|
||||
// From that we create a new FileList.
|
||||
FileListClonedData* fileListClonedData;
|
||||
if (JS_ReadBytes(reader, &fileListClonedData, sizeof(fileListClonedData))) {
|
||||
MOZ_ASSERT(fileListClonedData);
|
||||
|
||||
// nsRefPtr<FileList> needs to go out of scope before toObjectOrNull() is
|
||||
// called because the static analysis thinks dereferencing XPCOM objects
|
||||
// can GC (because in some cases it can!), and a return statement with a
|
||||
// JSObject* type means that JSObject* is on the stack as a raw pointer
|
||||
// while destructors are running.
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
{
|
||||
nsRefPtr<FileList> fileList =
|
||||
FileList::Create(scInfo->window, fileListClonedData);
|
||||
if (!fileList || !ToJSValue(cx, fileList, &val)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return &val.toObject();
|
||||
}
|
||||
}
|
||||
|
||||
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
||||
js::GetContextStructuredCloneCallbacks(cx);
|
||||
|
||||
if (runtimeCallbacks) {
|
||||
return runtimeCallbacks->read(cx, reader, tag, data, nullptr);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
PostMessageEvent::WriteStructuredClone(JSContext* cx,
|
||||
JSStructuredCloneWriter* writer,
|
||||
JS::Handle<JSObject*> obj,
|
||||
void *closure)
|
||||
{
|
||||
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
|
||||
NS_ASSERTION(scInfo, "Must have scInfo!");
|
||||
|
||||
// See if this is a File/Blob object.
|
||||
{
|
||||
Blob* blob = nullptr;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, obj, blob))) {
|
||||
BlobImpl* blobImpl = blob->Impl();
|
||||
if (JS_WriteUint32Pair(writer, SCTAG_DOM_BLOB, 0) &&
|
||||
JS_WriteBytes(writer, &blobImpl, sizeof(blobImpl))) {
|
||||
scInfo->event->StoreISupports(blobImpl);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if this is a FileList object.
|
||||
{
|
||||
FileList* fileList = nullptr;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(FileList, obj, fileList))) {
|
||||
nsRefPtr<FileListClonedData> fileListClonedData =
|
||||
fileList->CreateClonedData();
|
||||
MOZ_ASSERT(fileListClonedData);
|
||||
FileListClonedData* ptr = fileListClonedData.get();
|
||||
if (JS_WriteUint32Pair(writer, SCTAG_DOM_FILELIST, 0) &&
|
||||
JS_WriteBytes(writer, &ptr, sizeof(ptr))) {
|
||||
scInfo->event->StoreISupports(fileListClonedData);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
||||
js::GetContextStructuredCloneCallbacks(cx);
|
||||
|
||||
if (runtimeCallbacks) {
|
||||
return runtimeCallbacks->write(cx, writer, obj, nullptr);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
PostMessageEvent::ReadTransferStructuredClone(JSContext* aCx,
|
||||
JSStructuredCloneReader* reader,
|
||||
uint32_t tag, void* aData,
|
||||
uint64_t aExtraData,
|
||||
void* aClosure,
|
||||
JS::MutableHandle<JSObject*> returnObject)
|
||||
{
|
||||
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
|
||||
NS_ASSERTION(scInfo, "Must have scInfo!");
|
||||
|
||||
if (tag == SCTAG_DOM_MAP_MESSAGEPORT) {
|
||||
MOZ_ASSERT(!aData);
|
||||
// aExtraData is the index of this port identifier.
|
||||
ErrorResult rv;
|
||||
nsRefPtr<MessagePort> port =
|
||||
MessagePort::Create(scInfo->window,
|
||||
scInfo->event->GetPortIdentifier(aExtraData),
|
||||
rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scInfo->clonedPorts.AppendElement(port);
|
||||
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!GetOrCreateDOMReflector(aCx, port, &value)) {
|
||||
JS_ClearPendingException(aCx);
|
||||
return false;
|
||||
}
|
||||
|
||||
returnObject.set(&value.toObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
PostMessageEvent::TransferStructuredClone(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
void* aClosure,
|
||||
uint32_t* aTag,
|
||||
JS::TransferableOwnership* aOwnership,
|
||||
void** aContent,
|
||||
uint64_t* aExtraData)
|
||||
{
|
||||
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
|
||||
NS_ASSERTION(scInfo, "Must have scInfo!");
|
||||
|
||||
MessagePortBase* port = nullptr;
|
||||
nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (scInfo->transferredPorts.Contains(port)) {
|
||||
// No duplicates.
|
||||
return false;
|
||||
}
|
||||
|
||||
// We use aExtraData to store the index of this new port identifier.
|
||||
MessagePortIdentifier* identifier =
|
||||
scInfo->event->NewPortIdentifier(aExtraData);
|
||||
|
||||
if (!port->CloneAndDisentangle(*identifier)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scInfo->transferredPorts.AppendElement(port);
|
||||
|
||||
*aTag = SCTAG_DOM_MAP_MESSAGEPORT;
|
||||
*aOwnership = JS::SCTAG_TMO_CUSTOM;
|
||||
*aContent = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PostMessageEvent::FreeTransferStructuredClone(uint32_t aTag,
|
||||
JS::TransferableOwnership aOwnership,
|
||||
void *aContent,
|
||||
uint64_t aExtraData,
|
||||
void* aClosure)
|
||||
{
|
||||
if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
|
||||
MOZ_ASSERT(aClosure);
|
||||
MOZ_ASSERT(!aContent);
|
||||
|
||||
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
|
||||
MessagePort::ForceClose(scInfo->event->GetPortIdentifier(aExtraData));
|
||||
}
|
||||
}
|
||||
|
||||
PostMessageEvent::PostMessageEvent(nsGlobalWindow* aSource,
|
||||
const nsAString& aCallerOrigin,
|
||||
nsGlobalWindow* aTargetWindow,
|
||||
@ -42,6 +282,20 @@ PostMessageEvent::~PostMessageEvent()
|
||||
MOZ_COUNT_DTOR(PostMessageEvent);
|
||||
}
|
||||
|
||||
const MessagePortIdentifier&
|
||||
PostMessageEvent::GetPortIdentifier(uint64_t aId)
|
||||
{
|
||||
MOZ_ASSERT(aId < mPortIdentifiers.Length());
|
||||
return mPortIdentifiers[aId];
|
||||
}
|
||||
|
||||
MessagePortIdentifier*
|
||||
PostMessageEvent::NewPortIdentifier(uint64_t* aPosition)
|
||||
{
|
||||
*aPosition = mPortIdentifiers.Length();
|
||||
return mPortIdentifiers.AppendElement();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PostMessageEvent::Run()
|
||||
{
|
||||
@ -93,9 +347,13 @@ PostMessageEvent::Run()
|
||||
}
|
||||
}
|
||||
|
||||
// Deserialize the structured clone data
|
||||
JS::Rooted<JS::Value> messageData(cx);
|
||||
nsCOMPtr<nsPIDOMWindow> window = targetWindow.get();
|
||||
if (!Read(window, cx, &messageData)) {
|
||||
StructuredCloneInfo scInfo;
|
||||
scInfo.event = this;
|
||||
scInfo.window = targetWindow;
|
||||
|
||||
if (!mBuffer.read(cx, &messageData, &sPostMessageCallbacks, &scInfo)) {
|
||||
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
}
|
||||
|
||||
@ -110,7 +368,7 @@ PostMessageEvent::Run()
|
||||
EmptyString(), mSource);
|
||||
|
||||
event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()),
|
||||
GetTransferredPorts()));
|
||||
scInfo.clonedPorts));
|
||||
|
||||
// We can't simply call dispatchEvent on the window because doing so ends
|
||||
// up flipping the trusted bit on the event, and we don't want that to
|
||||
@ -134,5 +392,19 @@ PostMessageEvent::Run()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
PostMessageEvent::Write(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
JS::Handle<JS::Value> aTransfer, nsPIDOMWindow* aWindow)
|
||||
{
|
||||
// We *must* clone the data here, or the JS::Value could be modified
|
||||
// by script
|
||||
StructuredCloneInfo scInfo;
|
||||
scInfo.event = this;
|
||||
scInfo.window = aWindow;
|
||||
|
||||
return mBuffer.write(aCx, aMessage, aTransfer, &sPostMessageCallbacks,
|
||||
&scInfo);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -7,7 +7,7 @@
|
||||
#ifndef mozilla_dom_PostMessageEvent_h
|
||||
#define mozilla_dom_PostMessageEvent_h
|
||||
|
||||
#include "mozilla/dom/StructuredCloneHelper.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsTArray.h"
|
||||
@ -28,7 +28,6 @@ class MessagePortIdentifier;
|
||||
* which asynchronously creates and dispatches events.
|
||||
*/
|
||||
class PostMessageEvent final : public nsRunnable
|
||||
, public StructuredCloneHelper
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
@ -39,14 +38,69 @@ public:
|
||||
nsIPrincipal* aProvidedPrincipal,
|
||||
bool aTrustedCaller);
|
||||
|
||||
bool Write(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
JS::Handle<JS::Value> aTransfer, nsPIDOMWindow* aWindow);
|
||||
|
||||
private:
|
||||
~PostMessageEvent();
|
||||
|
||||
const MessagePortIdentifier& GetPortIdentifier(uint64_t aId);
|
||||
|
||||
MessagePortIdentifier* NewPortIdentifier(uint64_t* aPosition);
|
||||
|
||||
bool StoreISupports(nsISupports* aSupports)
|
||||
{
|
||||
mSupportsArray.AppendElement(aSupports);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
ReadStructuredClone(JSContext* cx,
|
||||
JSStructuredCloneReader* reader,
|
||||
uint32_t tag,
|
||||
uint32_t data,
|
||||
void* closure);
|
||||
|
||||
static bool
|
||||
WriteStructuredClone(JSContext* cx,
|
||||
JSStructuredCloneWriter* writer,
|
||||
JS::Handle<JSObject*> obj,
|
||||
void *closure);
|
||||
|
||||
static bool
|
||||
ReadTransferStructuredClone(JSContext* aCx,
|
||||
JSStructuredCloneReader* reader,
|
||||
uint32_t tag, void* aData,
|
||||
uint64_t aExtraData,
|
||||
void* aClosure,
|
||||
JS::MutableHandle<JSObject*> returnObject);
|
||||
|
||||
static bool
|
||||
TransferStructuredClone(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
void* aClosure,
|
||||
uint32_t* aTag,
|
||||
JS::TransferableOwnership* aOwnership,
|
||||
void** aContent,
|
||||
uint64_t* aExtraData);
|
||||
|
||||
static void
|
||||
FreeTransferStructuredClone(uint32_t aTag,
|
||||
JS::TransferableOwnership aOwnership,
|
||||
void *aContent,
|
||||
uint64_t aExtraData,
|
||||
void* aClosure);
|
||||
|
||||
static const JSStructuredCloneCallbacks sPostMessageCallbacks;
|
||||
|
||||
JSAutoStructuredCloneBuffer mBuffer;
|
||||
nsRefPtr<nsGlobalWindow> mSource;
|
||||
nsString mCallerOrigin;
|
||||
nsRefPtr<nsGlobalWindow> mTargetWindow;
|
||||
nsCOMPtr<nsIPrincipal> mProvidedPrincipal;
|
||||
bool mTrustedCaller;
|
||||
nsTArray<nsCOMPtr<nsISupports>> mSupportsArray;
|
||||
nsTArray<MessagePortIdentifier> mPortIdentifiers;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -6,10 +6,6 @@
|
||||
|
||||
#include "StructuredCloneHelper.h"
|
||||
|
||||
#include "mozilla/dom/BlobBinding.h"
|
||||
#include "mozilla/dom/FileListBinding.h"
|
||||
#include "mozilla/dom/StructuredCloneTags.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@ -103,8 +99,6 @@ const JSStructuredCloneCallbacks gCallbacks = {
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// StructuredCloneHelperInternal class
|
||||
|
||||
bool
|
||||
StructuredCloneHelperInternal::Write(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue)
|
||||
@ -115,17 +109,6 @@ StructuredCloneHelperInternal::Write(JSContext* aCx,
|
||||
return mBuffer->write(aCx, aValue, &gCallbacks, this);
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneHelperInternal::Write(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aTransfer)
|
||||
{
|
||||
MOZ_ASSERT(!mBuffer, "Double Write is not allowed");
|
||||
|
||||
mBuffer = new JSAutoStructuredCloneBuffer(&gCallbacks, this);
|
||||
return mBuffer->write(aCx, aValue, aTransfer, &gCallbacks, this);
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneHelperInternal::Read(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
@ -149,6 +132,7 @@ StructuredCloneHelperInternal::ReadTransferCallback(JSContext* aCx,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
StructuredCloneHelperInternal::WriteTransferCallback(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
@ -170,220 +154,5 @@ StructuredCloneHelperInternal::FreeTransferCallback(uint32_t aTag,
|
||||
MOZ_CRASH("Nothing to free.");
|
||||
}
|
||||
|
||||
// StructuredCloneHelper class
|
||||
|
||||
StructuredCloneHelper::StructuredCloneHelper(uint32_t aFlags)
|
||||
: mFlags(aFlags)
|
||||
, mParent(nullptr)
|
||||
{}
|
||||
|
||||
StructuredCloneHelper::~StructuredCloneHelper()
|
||||
{}
|
||||
|
||||
bool
|
||||
StructuredCloneHelper::Write(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aTransfer)
|
||||
{
|
||||
bool ok = StructuredCloneHelperInternal::Write(aCx, aValue, aTransfer);
|
||||
mTransferringPort.Clear();
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneHelper::Read(nsISupports* aParent,
|
||||
JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
mozilla::AutoRestore<nsISupports*> guard(mParent);
|
||||
mParent = aParent;
|
||||
|
||||
return StructuredCloneHelperInternal::Read(aCx, aValue);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
StructuredCloneHelper::ReadCallback(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
uint32_t aIndex)
|
||||
{
|
||||
if (aTag == SCTAG_DOM_BLOB) {
|
||||
MOZ_ASSERT(!(mFlags & eBlobNotSupported));
|
||||
|
||||
BlobImpl* blobImpl;
|
||||
if (JS_ReadBytes(aReader, &blobImpl, sizeof(blobImpl))) {
|
||||
MOZ_ASSERT(blobImpl);
|
||||
|
||||
// nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
|
||||
// called because the static analysis thinks dereferencing XPCOM objects
|
||||
// can GC (because in some cases it can!), and a return statement with a
|
||||
// JSObject* type means that JSObject* is on the stack as a raw pointer
|
||||
// while destructors are running.
|
||||
JS::Rooted<JS::Value> val(aCx);
|
||||
{
|
||||
nsRefPtr<Blob> blob = Blob::Create(mParent, blobImpl);
|
||||
if (!ToJSValue(aCx, blob, &val)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return &val.toObject();
|
||||
}
|
||||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_FILELIST) {
|
||||
MOZ_ASSERT(!(mFlags & eFileListNotSupported));
|
||||
|
||||
FileListClonedData* fileListClonedData;
|
||||
if (JS_ReadBytes(aReader, &fileListClonedData,
|
||||
sizeof(fileListClonedData))) {
|
||||
MOZ_ASSERT(fileListClonedData);
|
||||
|
||||
// nsRefPtr<FileList> needs to go out of scope before toObjectOrNull() is
|
||||
// called because the static analysis thinks dereferencing XPCOM objects
|
||||
// can GC (because in some cases it can!), and a return statement with a
|
||||
// JSObject* type means that JSObject* is on the stack as a raw pointer
|
||||
// while destructors are running.
|
||||
JS::Rooted<JS::Value> val(aCx);
|
||||
{
|
||||
nsRefPtr<FileList> fileList =
|
||||
FileList::Create(mParent, fileListClonedData);
|
||||
if (!fileList || !ToJSValue(aCx, fileList, &val)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return &val.toObject();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_DOMReadStructuredClone(aCx, aReader, aTag, aIndex, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneHelper::WriteCallback(JSContext* aCx,
|
||||
JSStructuredCloneWriter* aWriter,
|
||||
JS::Handle<JSObject*> aObj)
|
||||
{
|
||||
// See if this is a File/Blob object.
|
||||
if (!(mFlags & eBlobNotSupported)) {
|
||||
Blob* blob = nullptr;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob))) {
|
||||
BlobImpl* blobImpl = blob->Impl();
|
||||
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB, 0) &&
|
||||
JS_WriteBytes(aWriter, &blobImpl, sizeof(blobImpl)) &&
|
||||
StoreISupports(blobImpl);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(mFlags & eFileListNotSupported)) {
|
||||
FileList* fileList = nullptr;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(FileList, aObj, fileList))) {
|
||||
nsRefPtr<FileListClonedData> fileListClonedData =
|
||||
fileList->CreateClonedData();
|
||||
MOZ_ASSERT(fileListClonedData);
|
||||
FileListClonedData* ptr = fileListClonedData.get();
|
||||
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILELIST, 0) &&
|
||||
JS_WriteBytes(aWriter, &ptr, sizeof(ptr)) &&
|
||||
StoreISupports(fileListClonedData);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneHelper::ReadTransferCallback(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
void* aContent,
|
||||
uint64_t aExtraData,
|
||||
JS::MutableHandleObject aReturnObject)
|
||||
{
|
||||
if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
|
||||
MOZ_ASSERT(!(mFlags & eMessagePortNotSupported));
|
||||
|
||||
// This can be null.
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mParent);
|
||||
|
||||
MOZ_ASSERT(aExtraData < mPortIdentifiers.Length());
|
||||
const MessagePortIdentifier& portIdentifier = mPortIdentifiers[aExtraData];
|
||||
|
||||
// aExtraData is the index of this port identifier.
|
||||
ErrorResult rv;
|
||||
nsRefPtr<MessagePort> port =
|
||||
MessagePort::Create(window, portIdentifier, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mTransferredPorts.AppendElement(port);
|
||||
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!GetOrCreateDOMReflector(aCx, port, &value)) {
|
||||
JS_ClearPendingException(aCx);
|
||||
return false;
|
||||
}
|
||||
|
||||
aReturnObject.set(&value.toObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
StructuredCloneHelper::WriteTransferCallback(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
uint32_t* aTag,
|
||||
JS::TransferableOwnership* aOwnership,
|
||||
void** aContent,
|
||||
uint64_t* aExtraData)
|
||||
{
|
||||
if (!(mFlags & eMessagePortNotSupported)) {
|
||||
MessagePortBase* port = nullptr;
|
||||
nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (mTransferringPort.Contains(port)) {
|
||||
// No duplicates.
|
||||
return false;
|
||||
}
|
||||
|
||||
// We use aExtraData to store the index of this new port identifier.
|
||||
*aExtraData = mPortIdentifiers.Length();
|
||||
MessagePortIdentifier* identifier = mPortIdentifiers.AppendElement();
|
||||
|
||||
if (!port->CloneAndDisentangle(*identifier)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mTransferringPort.AppendElement(port);
|
||||
|
||||
*aTag = SCTAG_DOM_MAP_MESSAGEPORT;
|
||||
*aOwnership = JS::SCTAG_TMO_CUSTOM;
|
||||
*aContent = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
StructuredCloneHelper::FreeTransferCallback(uint32_t aTag,
|
||||
JS::TransferableOwnership aOwnership,
|
||||
void* aContent,
|
||||
uint64_t aExtraData)
|
||||
{
|
||||
if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
|
||||
MOZ_ASSERT(!(mFlags & eMessagePortNotSupported));
|
||||
MOZ_ASSERT(!aContent);
|
||||
MOZ_ASSERT(aExtraData < mPortIdentifiers.Length());
|
||||
MessagePort::ForceClose(mPortIdentifiers[aExtraData]);
|
||||
}
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include "js/StructuredClone.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -71,109 +69,6 @@ protected:
|
||||
nsAutoPtr<JSAutoStructuredCloneBuffer> mBuffer;
|
||||
};
|
||||
|
||||
class MessagePortBase;
|
||||
class MessagePortIdentifier;
|
||||
|
||||
class StructuredCloneHelper : public StructuredCloneHelperInternal
|
||||
{
|
||||
public:
|
||||
enum StructuredCloneHelperFlags {
|
||||
eAll = 0,
|
||||
|
||||
// Disable the cloning of blobs. If a blob is part of the cloning value,
|
||||
// an exception will be thrown.
|
||||
eBlobNotSupported = 1 << 0,
|
||||
|
||||
// Disable the cloning of FileLists. If a FileList is part of the cloning
|
||||
// value, an exception will be thrown.
|
||||
eFileListNotSupported = 1 << 1,
|
||||
|
||||
// MessagePort can just be transfered. Using this flag we do not support
|
||||
// the transfering.
|
||||
eMessagePortNotSupported = 1 << 2,
|
||||
};
|
||||
|
||||
// aFlags is a bitmap of StructuredCloneHelperFlags.
|
||||
explicit StructuredCloneHelper(uint32_t aFlags = eAll);
|
||||
virtual ~StructuredCloneHelper();
|
||||
|
||||
bool Write(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aTransfer);
|
||||
|
||||
bool Read(nsISupports* aParent,
|
||||
JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
|
||||
nsTArray<nsRefPtr<MessagePortBase>>& GetTransferredPorts()
|
||||
{
|
||||
MOZ_ASSERT(!(mFlags & eMessagePortNotSupported));
|
||||
return mTransferredPorts;
|
||||
}
|
||||
|
||||
// Custom Callbacks
|
||||
|
||||
virtual JSObject* ReadCallback(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
uint32_t aIndex) override;
|
||||
|
||||
virtual bool WriteCallback(JSContext* aCx,
|
||||
JSStructuredCloneWriter* aWriter,
|
||||
JS::Handle<JSObject*> aObj) override;
|
||||
|
||||
virtual bool ReadTransferCallback(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
void* aContent,
|
||||
uint64_t aExtraData,
|
||||
JS::MutableHandleObject aReturnObject) override;
|
||||
|
||||
virtual bool WriteTransferCallback(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
uint32_t* aTag,
|
||||
JS::TransferableOwnership* aOwnership,
|
||||
void** aContent,
|
||||
uint64_t* aExtraData) override;
|
||||
|
||||
virtual void FreeTransferCallback(uint32_t aTag,
|
||||
JS::TransferableOwnership aOwnership,
|
||||
void* aContent,
|
||||
uint64_t aExtraData) override;
|
||||
private:
|
||||
bool StoreISupports(nsISupports* aSupports)
|
||||
{
|
||||
MOZ_ASSERT(aSupports);
|
||||
mSupportsArray.AppendElement(aSupports);
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is our bitmap.
|
||||
uint32_t mFlags;
|
||||
|
||||
// Useful for the structured clone algorithm:
|
||||
|
||||
nsTArray<nsCOMPtr<nsISupports>> mSupportsArray;
|
||||
|
||||
// This raw pointer is set and unset into the ::Read(). It's always null
|
||||
// outside that method. For this reason it's a raw pointer.
|
||||
nsISupports* MOZ_NON_OWNING_REF mParent;
|
||||
|
||||
// This hashtable contains the ports while doing write (transferring and
|
||||
// mapping transferred objects to the objects in the clone). It's an empty
|
||||
// array outside the 'Write()' method.
|
||||
nsTArray<nsRefPtr<MessagePortBase>> mTransferringPort;
|
||||
|
||||
// This array contains the ports once we've finished the reading. It's
|
||||
// generated from the mPortIdentifiers array.
|
||||
nsTArray<nsRefPtr<MessagePortBase>> mTransferredPorts;
|
||||
|
||||
// This array contains the identifiers of the MessagePorts. Based on these we
|
||||
// are able to reconnect the new transferred ports with the other
|
||||
// MessageChannel ports.
|
||||
nsTArray<MessagePortIdentifier> mPortIdentifiers;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
|
@ -8564,7 +8564,7 @@ nsGlobalWindow::PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessa
|
||||
JS::Rooted<JS::Value> message(aCx, aMessage);
|
||||
JS::Rooted<JS::Value> transfer(aCx, aTransfer);
|
||||
|
||||
if (!event->Write(aCx, message, transfer)) {
|
||||
if (!event->Write(aCx, message, transfer, this)) {
|
||||
aError.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user