How JavaScript execute can obtain data from the main app

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

Re: How JavaScript execute can obtain data from the main app

Postby thedarkbrainer » Sun Mar 22, 2020 9:00 pm

I managed to make it without doing anything fancy.
Only following the example and trying to mimic CefCSharp, i.e. functions from the API are functions that return a JavaScript promise.

Client code looks like this: (C++ code something like this)
Code: Select all
ptr->AddJavaScriptExecute(
   "API = {};"
   "API.getData = () => new Promise(function(resolve, reject) { API.getDataInternal(resolve, reject); } );"
);

ptr->AddJavaScriptFunction( "API.getDataInternal",
   [&](const TXString& name, const std::vector<TVariant>& args, IJSFunctionCallbackContext* context)
   {
      TXString result = "return data to JavaScript";

      std::vector<TVariant> callArgs;
      callArgs.push_back( result );      // add the arguments to be passed to the 'resolve' function
      context->Call( args[0], callArgs ); // this relies on the call from the Promise above: args[0] = <the resolve function>; args[1] = <the reject function>;
   });


The JavaScript side is something like this:
Code: Select all
API.getData().then(function(response) {
   alert("Success!", response);
});


From the CEF side, its not much different than the example in the documentation. Just careful passing around parameters, so the callbacks to the Renderer process can look it up for the actual execution.

The script and functions that need to be executed and created are being added with a separate message to the Renderer process -- packaged, unpackages and executed inside the V8Context after the message and at OnContextCreated.

Code: Select all
void CJavaScriptDelegate::ProcesPackage(const CJavaScriptPackage& package, CefRefPtr<CefV8Context> context)
{
   for(const auto& code : package.farrCode)
   {
      CefRefPtr<CefV8Value> ret;
      CefRefPtr<CefV8Exception> ex;
      context->Eval( code.operator const wchar_t*(), "", 0, ret, ex );
   }

   for(const auto& itVar : package.fmapVariables)
   {
      CefRefPtr<CefV8Value> value = CJavaScriptDelegate::GetCefV8Value( itVar.second );

      TString name;
      CefRefPtr<CefV8Value> object = this->GetOrCreateObject( context, itVar.first, name );
      object->SetValue( name.operator const wchar_t*(), value, V8_PROPERTY_ATTRIBUTE_NONE );
   }

   for(const auto& it : package.fmapFunctions)
   {
      TXString functionName;
      CefRefPtr<CefV8Value> object = this->GetOrCreateObject( context, it.first, functionName );

      const wchar_t* szFunctionName = functionName;

      const CJavaScriptPackage::SFunctionCallback& callbacKData = it.second;

      CefRefPtr<CefV8Handler>   funcHandler( new CJavaScriptV8Handler( callbacKData.fRendererCallback ) );
      CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction( szFunctionName, funcHandler );

      object->SetValue( szFunctionName, func, V8_PROPERTY_ATTRIBUTE_NONE );
   }
}

CefRefPtr<CefV8Value> CJavaScriptDelegate::GetOrCreateObject(CefRefPtr<CefV8Context> context, const TString& qualifiedName, TString& outName)
{
   CefRefPtr<CefV8Value> resultObject = context->GetGlobal();

   outName.Clear();

   TStringSTLArray   nameTokens;
   TStringExt::Tokenize( qualifiedName, nameTokens, "." );

   size_t tokensCnt = nameTokens.size();
   if ( tokensCnt <= 1 )
   {
       outName = qualifiedName;
   }
   else
   {
      // find sub-objects for all but the last one
      for(size_t iToken=0; iToken<tokensCnt-1; iToken++)
      {
         const wchar_t* szName = nameTokens[ iToken ];
         if ( resultObject->HasValue( szName ) )
         {
            resultObject = resultObject->GetValue( szName );
         }
         else
         {
            CefRefPtr<CefV8Value> subObj = CefV8Value::CreateObject( nullptr, nullptr );
            resultObject->SetValue( szName, subObj, V8_PROPERTY_ATTRIBUTE_NONE );
            resultObject = subObj;
         }
      }

      // and the last one goes out as a name
      outName = nameTokens[ tokensCnt - 1 ];
   }

   return resultObject;
}
thedarkbrainer
Newbie
 
Posts: 7
Joined: Sun Mar 15, 2020 10:05 pm

Previous

Return to Support Forum

Who is online

Users browsing this forum: Google [Bot] and 87 guests