SIGN IN SIGN UP
cefsharp / CefSharp UNCLAIMED

.NET (WPF and Windows Forms) bindings for the Chromium Embedded Framework

0 0 1 C#
// Copyright © 2015 The CefSharp Authors. All rights reserved.
2015-06-27 16:06:47 +02:00
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
#include "Stdafx.h"
#include "include\cef_values.h"
#include "include\cef_parser.h"
2015-06-27 16:06:47 +02:00
#include "V8Serialization.h"
#include "Primitives.h"
using namespace System::Collections::Generic;
namespace
{
String^ GetJavascriptName(System::Reflection::MemberInfo^ memberInfo, IJavascriptNameConverter^ nameConverter)
{
if (nameConverter == nullptr)
{
return memberInfo->Name;
}
return nameConverter->ConvertReturnedObjectPropertyAndFieldToNameJavascript(memberInfo);
}
}
2015-06-27 16:06:47 +02:00
namespace CefSharp
{
namespace Internals
{
namespace Serialization
{
template<typename TList, typename TIndex>
void SerializeV8Object(const CefRefPtr<TList>& list, const TIndex& index, Object^ obj, IJavascriptNameConverter^ nameConverter)
{
// Collection of ancestors to currently serialised object.
// This enables prevention of endless loops due to cycles in graphs where
// a child references one of its ancestors.
auto ancestors = gcnew HashSet<Object^>();
SerializeV8SimpleObject(list, index, obj, ancestors, nameConverter);
}
template<typename TList, typename TIndex>
void SerializeV8SimpleObject(const CefRefPtr<TList>& list, const TIndex& index, Object^ obj, HashSet<Object^>^ ancestors, IJavascriptNameConverter^ nameConverter)
{
list->SetNull(index);
if (obj == nullptr || ancestors->Contains(obj))
{
return;
}
ancestors->Add(obj);
auto type = obj->GetType();
Type^ underlyingType = Nullable::GetUnderlyingType(type);
if (underlyingType != nullptr) type = underlyingType;
if (type == Boolean::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetBool(index, safe_cast<bool>(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == Int32::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetInt(index, safe_cast<int>(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == String::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetString(index, StringUtils::ToNative(safe_cast<String^>(obj)));
2015-08-07 12:56:16 +10:00
}
else if (type == Double::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetDouble(index, safe_cast<double>(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == Decimal::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetDouble(index, Convert::ToDouble(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == SByte::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetInt(index, Convert::ToInt32(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == Int16::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetInt(index, Convert::ToInt32(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == Int64::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetDouble(index, Convert::ToDouble(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == Byte::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetInt(index, Convert::ToInt32(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == UInt16::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetInt(index, Convert::ToInt32(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == UInt32::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetDouble(index, Convert::ToDouble(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == UInt64::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetDouble(index, Convert::ToDouble(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == Single::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetDouble(index, Convert::ToDouble(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == Char::typeid)
2015-08-07 12:56:16 +10:00
{
list->SetInt(index, Convert::ToInt32(obj));
2015-08-07 12:56:16 +10:00
}
else if (type == DateTime::typeid)
2015-08-07 12:56:16 +10:00
{
SetCefTime(list, index, CefTimeUtils::FromDateTimeToBaseTime(safe_cast<DateTime>(obj)));
2015-08-07 12:56:16 +10:00
}
// Serialize enum to sbyte, short, int, long, byte, ushort, uint, ulong (check type of enum)
else if (type->IsEnum)
{
auto subType = System::Enum::GetUnderlyingType(type);
if (subType == SByte::typeid ||
subType == Int16::typeid ||
subType == Int32::typeid ||
subType == Byte::typeid ||
subType == UInt16::typeid)
{
list->SetInt(index, Convert::ToInt32(obj));
}
else if (subType == Int64::typeid ||
subType == UInt32::typeid ||
subType == UInt64::typeid)
{
list->SetDouble(index, Convert::ToDouble(obj));
}
else
{
//Unexpected type, just convert it to a string
2019-07-20 12:19:08 +10:00
list->SetString(index, StringUtils::ToNative(Convert::ToString(obj)));
}
}
// ExpandoObject only implements IDictionary<string,object> not the non-generic System.Collection.IDictionary like Dictionary does
else if (type == System::Dynamic::ExpandoObject::typeid)
{
auto subDict = CefDictionaryValue::Create();
auto dict = (System::Collections::Generic::IDictionary<String^, Object^>^) obj;
for each (auto kvp in dict)
{
auto fieldName = StringUtils::ToNative(Convert::ToString(kvp.Key));
SerializeV8SimpleObject(subDict, fieldName, kvp.Value, ancestors, nameConverter);
}
list->SetDictionary(index, subDict);
}
// Serialize dictionary to CefDictionary (key,value pairs)
else if (System::Collections::IDictionary::typeid->IsAssignableFrom(type))
{
auto subDict = CefDictionaryValue::Create();
auto dict = (System::Collections::IDictionary^) obj;
for each (System::Collections::DictionaryEntry kvp in dict)
{
auto fieldName = StringUtils::ToNative(Convert::ToString(kvp.Key));
SerializeV8SimpleObject(subDict, fieldName, kvp.Value, ancestors, nameConverter);
}
list->SetDictionary(index, subDict);
}
else if (System::Collections::IEnumerable::typeid->IsAssignableFrom(type))
{
auto subList = CefListValue::Create();
auto enumerable = (System::Collections::IEnumerable^) obj;
int i = 0;
for each (Object^ arrObj in enumerable)
{
SerializeV8SimpleObject(subList, i, arrObj, ancestors, nameConverter);
i++;
}
list->SetList(index, subList);
}
else if (CefSharp::Web::JsonString::typeid->IsAssignableFrom(type))
{
auto jsonString = (CefSharp::Web::JsonString^) obj;
//Tried to use CefParseJSONAndReturnError, keeps returning error when
//CefParseJson works for the same string, so must be a CEF bug
auto jsonValue = CefParseJSON(StringUtils::ToNative(jsonString->Json),
cef_json_parser_options_t::JSON_PARSER_ALLOW_TRAILING_COMMAS);
if (jsonValue.get())
{
list->SetValue(index, jsonValue);
}
else
{
list->SetString(index, CefString("V8Serialization - Unable to parse JSON"));
}
}
// Serialize class/structs to CefDictionary (key,value pairs)
else if (!type->IsPrimitive && !type->IsEnum)
{
auto fields = type->GetFields();
auto subDict = CefDictionaryValue::Create();
for (int i = 0; i < fields->Length; i++)
{
auto fieldName = GetJavascriptName(fields[i], nameConverter);
auto fieldValue = fields[i]->GetValue(obj);
SerializeV8SimpleObject(subDict, StringUtils::ToNative(fieldName), fieldValue, ancestors, nameConverter);
}
auto properties = type->GetProperties();
for (int i = 0; i < properties->Length; i++)
{
auto propertyName = GetJavascriptName(properties[i], nameConverter);
auto propertyValue = properties[i]->GetValue(obj);
SerializeV8SimpleObject(subDict, StringUtils::ToNative(propertyName), propertyValue, ancestors, nameConverter);
}
list->SetDictionary(index, subDict);
}
else
{
2019-07-20 12:19:08 +10:00
list->SetString(index, StringUtils::ToNative("Unable to serialize Type - " + obj->GetType()->ToString()));
}
ancestors->Remove(obj);
}
2015-06-27 16:06:47 +02:00
}
}
}