问题描述
我最近将Java Chromium嵌入式框架(https://github.com/chromiumembedded/java-cef)集成到了Netbeans(RCP)应用程序项目(Java:JDK11)中。
浏览器窗口显示在Netbeans TopComponent中,并且通常可以正常工作。
但是,我发现了几个很小但很讨厌的错误,它们始终遵循相同的模式: 无论我执行的涉及jcef浏览器的任何代码始终只能在第二次执行时起作用,而在第一次执行时却几乎被忽略。 但是,没有错误消息或日志或类似的东西,并且当我使用调试工具进行调试时,代码似乎已执行。
三个例子:
- 实现返回按钮:
这只是检查CefBrowser实例是否为true
返回browser.canGoBack()
。如果它返回true
,则会激活一个按钮。
该值正确地从false
开始,但是在第二次更改url之后才返回true。(显然应该在第一次更改之后发生)
从那里开始就可以了。...除非您(使用返回按钮)返回主页。然后,它显然应该再次返回false
-不会。
再次调用其他URL将为false
返回canGoBack()
(然后显然应该为true
),并且仅在第二个URL再次更改后返回true
。
因此,canGoBack
的返回值始终显示它应该从其前一次执行中显示的返回值,就像是滞后了一次一样。 / li> - 实现“转到”功能:
该功能仅将您带到指定的网站而非首页。从第二次起,它仍然可以正常工作,但是第一次,该代码将被忽略。 (尽管我通过Debugger确认,即使是第一次也可以正确执行代码) - 实现登录对话框:
如果浏览器注意到需要身份验证,则会打开一个对话框,用户可以在其中输入BASIC凭证。
然后再次获得该对话框打开后,将正确返回凭据(通过Log确认),并将其移交给相应的功能,并且它适用于第二次尝试,但不适用于第一次尝试。 (凭据是相同的)。
实际上,我已经通过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才会加载到浏览器中,并因此从变量中删除。
当然,也可以使用列表来完成此操作,但是我想不出一个有用的方案。
检查浏览器是否已完成加载,应使用onLoadingStateChange
的覆盖方法CefLoadHandlerAdapter
。
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);
}
}
}
});
原始问题的第一个示例也存在类似的问题。
最后,通过onLoadingStateChange
变量激活了上述canGoBack
中的“后退”按钮,对我来说是成功的秘诀。
现在,第三个示例(显示两次登录对话框)原来是一个问题,该问题也出现在jcef github页面的官方详细示例代码中。 这个问题似乎又可能是线程问题,但是我不确定这次。 作为解决方法,我实现了以下解决方案:
- 添加用于用户名和密码的类变量
- 如果这些变量为空,请在
getAuthCredentials
方法内启动登录对话框(请参阅原始问题),并将给定的用户名和密码保存在这些类变量中。 - 然后执行
browser.reload();
- 然后浏览器将再次进行身份验证,但是这次变量将不会为空,您可以将它们传递给
callback.Continue(username,password);
,从而仅向用户显示一个登录对话框。
此过程也非常快,因此用户希望能够注意到重新加载。