Disclosure Statement: This site contains affiliate links, which means that I may receive a commission if you make a purchase using these links. As an eBay Partner, I earn from qualifying purchases.

Get document

X11
Posts: 49
Joined: Thu Jul 25, 2019 10:15 am

Get document

Post by X11 »

how get Document: ICefDomDocument from Chromium1

Code: Select all


SimpleNodeSearch(Chromium1...???, 'link-ajax j-v-contacts-expand-link');
Thanx
User avatar
salvadordf
Posts: 4052
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Get document

Post 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.
X11
Posts: 49
Joined: Thu Jul 25, 2019 10:15 am

Re: Get document

Post 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'
User avatar
salvadordf
Posts: 4052
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Get document

Post 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.
X11
Posts: 49
Joined: Thu Jul 25, 2019 10:15 am

Re: Get document

Post by X11 »

Ok. But, how can I solve my problem (problem) now?
Thnx
User avatar
salvadordf
Posts: 4052
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Get document

Post by salvadordf »

replace this :

Code: Select all

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

Code: Select all

frame.SendProcessMessage(PID_BROWSER, msg);
X11
Posts: 49
Joined: Thu Jul 25, 2019 10:15 am

Re: Get document

Post 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;
User avatar
salvadordf
Posts: 4052
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Get document

Post 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.
X11
Posts: 49
Joined: Thu Jul 25, 2019 10:15 am

Re: Get document

Post by X11 »

ok, where, how?
User avatar
salvadordf
Posts: 4052
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Get document

Post 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;
Post Reply