gecko-dev/dom/base/nsStructuredCloneContainer.cpp
Kan-Ru Chen 506dfe6ea3 Bug 1264642 - Part 4. Use BufferList to replace raw buffers in StructuredClone. r=baku r=billm r=jorendorff
In JS StructuredClone BufferList<SystemAllocPolicy> is typedef'd to
JSStructuredCloneData and use everywhere in gecko that stores structured
clone data.

This patch changed some raw pointers to UniquePtr<JSStructuredCloneData>
and some to stack allocated JSStructuredCloneData for better life time
management. Some parameters or methods are deleted because of changing
to the new data structure.

MessagePortMessage now has the exactly same structure with
ClonedMessageData. Maybe in the future they can be consolidated.

MozReview-Commit-ID: 1IY9p5eKLgv
2016-08-23 00:40:46 +08:00

180 lines
4.1 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsStructuredCloneContainer.h"
#include "nsCOMPtr.h"
#include "nsIGlobalObject.h"
#include "nsIVariant.h"
#include "nsIXPConnect.h"
#include "nsServiceManagerUtils.h"
#include "nsContentUtils.h"
#include "jsapi.h"
#include "xpcpublic.h"
#include "mozilla/Base64.h"
#include "mozilla/dom/ScriptSettings.h"
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_ADDREF(nsStructuredCloneContainer)
NS_IMPL_RELEASE(nsStructuredCloneContainer)
NS_INTERFACE_MAP_BEGIN(nsStructuredCloneContainer)
NS_INTERFACE_MAP_ENTRY(nsIStructuredCloneContainer)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
nsStructuredCloneContainer::nsStructuredCloneContainer()
: mVersion(0)
{
}
nsStructuredCloneContainer::~nsStructuredCloneContainer()
{
}
NS_IMETHODIMP
nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData,
JSContext* aCx)
{
if (DataLength()) {
return NS_ERROR_FAILURE;
}
ErrorResult rv;
Write(aCx, aData, rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
mVersion = JS_STRUCTURED_CLONE_VERSION;
return NS_OK;
}
NS_IMETHODIMP
nsStructuredCloneContainer::InitFromBase64(const nsAString &aData,
uint32_t aFormatVersion)
{
if (DataLength()) {
return NS_ERROR_FAILURE;
}
NS_ConvertUTF16toUTF8 data(aData);
nsAutoCString binaryData;
nsresult rv = Base64Decode(data, binaryData);
NS_ENSURE_SUCCESS(rv, rv);
if (!CopyExternalData(binaryData.get(), binaryData.Length())) {
return NS_ERROR_OUT_OF_MEMORY;
}
mVersion = aFormatVersion;
return NS_OK;
}
nsresult
nsStructuredCloneContainer::DeserializeToJsval(JSContext* aCx,
JS::MutableHandle<JS::Value> aValue)
{
aValue.setNull();
JS::Rooted<JS::Value> jsStateObj(aCx);
ErrorResult rv;
Read(aCx, &jsStateObj, rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
aValue.set(jsStateObj);
return NS_OK;
}
NS_IMETHODIMP
nsStructuredCloneContainer::DeserializeToVariant(JSContext* aCx,
nsIVariant** aData)
{
NS_ENSURE_ARG_POINTER(aData);
*aData = nullptr;
if (!DataLength()) {
return NS_ERROR_FAILURE;
}
// Deserialize to a JS::Value.
JS::Rooted<JS::Value> jsStateObj(aCx);
nsresult rv = DeserializeToJsval(aCx, &jsStateObj);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Now wrap the JS::Value as an nsIVariant.
nsCOMPtr<nsIVariant> varStateObj;
nsCOMPtr<nsIXPConnect> xpconnect = do_GetService(nsIXPConnect::GetCID());
NS_ENSURE_STATE(xpconnect);
xpconnect->JSValToVariant(aCx, jsStateObj, getter_AddRefs(varStateObj));
NS_ENSURE_STATE(varStateObj);
varStateObj.forget(aData);
return NS_OK;
}
NS_IMETHODIMP
nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut)
{
aOut.Truncate();
if (!DataLength()) {
return NS_ERROR_FAILURE;
}
if (HasClonedDOMObjects()) {
return NS_ERROR_FAILURE;
}
auto iter = Data().Iter();
size_t size = Data().Size();
nsAutoCString binaryData;
binaryData.SetLength(size);
Data().ReadBytes(iter, binaryData.BeginWriting(), size);
nsAutoCString base64Data;
nsresult rv = Base64Encode(binaryData, base64Data);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
CopyASCIItoUTF16(base64Data, aOut);
return NS_OK;
}
NS_IMETHODIMP
nsStructuredCloneContainer::GetSerializedNBytes(uint64_t* aSize)
{
NS_ENSURE_ARG_POINTER(aSize);
if (!DataLength()) {
return NS_ERROR_FAILURE;
}
*aSize = DataLength();
return NS_OK;
}
NS_IMETHODIMP
nsStructuredCloneContainer::GetFormatVersion(uint32_t* aFormatVersion)
{
NS_ENSURE_ARG_POINTER(aFormatVersion);
if (!DataLength()) {
return NS_ERROR_FAILURE;
}
*aFormatVersion = mVersion;
return NS_OK;
}