Bug 1201806 - part 2 - nsStructuredCloneContainer should use StructuredCloneIPCHelper, r=smaug

This commit is contained in:
Andrea Marchesini 2015-09-09 08:11:38 +01:00
parent 9f01064ca4
commit 2b83fc3f33
6 changed files with 75 additions and 122 deletions

View File

@ -171,28 +171,6 @@ public:
void MoveBufferDataToArray(FallibleTArray<uint8_t>& aArray,
ErrorResult& aRv);
// If you receive a buffer from IPC, you can use this method to retrieve a
// JS::Value. It can happen that you want to pre-populate the array of Blobs
// and/or the PortIdentifiers.
void ReadFromBuffer(nsISupports* aParent,
JSContext* aCx,
uint64_t* aBuffer,
size_t aBufferLength,
JS::MutableHandle<JS::Value> aValue,
ErrorResult &aRv);
void ReadFromBuffer(nsISupports* aParent,
JSContext* aCx,
uint64_t* aBuffer,
size_t aBufferLength,
uint32_t aAlgorithmVersion,
JS::MutableHandle<JS::Value> aValue,
ErrorResult &aRv);
// Use this method to free a buffer generated by MoveToBuffer().
void FreeBuffer(uint64_t* aBuffer,
size_t aBufferLength);
bool HasClonedDOMObjects() const
{
return !mBlobImplArray.IsEmpty() ||
@ -261,6 +239,28 @@ public:
void* aContent,
uint64_t aExtraData) override;
protected:
// If you receive a buffer from IPC, you can use this method to retrieve a
// JS::Value. It can happen that you want to pre-populate the array of Blobs
// and/or the PortIdentifiers.
void ReadFromBuffer(nsISupports* aParent,
JSContext* aCx,
uint64_t* aBuffer,
size_t aBufferLength,
JS::MutableHandle<JS::Value> aValue,
ErrorResult &aRv);
void ReadFromBuffer(nsISupports* aParent,
JSContext* aCx,
uint64_t* aBuffer,
size_t aBufferLength,
uint32_t aAlgorithmVersion,
JS::MutableHandle<JS::Value> aValue,
ErrorResult &aRv);
// Use this method to free a buffer generated by MoveToBuffer().
void FreeBuffer(uint64_t* aBuffer,
size_t aBufferLength);
bool mSupportsCloning;
bool mSupportsTransferring;
ContextSupport mContext;

View File

@ -16,7 +16,6 @@
#include "xpcpublic.h"
#include "mozilla/Base64.h"
#include "mozilla/dom/StructuredCloneHelper.h"
#include "mozilla/dom/ScriptSettings.h"
using namespace mozilla;
@ -31,24 +30,19 @@ NS_INTERFACE_MAP_BEGIN(nsStructuredCloneContainer)
NS_INTERFACE_MAP_END
nsStructuredCloneContainer::nsStructuredCloneContainer()
: StructuredCloneHelper(CloningSupported, TransferringNotSupported,
DifferentProcess)
, mState(eNotInitialized) , mData(nullptr), mSize(0), mVersion(0)
: mVersion(0)
{
}
nsStructuredCloneContainer::~nsStructuredCloneContainer()
{
if (mData) {
free(mData);
}
}
NS_IMETHODIMP
nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData,
JSContext* aCx)
{
if (mState != eNotInitialized) {
if (DataLength()) {
return NS_ERROR_FAILURE;
}
@ -58,7 +52,7 @@ nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData,
return rv.StealNSResult();
}
mState = eInitializedFromJSVal;
mVersion = JS_STRUCTURED_CLONE_VERSION;
return NS_OK;
}
@ -67,7 +61,7 @@ nsStructuredCloneContainer::InitFromBase64(const nsAString &aData,
uint32_t aFormatVersion,
JSContext* aCx)
{
if (mState != eNotInitialized) {
if (DataLength()) {
return NS_ERROR_FAILURE;
}
@ -77,15 +71,11 @@ nsStructuredCloneContainer::InitFromBase64(const nsAString &aData,
nsresult rv = Base64Decode(data, binaryData);
NS_ENSURE_SUCCESS(rv, rv);
// Copy the string's data into our own buffer.
mData = (uint64_t*) malloc(binaryData.Length());
NS_ENSURE_STATE(mData);
memcpy(mData, binaryData.get(), binaryData.Length());
if (!CopyExternalData(binaryData.get(), binaryData.Length())) {
return NS_ERROR_OUT_OF_MEMORY;
}
mSize = binaryData.Length();
mVersion = aFormatVersion;
mState = eInitializedFromBase64;
return NS_OK;
}
@ -96,21 +86,10 @@ nsStructuredCloneContainer::DeserializeToJsval(JSContext* aCx,
aValue.setNull();
JS::Rooted<JS::Value> jsStateObj(aCx);
if (mState == eInitializedFromJSVal) {
ErrorResult rv;
Read(nullptr, aCx, &jsStateObj, rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
} else {
MOZ_ASSERT(mState == eInitializedFromBase64);
MOZ_ASSERT(mData);
ErrorResult rv;
ReadFromBuffer(nullptr, aCx, mData, mSize, mVersion, &jsStateObj, rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
ErrorResult rv;
Read(aCx, &jsStateObj, rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
aValue.set(jsStateObj);
@ -124,7 +103,7 @@ nsStructuredCloneContainer::DeserializeToVariant(JSContext* aCx,
NS_ENSURE_ARG_POINTER(aData);
*aData = nullptr;
if (mState == eNotInitialized) {
if (!DataLength()) {
return NS_ERROR_FAILURE;
}
@ -151,29 +130,15 @@ nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut)
{
aOut.Truncate();
if (mState == eNotInitialized) {
if (!DataLength()) {
return NS_ERROR_FAILURE;
}
uint64_t* data;
size_t size;
if (mState == eInitializedFromJSVal) {
if (HasClonedDOMObjects()) {
return NS_ERROR_FAILURE;
}
data = BufferData();
size = BufferSize();
} else {
MOZ_ASSERT(mState == eInitializedFromBase64);
MOZ_ASSERT(mData);
data = mData;
size = mSize;
if (HasClonedDOMObjects()) {
return NS_ERROR_FAILURE;
}
nsAutoCString binaryData(reinterpret_cast<char*>(data), size);
nsAutoCString binaryData(reinterpret_cast<char*>(Data()), DataLength());
nsAutoCString base64Data;
nsresult rv = Base64Encode(binaryData, base64Data);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -189,22 +154,11 @@ nsStructuredCloneContainer::GetSerializedNBytes(uint64_t* aSize)
{
NS_ENSURE_ARG_POINTER(aSize);
if (mState == eNotInitialized) {
if (!DataLength()) {
return NS_ERROR_FAILURE;
}
if (mState == eInitializedFromJSVal) {
*aSize = BufferSize();
return NS_OK;
}
MOZ_ASSERT(mState == eInitializedFromBase64);
// mSize is a size_t, while aSize is a uint64_t. We rely on an implicit cast
// here so that we'll get a compile error if a size_t-to-uint64_t cast is
// narrowing.
*aSize = mSize;
*aSize = DataLength();
return NS_OK;
}
@ -213,16 +167,10 @@ nsStructuredCloneContainer::GetFormatVersion(uint32_t* aFormatVersion)
{
NS_ENSURE_ARG_POINTER(aFormatVersion);
if (mState == eNotInitialized) {
if (!DataLength()) {
return NS_ERROR_FAILURE;
}
if (mState == eInitializedFromJSVal) {
*aFormatVersion = JS_STRUCTURED_CLONE_VERSION;
return NS_OK;
}
MOZ_ASSERT(mState == eInitializedFromBase64);
*aFormatVersion = mVersion;
return NS_OK;
}

View File

@ -9,7 +9,7 @@
#include "nsIStructuredCloneContainer.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/StructuredCloneHelper.h"
#include "mozilla/dom/StructuredCloneIPCHelper.h"
#define NS_STRUCTUREDCLONECONTAINER_CONTRACTID \
"@mozilla.org/docshell/structured-clone-container;1"
@ -23,7 +23,7 @@
class nsStructuredCloneContainer final
: public nsIStructuredCloneContainer
, public mozilla::dom::StructuredCloneHelper
, public mozilla::dom::StructuredCloneIPCHelper
{
public:
nsStructuredCloneContainer();
@ -34,16 +34,6 @@ class nsStructuredCloneContainer final
private:
~nsStructuredCloneContainer();
enum {
eNotInitialized = 0,
eInitializedFromJSVal,
eInitializedFromBase64,
} mState;
uint64_t* mData;
// This needs to be size_t rather than a PR-type so it matches the JS API.
size_t mSize;
uint32_t mVersion;
};

View File

@ -11,7 +11,7 @@
#include "mozilla/dom/File.h"
#include "mozilla/dom/MessageEvent.h"
#include "mozilla/dom/MessageEventBinding.h"
#include "mozilla/dom/StructuredCloneHelper.h"
#include "mozilla/dom/StructuredCloneIPCHelper.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerScope.h"
#include "mozilla/dom/ScriptSettings.h"
@ -85,19 +85,17 @@ BroadcastChannelChild::RecvNotify(const ClonedMessageData& aData)
return true;
}
JSContext* cx = jsapi.cx();
const SerializedStructuredCloneBuffer& buffer = aData.data();
StructuredCloneHelper cloneHelper(StructuredCloneHelper::CloningSupported,
StructuredCloneHelper::TransferringNotSupported,
StructuredCloneHelper::DifferentProcess);
StructuredCloneIPCHelper cloneHelper;
cloneHelper.BlobImpls().AppendElements(blobs);
const SerializedStructuredCloneBuffer& buffer = aData.data();
cloneHelper.UseExternalData(buffer.data, buffer.dataLength);
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> value(cx, JS::NullValue());
if (buffer.dataLength) {
ErrorResult rv;
cloneHelper.ReadFromBuffer(mBC->GetParentObject(), cx,
buffer.data, buffer.dataLength, &value, rv);
cloneHelper.Read(cx, &value, rv);
if (NS_WARN_IF(rv.Failed())) {
return true;
}

View File

@ -30,7 +30,7 @@ StructuredCloneIPCHelper::Copy(const StructuredCloneIPCHelper& aHelper)
return true;
}
uint64_t* data = static_cast<uint64_t*>(malloc(aHelper.mDataLength));
uint64_t* data = static_cast<uint64_t*>(js_malloc(aHelper.mDataLength));
if (!data) {
return false;
}
@ -39,7 +39,7 @@ StructuredCloneIPCHelper::Copy(const StructuredCloneIPCHelper& aHelper)
mData = data;
mDataLength = aHelper.mDataLength;
mDataOwned = eAllocated;
mDataOwned = eJSAllocated;
MOZ_ASSERT(BlobImpls().IsEmpty());
BlobImpls().AppendElements(aHelper.BlobImpls());
@ -122,5 +122,23 @@ StructuredCloneIPCHelper::ReadIPCParams(const IPC::Message* aMsg,
return true;
}
bool
StructuredCloneIPCHelper::CopyExternalData(const void* aData,
size_t aDataLength)
{
MOZ_ASSERT(!mData);
uint64_t* data = static_cast<uint64_t*>(js_malloc(aDataLength));
if (!data) {
return false;
}
memcpy(data, aData, aDataLength);
mData = data;
mDataLength = aDataLength;
mDataOwned = eJSAllocated;
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -16,7 +16,7 @@ class Message;
namespace mozilla {
namespace dom {
class StructuredCloneIPCHelper final : public StructuredCloneHelper
class StructuredCloneIPCHelper : public StructuredCloneHelper
{
public:
StructuredCloneIPCHelper()
@ -32,9 +32,7 @@ public:
~StructuredCloneIPCHelper()
{
if (mDataOwned == eAllocated) {
free(mData);
} else if (mDataOwned == eJSAllocated) {
if (mDataOwned == eJSAllocated) {
js_free(mData);
}
}
@ -70,6 +68,8 @@ public:
MOZ_ASSERT(mDataOwned == eNone);
}
bool CopyExternalData(const void* aData, size_t aDataLength);
uint64_t* Data() const
{
return mData;
@ -89,8 +89,7 @@ private:
size_t mDataLength;
enum {
eNone,
eAllocated,
eJSAllocated
eJSAllocated,
} mDataOwned;
};