diff --git a/CefSharp.BrowserSubprocess.Core/CefSharp.BrowserSubprocess.Core.vcxproj b/CefSharp.BrowserSubprocess.Core/CefSharp.BrowserSubprocess.Core.vcxproj index 2e2ce536a7..3c11f2d64c 100644 --- a/CefSharp.BrowserSubprocess.Core/CefSharp.BrowserSubprocess.Core.vcxproj +++ b/CefSharp.BrowserSubprocess.Core/CefSharp.BrowserSubprocess.Core.vcxproj @@ -155,6 +155,7 @@ + @@ -171,9 +172,11 @@ + + @@ -193,6 +196,7 @@ Create + diff --git a/CefSharp.BrowserSubprocess.Core/CefSharp.BrowserSubprocess.Core.vcxproj.filters b/CefSharp.BrowserSubprocess.Core/CefSharp.BrowserSubprocess.Core.vcxproj.filters index 5550541d56..5c744c4a0f 100644 --- a/CefSharp.BrowserSubprocess.Core/CefSharp.BrowserSubprocess.Core.vcxproj.filters +++ b/CefSharp.BrowserSubprocess.Core/CefSharp.BrowserSubprocess.Core.vcxproj.filters @@ -68,6 +68,12 @@ Header Files + + Header Files + + + Header Files + @@ -112,6 +118,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/CefSharp.BrowserSubprocess.Core/Serialization/V8Serialization.cpp b/CefSharp.BrowserSubprocess.Core/Serialization/V8Serialization.cpp new file mode 100644 index 0000000000..90d86ac6be --- /dev/null +++ b/CefSharp.BrowserSubprocess.Core/Serialization/V8Serialization.cpp @@ -0,0 +1,85 @@ +// Copyright © 2010-2015 The CefSharp Project. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +#include "Stdafx.h" +#include "V8Serialization.h" +#include "JavascriptCallbackRegistry.h" +#include "../CefSharp.Core/Internals/Serialization/Primitives.h" + +namespace CefSharp +{ + namespace Internals + { + namespace Serialization + { + template + void SerializeV8Object(CefRefPtr obj, CefRefPtr list, TIndex index, JavascriptCallbackRegistry^ callbackRegistry) + { + if (obj->IsNull() || obj->IsUndefined()) + { + list->SetNull(index); + } + else if (obj->IsBool()) + list->SetBool(index, obj->GetBoolValue()); + else if (obj->IsInt()) + list->SetInt(index, obj->GetIntValue()); + else if (obj->IsDouble()) + list->SetDouble(index, obj->GetDoubleValue()); + else if (obj->IsString()) + list->SetString(index, obj->GetStringValue()); + else if (obj->IsDate()) + SetCefTime(obj->GetDateValue(), list, index); + else if (obj->IsArray()) + { + int arrLength = obj->GetArrayLength(); + std::vector keys; + if (arrLength > 0 && obj->GetKeys(keys)) + { + auto array = CefListValue::Create(); + for (int i = 0; i < arrLength; i++) + { + SerializeV8Object(obj->GetValue(keys[i]), array, i, callbackRegistry); + } + + list->SetList(index, array); + } + else + { + list->SetNull(index); + } + } + else if (obj->IsFunction()) + { + auto context = CefV8Context::GetCurrentContext(); + auto jsCallback = callbackRegistry->Register(context, obj); + SetJsCallback(jsCallback, list, index); + } + else if (obj->IsObject()) + { + std::vector keys; + if (obj->GetKeys(keys) && keys.size() > 0) + { + auto result = CefDictionaryValue::Create(); + for (int i = 0; i < keys.size(); i++) + { + auto p_keyStr = StringUtils::ToClr(keys[i].ToString()); + if ((obj->HasValue(keys[i])) && (!p_keyStr->StartsWith("__"))) + { + SerializeV8Object(obj->GetValue(keys[i]), result, keys[i], callbackRegistry); + } + } + list->SetDictionary(index, result); + } + } + else + { + list->SetNull(index); + } + } + + template void SerializeV8Object(CefRefPtr value, CefRefPtr list, int index, JavascriptCallbackRegistry^ callbackRegistry); + template void SerializeV8Object(CefRefPtr value, CefRefPtr list, CefString index, JavascriptCallbackRegistry^ callbackRegistry); + } + } +} \ No newline at end of file diff --git a/CefSharp.BrowserSubprocess.Core/Serialization/V8Serialization.h b/CefSharp.BrowserSubprocess.Core/Serialization/V8Serialization.h new file mode 100644 index 0000000000..d5b7a69a3f --- /dev/null +++ b/CefSharp.BrowserSubprocess.Core/Serialization/V8Serialization.h @@ -0,0 +1,25 @@ +// Copyright © 2010-2015 The CefSharp Project. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +#pragma once + +#include "include/cef_v8.h" + +namespace CefSharp +{ + namespace Internals + { + ref class JavascriptCallbackRegistry; + + namespace Serialization + { + //Functions to sserialize data to be sent to the browser process. + + //Serializes a V8 structure into a given index of a CefListValue or CefDictionaryValue + //JavascriptCallbackRegistry should be passed to save V8Values with function types + template + void SerializeV8Object(CefRefPtr value, CefRefPtr list, TIndex index, JavascriptCallbackRegistry^ callbackRegistry); + } + } +} \ No newline at end of file diff --git a/CefSharp.Core/CefSharp.Core.vcxproj b/CefSharp.Core/CefSharp.Core.vcxproj index b19988af5f..0471d257d9 100644 --- a/CefSharp.Core/CefSharp.Core.vcxproj +++ b/CefSharp.Core/CefSharp.Core.vcxproj @@ -230,6 +230,8 @@ + + Create @@ -272,9 +274,11 @@ + + diff --git a/CefSharp.Core/CefSharp.Core.vcxproj.filters b/CefSharp.Core/CefSharp.Core.vcxproj.filters index 42ee67e836..6c28533b63 100644 --- a/CefSharp.Core/CefSharp.Core.vcxproj.filters +++ b/CefSharp.Core/CefSharp.Core.vcxproj.filters @@ -59,6 +59,12 @@ Source Files + + Source Files + + + Source Files + @@ -181,6 +187,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/CefSharp.Core/Internals/Serialization/Primitives.cpp b/CefSharp.Core/Internals/Serialization/Primitives.cpp new file mode 100644 index 0000000000..ce2cc91efb --- /dev/null +++ b/CefSharp.Core/Internals/Serialization/Primitives.cpp @@ -0,0 +1,155 @@ +// Copyright © 2010-2015 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +#include "Stdafx.h" +#include "Primitives.h" + +#include "include/cef_app.h" + +using namespace std; + +namespace CefSharp +{ + namespace Internals + { + namespace Serialization + { + enum class PrimitiveType : unsigned char + { + INT64, + CEFTIME, + JSCALLBACK + }; + + template + bool IsType(PrimitiveType type, CefRefPtr list, TIndex index) + { + auto result = list->GetType(index) == VTYPE_BINARY; + if (result) + { + underlying_type::type typeRead; + auto binaryValue = list->GetBinary(index); + binaryValue->GetData(&typeRead, sizeof(underlying_type::type), 0); + result = typeRead == static_cast::type>(type); + } + return result; + } + + template + void SetInt64(const int64 &value, CefRefPtr list, TIndex index) + { + unsigned char mem[1 + sizeof(int64)]; + mem[0] = static_cast(PrimitiveType::INT64); + memcpy(reinterpret_cast(mem + 1), &value, sizeof(int64)); + + auto binaryValue = CefBinaryValue::Create(mem, sizeof(mem)); + list->SetBinary(index, binaryValue); + } + + template + int64 GetInt64(CefRefPtr list, TIndex index) + { + int64 result; + + auto binaryValue = list->GetBinary(index); + binaryValue->GetData(&result, sizeof(int64), 1); + + return result; + } + + template + bool IsInt64(CefRefPtr list, TIndex index) + { + return IsType(PrimitiveType::INT64, list, index); + } + + template + void SetCefTime(const CefTime &value, CefRefPtr list, TIndex index) + { + auto doubleT = value.GetDoubleT(); + unsigned char mem[1 + sizeof(double)]; + mem[0] = static_cast(PrimitiveType::CEFTIME); + memcpy(reinterpret_cast(mem + 1), &doubleT, sizeof(double)); + + auto binaryValue = CefBinaryValue::Create(mem, sizeof(mem)); + list->SetBinary(index, binaryValue); + } + + template + CefTime GetCefTime(CefRefPtr list, TIndex index) + { + double doubleT; + + auto binaryValue = list->GetBinary(index); + binaryValue->GetData(&doubleT, sizeof(double), 1); + + return CefTime(doubleT); + } + + template + bool IsCefTime(CefRefPtr list, TIndex index) + { + return IsType(PrimitiveType::CEFTIME, list, index); + } + template + void SetJsCallback(JavascriptCallback^ value, CefRefPtr list, TIndex index) + { + auto id = value->Id; + auto browserId = value->BrowserId; + + unsigned char mem[1 + sizeof(int) + sizeof(int64)]; + mem[0] = static_cast(PrimitiveType::JSCALLBACK); + memcpy(reinterpret_cast(mem + 1), &browserId, sizeof(int)); + memcpy(reinterpret_cast(mem + 1 + sizeof(int)), &id, sizeof(int64)); + + auto binaryValue = CefBinaryValue::Create(mem, sizeof(mem)); + list->SetBinary(index, binaryValue); + } + + template + JavascriptCallback^ GetJsCallback(CefRefPtr list, TIndex index) + { + auto result = gcnew JavascriptCallback(); + int64 id; + int browserId; + + auto binaryValue = list->GetBinary(index); + binaryValue->GetData(&browserId, sizeof(int), 1); + binaryValue->GetData(&id, sizeof(int64), 1 + sizeof(int)); + + result->Id = id; + result->BrowserId = browserId; + + return result; + } + + template + bool IsJsCallback(CefRefPtr list, TIndex index) + { + return IsType(PrimitiveType::JSCALLBACK, list, index); + } + + template void SetInt64(const int64 &value, CefRefPtr list, int index); + template void SetInt64(const int64 &value, CefRefPtr list, CefString index); + template int64 GetInt64(CefRefPtr list, int index); + template int64 GetInt64(CefRefPtr list, CefString index); + template bool IsInt64(CefRefPtr list, int index); + template bool IsInt64(CefRefPtr list, CefString index); + + template void SetCefTime(const CefTime &value, CefRefPtr list, int index); + template void SetCefTime(const CefTime &value, CefRefPtr list, CefString index); + template CefTime GetCefTime(CefRefPtr list, int index); + template CefTime GetCefTime(CefRefPtr list, CefString index); + template bool IsCefTime(CefRefPtr list, int index); + template bool IsCefTime(CefRefPtr list, CefString index); + + template void SetJsCallback(JavascriptCallback^ value, CefRefPtr list, int index); + template void SetJsCallback(JavascriptCallback^ value, CefRefPtr list, CefString index); + template JavascriptCallback^ GetJsCallback(CefRefPtr list, int index); + template JavascriptCallback^ GetJsCallback(CefRefPtr list, CefString index); + template bool IsJsCallback(CefRefPtr list, int index); + template bool IsJsCallback(CefRefPtr list, CefString index); + } + } +} \ No newline at end of file diff --git a/CefSharp.Core/Internals/Serialization/Primitives.h b/CefSharp.Core/Internals/Serialization/Primitives.h new file mode 100644 index 0000000000..e451ae6ffb --- /dev/null +++ b/CefSharp.Core/Internals/Serialization/Primitives.h @@ -0,0 +1,37 @@ +// Copyright © 2010-2015 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +#pragma once + +namespace CefSharp +{ + namespace Internals + { + namespace Serialization + { + //Functions to serialize/deserialize specific types into CefBinaryValue + + template + void SetInt64(const int64 &value, CefRefPtr list, TIndex index); + template + int64 GetInt64(CefRefPtr list, TIndex index); + template + bool IsInt64(CefRefPtr list, TIndex index); + + template + void SetCefTime(const CefTime &value, CefRefPtr list, TIndex index); + template + CefTime GetCefTime(CefRefPtr list, TIndex index); + template + bool IsCefTime(CefRefPtr list, TIndex index); + + template + void SetJsCallback(JavascriptCallback^ value, CefRefPtr list, TIndex index); + template + JavascriptCallback^ GetJsCallback(CefRefPtr list, TIndex index); + template + bool IsJsCallback(CefRefPtr list, TIndex index); + } + } +} \ No newline at end of file diff --git a/CefSharp.Core/Internals/Serialization/V8Serialization.cpp b/CefSharp.Core/Internals/Serialization/V8Serialization.cpp new file mode 100644 index 0000000000..d0e91f5870 --- /dev/null +++ b/CefSharp.Core/Internals/Serialization/V8Serialization.cpp @@ -0,0 +1,93 @@ +// Copyright © 2010-2015 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +#include "Stdafx.h" +#include "V8Serialization.h" +#include "Primitives.h" + +namespace CefSharp +{ + namespace Internals + { + namespace Serialization + { + template + Object^ DeserializeV8Object(CefRefPtr list, TIndex index, IJavascriptCallbackFactory^ javascriptCallbackFactory) + { + Object^ result = nullptr; + auto type = list->GetType(index); + + if (type == VTYPE_BOOL) + { + result = list->GetBool(index); + } + else if (type == VTYPE_INT) + { + result = list->GetInt(index); + } + else if (IsInt64(list, index)) + { + result = GetInt64(list, index); + } + else if (IsCefTime(list, index)) + { + auto cefTime = GetCefTime(list, index); + result = ConvertCefTimeToDateTime(cefTime); + } + else if (IsJsCallback(list, index) && javascriptCallbackFactory != nullptr) + { + auto jsCallbackDto = GetJsCallback(list, index); + result = javascriptCallbackFactory->Create(jsCallbackDto); + } + else if (type == VTYPE_DOUBLE) + { + result = list->GetDouble(index); + } + else if (type == VTYPE_STRING) + { + result = StringUtils::ToClr(list->GetString(index)); + } + else if (type == VTYPE_LIST) + { + auto subList = list->GetList(index); + auto array = gcnew List(subList->GetSize()); + for (auto i = 0; i < subList->GetSize(); i++) + { + array->Add(DeserializeV8Object(subList, i, javascriptCallbackFactory)); + } + result = array; + } + else if (type == VTYPE_DICTIONARY) + { + auto dict = gcnew Dictionary(); + auto subDict = list->GetDictionary(index); + std::vector keys; + subDict->GetKeys(keys); + + for (auto i = 0; i < keys.size(); i++) + { + dict->Add(StringUtils::ToClr(keys[i]), DeserializeV8Object(subDict, keys[i], javascriptCallbackFactory)); + } + + result = dict; + } + + return result; + } + + DateTime ConvertCefTimeToDateTime(CefTime time) + { + auto epoch = time.GetDoubleT(); + if (epoch == 0) + { + return DateTime::MinValue; + } + return DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(epoch).ToLocalTime(); + } + + template Object^ DeserializeV8Object(CefRefPtr list, int index, IJavascriptCallbackFactory^ javascriptCallbackFactory); + template Object^ DeserializeV8Object(CefRefPtr list, CefString index, IJavascriptCallbackFactory^ javascriptCallbackFactory); + } + } +} \ No newline at end of file diff --git a/CefSharp.Core/Internals/Serialization/V8Serialization.h b/CefSharp.Core/Internals/Serialization/V8Serialization.h new file mode 100644 index 0000000000..7148468916 --- /dev/null +++ b/CefSharp.Core/Internals/Serialization/V8Serialization.h @@ -0,0 +1,24 @@ +// Copyright © 2010-2015 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +#pragma once + +namespace CefSharp +{ + namespace Internals + { + namespace Serialization + { + //Functions to deserialize data returned from the render process. + + //Deserializes data into Object from a given index of a CefListValue or CefDictionaryValue + //IJavascriptCallbackFactory implementation should be passed to allow creation of valid javascript callbacks + template + Object^ DeserializeV8Object(CefRefPtr list, TIndex index, IJavascriptCallbackFactory^ javascriptCallbackFactory); + + //Converts CefTime to DateTime + DateTime ConvertCefTimeToDateTime(CefTime time); + } + } +} \ No newline at end of file diff --git a/CefSharp/CefSharp.csproj b/CefSharp/CefSharp.csproj index 1864dcf7bb..b0b6140a44 100644 --- a/CefSharp/CefSharp.csproj +++ b/CefSharp/CefSharp.csproj @@ -112,6 +112,7 @@ Code + diff --git a/CefSharp/Internals/IJavascriptCallbackFactory.cs b/CefSharp/Internals/IJavascriptCallbackFactory.cs new file mode 100644 index 0000000000..f9804e31d8 --- /dev/null +++ b/CefSharp/Internals/IJavascriptCallbackFactory.cs @@ -0,0 +1,14 @@ +// Copyright © 2010-2015 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +namespace CefSharp.Internals +{ + /// + /// Interface to convert a JavascriptCallback dto to a callable implementation. + /// + public interface IJavascriptCallbackFactory + { + IJavascriptCallback Create(JavascriptCallback callback); + } +}