chromiumembedded / cef

Chromium Embedded Framework (CEF). A simple framework for embedding Chromium-based browsers in other applications.
https://bitbucket.org/chromiumembedded/cef/
Other
3.09k stars 450 forks source link

HasDocument never returns True for InertiaJS Applications #3682

Open cjserio opened 2 months ago

cjserio commented 2 months ago

It seems like CEF does not like applications built with InertiaJS. Our application, even a very barebones test application seems to load fine with even the latest CEF (123.0.8) but CefBrowser::HasDocument always returns False. I've tried this on Mac and Windows builds and both display the same behavior. I should also mention that HasDocument seems to be working fine for every other website I throw at is, so long as it's not an InertiaJS application.

Steps to reproduce the behavior: 1) Navigate to an InertiaJS application such as https://demo.inertiajs.com/login 2) Check return value from CefBrowser::HasDocument

Windows 10 and MacOS 14.4 CEF (123.0.8)

magreenblatt commented 2 months ago

Where in your code are you testing CefBrowser::HasDocument? Have you tried implementing the CefRequestHandler::OnDocumentAvailableInMainFrame callback?

This status/callback is based on Chromium calling WebContentsObserver::PrimaryMainDocumentElementAvailable. If that's not working then it would be some issue in Chromium, and you would need to build/debug the Chromium code to figure out what, exactly, is going wrong.

cjserio commented 2 months ago

Ok THIS behaves strangely. OnDocumentAvailableInMainFrame does get called and if i use that browser I get back TRUE.

void myClass::OnDocumentAvailableInMainFrame(CefRefPtr<CefBrowser> browser)
{
   printf("OnDocumentAvailableInMainFrame: Browser says document %s\n", browser->HasDocument() ? "True" : "False");

    if(m_browser == browser)
        printf("They're the same\n");
    else
        printf("They're different\n");
}

The issue seems to be that the browser I get in that callback differs from the one that we cache (m_browser) from OnAfterCreated.

So to summarize, m_browser is different than the callback browser. The callback browser properly answers the HasDocument() question, the cached m_browser does not.

magreenblatt commented 2 months ago

You can't compare CefRefPtr<> directly. What does m_browser->IsSame(browser) return? Also, check both browser->HasDocument() and m_browser->HasDocument() in OnDocumentAvailableInMainFrame.

cjserio commented 2 months ago

Ah of course, they're ref counted.

So this code:

void myClass::OnDocumentAvailableInMainFrame(CefRefPtr<CefBrowser> browser)
{
    printf("OnDocumentAvailableInMainFrame: Browser says document %s\n", browser->HasDocument() ? "True" : "False");
    printf("Is Same Browser: %s\n", m_browser->IsSame(browser) ? "Yes" : "No");
    printf("m_browser->HasDocument() = %s, browser->HasDocument() = %s\n", m_browser->HasDocument() ? "True" : "False", browser->HasDocument() ? "True" : "False");
}

Results in this printout:

OnDocumentAvailableInMainFrame: Browser says document True
Is Same Browser: Yes
m_browser->HasDocument() = True, browser->HasDocument() = True
magreenblatt commented 2 months ago

OK, so the issue looks like your timing of the HasDocument call. I suggest you use the OnDocumentAvailableInMainFrame callback instead, for better reliability.

cjserio commented 2 months ago

I'm polling the cached browser every frame and it's False before and long after the callback from OnDocumentAvailableInMainFrame. It doesn't seem like I'm mis-timing it.

magreenblatt commented 2 months ago

I'm polling the cached browser every frame

From where exactly?

cjserio commented 2 months ago

From our application's main loop. Once the browser's loaded and we get OnAfterCreated called, we stash the m_browser instance to communicate with the browser during its lifetime. So we're polling m_browser->IsLoading() and m_browser->HasDocument() to know when everything's finally ready.

magreenblatt commented 2 months ago

You might run in a debugger to see if CefBrowserContentsDelegate::DidFinishNavigation is setting has_document_ = false (code) after the call to OnDocumentAvailableInMainFrame.

cjserio commented 2 months ago

Yes, this line is being hit:

https://github.com/chromiumembedded/cef/blob/81a0648ee1069b2464791249630fd5cbe41bfa1c/libcef/browser/browser_contents_delegate.cc#L478C5-L478C18

magreenblatt commented 2 months ago

Yes, this line is being hit:

After the call to OnDocumentAvailableInMainFrame for same (main) frame?

cjserio commented 2 months ago

It's definitely after OnDocumentAvailableInMainFrame though I'm not exactly sure how to compare the frames properly.

cjserio commented 2 months ago

Hello! I still assert this is a bug and should be reopened. I believe the HasDocument accessor exists to be "polled" so that events such as OnDocumentAvailableInMainFrame don't have to be tracked and cached by the client. Is there more information I can get you to aid in resolving this? It's currently preventing our application from working and while we can and will cache the value from OnDocumentAvailableInMainFrame, I'd like to see HasDocument fixed so we can go back to polling in the near future.

magreenblatt commented 2 months ago

I still assert this is a bug and should be reopened.

Agreed.