fpCef3: browser talk to Host (=Lazarus app)
lazarus / 38-Networking and Web Programming
----------------------------------------------------------------------
PaulANormanNZ · 2018-01-22 03:01
Before I start dredging the enormous thousands of the CEF Forum
messages -
1. has any one successfully implemented Javascript in a hosted
document "talking" to FP objects / procedures in a Lazarus Host
project - I see hints in the DOM that this might be achievable...
2. Also in a similar way I see that we can call a JavaScript function
in the Browser from Lazarus - can we receive a returned string,
object etc... into Lazarus from the hosted browser?
Ok, so we can do...
Code: HTML5 [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
Hi!
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i procedure
TForm1.btnDoJavaScriptClick(Sender: TObject);begin
Chromium.Browser.MainFrame.ExecuteJavaScript('myFunct("hello")',
'about:blank', 0);end;
And a nice alert() or whatever requested will take place.
But can I usefully receive something back to a Lazarus app from
JavaScript in the Browser? As in the html script being along the lines
of...
Code: Javascript [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
And then (pseudo code) something looking a bit like...
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i var
ResponseText : string; ResponseText :=
Chromium.Browser.MainFrame.ExecuteJavaScript('myFunct("hello")',
'about:blank', 0) as string;
Or even an ICef object or variant of some sort?
Any help appreciated please,
Paul
----------------------------------------------------------------------
PaulANormanNZ · 2018-01-22 03:47
P.S. related to other posts I've made on fpCEF - I'm thinking it
would be useful to be able to exchange JSON strings between Lazarus
and the hosted CEF browser,
where carefully crafted JavaScript in the browser frame document could
handle many things and return results to Lazarus
- avoiding much Lazarus coding perhaps - why rebuild the wheel if
JavaScript in the Lazarus hosted Browser can already drive the DOM?
----------------------------------------------------------------------
avra · 2018-01-22 07:23
Quote from: PaulANormanNZ on January 22, 2018, 04:47:29 amcarefully
crafted JavaScript in the browser frame document could handle many
things and return results to LazarusIf you decide to take this route
then JSONRPC might be interesting to you:
FPC: https://github.com/graemeg/freepascal/tree/master/packages/fcl-
web/examples/jsonrpc/demo1
3rd party: http://www.jbsolucoes.net/ceosserver/
----------------------------------------------------------------------
dliw · 2018-01-22 09:59
If you combine the DomAccess and JavaScript fpCEF examples, you have
all you need.
Also see this code on how to use messaging:
https://forum.lazarus.freepascal.org/index.php/topic,34519.msg226411.h
tml#msg226411
fpCEF already provides an OOP abstraction for all low level APIs, but
one cannot abstract the complexity of having multiple processes.
For message passing you have ICefProcessMessage, which allows you to
pass all default value types and even binary streams (see ICefValue).
Of course you could pass data only via JSON strings, but IMO you would
only replace the existing in-built system with a different one adding
even more complexity.
----------------------------------------------------------------------
PaulANormanNZ · 2018-02-02 07:40
Hi,
Thanks for the Posts.
Still just wondering ...
1. has any one successfully implemented Javascript in a hosted
document "talking" to FP objects / procedures in a Lazarus Host
project - I see hints in the DOM that this might be achievable...
2. Also in a similar way I see that we can call a JavaScript function
in the Browser from Lazarus - can we receive a returned string,
object etc... into Lazarus from the hosted browser?
- I can't yet see how messaging does that. Can these get "things"
back to the application?...
QuoteFor message passing you have ICefProcessMessage, which allows you
to pass all default value types and even binary streams (see
ICefValue).
Any thoughts please,
Paul
----------------------------------------------------------------------
dliw · 2018-02-02 09:01
The answer to both is: yes
Please see the Javascript example:
1. See TCustomRenderProcessHandler.OnWebKitInitialized:
There is
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i native
function GetTestParam()which registers a Pascal function in
Javascript.
Every time you call a native function the registered handler
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
TMyHandler.Executeis called.
There you have every information needed to handle the call:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i //
Structure that should be implemented to handle V8 function calls.
The// functions of this structure will be called on the thread
associated with the// V8 function.TCefV8Handler = record [..] //
Handle execution of the function identified by |name|. |object| is
the // receiver ('this' object) of the function. |arguments| is the
list of // arguments passed to the function. If execution succeeds
set |retval| to the // function return value. If execution fails set
|exception| to the exception // that will be thrown. Return true (1)
if execution was handled. execute: function(self: PCefv8Handler;
const name: PCefString; object_: PCefv8Value; argumentsCount:
csize_t; arguments: PCefV8ValueArray; out retval: PCefV8Value;
exception: PCefString): Integer; cconv;end;
This also is the bridge between Pascal and Javascript: You can pass
data to Pascal by calling a native function, you can pass data to
Javascript by calling a Javascript function, which in turn calls a
native function: retval can be a ICefDictionaryValue, so it is not
limited to a single value.
If you have a lot of data to pass to Javascript, you could also
register a custom scheme with a custom scheme handler (think of it as
a custom protocol, e.g. cefinternal://). Javascript then could load
data from this scheme (e.g. JSON files).
QuoteAny thoughts please,Code has already been posted here.
The relevant parts are:
1. A custom render process handler for the render process:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i type
TCustomRenderProcessHandler = class(TCefRenderProcessHandlerOwn)
protected function OnProcessMessageReceived(const browser:
ICefBrowser; sourceProcess: TCefProcessId; const message:
ICefProcessMessage): Boolean; override; end;
2. Implement messages, the example defines the message visitdom.
You can pass data via ICefProcessMessage.ArgumentList.
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i function
TCustomRenderProcessHandler.OnProcessMessageReceived (const browser:
ICefBrowser; sourceProcess: TCefProcessId; const message:
ICefProcessMessage): Boolean;begin case message.Name of
'visitdom': begin
browser.MainFrame.VisitDomProc(@VisitDOM); Result := True;
end; else Result := inherited; end;end;
This part is for communicating UI process to render process
3. The counterpart for the UI process is OnProcessMessageReceived in
TChromium. There you can handle messages for communicating render
process to UI process.
4. Send messages:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
browser.SendProcessMessage(PID_RENDERER,
TCefProcessMessageRef.New('visitdom'));
For also passing data you only need to set
TCefProcessMessageRef.ArgumentList.
I really hope this helps you to get started finally.
----------------------------------------------------------------------
PaulANormanNZ · 2018-02-03 00:48
Thanks,
QuoteI really hope this helps you to get started finally.
I'm sure it will, for some reason it just hadn't "clicked" into place
- it actually seems all very indirect, or "bulky" in approach I
suppose.
Will get head down and follow it all through.
Thanks again for patiently explaining it,
Paul