Page 1 of 1
Eval
Posted: Mon Jul 24, 2017 8:25 pm
by xpert13
Hello. guys.
Help me please to understand how can I use Eval method of V8Context.
First of all I need to get V8Context. When I try go use next code in main process it throw error:
Code: Select all
TCefv8ContextRef.Current.Eval(sScript, '', 1, TempValue, TempException);
The process need to be PID_BROWSER (I am right?). But how can I send message to this process and read this message?
Re: Eval
Posted: Tue Jul 25, 2017 12:08 pm
by salvadordf
Hi,
The V8 engine runs in a separate process and you would need to send and receive messages between processes to use eval.
It's much easier to use TChromium.ExecuteJavaScript to execute a JS script.
The MiniBrowser demo has all the code necessary to execute and get the results from the scripts in the Delphi form.
Re: Eval
Posted: Tue Jul 25, 2017 7:07 pm
by xpert13
It's much easier to use TChromium.ExecuteJavaScript to execute a JS script.
I know, but I need eval.
The MiniBrowser demo has all the code necessary to execute and get the results from the scripts in the Delphi form.
The MiniBrowser has too much functions and I don't understand which of them useful for me and which is not
Re: Eval
Posted: Tue Jul 25, 2017 8:57 pm
by salvadordf
Hi,
I uploaded a separate demo called JSExtension only with the JavaScript extension code.
You should be able to call TCefv8ContextRef.Current.Eval inside the extension in uTestExtension.pas and get the results in the
TJSExtensionFrm.Chromium1ProcessMessageReceived event.
The code comments explain all the steps.
Re: Eval
Posted: Thu Jul 27, 2017 6:00 pm
by xpert13
I don't need extensions but your demo code was helpful for me. The right solution in my case was:
1. Create TCefCustomRenderProcessHandler, fill MessageName and OnCustomMessage properties
Code: Select all
FProcessHandler := TCefCustomRenderProcessHandler.Create;
FProcessHandler.MessageName := EVAL_JS;
FProcessHandler.OnCustomMessage := RenderProcessHandler_OnCustomMessage;
GlobalCEFApp.RenderProcessHandler := FProcessHandler as ICefRenderProcessHandler;
2. Send to render process message with code for eval
Code: Select all
var
msg: ICefProcessMessage;
begin
msg := TCefProcessMessageRef.New(EVAL_JS);
msg.ArgumentList.SetString(0, sScript);
FChromium.SendProcessMessage(PID_RENDERER, msg);
3. Catch this message in render proccess
Code: Select all
procedure TChromiumClient.RenderProcessHandler_OnCustomMessage(const pBrowser: ICefBrowser;
uSourceProcess: TCefProcessId; const pMessage: ICefProcessMessage);
var
pV8Context : ICefv8Context;
pReturnValue : ICefv8Value;
pException : ICefV8Exception;
begin
if (pMessage = nil) or (pMessage.ArgumentList = nil) then exit;
if pMessage.Name = EVAL_JS then
begin
pV8Context := pBrowser.MainFrame.GetV8Context;
if pV8Context.Enter then
begin
pV8Context.Eval(pMessage.ArgumentList.GetString(0), '', 1, pReturnValue, pException);
ParseEvalJsAnswer(pMessage, pBrowser, pReturnValue, pException);
pV8Context.Exit;
end;
end;
end;
4. Parse the results and send message back to browser process
Code: Select all
procedure TChromiumClient.ParseEvalJsAnswer(const pMessage: ICefProcessMessage; pBrowser: ICefBrowser;
pReturnValue : ICefv8Value; pException : ICefV8Exception);
var
pAnswer: ICefProcessMessage;
strResult : String;
bGoodDataType : Boolean;
begin
pAnswer := TCefProcessMessageRef.New(EVAL_JS);
if (pReturnValue = nil) or (not pReturnValue.IsValid) then
begin
pAnswer.ArgumentList.SetBool(0, false);
pAnswer.ArgumentList.SetString(1, pException.Message);
end else
begin
bGoodDataType := True;
if pReturnValue.IsString then strResult := pReturnValue.GetStringValue
else if pReturnValue.IsBool then strResult := BooleanToStr(pReturnValue.GetBoolValue)
else if pReturnValue.IsInt then strResult := IntToStr(pReturnValue.GetIntValue)
else if pReturnValue.IsUInt then strResult := IntToStr(pReturnValue.GetUIntValue)
else if pReturnValue.IsDouble then strResult := FloatToStr(pReturnValue.GetDoubleValue)
else bGoodDataType := False;
if bGoodDataType then
begin
pAnswer.ArgumentList.SetBool(0, true);
pAnswer.ArgumentList.SetString(1, strResult);
end else
begin
pAnswer.ArgumentList.SetBool(0, false);
pAnswer.ArgumentList.SetString(1, 'Result data type need to be string, int, uint or double!');
end;
end;
pBrowser.SendProcessMessage(PID_BROWSER, pAnswer);
end;
5. And catch result message in OnProcessMessageReceived of browser process
P.S. Thank you,
salvadordf, for your work and help.