Page 1 of 2

OnWebKitInitialized isn't fired

Posted: Thu Aug 31, 2017 1:34 pm
by Albus
Hi, I'm trying to register an own extension to chromium with the CefRegisterExtension command. Here is my code:

Code: Select all

procedure ProcessHandler_OnWebKitInitializedEvent;
var
  code: string;
begin
  code := '__defineGetter__(''app'', function(){native function $get();return $get()});';
  CefRegisterExtension('app', code, TDVCefBridge.Create as ICefv8Handler);
end;

class procedure TMyClass.InitChromium;
var
  TempProcessHandler: TCefCustomRenderProcessHandler;
begin
  TDVCefBridge.FCallbackClasses := TDictionary<TChromium,TValue>.Create;

  TempProcessHandler := TCefCustomRenderProcessHandler.Create;
  TempProcessHandler.OnWebKitInitializedEvent := ProcessHandler_OnWebKitInitializedEvent;

  GlobalCEFApp := TCefApplication.Create;
  GlobalCEFApp.CheckCEFFiles := False;
  GlobalCEFApp.EnableHighDPISupport := True;
  GlobalCEFApp.RenderProcessHandler := TempProcessHandler as ICefRenderProcessHandler;
  GlobalCEFApp.StartMainProcess;
end;
I call the InitChromium procedure as first command in the dpr file. But neither the event procedure is ever called nor I can access "app" in JavaScript.

But when I add "GlobalCEFApp.SingleProcess := True;" to the Init procedure, everything works fine. But this is not an option for production use.

Can anyone help me? If you need more code or explanations, just ask :)

Re: OnWebKitInitialized isn't fired

Posted: Thu Aug 31, 2017 4:02 pm
by salvadordf
Hi Albus,

The TCefCustomRenderProcessHandler.OnWebKitInitializedEvent event is triggered after a browser is created.
In the JSExtension demo the browser is created in the TJSExtensionFrm.FormShow event with the call to Chromium1.CreateBrowser(CEFWindowParent1, '').

You can check this by adding text messages to the 'debug.log' file with something like this :
CefLog('CEF4Delphi', 1, CEF_LOG_SEVERITY_ERROR, 'My custom debug text');
You'll probably need to add uCEFMiscFunctions and uCEFConstants to the uses clause to use the CefLog function.

Without the rest of your code, I can only tell you that the GlobalCEFApp.StartMainProcess call MUST be in a if..then clause like this :

Code: Select all

  if GlobalCEFApp.StartMainProcess then
    begin
      Application.Initialize;
      {$IFDEF DELPHI11_UP}
      Application.MainFormOnTaskbar := True;
      {$ENDIF}
      Application.CreateForm(TJSExtensionFrm, JSExtensionFrm);
      Application.CreateForm(TSimpleTextViewerFrm, SimpleTextViewerFrm);
      Application.Run;
    end;
If you don't do this you'll have problems with the subprocesses as explained in this web page :
https://www.briskbard.com/index.php?lang=en&pageid=cef

Take a look at the JSExtension demo to register your own extension.

Re: OnWebKitInitialized isn't fired

Posted: Fri Sep 01, 2017 9:08 am
by Albus
Hi, I changed my code know so I use the if-statement, but "nothing" changed. Where can I find the log file?

Re: OnWebKitInitialized isn't fired

Posted: Fri Sep 01, 2017 10:01 am
by salvadordf
I forgot to tell you that you have to add this before the GlobalCEFApp.StartMainProcess call :

Code: Select all

  GlobalCEFApp.LogFile              := 'debug.log';
  GlobalCEFApp.LogSeverity          := LOGSEVERITY_ERROR;
The 'debug.log' file will be next to your EXE.

Take the JSExtension as a base for your application. It's a working example of a simple javascript extension and its registration.

Edit : Be sure to give a unique name to your extension. There should be nothing called the same way.

Re: OnWebKitInitialized isn't fired

Posted: Fri Sep 01, 2017 11:11 am
by Albus
The log says that the OnWebkitinitialized Event is called twice (I have two browsers in my app), but still I can't access the registered extension from JavaScript.
But if I activate GlobalCEFApp.SingleProcess it works.

Re: OnWebKitInitialized isn't fired

Posted: Fri Sep 01, 2017 12:11 pm
by Albus
Hm, I added some more logging, and saw that the Execute function is called every time a try to access the extension. But I can't debug the function (I think because of mutli processes?). Is there any way to debug the execute function without using singleprocess mode? Because in single process mode everything works fine

Re: OnWebKitInitialized isn't fired

Posted: Fri Sep 01, 2017 12:28 pm
by Albus
Ok, I managed to debug the subprocess and found out directly where the error is. I had reimplemented the Execute function for the extensions to support some of my own behavior. This also includes storing values in a Dictionary from within the application, which are queried later in the Execute function. However, this dictionary is never filled in the subprocesses, and since it is empty, my Execute function terminates at the beginning with the return value False.

Re: OnWebKitInitialized isn't fired

Posted: Fri Sep 01, 2017 12:55 pm
by salvadordf
Yes, javascript is executed in a different process and Delphi can't debug it.

As far as I know, you only have 3 options :
  • Use a single process and use Delphi to debug it.
  • Use multiple processes and call CefLog.
  • Use the DevTools.
In your case, I would call CefLog in multiple places. When you detect what part of the code is not executed then add more CefLog calls there with the variable contents converted to text.

You might find the DevTools useful to see any console error messages or to set javascript breakpoints. Take a look at the MiniBrowser demo to add the DevTools to your app.

Edit : I wrote this for your previous message :P I see now that you found the solution for yourself.

Re: OnWebKitInitialized isn't fired

Posted: Fri Sep 01, 2017 1:04 pm
by Albus
My solution for debugging is the "Connect with process" function in the IDE. I started the application without debugging and then I connected the IDE to the right subprocess.

However I need a solution for this problem. Even we have to use the single process mode in production or there is an other better solution, because single process mode shouldn't been used for production.

Re: OnWebKitInitialized isn't fired

Posted: Fri Sep 01, 2017 1:21 pm
by salvadordf
Perhaps you can use messages between processes to do that.

The JSEval demo sends messages in both ways :
Browser process <-> Render process