Page 1 of 1

cefQuery usage in JCEF asynchronous or synchronous?

PostPosted: Thu Aug 10, 2017 3:09 pm
by Aaron
In testing calling cefQuery our JS code appears to hang until our executing Java thread (inside the onQuery()) completes. Is this behavior expected? All the CEF documentation seems to suggest that the call initiated by cefQuery is done so asynchronously, but perhaps this is not true for JCEF? Additionally, the last line of Marshall's reply here viewtopic.php?f=17&t=12317 reads:

You should perform communication with your back-end server on a separate thread and execute CefQueryCallback asynchronously once the response is available.

Which could be interpreted as not doing that would result in the entire operation (JS->Java->JS) being performed synchronously.

Indeed, using a separate thread within our onQuery() method causes the operation perform asynchronously, which suggests that the JS code is in fact waiting for our thread to return before proceeding. My question is is this necessary? Or are we somehow using cefQuery incorrectly. I'll mention that we're not actually calling cefQuery, but a custom function (call it fooCefQuery) which is functionally identical to cefQuery, and is registered like so:

CefMessageRouter fooMessageRouter= CefMessageRouter.create(new CefMessageRouterConfig(FOO_CEF_QUERY, FOO_CEF_QUERY_CANCEL));

Re: cefQuery usage in JCEF asynchronous or synchronous?

PostPosted: Thu Aug 10, 2017 3:26 pm
by magreenblatt
What does your JS code look like? What do you mean when you say the JS code "hangs"?

Re: cefQuery usage in JCEF asynchronous or synchronous?

PostPosted: Thu Aug 10, 2017 3:57 pm
by Aaron
Thanks for the fast reply!

Our code looks like this:
Code: Select all
      return Observable.create(observer => {
            this.window.fooCefQuery({
                request: 'get-data',
                persistent: true,
                onSuccess: function(response) {
                    observer.next(response);
                    observer.complete();
                },
                onFailure: function(error_code, error_message) {
                    observer.error(error_code+":"+error_message);
                    observer.complete();
                }
            });
        })


by "hang", I mean that given the below, the JS stops executing between the submit call and do some more stuff, and does not continue on (to do some more stuff), until our Java thread has returned
Code: Select all
//do some stuff
//call submit on our Observable
//do some more stuff


We tested this by calling cefQueryCallback.success() immediately in our Java code, but then calling thread.sleep() for 10 seconds before returning. In that test, do some more stuff wasn't executed until after the 10 second delay.

Re: cefQuery usage in JCEF asynchronous or synchronous?

PostPosted: Thu Aug 10, 2017 7:08 pm
by magreenblatt
Calling thread.sleep in onQuery will block the browser process UI thread. That will keep many things from working properly. Never block the UI or IO threads.

Re: cefQuery usage in JCEF asynchronous or synchronous?

PostPosted: Fri Aug 11, 2017 8:45 am
by Aaron
The thread.sleep call isn't part of our actual code, it was just to test whether the JS code was indeed waiting for the onQuery call to finish. So then it sounds like the right thing to do is place the work on a separate thread within onQuery if we don't want our JS code to wait for that work to complete. Is that correct?

I guess a follow-up question would be what does "asynchronous" mean in the below context (from: https://bitbucket.org/chromiumembedded/ ... ew-default )

// When |window.cefQuery| is executed the request is sent asynchronously to one
// or more C++ Handler objects registered in the browser process.


To me that suggests after calling window.cefQuery, the next line of JS code would execute immediately, which is not what we see.

Re: cefQuery usage in JCEF asynchronous or synchronous?

PostPosted: Fri Aug 11, 2017 10:26 am
by magreenblatt
If you do this:

Code: Select all
window.cefQuery(...);
// next line


Then next line will be executed immediately in the renderer process. If you're blocking the browser process UI thread then you may not see the result of that execution immediately because the UI thread is likely responsible for displaying it.

Re: cefQuery usage in JCEF asynchronous or synchronous?

PostPosted: Tue Aug 15, 2017 5:59 pm
by Aaron
I see. That looks to be the issue. Confirmed via timestamps that the next line was being called immediately.

Out of curiosity, is there a reason the call to OnQuery() is dispatched on the browser process UI thread? I would think the first thing every handler would want to do is move the work to a different thread.