зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1138886 - Structured Clone for MozNDEFRecord. r=smaug
From 9b1bdef0b25b41d0448662ec689a961ae4e8fcd2 Mon Sep 17 00:00:00 2001 --- dom/base/StructuredCloneTags.h | 2 + dom/base/nsJSEnvironment.cpp | 29 +++++++++ dom/nfc/MozNDEFRecord.cpp | 122 ++++++++++++++++++++++++++++++++++--- dom/nfc/MozNDEFRecord.h | 20 ++++-- js/xpconnect/src/ExportHelpers.cpp | 36 ++++++++++- 5 files changed, 193 insertions(+), 16 deletions(-)
This commit is contained in:
Родитель
e4ffc04ba5
Коммит
38c3210ae5
|
@ -39,6 +39,8 @@ enum StructuredCloneTags {
|
|||
SCTAG_DOM_SYSTEM_PRINCIPAL,
|
||||
SCTAG_DOM_CONTENT_PRINCIPAL,
|
||||
|
||||
SCTAG_DOM_NFC_NDEF,
|
||||
|
||||
SCTAG_DOM_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -59,6 +59,9 @@
|
|||
#include "mozilla/dom/ErrorEvent.h"
|
||||
#include "mozilla/dom/ImageDataBinding.h"
|
||||
#include "mozilla/dom/ImageData.h"
|
||||
#ifdef MOZ_NFC
|
||||
#include "mozilla/dom/MozNDEFRecord.h"
|
||||
#endif // MOZ_NFC
|
||||
#include "mozilla/dom/StructuredClone.h"
|
||||
#include "mozilla/dom/SubtleCryptoBinding.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
|
@ -2514,6 +2517,24 @@ NS_DOMReadStructuredClone(JSContext* cx,
|
|||
}
|
||||
|
||||
return result.toObjectOrNull();
|
||||
} else if (tag == SCTAG_DOM_NFC_NDEF) {
|
||||
#ifdef MOZ_NFC
|
||||
nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(cx));
|
||||
if (!global) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Prevent the return value from being trashed by a GC during ~nsRefPtr.
|
||||
JS::Rooted<JSObject*> result(cx);
|
||||
{
|
||||
nsRefPtr<MozNDEFRecord> ndefRecord = new MozNDEFRecord(global);
|
||||
result = ndefRecord->ReadStructuredClone(cx, reader) ?
|
||||
ndefRecord->WrapObject(cx) : nullptr;
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Don't know what this is. Bail.
|
||||
|
@ -2565,6 +2586,14 @@ NS_DOMWriteStructuredClone(JSContext* cx,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_NFC
|
||||
MozNDEFRecord* ndefRecord;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(MozNDEFRecord, obj, ndefRecord))) {
|
||||
return JS_WriteUint32Pair(writer, SCTAG_DOM_NFC_NDEF, 0) &&
|
||||
ndefRecord->WriteStructuredClone(cx, writer);
|
||||
}
|
||||
#endif // MOZ_NFC
|
||||
|
||||
// Don't know what this is
|
||||
xpc::Throw(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
return false;
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
/* Copyright © 2013 Deutsche Telekom, Inc. */
|
||||
|
||||
#include "MozNDEFRecord.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#include "mozilla/dom/MozNDEFRecordBinding.h"
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -18,13 +20,13 @@ namespace dom {
|
|||
NS_IMPL_CYCLE_COLLECTION_CLASS(MozNDEFRecord)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MozNDEFRecord)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
tmp->DropData();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MozNDEFRecord)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
@ -107,14 +109,14 @@ MozNDEFRecord::Constructor(const GlobalObject& aGlobal,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!win) {
|
||||
nsCOMPtr<nsISupports> parent = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!parent) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSContext* context = aGlobal.Context();
|
||||
nsRefPtr<MozNDEFRecord> ndefRecord = new MozNDEFRecord(win, aOptions.mTnf);
|
||||
nsRefPtr<MozNDEFRecord> ndefRecord = new MozNDEFRecord(parent, aOptions.mTnf);
|
||||
ndefRecord->InitType(context, aOptions.mType);
|
||||
ndefRecord->InitId(context, aOptions.mId);
|
||||
ndefRecord->InitPayload(context, aOptions.mPayload);
|
||||
|
@ -132,20 +134,20 @@ MozNDEFRecord::Constructor(const GlobalObject& aGlobal,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!win) {
|
||||
nsCOMPtr<nsISupports> parent = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!parent) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<MozNDEFRecord> ndefRecord = new MozNDEFRecord(win, TNF::Well_known);
|
||||
nsRefPtr<MozNDEFRecord> ndefRecord = new MozNDEFRecord(parent, TNF::Well_known);
|
||||
ndefRecord->InitType(aGlobal.Context(), RTD::U);
|
||||
ndefRecord->InitPayload(aGlobal.Context(), aUri);
|
||||
return ndefRecord.forget();
|
||||
}
|
||||
|
||||
MozNDEFRecord::MozNDEFRecord(nsPIDOMWindow* aWindow, TNF aTnf)
|
||||
: mWindow(aWindow) // For GetParentObject()
|
||||
MozNDEFRecord::MozNDEFRecord(nsISupports* aParent, TNF aTnf)
|
||||
: mParent(aParent) // For GetParentObject()
|
||||
, mTnf(aTnf)
|
||||
, mSize(3) // 1(flags) + 1(type_length) + 1(payload_length)
|
||||
{
|
||||
|
@ -181,6 +183,72 @@ MozNDEFRecord::GetAsURI(nsAString& aRetVal)
|
|||
nsDependentCSubstring(reinterpret_cast<char*>(&payloadData[1]), payloadLen - 1)));
|
||||
}
|
||||
|
||||
bool
|
||||
MozNDEFRecord::WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWriter) const
|
||||
{
|
||||
uint8_t* dummy;
|
||||
uint32_t typeLen = 0, idLen = 0, payloadLen = 0;
|
||||
if (mType) {
|
||||
js::GetUint8ArrayLengthAndData(mType, &typeLen, &dummy);
|
||||
}
|
||||
|
||||
if (mId) {
|
||||
js::GetUint8ArrayLengthAndData(mId, &idLen, &dummy);
|
||||
}
|
||||
|
||||
if (mPayload) {
|
||||
js::GetUint8ArrayLengthAndData(mPayload, &payloadLen, &dummy);
|
||||
}
|
||||
|
||||
return JS_WriteUint32Pair(aWriter, static_cast<uint32_t>(mTnf), typeLen) &&
|
||||
JS_WriteUint32Pair(aWriter, idLen, payloadLen) &&
|
||||
WriteUint8Array(aCx, aWriter, mType, typeLen) &&
|
||||
WriteUint8Array(aCx, aWriter, mId, idLen) &&
|
||||
WriteUint8Array(aCx, aWriter, mPayload, payloadLen);
|
||||
}
|
||||
|
||||
bool
|
||||
MozNDEFRecord::ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader)
|
||||
{
|
||||
uint32_t tnf, typeLen, idLen, payloadLen;
|
||||
|
||||
if (!JS_ReadUint32Pair(aReader, &tnf, &typeLen) ||
|
||||
!JS_ReadUint32Pair(aReader, &idLen, &payloadLen)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mTnf = static_cast<TNF>(tnf);
|
||||
|
||||
if (typeLen) {
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!JS_ReadTypedArray(aReader, &value)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(value.isObject());
|
||||
InitType(aCx, value.toObject(), typeLen);
|
||||
}
|
||||
|
||||
if (idLen) {
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!JS_ReadTypedArray(aReader, &value)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(value.isObject());
|
||||
InitId(aCx, value.toObject(), idLen);
|
||||
}
|
||||
|
||||
if (payloadLen) {
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!JS_ReadTypedArray(aReader, &value)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(value.isObject());
|
||||
InitPayload(aCx, value.toObject(), payloadLen);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MozNDEFRecord::InitType(JSContext* aCx, const Optional<Uint8Array>& aType)
|
||||
{
|
||||
|
@ -203,6 +271,13 @@ MozNDEFRecord::InitType(JSContext* aCx, RTD rtd)
|
|||
IncSize(rtdType.length);
|
||||
}
|
||||
|
||||
void
|
||||
MozNDEFRecord::InitType(JSContext* aCx, JSObject& aType, uint32_t aLen)
|
||||
{
|
||||
mType = &aType;
|
||||
IncSize(aLen);
|
||||
}
|
||||
|
||||
void
|
||||
MozNDEFRecord::InitId(JSContext* aCx, const Optional<Uint8Array>& aId)
|
||||
{
|
||||
|
@ -216,6 +291,13 @@ MozNDEFRecord::InitId(JSContext* aCx, const Optional<Uint8Array>& aId)
|
|||
IncSize(1 /* id_length */ + id.Length());
|
||||
}
|
||||
|
||||
void
|
||||
MozNDEFRecord::InitId(JSContext* aCx, JSObject& aId, uint32_t aLen)
|
||||
{
|
||||
mId = &aId;
|
||||
IncSize(1 /* id_length */ + aLen);
|
||||
}
|
||||
|
||||
void
|
||||
MozNDEFRecord::InitPayload(JSContext* aCx, const Optional<Uint8Array>& aPayload)
|
||||
{
|
||||
|
@ -246,6 +328,13 @@ MozNDEFRecord::InitPayload(JSContext* aCx, const nsAString& aUri)
|
|||
IncSizeForPayload(uri.Length() + 1);
|
||||
}
|
||||
|
||||
void
|
||||
MozNDEFRecord::InitPayload(JSContext* aCx, JSObject& aPayload, uint32_t aLen)
|
||||
{
|
||||
mPayload = &aPayload;
|
||||
IncSizeForPayload(aLen);
|
||||
}
|
||||
|
||||
void
|
||||
MozNDEFRecord::IncSize(uint32_t aCount)
|
||||
{
|
||||
|
@ -262,6 +351,19 @@ MozNDEFRecord::IncSizeForPayload(uint32_t aLen)
|
|||
IncSize(aLen);
|
||||
}
|
||||
|
||||
bool
|
||||
MozNDEFRecord::WriteUint8Array(JSContext* aCx, JSStructuredCloneWriter* aWriter, JSObject* aObj, uint32_t aLen) const
|
||||
{
|
||||
if (!aLen) {
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> obj(aCx, aObj);
|
||||
JSAutoCompartment ac(aCx, obj);
|
||||
JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*obj));
|
||||
return JS_WriteTypedArray(aWriter, value);
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
MozNDEFRecord::GetURIIdentifier(const nsCString& aUri)
|
||||
{
|
||||
|
|
|
@ -19,9 +19,11 @@
|
|||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "js/GCAPI.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsIGlobalObject;
|
||||
struct JSContext;
|
||||
struct JSStructuredCloneWriter;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -36,13 +38,13 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MozNDEFRecord)
|
||||
|
||||
public:
|
||||
MozNDEFRecord(nsPIDOMWindow* aWindow, TNF aTnf);
|
||||
MozNDEFRecord(nsISupports* aParent, TNF aTnf = TNF::Empty);
|
||||
|
||||
~MozNDEFRecord();
|
||||
|
||||
nsIDOMWindow* GetParentObject() const
|
||||
nsISupports* GetParentObject() const
|
||||
{
|
||||
return mWindow;
|
||||
return mParent;
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
@ -92,18 +94,26 @@ public:
|
|||
}
|
||||
|
||||
void GetAsURI(nsAString& aRetVal);
|
||||
|
||||
// Structured clone methods use these to clone MozNDEFRecord.
|
||||
bool WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWriter) const;
|
||||
bool ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader);
|
||||
private:
|
||||
MozNDEFRecord() = delete;
|
||||
nsRefPtr<nsPIDOMWindow> mWindow;
|
||||
nsRefPtr<nsISupports> mParent;
|
||||
void HoldData();
|
||||
void DropData();
|
||||
void InitType(JSContext* aCx, const Optional<Uint8Array>& aType);
|
||||
void InitType(JSContext* aCx, const RTD rtd);
|
||||
void InitType(JSContext* aCx, JSObject& aType, uint32_t aLen);
|
||||
void InitId(JSContext* aCx, const Optional<Uint8Array>& aId);
|
||||
void InitId(JSContext* aCx, JSObject& aId, uint32_t aLen);
|
||||
void InitPayload(JSContext* aCx, const Optional<Uint8Array>& aPayload);
|
||||
void InitPayload(JSContext* aCx, const nsAString& aUri);
|
||||
void InitPayload(JSContext* aCx, JSObject& aPayload, uint32_t aLen);
|
||||
void IncSize(uint32_t aCount);
|
||||
void IncSizeForPayload(uint32_t aLen);
|
||||
bool WriteUint8Array(JSContext* aCx, JSStructuredCloneWriter* aWriter, JSObject* aObj, uint32_t aLen) const;
|
||||
|
||||
static bool
|
||||
ValidateTNF(const MozNDEFRecordOptions& aOptions, ErrorResult& aRv);
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/BlobBinding.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#ifdef MOZ_NFC
|
||||
#include "mozilla/dom/MozNDEFRecord.h"
|
||||
#endif
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsIDOMFileList.h"
|
||||
|
@ -38,7 +41,8 @@ enum StackScopedCloneTags {
|
|||
SCTAG_BASE = JS_SCTAG_USER_MIN,
|
||||
SCTAG_REFLECTOR,
|
||||
SCTAG_BLOB,
|
||||
SCTAG_FUNCTION
|
||||
SCTAG_FUNCTION,
|
||||
SCTAG_DOM_NFC_NDEF
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS StackScopedCloneData {
|
||||
|
@ -121,6 +125,26 @@ StackScopedCloneRead(JSContext *cx, JSStructuredCloneReader *reader, uint32_t ta
|
|||
return val.toObjectOrNull();
|
||||
}
|
||||
|
||||
if (tag == SCTAG_DOM_NFC_NDEF) {
|
||||
#ifdef MOZ_NFC
|
||||
nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(cx));
|
||||
if (!global) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Prevent the return value from being trashed by a GC during ~nsRefPtr.
|
||||
JS::Rooted<JSObject*> result(cx);
|
||||
{
|
||||
nsRefPtr<MozNDEFRecord> ndefRecord = new MozNDEFRecord(global);
|
||||
result = ndefRecord->ReadStructuredClone(cx, reader) ?
|
||||
ndefRecord->WrapObject(cx) : nullptr;
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("Encountered garbage in the clone stream!");
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -192,6 +216,16 @@ StackScopedCloneWrite(JSContext *cx, JSStructuredCloneWriter *writer,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_NFC
|
||||
{
|
||||
MozNDEFRecord* ndefRecord;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(MozNDEFRecord, obj, ndefRecord))) {
|
||||
return JS_WriteUint32Pair(writer, SCTAG_DOM_NFC_NDEF, 0) &&
|
||||
ndefRecord->WriteStructuredClone(cx, writer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
JS_ReportError(cx, "Encountered unsupported value type writing stack-scoped structured clone");
|
||||
return false;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче