createBrowser with createImmediately doesn't load url

Having problems with building or using the JCEF Java binding? Ask your questions here.

createBrowser with createImmediately doesn't load url

Postby chandan » Fri Jul 03, 2020 6:59 am

Hi,

I am using JCEF in our application where we are creating a single instance of cef browser. The loadURL api is called to load the URLs using the cefBrowser insatance. First time when the browser is not created I am creating the browser with the given url using the createBrowser api. Once the browser is created the urls are loaded on the browser using loadUrl api. But, I have noticed that the browser doesn't load the url for the first time if I use createImmediately = true. From second time onward the browser can load the URLs. if I use createImmediately = false, everything works fine. However, the JVM crashes on CefApp dispose if I use createImmediately = false. The same issue as I raised in https://bitbucket.org/chromiumembedded/java-cef/issues/369/jcef-crash-on-re-parent-in

I want to use createImmediately = true to avoid the JVM crash issue, but due the above issue I am unable to use createImmediately = true

Please refer to the following sample code to understand the issue.

Code: Select all
package test;

import org.cef.CefApp;
import org.cef.CefApp.CefAppState;
import org.cef.CefApp.CefVersion;
import org.cef.CefClient;
import org.cef.CefSettings;
import org.cef.OS;
import org.cef.browser.CefBrowser;
import org.cef.handler.CefAppHandlerAdapter;
import org.cef.handler.CefDisplayHandlerAdapter;
import org.cef.handler.CefLifeSpanHandlerAdapter;
import org.cef.handler.CefLoadHandlerAdapter;
import java.awt.*;



/**
 * @author Chandan Talukdar
 */

public class JCEFBrowser {
    private static final String[] COMMAND_LINE_ARGS =
        {/*"--renderer-process-limit=1"*//*, "--disable-gpu", "--in-process-gpu"*/};
    private CefClient cefClient ;
    private boolean browserCreated;
    private CefBrowser cefBrowser;
    private static JCEFBrowser jcefBrowser;


    static JCEFBrowser getBrowserInstance() {
        if(jcefBrowser == null) {
            jcefBrowser = new JCEFBrowser();
        }
        return jcefBrowser;
    }

    JCEFBrowser() {
        initializeCefClient();
    }


    private void initializeCefClient() {

        cefClient = getCefApp().createClient();

        // The different life span phases can be captured with LifeSpanHandler
        cefClient.addLifeSpanHandler(new CefLifeSpanHandlerAdapter() {
            @Override
            public void onAfterCreated(CefBrowser browser) {
                // Browser is created and ready to load a URL
                System.out.println("Browser Created: " + browser.getIdentifier());
                browserCreated = true;
            }

            @Override
            public void onAfterParentChanged(CefBrowser browser) {
                System.out.println("Browser onAfterParentChanged: " + browser.getIdentifier());
            }

            @Override
            public boolean doClose(CefBrowser browser) {
                boolean result = browser.doClose();
                return result;
            }

            @Override
            public void onBeforeClose(CefBrowser browser) {
                browserCreated = false;
                cefBrowser = null;
            }
        });

        cefClient.addLoadHandler(new CefLoadHandlerAdapter() {
            @Override
            public void onLoadingStateChange(CefBrowser browser, boolean isLoading,
                                             boolean canGoBack, boolean canGoForward) {
                if (!isLoading) {
                    System.out.println("Browser loaded: " + browser.getIdentifier());
                }
            }


        });

        cefClient.addDisplayHandler(new CefDisplayHandlerAdapter() {
            @Override
            public boolean onConsoleMessage(CefBrowser browser, CefSettings.LogSeverity level,
                                            String message, String source, int line) {
                return true;
            }
        });
    }

    private CefApp getCefApp() {
        if (CefApp.getState() != CefApp.CefAppState.INITIALIZED) {
             CefSettings settings = new CefSettings();
            settings.windowless_rendering_enabled = OS.isLinux();
            CefApp cefApp = CefApp.getInstance(COMMAND_LINE_ARGS, settings);
            CefVersion version = cefApp.getVersion();
            System.out.println("Using CEF version:\n" + version);
            CefApp.addAppHandler(new CefAppHandlerAdapter(COMMAND_LINE_ARGS) {
                @Override
                public void stateHasChanged(CefAppState cefAppState) {
                    if (cefAppState == CefAppState.TERMINATED) {
                        System.out.println("State is TERMINATED");
                        System.exit(0);
                    }
                }
            });
            return cefApp;
        } else {
            return CefApp.getInstance();
        }
    }


    private void createBrowser(String url, boolean createImmediately) {
        cefBrowser = cefClient.createBrowser(url,  OS.isLinux(), false);
        if(createImmediately) {
            cefBrowser.createImmediately();
        }
    }

    Component getComponent() {
        return cefBrowser.getUIComponent();
    }



    void loadURL(String url) {
        if(!browserCreated) {
            createBrowser(url, true);
        } else {
            cefBrowser.loadURL(url);
        }

    }

}


Code: Select all
package test;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
 * @author Chandan Talukdar
 */

class JCEFModal extends JFrame {

    JCEFModal( String title) {
        setName(title);
        Component component = createUIComponents();
        add(component);
        setSize(800, 600);
        setVisible(true);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                dispose();
            }
        });

    }

    private Component createUIComponents() {

        JCEFBrowser jcefBrowser = JCEFBrowser.getBrowserInstance();

        String htmlUrl = "www.google.com";

            jcefBrowser.loadURL(htmlUrl);

        jcefBrowser.getComponent().setVisible(true);

        return jcefBrowser.getComponent();

    }


}


Code: Select all
package test;

import org.cef.CefApp;
import javax.swing.*;
import java.awt.event.*;


/**
 * @author Chandan Talukdar
 */

public class JCefExample extends JFrame {


    private JCefExample(String title) {
        setTitle(title);
        setName(title);

        JButton button = new JButton("click");
        button.addActionListener(
            e -> new JCEFModal("JCEFExampleModal")
        );
        button.setBounds(165, 135, 115, 55);
        add(button);
        setSize(500, 400);
        setLayout(null);
        setVisible(true);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                CefApp.getInstance().dispose();
                dispose();
            }
        });
    }

    public static void main(String[] args) {
        new JCefExample("JCEF Example");
    }
}


I am Using:
1. JCEF Version = 81.2.24.251
CEF Version = 81.2.24
Chromium Version = 81.0.4044.113
2. Java version used is 1.8.0_201-b09 and OS is Windows 10 x64 bit

Any suggestion is much appreciated. Thanks

Chandan
chandan
Techie
 
Posts: 10
Joined: Wed May 27, 2020 4:41 am

Re: createBrowser with createImmediately doesn't load url

Postby magreenblatt » Fri Jul 03, 2020 10:40 am

But, I have noticed that the browser doesn't load the url for the first time if I use createImmediately = true

Are you passing the URL to createBrowser, and then calling createImmediately? Are you saying that the URL doesn't load in that case? Does the browser otherwise display and work as expected?
magreenblatt
Site Admin
 
Posts: 12382
Joined: Fri May 29, 2009 6:57 pm

Re: createBrowser with createImmediately doesn't load url

Postby chandan » Sat Jul 04, 2020 7:27 am

Yes. I am passing the URL to createBrowser and then calling the createImmediately

Code: Select all
        cefBrowser = cefClient.createBrowser(url,  OS.isLinux(), false);
        if(createImmediately) {
            cefBrowser.createImmediately();
        }


The browser doesn't load the url for the first time. From second time it loads properly. You can refer to the attached program.

If I don't call createImmediately, everything works fine. But there's a JVM crash issue observed during CefApp dispose. However, the JVM crash is not observed when createImmediately is called.
chandan
Techie
 
Posts: 10
Joined: Wed May 27, 2020 4:41 am

Re: createBrowser with createImmediately doesn't load url

Postby shannah » Thu Jul 09, 2020 12:04 pm

I hit the same issue. You can't set the URL until onAfterCreated() has been fired. I set up a callback in this method using the LifeSpanHandler

Code: Select all
 browser_.getClient().addLifeSpanHandler(new CefLifeSpanHandlerAdapter() {
            @Override
            public void onAfterCreated(CefBrowser browser) {
                browserCount_++;
                ready_ = true;
                if (readyCallback != null) {
                    readyCallback.run();
                }
            }

            //...
        });


Then I create wrappers for what I need, e.g.

Code: Select all
List<Runnable> onReady = new ArrayList<>();
Runnable readyCallback = ()->{
    while (!onReady.isEmpty()) onReady.remove(0).run();
};
...
public void setURL(String url) {
    if (!ready_) {
        onReady.add(()->{setURL(url);};
        return;
    }
    browser.setURL(url);
}

shannah
Techie
 
Posts: 30
Joined: Wed Jul 08, 2020 8:01 am


Return to JCEF Forum

Who is online

Users browsing this forum: No registered users and 18 guests