Skip to content

JSB - Forward binding result to BindObjectAsync #5091

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ namespace CefSharp
{
void JavascriptAsyncMethodCallback::Success(const CefRefPtr<CefV8Value>& result)
{
if (_resolve.get() && _context.get() && _context->Enter())
if (_promise.get() && _context.get() && _context->Enter())
{
try
{
CefV8ValueList args;
args.push_back(result);
_resolve->ExecuteFunction(nullptr, args);
_promise->ResolvePromise(result);
}
finally
{
Expand All @@ -30,13 +28,11 @@ namespace CefSharp

void JavascriptAsyncMethodCallback::Fail(const CefString& exception)
{
if (_reject.get() && _context.get() && _context->Enter())
if (_promise.get() && _context.get() && _context->Enter())
{
try
{
CefV8ValueList args;
args.push_back(CefV8Value::CreateString(exception));
_reject->ExecuteFunction(nullptr, args);
_promise->RejectPromise(exception);
}
finally
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,19 @@ namespace CefSharp
{
private:
MCefRefPtr<CefV8Context> _context;
MCefRefPtr<CefV8Value> _resolve;
MCefRefPtr<CefV8Value> _reject;
MCefRefPtr<CefV8Value> _promise;

public:
JavascriptAsyncMethodCallback(CefRefPtr<CefV8Context> context, CefRefPtr<CefV8Value> resolve, CefRefPtr<CefV8Value> reject)
:_context(context), _resolve(resolve.get()), _reject(reject.get())
JavascriptAsyncMethodCallback(CefRefPtr<CefV8Context> context, CefRefPtr<CefV8Value> promise)
:_context(context), _promise(promise.get())
{

}

!JavascriptAsyncMethodCallback()
{
_resolve = nullptr;
_reject = nullptr;
_context = nullptr;
_promise = nullptr;
}

~JavascriptAsyncMethodCallback()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,10 @@ namespace CefSharp
auto context = CefV8Context::GetCurrentContext();
auto frame = context->GetFrame();

CefRefPtr<CefV8Value> promiseData;
CefRefPtr<CefV8Exception> promiseException;
//this will create a promise and give us the reject/resolve functions {p: Promise, res: resolve(), rej: reject()}
if (!context->Eval(CefAppUnmanagedWrapper::kPromiseCreatorScript, CefString(), 0, promiseData, promiseException))
{
LOG(WARNING) << "JavascriptAsyncMethodHandler::Execute promiseData returned exception: " + promiseException->GetMessage().ToString();

exception = promiseException->GetMessage();

return true;
}

//when refreshing the browser this is sometimes null, in this case return true and log message
//https://github.com/cefsharp/CefSharp/pull/2446
if (promiseData == nullptr)
{
LOG(WARNING) << "JavascriptAsyncMethodHandler::Execute promiseData returned nullptr";

return true;
}

retval = promiseData->GetValue("p");
CefRefPtr<CefV8Value> promise = CefV8Value::CreatePromise();
retval = promise;

auto resolve = promiseData->GetValue("res");
auto reject = promiseData->GetValue("rej");
auto callback = gcnew JavascriptAsyncMethodCallback(context, resolve, reject);
auto callback = gcnew JavascriptAsyncMethodCallback(context, promise);
auto callbackId = _methodCallbackSave->Invoke(callback);

auto request = CefProcessMessage::Create(kJavascriptAsyncMethodCallRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ namespace CefSharp
{
namespace Async
{
void JavascriptAsyncObjectWrapper::Bind(JavascriptObject^ object, const CefRefPtr<CefV8Value> &value)
CefRefPtr<CefV8Value> JavascriptAsyncObjectWrapper::ConvertToV8Value(JavascriptObject^ object)
{
//V8Value that represents this javascript object - only one per complex type, no accessor
auto javascriptObject = CefV8Value::CreateObject(nullptr, nullptr);
auto objectName = StringUtils::ToNative(object->JavascriptName);
value->SetValue(objectName, javascriptObject, V8_PROPERTY_ATTRIBUTE_NONE);

for each (JavascriptMethod^ method in Enumerable::OfType<JavascriptMethod^>(object->Methods))
{
Expand All @@ -29,6 +28,8 @@ namespace CefSharp

_wrappedMethods->Add(wrappedMethod);
}

return javascriptObject;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace CefSharp
}
}

void Bind(JavascriptObject^ object, const CefRefPtr<CefV8Value> &value);
CefRefPtr<CefV8Value> ConvertToV8Value(JavascriptObject^ object);
};
}
}
Expand Down
91 changes: 32 additions & 59 deletions CefSharp.BrowserSubprocess.Core/BindObjectAsyncHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ namespace CefSharp

if (frame.get() && frame->IsValid())
{
const auto resultPromise = CefV8Value::CreatePromise();
if (boundObjectRequired || ignoreCache)
{
//If the number of cached objects matches the number of args
Expand Down Expand Up @@ -162,57 +163,17 @@ namespace CefSharp
}

//Cached objects only contains a list of objects not already bound
rootObject->Bind(cachedObjects, context->GetGlobal());
auto bindResult = rootObject->Bind(cachedObjects, context->GetGlobal());

//Objects already bound or ignore cache
CefRefPtr<CefV8Value> promiseResolve;
CefRefPtr<CefV8Exception> promiseException;

auto promiseResolveScript = StringUtils::ToNative("Promise.resolve({Success:true, Count:" + cachedObjects->Count + ", Message:'OK'});");

if (context->Eval(promiseResolveScript, CefString(), 0, promiseResolve, promiseException))
{
retval = promiseResolve;
}
else
{
exception = promiseException->GetMessage();

return true;
}
const auto resultForPromise = CreateBindResult(cachedObjects->Count, "OK", true, bindResult);
resultPromise->ResolvePromise(resultForPromise);

NotifyObjectBound(frame, objectNamesWithBoundStatus);
}
else
{
CefRefPtr<CefV8Value> promiseData;
CefRefPtr<CefV8Exception> promiseException;
//this will create a promise and give us the reject/resolve functions {p: Promise, res: resolve(), rej: reject()}
if (!context->Eval(CefAppUnmanagedWrapper::kPromiseCreatorScript, CefString(), 0, promiseData, promiseException))
{
exception = promiseException->GetMessage();

return true;
}

//when refreshing the browser this is sometimes null, in this case return true and log message
//https://github.com/cefsharp/CefSharp/pull/2446
if (promiseData == nullptr)
{
LOG(WARNING) << "BindObjectAsyncHandler::Execute promiseData returned nullptr";

return true;
}

//return the promose
retval = promiseData->GetValue("p");

//References to the promise resolve and reject methods
auto resolve = promiseData->GetValue("res");
auto reject = promiseData->GetValue("rej");

auto callback = gcnew JavascriptAsyncMethodCallback(context, resolve, reject);

auto callback = gcnew JavascriptAsyncMethodCallback(context, resultPromise);
auto request = CefProcessMessage::Create(kJavascriptRootObjectRequest);
auto argList = request->GetArgumentList();

Expand All @@ -228,25 +189,16 @@ namespace CefSharp
else
{
//Objects already bound or ignore cache
CefRefPtr<CefV8Value> promiseResolve;
CefRefPtr<CefV8Exception> promiseException;

auto promiseResolveScript = CefString("Promise.resolve({Success:false, Count:0, Message:'Object(s) already bound'});");

if (context->Eval(promiseResolveScript, CefString(), 0, promiseResolve, promiseException))
{
retval = promiseResolve;
const auto resultForPromise = CreateBindResult(0, "Object(s) already bound", false, CefV8Value::CreateArray(0));
resultPromise->ResolvePromise(resultForPromise);

if (notifyIfAlreadyBound)
{
NotifyObjectBound(frame, objectNamesWithBoundStatus);
}
}
else
if (notifyIfAlreadyBound)
{
exception = promiseException->GetMessage();
NotifyObjectBound(frame, objectNamesWithBoundStatus);
}
}

retval = resultPromise;
}
else
{
Expand All @@ -267,6 +219,27 @@ namespace CefSharp
return true;
}

static CefRefPtr<CefV8Value> CreateBindResult(int count, String^ message, bool isSuccess, const CefRefPtr<CefV8Value> bindResult)
{
auto response = CefV8Value::CreateObject(nullptr, nullptr);

const auto countResult = CefV8Value::CreateInt(count);
const auto messageResult = CefV8Value::CreateString(StringUtils::ToNative(message));
const auto successResult = CefV8Value::CreateBool(isSuccess);

response->SetValue("Count", countResult, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
response->SetValue("Message", messageResult, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
response->SetValue("Success", successResult, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
response->SetValue("BindResult", bindResult, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);

response->SetValue("count", countResult, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
response->SetValue("message", messageResult, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
response->SetValue("success", successResult, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
response->SetValue("bindResult", bindResult, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);

return response;
}

private:
void NotifyObjectBound(const CefRefPtr<CefFrame> frame, List<Tuple<String^, bool, bool>^>^ objectNamesWithBoundStatus)
{
Expand Down
24 changes: 3 additions & 21 deletions CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,6 @@ namespace CefSharp
{
namespace BrowserSubprocess
{
const CefString CefAppUnmanagedWrapper::kPromiseCreatorScript = ""
"(function()"
"{"
" var result = {};"
" var promise = new Promise(function(resolve, reject) {"
" result.res = resolve; result.rej = reject;"
" });"
" result.p = promise;"
" return result;"
"})();";

const CefString kRenderProcessId = CefString("RenderProcessId");
const CefString kRenderProcessIdCamelCase = CefString("renderProcessId");
Expand Down Expand Up @@ -658,27 +648,19 @@ namespace CefSharp

try
{
rootObject->Bind(javascriptObjects, context->GetGlobal());
auto bindResult = rootObject->Bind(javascriptObjects, context->GetGlobal());

if (_registerBoundObjectRegistry->TryGetAndRemoveMethodCallback(callbackId, callback))
{
//Response object has no Accessor or Interceptor
auto response = CefV8Value::CreateObject(nullptr, nullptr);

response->SetValue("Count", CefV8Value::CreateInt(javascriptObjects->Count), CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);

if (javascriptObjects->Count > 0)
{
//TODO: JSB Should we include a list of successfully bound object names?
response->SetValue("Success", CefV8Value::CreateBool(true), CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
response->SetValue("Message", CefV8Value::CreateString("OK"), CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
callback->Success(response);
callback->Success(BindObjectAsyncHandler::CreateBindResult(javascriptObjects->Count, "OK", true, bindResult));
}
else
{
response->SetValue("Success", CefV8Value::CreateBool(false), CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
response->SetValue("Message", CefV8Value::CreateString("Zero objects bounds"), CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
callback->Success(response);
callback->Success(BindObjectAsyncHandler::CreateBindResult(javascriptObjects->Count, "Zero objects bounds", false, bindResult));
}

//Send message notifying Browser Process of which objects were bound
Expand Down
1 change: 0 additions & 1 deletion CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ namespace CefSharp
gcroot<RegisterBoundObjectRegistry^> _registerBoundObjectRegistry;

public:
static const CefString kPromiseCreatorScript;

CefAppUnmanagedWrapper(IRenderProcessHandler^ handler, List<CefCustomScheme^>^ schemes, bool enableFocusedNodeChanged, Action<CefBrowserWrapper^>^ onBrowserCreated, Action<CefBrowserWrapper^>^ onBrowserDestroyed) : SubProcessApp(schemes)
{
Expand Down
6 changes: 3 additions & 3 deletions CefSharp.BrowserSubprocess.Core/JavascriptObjectWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace CefSharp
{
namespace BrowserSubprocess
{
void JavascriptObjectWrapper::Bind(JavascriptObject^ object, const CefRefPtr<CefV8Value>& v8Value, JavascriptCallbackRegistry^ callbackRegistry)
CefRefPtr<CefV8Value> JavascriptObjectWrapper::ConvertToV8Value(JavascriptObject^ object, JavascriptCallbackRegistry^ callbackRegistry)
{
_objectId = object->Id;

Expand All @@ -24,8 +24,6 @@ namespace CefSharp

//V8Value that represents this javascript object - only one per complex type
auto javascriptObject = CefV8Value::CreateObject(_jsPropertyHandler.get(), nullptr);
auto objectName = StringUtils::ToNative(object->JavascriptName);
v8Value->SetValue(objectName, javascriptObject, V8_PROPERTY_ATTRIBUTE_NONE);

for each (JavascriptMethod ^ method in Enumerable::OfType<JavascriptMethod^>(object->Methods))
{
Expand All @@ -42,6 +40,8 @@ namespace CefSharp

_wrappedProperties->Add(wrappedproperty);
}

return javascriptObject;
}

BrowserProcessResponse^ JavascriptObjectWrapper::GetProperty(String^ memberName)
Expand Down
2 changes: 1 addition & 1 deletion CefSharp.BrowserSubprocess.Core/JavascriptObjectWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ namespace CefSharp
}
}

void Bind(JavascriptObject^ object, const CefRefPtr<CefV8Value>& v8Value, JavascriptCallbackRegistry^ callbackRegistry);
CefRefPtr<CefV8Value> ConvertToV8Value(JavascriptObject^ object, JavascriptCallbackRegistry^ callbackRegistry);
BrowserProcessResponse^ GetProperty(String^ memberName);
BrowserProcessResponse^ SetProperty(String^ memberName, Object^ value);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ namespace CefSharp
if (javascriptProperty->IsComplexType)
{
auto javascriptObjectWrapper = gcnew JavascriptObjectWrapper(_browserProcess);
javascriptObjectWrapper->Bind(javascriptProperty->JsObject, v8Value, callbackRegistry);
const auto v8Obj = javascriptObjectWrapper->ConvertToV8Value(javascriptProperty->JsObject, callbackRegistry);

auto objectName = StringUtils::ToNative(javascriptProperty->JsObject->JavascriptName);
v8Value->SetValue(objectName, v8Obj, V8_PROPERTY_ATTRIBUTE_NONE);

_javascriptObjectWrapper = javascriptObjectWrapper;
}
Expand Down
Loading