title: JavaFX stop opening URL in WebView - open in browser instead
body: <p>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 works fine but I need to stop the WebView from displaying that page as well. I can think of several ways to do it but none of them work. Here is my code:</p>
  
  <pre><code>this.wv.getEngine().locationProperty().addListener(new ChangeListener&lt;String&gt;() {
      @Override
      public void changed(ObservableValue&lt;? extends String&gt; observable, String oldValue, String newValue)
      {
          Desktop d = Desktop.getDesktop();
          try
          {
              URI address = new URI(observable.getValue());
              if ((address.getQuery() + "").indexOf("_openmodal=true") &gt; -1)
              {
                  // wv.getEngine().load(oldValue); // 1
                  // wv.getEngine().getLoadWorker().cancel(); // 2
                  // wv.getEngine().executeScript("history.back()"); // 3
                  d.browse(address);
              }
          }
          catch (IOException | URISyntaxException e)
          {
              displayError(e);
          }
      }
  });
  </code></pre>
  
  <p>A bit more info about what happens in each of three cases</p>
  
  <h2>1. Loading the previous address</h2>
  
  <pre><code>wv.getEngine().load(oldValue);
  </code></pre>
  
  <p>This kills the JVM. Funnily enough, the page opens fine in the native browser.</p>
  
  <pre><code># A fatal error has been detected by the Java Runtime Environment:
  #
  #  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000005b8fef38, pid=7440, tid=8000
  #
  # JRE version: 7.0_09-b05
  # Java VM: Java HotSpot(TM) 64-Bit Server VM (23.5-b02 mixed mode windows-amd64 compressed oops)
  # Problematic frame:
  # C  [jfxwebkit.dll+0x2fef38]  Java_com_sun_webpane_platform_BackForwardList_bflItemGetIcon+0x184f58
  #
  # Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
  #
  # An error report file with more information is saved as:
  # C:\Users\Greg Balaga\eclipse\Companyapp\hs_err_pid7440.log
  #
  # If you would like to submit a bug report, please visit:
  #   http://bugreport.sun.com/bugreport/crash.jsp
  # The crash happened outside the Java Virtual Machine in native code.
  # See problematic frame for where to report the bug.
  </code></pre>
  
  <h2>2. Cancelling the worker</h2>
  
  <pre><code>wv.getEngine().getLoadWorker().cancel();
  </code></pre>
  
  <p>Does nothing, the page loads in both the WebView and native browser.</p>
  
  <h2>3. Using history.back()</h2>
  
  <pre><code>wv.getEngine().executeScript("history.back()");
  </code></pre>
  
  <p>Same as above, no effect.</p>
  
  <h2>4. Reacting to Stage changes instead</h2>
  
  <p>I have also tried to instead of looking the <code>locationProperty</code> of <code>WebEngine</code>, listen on chenges for <code>stateProperty</code> of the <code>Worker</code> and fire the same opening code if <code>newState == State.SCHEDULED</code>. There was no difference in result from previous method (apart from not actually being able to use #1).</p>
  
  <hr>
  
  <h2>Update</h2>
  
  <p>The code I'm using now still crashes the JVM:</p>
  
  <pre><code>this.wv.getEngine().locationProperty().addListener(new ChangeListener&lt;String&gt;() {
      @Override
      public void changed(ObservableValue&lt;? extends String&gt; observable, final String oldValue, String newValue)
      {
          Desktop d = Desktop.getDesktop();
          try
          {
              URI address = new URI(newValue);
              if ((address.getQuery() + "").indexOf("_openmodal=true") &gt; -1)
              {
                  Platform.runLater(new Runnable() {
                      @Override
                      public void run()
                      {
                          wv.getEngine().load(oldValue);
                      }
                  });
                  d.browse(address);
              }
          }
          catch (IOException | URISyntaxException e)
          {
              displayError(e);
          }
      }
  });
  </code></pre>
  
  <hr>
  
  <h2>Workaround</h2>
  
  <p>Ok I managed to make it work by tearing down the webview and rebuilding it.</p>
  
  <pre><code>this.wv.getEngine().locationProperty().addListener(new ChangeListener&lt;String&gt;() {
      @Override
      public void changed(ObservableValue&lt;? extends String&gt; observable, final String oldValue, String newValue)
      {
          Desktop d = Desktop.getDesktop();
          try
          {
              URI address = new URI(newValue);
              if ((address.getQuery() + "").indexOf("_openmodal=true") &gt; -1)
              {
                  Platform.runLater(new Runnable() {
                      @Override
                      public void run()
                      {
                          grid_layout.getChildren().remove(wv);
                          wv = new WebView();
                          grid_layout.add(wv, 0, 1);
                          wv.getEngine().load(oldValue);
                      }
                  });
                  d.browse(address);
              }
          }
          catch (IOException | URISyntaxException e)
          {
              displayError(e);
          }
      }
  });
  </code></pre>