SWT BrowserFunction 未注册

问题描述

我有一个 Java SWT 应用程序,它使用多个浏览器小部件来显示 html 文档。这些 html 文档有一些 javascript 代码,通过 browserFunction 实例与 Java 代码进行通信。它曾经像魅力一样工作很长一段时间,直到突然它开始变得混乱:问题似乎是 browserFunction 没有正确注册/附加到浏览器了。

我怀疑某些 SWT 依赖项出了问题,因为我没有更改代码中的任何内容,也没有更改 SWT 版本,即库本身。事实上,当我全新安装我的 Linux(Ubuntu 20.04.1 LTS)并在运行任何更新之前运行我的程序时:它按预期工作。然后我运行了'apt-get update && apt-get upgrade',之后问题又出现了。

下面是重现问题的代码片段:`

预期行为:点击“创建浏览器”按钮创建一个浏览器小部件,加载“test.html”。然后,单击“单击此处”链接通过 browserFunction 实例从 Javascript 调用 Java 函数,并将某些内容打印到 Java 控制台。您应该能够多次单击“创建浏览器”按钮,并使用“单击此处”链接创建多个浏览器小部件。

实际行为:“单击此处”链接仅适用于您创建的第一个浏览器小部件。从第二次开始,小部件仍然创建,html页面仍然加载,但“单击此处”链接提示以下javascript错误:“找不到变量:callJavaFunction”。

配置:Ubuntu 20.04 LTS(在18.04下也试过,结果相同),openjdk 11.0.11,swt.jar 4.924版(也在最新的4.942下试过,结果相同)>

我尝试过的其他事情:卸载 libwebkitgtk-1.0-0,重新安装,安装 libwebkitgtk-3.0-0,使用 Wayland 会话而不是 Xorg,使用 Unity 桌面,使用 Mate桌面。

同样,在进行任何更新之前,我设法让它在新安装的 Ubuntu 20.04 上运行,并且没有安装除 Java 之外的任何东西。然后,运行操作系统更新使问题再次出现。我花了几个小时浏览网页,但我真的很难理解所有这些 Webkit 和 GTK 的东西。

代码如下:

公共类Testwindow扩展复合{

int y = 0;

Testwindow(Shell shell) {
    
    super(shell,SWT.BORDER);

    this.setSize(600,700);
    
    Button button = new Button(this,SWT.PUSH);
    button.setText("Create a browser");
    button.setLocation(200,650);
    button.pack();
    button.addSelectionListener(new SelectionListener() {

        @Override
        public void widgetDefaultSelected(SelectionEvent arg0) {
            
        }

        @Override
        public void widgetSelected(SelectionEvent arg0) {
            createbrowser();
        }
        
    });

}

public void createbrowser() {
    System.out.println("\nCreate a new browser");
    
    browser browser = new browser(this,SWT.BORDER);
    browser.setSize(500,200);
    browser.setLocation(0,y);
    
    File htmlFile = new File("test.html");
    browser.setUrl(htmlFile.getAbsolutePath());
    
    final browserFunction brf = new JavaFunction(browser,"callJavaFunction");
    
    y = y + 200;
}

private static class JavaFunction extends browserFunction {
    String name;
    JavaFunction(browser browser,String name) {
        super(browser,name);
        this.name = name;
    }

    @Override
    public Object function(Object[] arguments) {
        System.out.println("Java called from Javascript");
        if (name.equals("callJavaFunction")) {
            System.out.println("function callJava with argument : "+arguments[0]);
        }
        return null;
    }
}

}`

'test.html'中的代码如下

<html>
<head>
<script type="text/javascript">
function hello(msg){
    try {
        callJavaFunction(msg);
        } catch(e) {
            alert(e.message);
        }
}
</script>
</head>
<body >
<a href="javascript:hello('link clicked')">click here</a>
</body>
</html>

...

我的主要课程如下:

public class Main {

public static void main(String[] args) {
    
    display display = new display();
        Shell shell = new Shell(display);
        shell.setText("Test");
        Testwindow testwindow = new Testwindow(shell);
        
        shell.setSize(600,700);
      
       shell.open();
        while (!shell.isdisposed()) {
          if (!display.readAnddispatch()) {
            display.sleep();
          }
        }
        display.dispose();

}

}

非常感谢任何可以对此有所了解的人......

解决方法

因此,我深入研究了我的更新历史记录,发现以下 4 个软件包导致了问题。降级它们会使 BrowserFunction 再次工作:

  • libjavascriptcoregtk-4.0-18
  • libwebkit2gtk-4.0-37
  • gir1.2-webkit2-4.0
  • gir1.2-javascriptcoregtk-4.0

最近从 2.30.6 版升级到 2.32.0 版是导致问题的原因。 出于某种原因,我无法恢复到 2.30.6,因为它在存储库中似乎不可用,但我可以降级到 2.28.1 版,这可以解决问题:sudo apt install PACKAGE_NAME=2.28.1- 1

然后,我使用以下命令来防止这些包再次更新:echo "PACKAGE_NAME hold" |须藤 dpkg --set-selections

在我使用我的程序的每台机器上每次全新安装后,我编写了以下 bash 脚本来处理它:

    #!/bin/bash

    echo "Downgrading the 4 packages to version 2.28.1-1..."

    sudo apt install libjavascriptcoregtk-4.0-18=2.28.1-1 libwebkit2gtk-4.0-37=2.28.1-1 gir1.2-webkit2-4.0=2.28.1-1 gir1.2-javascriptcoregtk-4.0=2.28.1-1

    echo ""
    echo "Keeping those 4 packages from upgrading again..."

    echo "libwebkit2gtk" && echo "libwebkit2gtk-4.0-37 hold" | sudo dpkg --set-selections
    echo "libjavascriptcoregtk-4.0-18" && echo "libjavascriptcoregtk-4.0-18 hold" | sudo dpkg --set-selections
    echo "gir1.2-webkit2-4.0" && echo "gir1.2-webkit2-4.0 hold" | sudo dpkg --set-selections
    echo "gir1.2-javascriptcoregtk-4.0" && echo "gir1.2-javascriptcoregtk-4.0 hold" | sudo dpkg --set-selections

    echo ""
    echo "Checking installed versions :"

    echo "libwebkit2gtk-4.0-37" && dpkg -s libwebkit2gtk-4.0-37 | grep Version
    echo "libjavascriptcoregtk-4.0-18" && dpkg -s libjavascriptcoregtk-4.0-18 | grep Version
    echo "gir1.2-webkit2-4.0" && dpkg -s gir1.2-webkit2-4.0 | grep Version
    echo "gir1.2-javascriptcoregtk-4.0" && dpkg -s gir1.2-javascriptcoregtk-4.0 | grep Version

    echo ""
    echo "Checking packages marked as 'held' from future upgrades"
    dpkg --get-selections | grep hold

    echo ""
    echo "done"

这是一个可行的解决方案,前提是那些以前的版本在存储库中仍然可用,人们可以假设在可预见的未来应该是这种情况。尽管如此,它们最终还是会消失,从长远来看是不可持续的。

我不确定这是否可以作为 Eclipse SWT 中所说的错误,但向他们标记问题似乎仍然很重要。因此,我将遵循 greg 的建议并在 Eclipse Bugzilla 中提交报告。