Page 1 of 2

Get document

Posted: Fri Jul 26, 2019 1:26 pm
by X11
how get Document: ICefDomDocument from Chromium1

Code: Select all


SimpleNodeSearch(Chromium1...???, 'link-ajax j-v-contacts-expand-link');
Thanx

Re: Get document

Posted: Fri Jul 26, 2019 2:14 pm
by salvadordf
The DOMVisitor demo shows how to get a ICefDomDocument instance and make simple node searches using TCefFastDomVisitor2.

Chromium allows you to access ICefDomDocument in the render process and you will need to send messages to the browser process to use the results in Delphi. Read the code comments for more details.

Re: Get document

Posted: Tue Aug 20, 2019 9:50 am
by X11
comment in uDOMVisitor
// To send messages from the render process you must use the browser.SendProcessMessage
// procedure with a PID_BROWSER parameter. The browser process receives those messages in
// the TChromium.OnProcessMessageReceived event.

Code: Select all

MSG1 = 'mymessage';
...
...
...

procedure TMiniBrowserFrm.Chromium1LoadEnd(Sender: TObject;
  const browser: ICefBrowser; const frame: ICefFrame;
  httpStatusCode: Integer);
var
  msg: ICefProcessMessage;
begin

  if frame.IsMain then
  begin
    msg := TCefProcessMessageRef.New(MSG1);
    msg.ArgumentList.SetString(0, 'Chromium1LoadEnd');

    browser.SendProcessMessage(PID_BROWSER, msg); // error here
    
  end;
end;
[dcc32 Error] uMiniBrowser.pas(978): E2003 Undeclared identifier: 'SendProcessMessage'

Re: Get document

Posted: Tue Aug 20, 2019 10:05 am
by salvadordf
Thanks for reporting this issue!

The latest CEF API moved that procedure to the ICefFrame interface. The demos use the right "frame" parameter to call SendProcessMessage but the comments are outdated.

It should say :

Code: Select all

// To send messages from the render process you must use the frame.SendProcessMessage
// procedure with a PID_BROWSER parameter. The browser process receives those messages in
// the TChromium.OnProcessMessageReceived event.
I'll fix it the next time I upload a new CEF4Delphi version.

Re: Get document

Posted: Tue Aug 20, 2019 10:10 am
by X11
Ok. But, how can I solve my problem (problem) now?
Thnx

Re: Get document

Posted: Tue Aug 20, 2019 10:14 am
by salvadordf
replace this :

Code: Select all

browser.SendProcessMessage(PID_BROWSER, msg);
with this :

Code: Select all

frame.SendProcessMessage(PID_BROWSER, msg);

Re: Get document

Posted: Tue Aug 20, 2019 10:48 am
by X11

Code: Select all

procedure CreateGlobalCEFApp;
begin
  GlobalCEFApp                          := TCefApplication.Create;
  GlobalCEFApp.RemoteDebuggingPort      := 9000;

  GlobalCEFApp.OnProcessMessageReceived := GlobalCEFApp_OnProcessMessageReceived;

  GlobalCEFApp.DisableFeatures          := 'NetworkService';
  GlobalCEFApp.Cache                    := 'cache';//ExtractFilePath(Application.ExeName) + 'Cache\' ;
  GlobalCEFApp.UserDataPath             := 'UserData';// ExtractFilePath(Application.ExeName) + 'UserData\';
  GlobalCEFApp.LogFile              := 'debug.log';
  GlobalCEFApp.LogSeverity          := LOGSEVERITY_INFO;

end;
on form i drop Memo1 and add code "MiniBrowserFrm.Memo1.Lines.Add('GlobalCEFApp_OnProcessMessageReceived');"

Code: Select all

procedure GlobalCEFApp_OnProcessMessageReceived(const browser       : ICefBrowser;
                                                const frame         : ICefFrame;
                                                      sourceProcess : TCefProcessId;
                                                const message       : ICefProcessMessage;
                                                var   aHandled      : boolean);
var
  TempFrame   : ICefFrame;
  TempVisitor : TCefFastDomVisitor2;
begin
  aHandled := False;
  MiniBrowserFrm.Memo1.Lines.Add('GlobalCEFApp_OnProcessMessageReceived');
  ...
  
  ....
end; 
but line "GlobalCEFApp_OnProcessMessageReceived" does not appear in Memo1




in memo i see only "Chromium1LoadEnd"

Code: Select all

procedure TMiniBrowserFrm.Chromium1LoadEnd(Sender: TObject;
  const browser: ICefBrowser; const frame: ICefFrame;
  httpStatusCode: Integer);
var
  msg: ICefProcessMessage;
begin
  if frame.IsMain then
  begin
    msg := TCefProcessMessageRef.New(MSG1);
    msg.ArgumentList.SetString(0, 'Chromium1LoadEnd');
    frame.SendProcessMessage(PID_BROWSER, msg);
    Memo1.Lines.Add('Chromium1LoadEnd');
  end;
end;

Re: Get document

Posted: Tue Aug 20, 2019 10:57 am
by salvadordf
GlobalCEFApp.OnProcessMessageReceived is executed in the render process and it's not possible to access anything from the browser process directly.
The Memo is one of the controls created in the browser process and it's not possible to use it from the render process.

You need to send a process message to send that information from the render process to the browser process.

Re: Get document

Posted: Tue Aug 20, 2019 11:00 am
by X11
ok, where, how?

Re: Get document

Posted: Tue Aug 20, 2019 11:13 am
by salvadordf
Add this inside the GlobalCEFApp_OnProcessMessageReceived procedure :

Code: Select all

procedure GlobalCEFApp_OnProcessMessageReceived(const browser       : ICefBrowser;
                                                const frame         : ICefFrame;
                                                      sourceProcess : TCefProcessId;
                                                const message       : ICefProcessMessage;
                                                var   aHandled      : boolean);
var
  msg: ICefProcessMessage;
begin
  msg := TCefProcessMessageRef.New(MY_CUSTOM_MESSAGE_NAME);
  msg.ArgumentList.SetString(0, 'This is the information I need to send to the browser process');
  frame.SendProcessMessage(PID_BROWSER, msg);
end;  
Then modify TChromium.OnProcessMessageReceived to handle a message with the "MY_CUSTOM_MESSAGE_NAME" name

Code: Select all

procedure TDOMVisitorFrm.Chromium1ProcessMessageReceived(Sender: TObject;
  const browser: ICefBrowser; const frame: ICefFrame; sourceProcess: TCefProcessId;
  const message: ICefProcessMessage; out Result: Boolean);
begin
  Result := False;

  if (message = nil) or (message.ArgumentList = nil) then exit;

  if (message.Name = MY_CUSTOM_MESSAGE_NAME) then
    begin
      // You should save message.ArgumentList.GetString(0) in a class field for later processing because TChromium.OnProcessMessageReceived is executed in a CEF thread and we shouldn't handle VCL controls outside the main application thread.
      Memo1.Lines.Add(message.ArgumentList.GetString(0));
      Result := True;
    end;
end;