JavaFX stop opening URL in WebView - open in browser instead

前端 未结 9 1232
無奈伤痛
無奈伤痛 2020-12-09 05:12

The embedded WebView browser I am using needs special handling for particular URLs, to open them in the native default browser instead of WebView. The actual browsing part w

9条回答
  •  既然无缘
    2020-12-09 05:55

    I found another solution:

    1. Register a CreatePopupHandler that returns a different WebEngine than the main one
    2. The main WebEngine sends the load-call to the secondary WebEngine
    3. Register a LocationChangeListener on the secondary WebEngine and catch the location change (including the address) and open it in our external browser
    4. Finally clean up the secondary WebEngine: stop loading & unload the URL

    I implemented it so the secondary WebEngine is initialized lazy. It may also be initialized in the constructor. Both has pros and contras.

    Note: This only triggers for Links which open as a popup. This usually is the case when an a-element has a target-attribute that is not "_self" or with JS: window.open(...).

    Here is the Magic ...

    Register it like this:

    engine.setCreatePopupHandler(new BrowserPopupHandler());
    

    The core class:

    public static class BrowserPopupHandler implements Callback
    {
    
        private WebEngine popupHandlerEngine;
    
        public WebEngine call(PopupFeatures popupFeatures)
        {
            // by returning null here the action would be canceled
            // by returning a different WebEngine (than the main one where we register our listener) the load-call will go to that one
            // we return a different WebEngine here and register a location change listener on it (see blow)
            return getPopupHandler();
        }
    
        private WebEngine getPopupHandler()
        {
            if (popupHandlerEngine == null) // lazy init - so we only initialize it when needed ...
            {
                synchronized (this) // double checked synchronization
                {
                    if (popupHandlerEngine == null)
                    {
                        popupHandlerEngine = initEngine();
                    }
                }
            }
            return popupHandlerEngine;
        }
    
        private WebEngine initEngine()
        {
            final WebEngine popupHandlerEngine = new WebEngine();
    
            // this change listener will trigger when our secondary popupHandlerEngine starts to load the url ...
            popupHandlerEngine.locationProperty().addListener(new ChangeListener()
            {
    
                public void changed(ObservableValue observable, String oldValue, String location)
                {
                    if (!location.isEmpty())
                    {
                        Platform.runLater(new Runnable()
                        {
    
                            public void run()
                            {
                                popupHandlerEngine.loadContent(""); // stop loading and unload the url
                                // -> does this internally: popupHandlerEngine.getLoadWorker().cancelAndReset();
                            }
    
                        });
    
                        try
                        {
                            // Open URL in Browser:
                            Desktop desktop = Desktop.getDesktop();
                            if (desktop.isSupported(Desktop.Action.BROWSE))
                            {
                                URI uri = new URI(location);
                                desktop.browse(uri);
                            }
                            else
                            {
                                System.out.println("Could not load URL: " + location);
                            }
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                }
    
            });
            return popupHandlerEngine;
        }
    
    }
    

提交回复
热议问题