JCEF 函数仅从第二次调用开始起作用(Java Chromium Embedded Framework)

JCEF functions only work from the second call onwards (Java Chromium Embedded Framework)

我最近在 Netbeans (RCP) 应用程序项目(Java:JDK11)中集成了 Java Chromium 嵌入式框架(https://github.com/chromiumembedded/java-cef)。

浏览器 Window 显示在 Netbeans TopComponent 中,通常工作正常。

然而,我注意到有几个相当小但令人讨厌的错误,它们总是遵循相同的模式: 我执行的任何与 jcef 浏览器有关的代码总是只在我第二次执行时有效,而在第一次执行时几乎被忽略。 但是,没有错误消息或日志或任何类似的东西,当我使用调试工具检查它时,代码似乎被执行了。

三个例子:

  1. 实现一个return按钮:
    这只是检查CefBrowser实例是否returns true for browser.canGoBack()。如果它 returns true 一个按钮被激活。
    该值正确地从 false 开始,但它 return 在第二次更改 url。(显然应该在第一个之后发生)
    从那里开始它工作得很好......除非你返回(使用 return 按钮)到主页。显然它应该再次 return false - 它没有。
    再次调用不同的 URL returns false for canGoBack()(然后显然应该是 true)并且只有 returns true 在第二个 URL 再次改变之后。
    所以 return 来自 canGoBack 始终显示它应该从上一次执行中显示的 return,就好像落后了一次。
  2. 实现“转到”功能:
    此功能只是将您带到主页以外的指定其他网站。再次从第二次开始工作正常,但第一次代码被忽略。 (尽管我通过调试器确认代码即使在第一次执行时也没有错误)
  3. 实现登录对话框:
    如果浏览器注意到需要身份验证,则会打开一个对话框,用户可以在其中输入 BASIC 凭据。
    再次打开对话框,return 正确输入凭据(通过日志确认),将其移交给适当的功能,它适用于第二次尝试,但不适用于第一次。 (凭据相同)
    事实上,我通过 Wireshark 确认,第一次执行 callback.Continue(ad.getUsername(), ad.getPassword()); 时,实际上没有任何内容发送到服务器...

第三个例子的代码:

cefClient_.addRequestHandler(new CefRequestHandlerAdapter() {
            @Override
            public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy, String host,
                    int port, String realm, String scheme, CefAuthCallback callback) {
               
                AuthenticationDialog ad = new AuthenticationDialog();                
                ad.authenticate(); // Shows Login Dialog
                LOGGER.log(Level.INFO, String.format("--->%s:%s", ad.getUsername(), ad.getPassword())); //This confirms that the variables are indeed correct even the first time around
                callback.Continue(ad.getUsername(), ad.getPassword());
                return true;
            }
        });

遗憾的是,我不知道是什么可能导致这些问题。

如果你们中的任何人遇到过这些相同的问题,或者对如何解决这些问题有任何想法,或者甚至不知道从哪里开始寻找解决方案,我将非常感谢您的意见。

提前致谢!

我找到了上述问题的答案。以防其他人将来偶然发现类似的问题,我将简要总结一下为我解决的问题。

显然,我遇到的大部分问题都是由线程问题引起的。看起来当你在 jcef 浏览器上执行命令时它的线程仍在处理某些东西,你的命令不会被执行,但也不会有任何错误消息或其他不需要的行为。

第二个问题的例子: 当执行 go(url) 命令时,浏览器尚未完全加载初始主页。这就是命令被忽略的原因。 为了解决这个问题,我添加了一个简单的 String 变量,它将保存某人想要加载的 URL,直到浏览器完成加载上一页。 只有这样 url 才会被加载到浏览器中,然后从变量中删除。 这当然也可以用列表之类的东西来完成,但我想不出一个有用的场景。 检查浏览器是否完成加载应该在 CefLoadHandlerAdapter.

的覆盖方法 onLoadingStateChange 中完成
client_.addLoadHandler(new CefLoadHandlerAdapter() {
        @Override
        public void onLoadingStateChange(CefBrowser browser, boolean isLoading,
                boolean canGoBack, boolean canGoForward) {
            if (!isLoading) {
                browser_ready = true;
                if (goOnReady != null) {
                    goURL(goOnReady);
                }
            }
        }
    });

原始问题中的第一个示例存在类似问题。 通过 canGoBack 变量激活上述 onLoadingStateChange 中的“后退”按钮最终对我有用。

现在第三个例子(登录对话框显示两次)原来是jcef github页面的官方详细示例代码中也存在的问题。 这个问题好像又是线程的问题,不过这次我不确定。 作为解决方法,我实施了以下解决方案:

  • 为用户名和密码添加 class 个变量
  • 如果这些变量为空,则在 getAuthCredentials 方法中启动登录对话框(参见原始问题)并将给定的用户名和密码保存在这些 class 变量中。
  • 然后执行browser.reload();
  • 然后浏览器将再次通过身份验证,但这次变量不会为空,您可以将它们交给 callback.Continue(username, password); 因此只向用户显示一个登录对话框。

这个过程也非常快,因此用户希望能够注意到重新加载。