Using CEF in a Host Application

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

Using CEF in a Host Application

Postby ba88 » Wed Jul 25, 2018 10:37 am

Hello everyone.

I am a developer of audio-processing plugins, and currently interested in using CEF to implement Web-based GUI.
I've been playing around with CEF for almost a week now, and I came across a few issues and dilemmas.
I would really appreciate any form of help/tips/thoughts regarding my progress so far.

First, some limitations of being an audio plugin, that should be taken into consideration:
  • A plugin is a small module, deployed as a dynamic lib. It has no executable and has to be loaded within a context of a host application - a DAW (Digital Audio Workstation).
  • When being shown on screen, the host application supplies the plugin with a window handle. The plugin is expected to handle draw/paint events which are sent to this handle from the host application. (The plugin is still alive and does processing even when the user hides its window).

A note regarding the current plugin infrastructure (might be worth noting):
  • There is a shell module which is created when the first plugin is loaded and destroyed when the host application quits. It is global to all loaded plugins.

Here are the issues that seem pretty crucial to me at the moment:
  1. The plugins are currently supported by over 30 different host applications, and I can’t guarantee that everyone would be cool with implementing the CefAppProtocol. Is there any way around this? Even by sacrificing some functionality (a plugin is anyway much more light-weight than an application). I currently have a Monkey Patch using Method Swizzling, and it feels a little hackish. I’m pretty new to Objective C development and wanted to know if this approach is acceptable, or should I expect some serious bugs? (reimplementing NSApp methods sounds kinda serious).
  2. I have no access to the application’s main message loop. I am dependent on the draw/paint events I receive whenever my window is being shown, and that’s it. Currently, I am calling CefDoMessageLoopWork() on each plugin’s draw event, but it seems a bit excessive. Any idea how to address this issue? Should I try Method Swizzling again?

In general, referring to the CEF sample projects, I see it as the shell being a CefApp, and every loaded plugin being a CefClient. I am currently able to embed a browser inside a plugin (although extremely buggy and unstable). Development is being done under Mac at the moment, but a Windows version is also planned (So if you foresee any issues there, I would be glad to hear them).

I know that this is not the typical application setup, but I feel that this is doable with CEF, so I would love to hear from you guys what you think, any pieces of advice, tips, and remarks. (I would prefer leaving CEF and Chromium frameworks untouched, so it could be deployed separately, as Chromium updates pretty frequently).

Thanks in advance!
ba88
Newbie
 
Posts: 5
Joined: Tue Jul 24, 2018 9:20 am

Re: Using CEF in a Host Application

Postby magreenblatt » Wed Jul 25, 2018 12:01 pm

Implementing the CefAppProtocol via swizzling should not damage the host application. You can see an example here: https://bitbucket.org/chromiumembedded/ ... m#lines-69. You can call CefDoMessageLoopWork using a timer in combination with CefBrowserProcessHandler::OnScheduleMessagePumpWork. You will need to parent the CEF browser window to an NSWindow retrieved from the host application. The Cocoa framework should then handle resizing for you.

For Windows see the discussion at viewtopic.php?f=6&t=15774. It covers most of the relevant details.

A bigger problem for you will be if multiple plugins attempt to load CEF at the same time in the same host application. In that case CEF support should be moved into the host application so that all plugins share the same single initialized version.
magreenblatt
Site Admin
 
Posts: 12407
Joined: Fri May 29, 2009 6:57 pm

Re: Using CEF in a Host Application

Postby ba88 » Wed Jul 25, 2018 1:40 pm

I think I have a solution for the initialization issue. I was able to initialize CEF on the first plugin instantiation and shut it down when the host application quits. It seems to be working fine at the moment.

Will get to implementing the message-loop part now.

Thank you! Much appreciated!
ba88
Newbie
 
Posts: 5
Joined: Tue Jul 24, 2018 9:20 am

Re: Using CEF in a Host Application

Postby ba88 » Wed Aug 01, 2018 9:48 am

Hello again,

So... I am currently able to open a plugin window and place the CEF browser inside of it - awesome! (I am using cefclient as a reference)
I modified cefclient's RootWindow class a bit to do so.
However, whenever I remove a plugin, the helper process remains alive (I am currently using cefclient Helper as the render process, no modifications at all).
Digging a little deeper, I see that I am reaching the BrowserHost::CloseBrowser(), but not getting a response.
Note: when I open a DevTool window, if I close it I will follow the same flow, but this time I DO get a response, as I am reaching the closing flow (WindowDestroyed() and such). The DevTools' subprocess does quit.
EDIT: Force Close doesn't seem to have any effect.
I am having trouble breaking and debugging in the CEF/Chromium code (the sources are being built at the moment), but from what I saw it looks like there is an issue with the 'beforeunload' functionality.

Before I get into the multi-process debugging, are there any things that I might have missed? Maybe some wrong configuration? (using the cefclient Helper as is?) some missing JS?
I think that I am missing out something pretty basic, but I am not sure even where to start looking.

Thanks a lot!
ba88
Newbie
 
Posts: 5
Joined: Tue Jul 24, 2018 9:20 am

Re: Using CEF in a Host Application

Postby magreenblatt » Wed Aug 01, 2018 11:22 am

See the documentation on the DoClose method: https://bitbucket.org/chromiumembedded/ ... dler.h-100. Your issue is most likely related to that flow.
magreenblatt
Site Admin
 
Posts: 12407
Joined: Fri May 29, 2009 6:57 pm

Re: Using CEF in a Host Application

Postby ba88 » Thu Aug 02, 2018 11:14 am

After building from sources and being able to debug properly, I noticed that my plugin was following the same path as cefclient, until receiving a response message from the renderer process.
My code was being blocked in: WebContentsImpl::Close(), because view_->IsEventTracking() was constantly true, resulting in an infinite loop.
Digging deeper, I finally noticed that my implementation of ClientApplication::isHandlingSendEvent was constantly returning YES (reminder: I used swizzled methods to expand the host application functionality).
I noticed that the YES value was sometimes of a grabage random value, and eventually, explicitly initializing BOOL ClientApplication::handlingSendEvent_ with NO solved everything.

I am still not 100% sure that this is the correct solution, because cefclient (which I built on my machine) was acting OK, and I used the same ClientApplication implementation in my plugin.
Are there any kind of build configuration/flags I should be aware of (Or something else which could affect the default values in ObjC)?

Thanks.
ba88
Newbie
 
Posts: 5
Joined: Tue Jul 24, 2018 9:20 am

Re: Using CEF in a Host Application

Postby magreenblatt » Thu Aug 02, 2018 12:48 pm

There's no swizzling in cefclient. Perhaps the swizzling causes variables not to be default-initialized.

See files in the binary distribution cmake directory for the compile/link configuration recommended by CEF.
magreenblatt
Site Admin
 
Posts: 12407
Joined: Fri May 29, 2009 6:57 pm

Re: Using CEF in a Host Application

Postby ba88 » Mon Aug 27, 2018 3:00 am

Hi again :)

The plugin slowly starts to take shape, thanks for all your help so far.
I am currently experiencing some GUI sluggishness, and found this reported bug:
https://bitbucket.org/chromiumembedded/cef/issues/2203/low-fps-with-cefdomessageloopwork-or
(I've set the message-pump to 60 fps and devtools is showing ~15fps)
Is there currently a workaround for this bug? (Or any lead on how to solve it?) Or might it be a different issue?

Thanks!
ba88
Newbie
 
Posts: 5
Joined: Tue Jul 24, 2018 9:20 am

Re: Using CEF in a Host Application

Postby kyr0 » Wed Aug 29, 2018 12:06 pm

Hi ba88,

it seems like we've got the exact same idea (using CEF in an Audio Plugin for rendering) - my idea even goes a little beyond and I would like to extend the integration to try to do DSP in-browser (using WebAssembly). But... I'm at the very beginning of the impl. and I would have to find exactly the same solutions you already found... and it doesn't sound like a very simple task...

Would you maybe be able to help me? I'm on an expert level regarding all web technologies (even wrote a book for O'Reilly) but a I'm a bloody beginner in C++ and Obj-C :/
I would like to help you with the web tech stuff / UI in response if you need any help.

Thanks in advance and best,
Aron
kyr0
Newbie
 
Posts: 7
Joined: Wed Aug 29, 2018 7:03 am


Return to Support Forum

Who is online

Users browsing this forum: Google [Bot] and 41 guests