Skip to content

Commit

Permalink
[embedlite] Fix (de)serialization of JSON messages. Fixes JB#37190
Browse files Browse the repository at this point in the history
Not an optimal fix but pipeline should be now there.
  • Loading branch information
rainemak committed Dec 17, 2018
1 parent 9f175ec commit 689d46d
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 41 deletions.
Expand Up @@ -331,7 +331,7 @@ EmbedLiteViewBaseParent::RecvSyncMessage(const nsString& aMessage,

NS_ENSURE_TRUE(mView, false);
char* retval = mView->GetListener()->RecvSyncMessage(aMessage.get(), aJSON.get());
if (retval) {
if (retval && aJSONRetVal) {
aJSONRetVal->AppendElement(NS_ConvertUTF8toUTF16(nsDependentCString(retval)));
delete retval;
}
Expand Down
44 changes: 18 additions & 26 deletions embedding/embedlite/modules/EmbedLiteJSON.cpp
Expand Up @@ -10,10 +10,12 @@
#include "EmbedLiteAppService.h"
#include "nsServiceManagerUtils.h"
#include "js/Value.h"
#include "jsapi.h"
#include "xpcprivate.h"
#include "nsJSUtils.h"
#include "nsDOMJSUtils.h"
#include "nsContentUtils.h"
#include "nsISimpleEnumerator.h"
#include "mozilla/dom/BindingUtils.h"

using namespace mozilla;
Expand All @@ -31,14 +33,12 @@ NS_IMPL_ISUPPORTS(EmbedLiteJSON, nsIEmbedLiteJSON)
nsresult
CreateObjectStatic(nsIWritablePropertyBag2 * *aObject)
{
#if 0
RefPtr<nsHashPropertyBag> hpb = new nsHashPropertyBag();
if (!hpb) {
return NS_ERROR_OUT_OF_MEMORY;
}

*aObject = hpb.forget().take();
#endif
return NS_OK;
}

Expand All @@ -52,26 +52,23 @@ EmbedLiteJSON::CreateObject(nsIWritablePropertyBag2 * *aObject)
bool
EmbedLiteJSON::JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData)
{
#if 0
nsAString* result = static_cast<nsAString*>(aData);
result->Append(static_cast<const char16_t*>(aBuf),
static_cast<uint32_t>(aLen));
#endif
return true;
}

nsresult
JSValToVariant(JSContext* cx, JS::Value& propval, nsIWritableVariant* aVariant)
{
#if 0
if (propval.isBoolean()) {
aVariant->SetAsBool(propval.toBoolean());
} else if (propval.isInt32()) {
aVariant->SetAsInt32(propval.toInt32());
} else if (propval.isDouble()) {
aVariant->SetAsDouble(propval.toDouble());
} else if (propval.isString()) {
JS::Rooted<JS::Value> val(cx, propval);
JS::RootedValue val(cx, propval);
JSString* propvalString = JS::ToString(cx, val);
nsAutoJSString vstr;
if (!propvalString || !vstr.init(cx, propvalString)) {
Expand All @@ -82,29 +79,29 @@ JSValToVariant(JSContext* cx, JS::Value& propval, nsIWritableVariant* aVariant)
NS_ERROR("Value is not primitive");
return NS_ERROR_FAILURE;
}
#endif
return NS_OK;
}

nsresult
ParseObject(JSContext* cx, JSObject* object, nsIWritablePropertyBag2* aBag)
{
#if 0
JS::RootedObject modObj(cx, object);
JS::AutoIdArray props(cx, JS_Enumerate(cx, modObj));
for (size_t i = 0; !!props && i < props.length(); ++i) {

JS::Rooted<JS::IdVector> props(cx, JS::IdVector(cx));
bool hasProps = JS_Enumerate(cx, modObj, &props);
for (size_t i = 0; hasProps && i < props.length(); ++i) {
jsid propid = props[i];
JS::Rooted<jsid> id(cx, props[i]);
JS::RootedId id(cx, props[i]);
JS::RootedValue propname(cx);
JS::Rooted<JS::Value> propval(cx);
JS::RootedValue propval(cx);

if (!JS_IdToValue(cx, propid, &propname) ||
!JS_GetPropertyById(cx, modObj, id, &propval)) {
NS_ERROR("Failed to get property by ID");
return NS_ERROR_FAILURE;
}

JS::Rooted<JS::Value> val(cx, propname);
JS::RootedValue val(cx, propname);
JSString* propnameString = JS::ToString(cx, val);
nsAutoJSString pstr;
if (!propnameString || !pstr.init(cx, propnameString)) {
Expand All @@ -119,13 +116,15 @@ ParseObject(JSContext* cx, JSObject* object, nsIWritablePropertyBag2* aBag)
bagSimple->SetProperty(pstr, value);
} else {
JS::RootedObject obj(cx, &propval.toObject());
if (JS_IsArrayObject(cx, obj)) {

bool isArray = false;
if (JS_IsArrayObject(cx, obj, &isArray) && isArray) {
nsCOMPtr<nsIWritableVariant> childElements = do_CreateInstance("@mozilla.org/variant;1");
uint32_t tmp;
if (JS_GetArrayLength(cx, obj, &tmp)) {
nsTArray<nsCOMPtr<nsIVariant>> childArray;
for (uint32_t i = 0; i < tmp; i++) {
JS::Rooted<JS::Value> v(cx);
JS::RootedValue v(cx);
if (!JS_GetElement(cx, obj, i, &v))
continue;
if (v.isPrimitive()) {
Expand Down Expand Up @@ -160,17 +159,15 @@ ParseObject(JSContext* cx, JSObject* object, nsIWritablePropertyBag2* aBag)
}
}
}
#endif
return NS_OK;
}

NS_IMETHODIMP
EmbedLiteJSON::ParseJSON(nsAString const& aJson, nsIPropertyBag2** aRoot)
{
#if 0
MOZ_ASSERT(NS_IsMainThread());
AutoSafeJSContext cx;
JS::Rooted<JS::Value> json(cx, JSVAL_NULL);
JS::RootedValue json(cx, JS::NullValue());
if (!JS_ParseJSON(cx,
static_cast<const char16_t*>(aJson.BeginReading()),
aJson.Length(),
Expand All @@ -192,13 +189,11 @@ EmbedLiteJSON::ParseJSON(nsAString const& aJson, nsIPropertyBag2** aRoot)
}

*aRoot = contextProps.forget().take();
#endif
return NS_OK;
}

static bool SetPropFromVariant(nsIProperty* aProp, JSContext* aCx, JSObject* aObj)
{
#if 0
JS::RootedValue rval(aCx);
nsString name;
nsCOMPtr<nsIVariant> aVariant;
Expand All @@ -215,16 +210,14 @@ static bool SetPropFromVariant(nsIProperty* aProp, JSContext* aCx, JSObject* aOb
NS_ERROR("Failed to set js object property");
return false;
}
#endif
return true;
}

NS_IMETHODIMP
EmbedLiteJSON::CreateJSON(nsIPropertyBag* aRoot, nsAString& outJson)
{
#if 0
AutoSafeJSContext cx;
JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, nullptr));
JS::RootedObject obj(cx, JS_NewObject(cx, nullptr));
if (!obj) {
return NS_ERROR_FAILURE;
}
Expand All @@ -244,9 +237,8 @@ EmbedLiteJSON::CreateJSON(nsIPropertyBag* aRoot, nsAString& outJson)
windowEnumerator->HasMoreElements(&more);
}
// Example from SaveProfileTask.cpp#74
JS::Rooted<JS::Value> vlt(cx, OBJECT_TO_JSVAL(obj));
NS_ENSURE_TRUE(JS_Stringify(cx, &vlt, JS::NullPtr(), JS::NullHandleValue, JSONCreator, &outJson), NS_ERROR_FAILURE);
JS::RootedValue value(cx, JS::ObjectValue(*obj));
NS_ENSURE_TRUE(JS_Stringify(cx, &value, nullptr, JS::NullHandleValue, JSONCreator, &outJson), NS_ERROR_FAILURE);
NS_ENSURE_TRUE(!outJson.IsEmpty(), NS_ERROR_FAILURE);
#endif
return NS_OK;
}
49 changes: 35 additions & 14 deletions embedding/embedlite/utils/TabChildHelper.cpp
Expand Up @@ -15,6 +15,8 @@
#include "nsIDOMDocument.h"
#include "mozilla/EventListenerManager.h"

#include "mozilla/dom/ipc/StructuredCloneData.h"

#include "nsNetUtil.h"
#include "nsIDOMWindowUtils.h"
#include "mozilla/dom/Element.h"
Expand Down Expand Up @@ -301,12 +303,12 @@ TabChildHelper::DoSendBlockingMessage(JSContext* aCx,
JSContext* cx = mTabChildGlobal->GetJSContextForEventHandlers();
JSAutoRequest ar(cx);

return false;
// FIXME: Need callback interface for simple JSON to avoid useless conversion here
#if 0
JS::Rooted<JS::Value> rval(cx, JS::NullValue());
if (aData.mDataLength &&
!ReadStructuredClone(cx, aData, &rval)) { // JS_ReadStructuredClone
if (aData.DataLength() > 0 &&
!JS_ReadStructuredClone(cx, aData.Data(), aData.DataLength(),
JS_STRUCTURED_CLONE_VERSION, &rval,
nullptr, nullptr)) {
JS_ClearPendingException(cx);
return false;
}
Expand All @@ -318,12 +320,26 @@ TabChildHelper::DoSendBlockingMessage(JSContext* aCx,
// FIXME : Return value should be written to nsTArray<StructuredCloneData> *aRetVal
InfallibleTArray<nsString> jsonRetVal;

bool retValue = false;

if (aIsSync) {
return mView->DoSendSyncMessage(nsString(aMessage).get(), json.get(), &jsonRetVal);
retValue = mView->DoSendSyncMessage(nsString(aMessage).get(), json.get(), &jsonRetVal);
} else {
retValue = mView->DoCallRpcMessage(nsString(aMessage).get(), json.get(), &jsonRetVal);
}

if (retValue && aRetVal) {
for (uint32_t i = 0; i < jsonRetVal.Length(); i++) {
mozilla::dom::ipc::StructuredCloneData* cloneData = aRetVal->AppendElement();

NS_ConvertUTF16toUTF8 data(jsonRetVal[i]);
if (!cloneData->CopyExternalData(data.get(), data.Length())) {
return false;
}
}
}

return mView->DoCallRpcMessage(nsString(aMessage).get(), json.get(), &jsonRetVal);
#endif
return retValue;
}

nsresult TabChildHelper::DoSendAsyncMessage(JSContext* aCx,
Expand All @@ -332,7 +348,6 @@ nsresult TabChildHelper::DoSendAsyncMessage(JSContext* aCx,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
{
#if 0
nsCOMPtr<nsIMessageBroadcaster> globalIMessageManager =
do_GetService("@mozilla.org/globalmessagemanager;1");
RefPtr<nsFrameMessageManager> globalMessageManager =
Expand All @@ -346,22 +361,28 @@ nsresult TabChildHelper::DoSendAsyncMessage(JSContext* aCx,
embedFrame->mWindow = window;
embedFrame->mMessageManager = mTabChildGlobal;
SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows);
globalMessageManager->ReceiveMessage(embedFrame, aMessage, false, &aData, &cpows, aPrincipal, nullptr);
contentFrameMessageManager->ReceiveMessage(embedFrame, aMessage, false, &aData, &cpows, aPrincipal, nullptr);

globalMessageManager->ReceiveMessage(embedFrame, nullptr, aMessage, false, &aData, &cpows, aPrincipal, nullptr);
contentFrameMessageManager->ReceiveMessage(embedFrame, nullptr, aMessage, false, &aData, &cpows, aPrincipal, nullptr);

if (!mView->HasMessageListener(aMessage)) {
LOGW("Message not registered msg:%s\n", NS_ConvertUTF16toUTF8(aMessage).get());
return NS_OK;
}

NS_ENSURE_TRUE(InitTabChildGlobal(), false);
if (!InitTabChildGlobal()) {
return NS_ERROR_UNEXPECTED;
}
JSContext* cx = mTabChildGlobal->GetJSContextForEventHandlers();
JSAutoRequest ar(cx);

// FIXME: Need callback interface for simple JSON to avoid useless conversion here
JS::Rooted<JS::Value> rval(cx, JS::NullValue());
if (aData.DataLength() &&
!ReadStructuredClone(cx, aData, &rval)) {

if (aData.DataLength() > 0 &&
!JS_ReadStructuredClone(cx, aData.Data(), aData.DataLength(),
JS_STRUCTURED_CLONE_VERSION, &rval,
nullptr, nullptr)) {
JS_ClearPendingException(cx);
return NS_ERROR_UNEXPECTED;
}
Expand All @@ -379,7 +400,7 @@ nsresult TabChildHelper::DoSendAsyncMessage(JSContext* aCx,
if (!mView->DoSendAsyncMessage(nsString(aMessage).get(), json.get())) {
return NS_ERROR_UNEXPECTED;
}
#endif

return NS_OK;
}

Expand Down

0 comments on commit 689d46d

Please sign in to comment.