diff --git a/.github/workflows/build-jcef.yml b/.github/workflows/build-jcef.yml
index c6f849d5..7c2c63c4 100644
--- a/.github/workflows/build-jcef.yml
+++ b/.github/workflows/build-jcef.yml
@@ -11,7 +11,7 @@ jobs:
       matrix:
         platform: [amd64, arm64]
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Install deps and build
         run: |
           sudo apt update
@@ -40,7 +40,7 @@ jobs:
       matrix:
         platform: [amd64, arm64]
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: ilammy/msvc-dev-cmd@v1
       - name: Build
         run: |
@@ -61,3 +61,35 @@ jobs:
             jcef_build/windows_${{ matrix.platform }}.tar.gz
             jcef_build/windows_${{ matrix.platform }}.tar.gz.sha256
           if-no-files-found: error
+
+  java-cef-macos:
+    runs-on: [macos-12]
+    strategy:
+      matrix:
+        platform: [amd64, arm64]
+    steps:
+      - uses: actions/checkout@v4
+      - name: Set up Python 3.9
+        uses: actions/setup-python@v4
+        with:
+          python-version: '3.9'
+      - run: |
+          brew install ninja
+          brew install python
+          brew install coreutils
+          sudo xcode-select --switch /Applications/Xcode_13.1.app
+          mkdir jcef_build && cd jcef_build
+          cmake -G "Ninja" -DPROJECT_ARCH=${{ matrix.platform }} -DCMAKE_BUILD_TYPE=Release ..
+          ninja -j4
+          mv native/Release macos_${{ matrix.platform }}
+          tar -czf macos_${{ matrix.platform }}.tar.gz macos_${{ matrix.platform }}
+          sha256sum macos_${{ matrix.platform }}.tar.gz > macos_${{ matrix.platform }}.tar.gz.sha256
+
+      - uses: actions/upload-artifact@v3
+        if: ${{ github.ref == 'refs/heads/master' }}
+        with:
+          name: 'macos_${{ matrix.platform }}'
+          path: |
+            jcef_build/macos_${{ matrix.platform }}.tar.gz
+            jcef_build/macos_${{ matrix.platform }}.tar.gz.sha256
+          if-no-files-found: error
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 22d0fc06..9e12f87e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -130,14 +130,9 @@ set_property(GLOBAL PROPERTY OS_FOLDERS ON)
 # CEF configuration.
 #
 
-# Specify the CEF branch
-if(NOT DEFINED CEF_BRANCH)
-  set(CEF_BRANCH "5845")
-endif()
-
 # Specify the CEF distribution version.
 if(NOT DEFINED CEF_VERSION)
-  set(CEF_VERSION "116.0.27+gd8c85ac+chromium-116.0.5845.190")
+  set(CEF_VERSION "122.1.10+gc902316+chromium-122.0.6261.112")
 endif()
 
 # Determine the platform.
@@ -172,7 +167,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
 
 # Download and extract the CEF binary distribution (executes DownloadCEF.cmake).
 include(DownloadCEF)
-DownloadCEF("${CEF_PLATFORM}" "${CEF_BRANCH}" "${CEF_VERSION}" "${CMAKE_SOURCE_DIR}/third_party/cef")
+DownloadCEF("${CEF_PLATFORM}" "${CEF_VERSION}" "${CMAKE_SOURCE_DIR}/third_party/cef")
 
 # Add the CEF binary distribution's cmake/ directory to the module path.
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CEF_ROOT}/cmake")
diff --git a/build.xml b/build.xml
index 010b5c57..a9227e30 100644
--- a/build.xml
+++ b/build.xml
@@ -30,7 +30,6 @@
       <compilerarg value="-XDignore.symbol.file"/>
       <classpath location="${jdk7.path}/jre/lib/rt.jar" />
       <classpath refid="class.path"/>
-      <src path="java/tests/"/>
       <src path="java/org/cef/"/>
     </javac>
     <copy todir="${out.path}">
@@ -47,11 +46,6 @@
         <include name="org/cef/**"/>
       </fileset>
     </jar>
-    <jar destfile="${out.path}/jcef-tests.jar" index="true" update="false">
-      <fileset dir="${out.path}">
-        <include name="tests/**"/>
-      </fileset>
-    </jar>
   </target>
     
   <target name="bundle" depends="jar">
@@ -64,7 +58,6 @@
                           icon="third_party/cef/res/CefIcon.icns">
       <classpath dir="${out.path}">
         <include name="jcef.jar"/>
-        <include name="jcef-tests.jar"/>
       </classpath>
       <classpath dir="third_party/jogamp/jar/">
         <include name="gluegen-rt.jar"/>
diff --git a/cmake/DownloadCEF.cmake b/cmake/DownloadCEF.cmake
index b2d11930..a64592bc 100644
--- a/cmake/DownloadCEF.cmake
+++ b/cmake/DownloadCEF.cmake
@@ -8,7 +8,7 @@
 # Visit https://cef-builds.spotifycdn.com/index.html for the list of
 # supported platforms and versions.
 
-function(DownloadCEF platform branch version download_dir)
+function(DownloadCEF platform version download_dir)
   # Specify the binary distribution type and download directory.
   set(CEF_DISTRIBUTION "cef_binary_${version}_${platform}")
   set(CEF_DOWNLOAD_DIR "${download_dir}")
@@ -21,19 +21,19 @@ function(DownloadCEF platform branch version download_dir)
     set(CEF_DOWNLOAD_FILENAME "${CEF_DISTRIBUTION}.tar.bz2")
     set(CEF_DOWNLOAD_PATH "${CEF_DOWNLOAD_DIR}/${CEF_DOWNLOAD_FILENAME}")
     if(NOT EXISTS "${CEF_DOWNLOAD_PATH}")
-      set(CEF_DOWNLOAD_URL "https://mcef-download.cinemamod.com/cef-builds/${branch}/${CEF_DOWNLOAD_FILENAME}")
+      set(CEF_DOWNLOAD_URL "https://cef-builds.spotifycdn.com/${CEF_DOWNLOAD_FILENAME}")
       string(REPLACE "+" "%2B" CEF_DOWNLOAD_URL_ESCAPED ${CEF_DOWNLOAD_URL})
 
       # Download the SHA1 hash for the binary distribution.
-      # message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}.sha1 from ${CEF_DOWNLOAD_URL_ESCAPED}...")
-      # file(DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}.sha1" "${CEF_DOWNLOAD_PATH}.sha1")
-      # file(READ "${CEF_DOWNLOAD_PATH}.sha1" CEF_SHA1)
+      message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}.sha1 from ${CEF_DOWNLOAD_URL_ESCAPED}...")
+      file(DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}.sha1" "${CEF_DOWNLOAD_PATH}.sha1")
+      file(READ "${CEF_DOWNLOAD_PATH}.sha1" CEF_SHA1)
 
       # Download the binary distribution and verify the hash.
       message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}...")
       file(
         DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}" "${CEF_DOWNLOAD_PATH}"
-        # EXPECTED_HASH SHA1=${CEF_SHA1}
+        EXPECTED_HASH SHA1=${CEF_SHA1}
         SHOW_PROGRESS
         )
     endif()
diff --git a/java/org/cef/CefApp.java b/java/org/cef/CefApp.java
index eff69e01..4dc5f438 100644
--- a/java/org/cef/CefApp.java
+++ b/java/org/cef/CefApp.java
@@ -37,7 +37,7 @@ public final class CefVersion {
         public final int CHROME_VERSION_PATCH;
 
         private CefVersion(int jcefCommitNo, int cefMajor, int cefMinor, int cefPatch,
-                int cefCommitNo, int chrMajor, int chrMin, int chrBuild, int chrPatch) {
+                           int cefCommitNo, int chrMajor, int chrMin, int chrBuild, int chrPatch) {
             JCEF_COMMIT_NUMBER = jcefCommitNo;
 
             CEF_VERSION_MAJOR = cefMajor;
@@ -102,6 +102,12 @@ public enum CefAppState {
          */
         INITIALIZED,
 
+        /**
+         * CEF initialization has failed (for example due to a second process using
+         * the same root_cache_path).
+         */
+        INITIALIZATION_FAILED,
+
         /**
          * CefApp is in its shutdown process. All CefClients and CefBrowser
          * instances will be disposed. No new CefClient or CefBrowser is allowed to
@@ -384,7 +390,11 @@ private final void initialize() {
             settings.locales_dir_path = localesPath.normalize().toAbsolutePath().toString();
         }
 
-        if (N_Initialize(appHandler_, settings)) setState(CefAppState.INITIALIZED);
+        if (N_Initialize(appHandler_, settings)) {
+            setState(CefAppState.INITIALIZED);
+        } else {
+            setState(CefAppState.INITIALIZATION_FAILED);
+        }
     }
 
     /**
diff --git a/java/org/cef/CefBrowserSettings.java b/java/org/cef/CefBrowserSettings.java
new file mode 100644
index 00000000..8733a418
--- /dev/null
+++ b/java/org/cef/CefBrowserSettings.java
@@ -0,0 +1,31 @@
+// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+package org.cef;
+
+/**
+ * Browser initialization settings. Specify NULL or 0 to get the recommended
+ * default values. The consequences of using custom values may not be well
+ * tested. Many of these and other settings can also configured using command-
+ * line switches.
+ */
+public class CefBrowserSettings {
+    /**
+     * The maximum rate in frames per second (fps) that CefRenderHandler::OnPaint
+     * will be called for a windowless browser. The actual fps may be lower if
+     * the browser cannot generate frames at the requested rate. The minimum
+     * value is 1 and the maximum value is 60 (default 30). This value can also
+     * be changed dynamically via {@code CefBrowser#setWindowlessFrameRate}
+     */
+    public int windowless_frame_rate = 0;
+
+    public CefBrowserSettings() {}
+
+    @Override
+    public CefBrowserSettings clone() {
+        CefBrowserSettings tmp = new CefBrowserSettings();
+        tmp.windowless_frame_rate = windowless_frame_rate;
+        return tmp;
+    }
+}
diff --git a/java/org/cef/CefClient.java b/java/org/cef/CefClient.java
index cb3a58c7..39034ea6 100644
--- a/java/org/cef/CefClient.java
+++ b/java/org/cef/CefClient.java
@@ -4,44 +4,21 @@
 
 package org.cef;
 
-import org.cef.browser.CefBrowser;
-import org.cef.browser.CefBrowserFactory;
-import org.cef.browser.CefFrame;
-import org.cef.browser.CefMessageRouter;
-import org.cef.browser.CefRequestContext;
-import org.cef.callback.CefAuthCallback;
-import org.cef.callback.CefBeforeDownloadCallback;
-import org.cef.callback.CefCallback;
-import org.cef.callback.CefContextMenuParams;
-import org.cef.callback.CefDownloadItem;
-import org.cef.callback.CefDownloadItemCallback;
-import org.cef.callback.CefDragData;
-import org.cef.callback.CefFileDialogCallback;
-import org.cef.callback.CefJSDialogCallback;
-import org.cef.callback.CefMenuModel;
-import org.cef.callback.CefPrintDialogCallback;
-import org.cef.callback.CefPrintJobCallback;
+import org.cef.browser.*;
+import org.cef.callback.*;
 import org.cef.handler.*;
 import org.cef.misc.BoolRef;
 import org.cef.misc.CefAudioParameters;
 import org.cef.misc.CefPrintSettings;
-import org.cef.misc.StringRef;
 import org.cef.network.CefRequest;
 import org.cef.network.CefRequest.TransitionType;
-import org.cef.network.CefResponse;
-import org.cef.network.CefURLRequest;
-
-import java.awt.Dimension;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
+
+import java.awt.*;
 import java.nio.ByteBuffer;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Vector;
-
-import javax.swing.SwingUtilities;
+import java.util.function.Consumer;
 
 /**
  * Client that owns a browser and renderer.
@@ -85,16 +62,20 @@ public void dispose() {
 
     // CefClientHandler
 
-    public CefBrowser createBrowser(
-            String url, boolean isTransparent) {
-        return createBrowser(url, isTransparent, null);
+    public CefBrowser createBrowser(String url, boolean isOffscreenRendered, boolean isTransparent,
+                                    CefRequestContext context) {
+        if (isDisposed_)
+            throw new IllegalStateException("Can't create browser. CefClient is disposed");
+        return CefBrowserFactory.create(
+                this, url, isOffscreenRendered, isTransparent, context, null);
     }
 
-    public CefBrowser createBrowser(String url, boolean isTransparent,
-                                    CefRequestContext context) {
+    public CefBrowser createBrowser(String url, boolean isOffscreenRendered, boolean isTransparent,
+                                    CefRequestContext context, CefBrowserSettings settings) {
         if (isDisposed_)
             throw new IllegalStateException("Can't create browser. CefClient is disposed");
-        return CefBrowserFactory.create(this, url, isTransparent, context);
+        return CefBrowserFactory.create(
+                this, url, isOffscreenRendered, isTransparent, context, settings);
     }
 
     @Override
@@ -125,7 +106,7 @@ protected CefDialogHandler getDialogHandler() {
     protected CefDisplayHandler getDisplayHandler() {
         return this;
     }
-    
+
     @Override
     protected CefAudioHandler getAudioHandler() {
         return this;
@@ -263,6 +244,12 @@ public void onTitleChange(CefBrowser browser, String title) {
             displayHandler_.onTitleChange(browser, title);
     }
 
+    @Override
+    public void OnFullscreenModeChange(CefBrowser browser, boolean fullscreen) {
+        if (displayHandler_ != null && browser != null)
+            displayHandler_.OnFullscreenModeChange(browser, fullscreen);
+    }
+
     @Override
     public boolean onTooltip(CefBrowser browser, String text) {
         if (displayHandler_ != null && browser != null) {
@@ -687,6 +674,15 @@ public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects,
             realHandler.onPaint(browser, popup, dirtyRects, buffer, width, height);
     }
 
+    @Override
+    public void addOnPaintListener(Consumer<CefPaintEvent> listener) {}
+
+    @Override
+    public void setOnPaintListener(Consumer<CefPaintEvent> listener) {}
+
+    @Override
+    public void removeOnPaintListener(Consumer<CefPaintEvent> listener) {}
+
     @Override
     public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y) {
         if (browser == null) return false;
@@ -791,39 +787,39 @@ public void onMouseEvent(
     public boolean getScreenInfo(CefBrowser arg0, CefScreenInfo arg1) {
         return false;
     }
-    
+
     // CefAudioHandler
-    
+
     public CefClient addAudioHandler(CefAudioHandler handler) {
         if (audioHandler_ == null) audioHandler_ = handler;
         return this;
     }
-    
+
     public void removeAudioHandler() {
         audioHandler_ = null;
     }
-    
+
     @Override
     public boolean getAudioParameters(CefBrowser browser, CefAudioParameters params) {
         if (audioHandler_ != null) return audioHandler_.getAudioParameters(browser, params);
         return false;
     }
-    
+
     @Override
     public void onAudioStreamStarted(CefBrowser browser, CefAudioParameters params, int channels) {
         if (audioHandler_ != null) audioHandler_.onAudioStreamStarted(browser, params, channels);
     }
-    
+
     @Override
     public void onAudioStreamPacket(CefBrowser browser, float[] data, int frames, long pts) {
         if (audioHandler_ != null) audioHandler_.onAudioStreamPacket(browser, data, frames, pts);
     }
-    
+
     @Override
     public void onAudioStreamStopped(CefBrowser browser) {
         if (audioHandler_ != null) audioHandler_.onAudioStreamStopped(browser);
     }
-    
+
     @Override
     public void onAudioStreamError(CefBrowser browser, String text) {
         if (audioHandler_ != null) audioHandler_.onAudioStreamError(browser, text);
diff --git a/java/org/cef/CefSettings.java b/java/org/cef/CefSettings.java
index a094b355..49583d0a 100644
--- a/java/org/cef/CefSettings.java
+++ b/java/org/cef/CefSettings.java
@@ -106,10 +106,39 @@ public ColorType clone() {
      * The location where cache data will be stored on disk. If empty an in-memory
      * cache will be used for some features and a temporary disk cache for others.
      * HTML5 databases such as localStorage will only persist across sessions if a
-     * cache path is specified.
+     * cache path is specified. If this is set and root_cache_path is also set, the cache_path
+     * directory must reside within root_cache_path.
      */
     public String cache_path = null;
 
+    /**
+     * The root directory for installation-specific data and the parent directory
+     * for profile-specific data. All CefSettings.cache_path and
+     * CefRequestContextSettings.cache_path values must have this parent
+     * directory in common. If this value is empty and CefSettings.cache_path is
+     * non-empty then it will default to the CefSettings.cache_path value. Any
+     * non-empty value must be an absolute path. If both values are empty then
+     * the default platform-specific directory will be used
+     * ("~/.config/cef_user_data" directory on Linux, "~/Library/Application
+     * Support/CEF/User Data" directory on MacOS, "AppData\Local\CEF\User Data"
+     * directory under the user profile directory on Windows). Use of the default
+     * directory is not recommended in production applications (see below).
+     *
+     * Multiple application instances writing to the same root_cache_path
+     * directory could result in data corruption. A process singleton lock based
+     * on the root_cache_path value is therefore used to protect against this.
+     * This singleton behavior applies to all CEF-based applications using
+     * version 120 or newer. You should customize root_cache_path for your
+     * application and implement CefAppHandler::
+     * onAlreadyRunningAppRelaunch, which will then be called on any app relaunch
+     * with the same root_cache_path value.
+     *
+     * Failure to set the root_cache_path value correctly may result in startup
+     * crashes or other unexpected behaviors (for example, the sandbox blocking
+     * read/write access to certain files).
+     */
+    public String root_cache_path = null;
+
     /**
      * To persist session cookies (cookies without an expiry date or validity
      * interval) by default when using the global cookie manager set this value to
@@ -245,6 +274,7 @@ public CefSettings clone() {
         tmp.windowless_rendering_enabled = windowless_rendering_enabled;
         tmp.command_line_args_disabled = command_line_args_disabled;
         tmp.cache_path = cache_path;
+        tmp.root_cache_path = root_cache_path;
         tmp.persist_session_cookies = persist_session_cookies;
         tmp.user_agent = user_agent;
         tmp.user_agent_product = user_agent_product;
diff --git a/java/org/cef/SystemBootstrap.java b/java/org/cef/SystemBootstrap.java
index 0a217ac4..342aaa82 100644
--- a/java/org/cef/SystemBootstrap.java
+++ b/java/org/cef/SystemBootstrap.java
@@ -13,7 +13,9 @@ public class SystemBootstrap {
     /**
      * Simple interface for how a library by name should be loaded.
      */
-    static public interface Loader { public void loadLibrary(String libname); }
+    static public interface Loader {
+        public void loadLibrary(String libname);
+    }
 
     /**
      * Default implementation is to call System.loadLibrary
diff --git a/java/org/cef/browser/CefBrowser.java b/java/org/cef/browser/CefBrowser.java
index e73bae58..d9343120 100644
--- a/java/org/cef/browser/CefBrowser.java
+++ b/java/org/cef/browser/CefBrowser.java
@@ -119,20 +119,20 @@ public interface CefBrowser {
      * @param identifier The unique frame identifier
      * @return The frame or NULL if not found
      */
-    public CefFrame getFrame(long identifier);
+    public CefFrame getFrameByIdentifier(String identifier);
 
     /**
      * Returns the frame with the specified name, or NULL if not found.
      * @param name The specified name
      * @return The frame or NULL if not found
      */
-    public CefFrame getFrame(String name);
+    public CefFrame getFrameByName(String name);
 
     /**
      * Returns the identifiers of all existing frames.
      * @return All identifiers of existing frames.
      */
-    public Vector<Long> getFrameIdentifiers();
+    public Vector<String> getFrameIdentifiers();
 
     /**
      * Returns the names of all existing frames.
@@ -331,19 +331,29 @@ public void runFileDialog(FileDialogMode mode, String title, String defaultFileP
     public void stopFinding(boolean clearSelection);
 
     /**
-     * Get an instance of the dev tools to be displayed in its own window or to be
+     * Get an instance of the DevTools to be displayed in its own window or to be
      * embedded within your UI. Only one instance per browser is available.
      */
     public CefBrowser getDevTools();
 
     /**
-     * Get an instance of the dev tools to be displayed in its own window or to be
+     * Get an instance of the DevTools to be displayed in its own window or to be
      * embedded within your UI. Only one instance per browser is available.
      *
      * @param inspectAt a position in the UI which should be inspected.
      */
     public CefBrowser getDevTools(Point inspectAt);
 
+    /**
+     * Get an instance of a client that can be used to leverage the DevTools
+     * protocol. Only one instance per browser is available.
+     *
+     * @see {@link CefDevToolsClient}
+     * @return DevTools client, or null if this browser is not yet created
+     *   or if it is closed or closing
+     */
+    public CefDevToolsClient getDevToolsClient();
+
     /**
      * If a misspelled word is currently selected in an editable node calling
      * this method will replace it with the specified |word|.
@@ -374,4 +384,26 @@ public void runFileDialog(FileDialogMode mode, String title, String defaultFileP
      * @throws UnsupportedOperationException if not supported
      */
     public CompletableFuture<BufferedImage> createScreenshot(boolean nativeResolution);
+
+    /**
+     * Set the maximum rate in frames per second (fps) that {@code CefRenderHandler::onPaint}
+     * will be called for a windowless browser. The actual fps may be
+     * lower if the browser cannot generate frames at the requested rate. The
+     * minimum value is 1, and the maximum value is 60 (default 30).
+     *
+     * @param frameRate the maximum frame rate
+     * @throws UnsupportedOperationException if not supported
+     */
+    public void setWindowlessFrameRate(int frameRate);
+
+    /**
+     * Returns the maximum rate in frames per second (fps) that {@code CefRenderHandler::onPaint}
+     * will be called for a windowless browser. The actual fps may be lower if the browser cannot
+     * generate frames at the requested rate. The minimum value is 1, and the maximum value is 60
+     * (default 30).
+     *
+     * @return the framerate, 0 if an error occurs
+     * @throws UnsupportedOperationException if not supported
+     */
+    public CompletableFuture<Integer> getWindowlessFrameRate();
 }
diff --git a/java/org/cef/browser/CefBrowserFactory.java b/java/org/cef/browser/CefBrowserFactory.java
index 98a1678e..853ce9b2 100644
--- a/java/org/cef/browser/CefBrowserFactory.java
+++ b/java/org/cef/browser/CefBrowserFactory.java
@@ -4,14 +4,15 @@
 
 package org.cef.browser;
 
+import org.cef.CefBrowserSettings;
 import org.cef.CefClient;
 
 /**
  * Creates a new instance of CefBrowser according the passed values
  */
 public class CefBrowserFactory {
-    public static CefBrowser create(CefClient client, String url,
-            boolean isTransparent, CefRequestContext context) {
-        return new CefBrowserOsr(client, url, isTransparent, context);
+    public static CefBrowser create(CefClient client, String url, boolean isOffscreenRendered,
+                                    boolean isTransparent, CefRequestContext context, CefBrowserSettings settings) {
+        return new CefBrowserOsr(client, url, isTransparent, context, settings);
     }
 }
diff --git a/java/org/cef/browser/CefBrowserOsr.java b/java/org/cef/browser/CefBrowserOsr.java
index cd80d9ba..2fd33b1b 100644
--- a/java/org/cef/browser/CefBrowserOsr.java
+++ b/java/org/cef/browser/CefBrowserOsr.java
@@ -4,6 +4,7 @@
 
 package org.cef.browser;
 
+import org.cef.CefBrowserSettings;
 import org.cef.CefClient;
 import org.cef.callback.CefDragData;
 import org.cef.handler.CefRenderHandler;
@@ -17,6 +18,8 @@
 import java.awt.image.BufferedImage;
 import java.nio.ByteBuffer;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Consumer;
 
 /**
  * This class represents an off-screen rendered browser.
@@ -32,13 +35,18 @@ public class CefBrowserOsr extends CefBrowser_N implements CefRenderHandler {
     private int depth_per_component = 8;
     private boolean isTransparent_;
 
-    public CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context) {
-        this(client, url, transparent, context, null, null);
+    private CopyOnWriteArrayList<Consumer<CefPaintEvent>> onPaintListeners =
+            new CopyOnWriteArrayList<>();
+
+    protected CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context,
+                            CefBrowserSettings settings) {
+        this(client, url, transparent, context, null, null, settings);
     }
 
     private CefBrowserOsr(CefClient client, String url, boolean transparent,
-            CefRequestContext context, CefBrowserOsr parent, Point inspectAt) {
-        super(client, url, context, parent, inspectAt);
+                          CefRequestContext context, CefBrowserOsr parent, Point inspectAt,
+                          CefBrowserSettings settings) {
+        super(client, url, context, parent, inspectAt, settings);
         isTransparent_ = transparent;
     }
 
@@ -79,6 +87,22 @@ public void onPopupShow(CefBrowser browser, boolean show) {
     public void onPopupSize(CefBrowser browser, Rectangle size) {
     }
 
+    @Override
+    public void addOnPaintListener(Consumer<CefPaintEvent> listener) {
+        onPaintListeners.add(listener);
+    }
+
+    @Override
+    public void setOnPaintListener(Consumer<CefPaintEvent> listener) {
+        onPaintListeners.clear();
+        onPaintListeners.add(listener);
+    }
+
+    @Override
+    public void removeOnPaintListener(Consumer<CefPaintEvent> listener) {
+        onPaintListeners.remove(listener);
+    }
+
     @Override
     public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height) {
     }
@@ -132,7 +156,7 @@ private void createBrowserIfRequired(boolean hasParent) {
                         getInspectAt());
             } else {
                 createBrowser(getClient(), windowHandle, getUrl(), true, isTransparent_,
-                        getRequestContext());
+                        null, getRequestContext());
             }
         } else if (hasParent && justCreated_) {
             notifyAfterParentChanged();
diff --git a/java/org/cef/browser/CefBrowser_N.java b/java/org/cef/browser/CefBrowser_N.java
index 6c3749f9..72502f64 100644
--- a/java/org/cef/browser/CefBrowser_N.java
+++ b/java/org/cef/browser/CefBrowser_N.java
@@ -4,13 +4,10 @@
 
 package org.cef.browser;
 
+import org.cef.CefBrowserSettings;
 import org.cef.CefClient;
-import org.cef.browser.CefRequestContext;
-import org.cef.callback.CefDragData;
-import org.cef.callback.CefNativeAdapter;
-import org.cef.callback.CefPdfPrintCallback;
-import org.cef.callback.CefRunFileDialogCallback;
-import org.cef.callback.CefStringVisitor;
+import org.cef.browser.CefDevToolsClient.DevToolsException;
+import org.cef.callback.*;
 import org.cef.event.CefKeyEvent;
 import org.cef.event.CefMouseEvent;
 import org.cef.event.CefMouseWheelEvent;
@@ -21,14 +18,9 @@
 import org.cef.misc.CefPdfPrintSettings;
 import org.cef.network.CefRequest;
 
-import java.awt.Component;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Window;
-import java.awt.event.WindowEvent;
+import java.awt.*;
 import java.util.Vector;
-
-import javax.swing.SwingUtilities;
+import java.util.concurrent.CompletableFuture;
 
 /**
  * This class represents all methods which are connected to the
@@ -44,17 +36,23 @@ public abstract class CefBrowser_N extends CefNativeAdapter implements CefBrowse
     private volatile CefBrowser_N parent_ = null;
     private volatile Point inspectAt_ = null;
     private volatile CefBrowser_N devTools_ = null;
+    private volatile CefDevToolsClient devToolsClient_ = null;
     private boolean closeAllowed_ = false;
     private volatile boolean isClosed_ = false;
     private volatile boolean isClosing_ = false;
+    private final CefBrowserSettings settings_;
 
     protected CefBrowser_N(CefClient client, String url, CefRequestContext context,
-            CefBrowser_N parent, Point inspectAt) {
+                           CefBrowser_N parent, Point inspectAt, CefBrowserSettings settings) {
         client_ = client;
         url_ = url;
         request_context_ = context;
         parent_ = parent;
         inspectAt_ = inspectAt;
+        if (settings != null)
+            settings_ = settings.clone();
+        else
+            settings_ = new CefBrowserSettings();
     }
 
     protected String getUrl() {
@@ -117,6 +115,9 @@ public synchronized void onBeforeClose() {
             parent_.devTools_ = null;
             parent_ = null;
         }
+        if (devToolsClient_ != null) {
+            devToolsClient_.close();
+        }
     }
 
     @Override
@@ -132,18 +133,49 @@ public synchronized CefBrowser getDevTools(Point inspectAt) {
         return devTools_;
     }
 
-    protected abstract CefBrowser_N createDevToolsBrowser(CefClient client, String url,
-            CefRequestContext context, CefBrowser_N parent, Point inspectAt);
+    @Override
+    public synchronized CefDevToolsClient getDevToolsClient() {
+        if (!isPending_ || isClosing_ || isClosed_) {
+            return null;
+        }
+        if (devToolsClient_ == null || devToolsClient_.isClosed()) {
+            devToolsClient_ = new CefDevToolsClient(this);
+        }
+        return devToolsClient_;
+    }
 
+    CompletableFuture<Integer> executeDevToolsMethod(String method, String parametersAsJson) {
+        CompletableFuture<Integer> future = new CompletableFuture<>();
+        N_ExecuteDevToolsMethod(method, parametersAsJson, new IntCallback() {
+            @Override
+            public void onComplete(int generatedMessageId) {
+                if (generatedMessageId <= 0) {
+                    future.completeExceptionally(new DevToolsException(
+                            String.format("Failed to execute DevTools method %s", method)));
+                } else {
+                    future.complete(generatedMessageId);
+                }
+            }
+        });
+        return future;
+    }
+
+    CefRegistration addDevToolsMessageObserver(CefDevToolsMessageObserver observer) {
+        return N_AddDevToolsMessageObserver(observer);
+    }
+
+
+    protected abstract CefBrowser_N createDevToolsBrowser(CefClient client, String url,
+                                                          CefRequestContext context, CefBrowser_N parent, Point inspectAt);
     /**
      * Create a new browser.
      */
     protected void createBrowser(CefClientHandler clientHandler, long windowHandle, String url,
-            boolean osr, boolean transparent, CefRequestContext context) {
+                                 boolean osr, boolean transparent, Component canvas, CefRequestContext context) {
         if (getNativeRef("CefBrowser") == 0 && !isPending_) {
             try {
-                N_CreateBrowser(
-                        clientHandler, windowHandle, url, osr, transparent, context);
+                N_CreateBrowser(clientHandler, windowHandle, url, osr, transparent, canvas, context,
+                        settings_);
             } catch (UnsatisfiedLinkError err) {
                 err.printStackTrace();
             }
@@ -161,12 +193,12 @@ private void notifyBrowserCreated() {
      * Create a new browser as dev tools
      */
     protected final void createDevTools(CefBrowser_N parent, CefClientHandler clientHandler,
-            long windowHandle, boolean osr, boolean transparent,
-            Point inspectAt) {
+                                        long windowHandle, boolean osr, boolean transparent,
+                                        Point inspectAt) {
         if (getNativeRef("CefBrowser") == 0 && !isPending_) {
             try {
                 isPending_ = N_CreateDevTools(
-                        parent, clientHandler, windowHandle, osr, transparent, inspectAt);
+                        parent, clientHandler, windowHandle, osr, transparent, null, inspectAt);
             } catch (UnsatisfiedLinkError err) {
                 err.printStackTrace();
             }
@@ -297,9 +329,9 @@ public CefFrame getFocusedFrame() {
     }
 
     @Override
-    public CefFrame getFrame(long identifier) {
+    public CefFrame getFrameByIdentifier(String identifier) {
         try {
-            return N_GetFrame(identifier);
+            return N_GetFrameByIdentifier(identifier);
         } catch (UnsatisfiedLinkError ule) {
             ule.printStackTrace();
             return null;
@@ -307,9 +339,9 @@ public CefFrame getFrame(long identifier) {
     }
 
     @Override
-    public CefFrame getFrame(String name) {
+    public CefFrame getFrameByName(String name) {
         try {
-            return N_GetFrame2(name);
+            return N_GetFrameByName(name);
         } catch (UnsatisfiedLinkError ule) {
             ule.printStackTrace();
             return null;
@@ -317,7 +349,7 @@ public CefFrame getFrame(String name) {
     }
 
     @Override
-    public Vector<Long> getFrameIdentifiers() {
+    public Vector<String> getFrameIdentifiers() {
         try {
             return N_GetFrameIdentifiers();
         } catch (UnsatisfiedLinkError ule) {
@@ -366,6 +398,7 @@ public boolean hasDocument() {
         return false;
     }
 
+    @Override
     public void viewSource() {
         try {
             N_ViewSource();
@@ -374,6 +407,7 @@ public void viewSource() {
         }
     }
 
+    @Override
     public void getSource(CefStringVisitor visitor) {
         try {
             N_GetSource(visitor);
@@ -382,6 +416,7 @@ public void getSource(CefStringVisitor visitor) {
         }
     }
 
+    @Override
     public void getText(CefStringVisitor visitor) {
         try {
             N_GetText(visitor);
@@ -478,8 +513,8 @@ public void setZoomLevel(double zoomLevel) {
 
     @Override
     public void runFileDialog(FileDialogMode mode, String title, String defaultFilePath,
-            Vector<String> acceptFilters, int selectedAcceptFilter,
-            CefRunFileDialogCallback callback) {
+                              Vector<String> acceptFilters, int selectedAcceptFilter,
+                              CefRunFileDialogCallback callback) {
         try {
             N_RunFileDialog(
                     mode, title, defaultFilePath, acceptFilters, selectedAcceptFilter, callback);
@@ -728,11 +763,38 @@ protected final void notifyMoveOrResizeStarted() {
         }
     }
 
+    public void setWindowlessFrameRate(int frameRate) {
+        try {
+            N_SetWindowlessFrameRate(frameRate);
+        } catch (UnsatisfiedLinkError ule) {
+            ule.printStackTrace();
+        }
+    }
+
+    public CompletableFuture<Integer> getWindowlessFrameRate() {
+        final CompletableFuture<Integer> future = new CompletableFuture<>();
+        try {
+            N_GetWindowlessFrameRate(future::complete);
+        } catch (UnsatisfiedLinkError ule) {
+            ule.printStackTrace();
+            future.complete(0);
+        }
+        return future;
+    }
+
+    private interface IntCallback {
+        void onComplete(int value);
+    }
+
     private final native boolean N_CreateBrowser(CefClientHandler clientHandler, long windowHandle,
-            String url, boolean osr, boolean transparent,
-            CefRequestContext context);
+                                                 String url, boolean osr, boolean transparent, Component canvas,
+                                                 CefRequestContext context, CefBrowserSettings settings);
     private final native boolean N_CreateDevTools(CefBrowser parent, CefClientHandler clientHandler,
-            long windowHandle, boolean osr, boolean transparent, Point inspectAt);
+                                                  long windowHandle, boolean osr, boolean transparent, Component canvas, Point inspectAt);
+    private final native void N_ExecuteDevToolsMethod(
+            String method, String parametersAsJson, IntCallback callback);
+    private final native CefRegistration N_AddDevToolsMessageObserver(
+            CefDevToolsMessageObserver observer);
     private final native long N_GetWindowHandle(long surfaceHandle);
     private final native boolean N_CanGoBack();
     private final native void N_GoBack();
@@ -745,9 +807,9 @@ private final native boolean N_CreateDevTools(CefBrowser parent, CefClientHandle
     private final native int N_GetIdentifier();
     private final native CefFrame N_GetMainFrame();
     private final native CefFrame N_GetFocusedFrame();
-    private final native CefFrame N_GetFrame(long identifier);
-    private final native CefFrame N_GetFrame2(String name);
-    private final native Vector<Long> N_GetFrameIdentifiers();
+    private final native CefFrame N_GetFrameByIdentifier(String identifier);
+    private final native CefFrame N_GetFrameByName(String name);
+    private final native Vector<String> N_GetFrameIdentifiers();
     private final native Vector<String> N_GetFrameNames();
     private final native int N_GetFrameCount();
     private final native boolean N_IsPopup();
@@ -765,8 +827,8 @@ private final native boolean N_CreateDevTools(CefBrowser parent, CefClientHandle
     private final native double N_GetZoomLevel();
     private final native void N_SetZoomLevel(double zoomLevel);
     private final native void N_RunFileDialog(FileDialogMode mode, String title,
-            String defaultFilePath, Vector<String> acceptFilters, int selectedAcceptFilter,
-            CefRunFileDialogCallback callback);
+                                              String defaultFilePath, Vector<String> acceptFilters, int selectedAcceptFilter,
+                                              CefRunFileDialogCallback callback);
     private final native void N_StartDownload(String url);
     private final native void N_Print();
     private final native void N_PrintToPDF(
@@ -789,5 +851,8 @@ private final native void N_DragTargetDragEnter(
     private final native void N_DragSourceEndedAt(Point pos, int operation);
     private final native void N_DragSourceSystemDragEnded();
     private final native void N_UpdateUI(Rectangle contentRect, Rectangle browserRect);
+    private final native void N_SetParent(long windowHandle, Component canvas);
     private final native void N_NotifyMoveOrResizeStarted();
+    private final native void N_SetWindowlessFrameRate(int frameRate);
+    private final native void N_GetWindowlessFrameRate(IntCallback frameRateCallback);
 }
diff --git a/java/org/cef/browser/CefDevToolsClient.java b/java/org/cef/browser/CefDevToolsClient.java
new file mode 100644
index 00000000..ee119469
--- /dev/null
+++ b/java/org/cef/browser/CefDevToolsClient.java
@@ -0,0 +1,165 @@
+// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+package org.cef.browser;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+
+public class CefDevToolsClient implements AutoCloseable {
+    private final Map<Integer, CompletableFuture<String>> queuedCommands_ =
+            Collections.synchronizedMap(new HashMap<>());
+    private final Set<EventListener> eventListeners_ =
+            Collections.synchronizedSet(new LinkedHashSet<>());
+    private CefRegistration registration_;
+    private final CefBrowser_N browser_;
+
+    /**
+     * Use {@link CefBrowser#getDevToolsClient()} to get an instance of this class.
+     */
+    CefDevToolsClient(CefBrowser_N browser) {
+        this.browser_ = browser;
+
+        registration_ = browser.addDevToolsMessageObserver(new CefDevToolsMessageObserver() {
+            @Override
+            public void onDevToolsMethodResult(
+                    CefBrowser browser, int messageId, boolean success, String result) {
+                CompletableFuture<String> future = getQueuedCommand(messageId);
+                if (success) {
+                    future.complete(result);
+                } else {
+                    future.completeExceptionally(
+                            new DevToolsException("DevTools method failed", result));
+                }
+            }
+
+            @Override
+            public void onDevToolsEvent(CefBrowser browser, String method, String parameters) {
+                for (EventListener eventListener : eventListeners_) {
+                    eventListener.onEvent(method, parameters);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void close() {
+        queuedCommands_.clear();
+        eventListeners_.clear();
+        registration_ = null;
+    }
+
+    public boolean isClosed() {
+        return registration_ == null;
+    }
+
+    private CompletableFuture<String> getQueuedCommand(Integer messageId) {
+        return queuedCommands_.computeIfAbsent(messageId, key -> new CompletableFuture<>());
+    }
+
+    /**
+     * Execute a method call over the DevTools protocol. See the <a
+     * href=https://chromedevtools.github.io/devtools-protocol/> DevTools protocol documentation</a>
+     * for details of supported methods and the expected syntax for parameters.
+     *
+     * <p>If an error occurs the returned future is completed exceptionally, otherwise its value is
+     * asynchronously set to the method result.
+     *
+     * <p>Call {@link #addEventListener(String, EventListener)} to subscribe to events.
+     *
+     * @param method the method name
+     * @return return a future with the method result if the method was executed successfully
+     */
+    public CompletableFuture<String> executeDevToolsMethod(String method) {
+        return executeDevToolsMethod(method, null);
+    }
+
+    /**
+     * Execute a method call over the DevTools protocol. See the <a
+     * href=https://chromedevtools.github.io/devtools-protocol/> DevTools protocol documentation</a>
+     * for details of supported methods and the expected syntax for parameters.
+     *
+     * <p>If an error occurs the returned future is completed exceptionally, otherwise its value is
+     * asynchronously set to the method result.
+     *
+     * <p>Call {@link #addEventListener(String, EventListener)} to subscribe to events.
+     *
+     * @param method the method name
+     * @param parametersAsJson JSON object with parameters, or null if no parameters are needed
+     * @return return a future with the method result if the method was executed successfully
+     */
+    public CompletableFuture<String> executeDevToolsMethod(String method, String parametersAsJson) {
+        if (isClosed()) {
+            CompletableFuture<String> future = new CompletableFuture<>();
+            future.completeExceptionally(new DevToolsException("Client is closed"));
+            return future;
+        }
+
+        return browser_.executeDevToolsMethod(method, parametersAsJson)
+                .thenCompose(this::getQueuedCommand);
+    }
+
+    /**
+     * Add an event listener for DevTools protocol events. Events by default are disabled
+     * and need to be enabled on a per domain basis, e.g. by sending Network.enable to enable
+     * network related events.
+     *
+     * @param eventListener the listener to add
+     */
+    public void addEventListener(EventListener eventListener) {
+        eventListeners_.add(eventListener);
+    }
+
+    /**
+     * Remove an event listener for DevTools protocol events.
+     *
+     * @param eventListener the listener to remove
+     */
+    public void removeEventListener(EventListener eventListener) {
+        eventListeners_.remove(eventListener);
+    }
+
+    public interface EventListener {
+        /**
+         * Method that will be called on receipt of an event.
+         * @param eventName the event name
+         * @param messageAsJson JSON object with the event message
+         */
+        void onEvent(String eventName, String messageAsJson);
+    }
+
+    public static final class DevToolsException extends Exception {
+        private static final long serialVersionUID = 3952948449841375372L;
+
+        private final String json_;
+
+        public DevToolsException(String message) {
+            this(message, null);
+        }
+
+        public DevToolsException(String message, String json) {
+            super(message);
+            this.json_ = json;
+        }
+
+        @Override
+        public String getMessage() {
+            String message = super.getMessage();
+            if (json_ != null) message += ": " + json_;
+            return message;
+        }
+
+        /**
+         * JSON object with the error details that were passed back by the DevTools
+         * host, or null if no further details are available.
+         */
+        public String getJson() {
+            return json_;
+        }
+    }
+}
diff --git a/java/org/cef/browser/CefDevToolsMessageObserver.java b/java/org/cef/browser/CefDevToolsMessageObserver.java
new file mode 100644
index 00000000..3a851356
--- /dev/null
+++ b/java/org/cef/browser/CefDevToolsMessageObserver.java
@@ -0,0 +1,34 @@
+// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+package org.cef.browser;
+
+/**
+ * Used internally by {@link CefDevToolsClient}.
+ * <p>
+ * Callback interface for {@link CefBrowser#addDevToolsMessageObserver(CefDevToolsMessageObserver)}.
+ * The methods of this class will be called on the CEF UI thread.
+ */
+interface CefDevToolsMessageObserver {
+    /**
+     * Method that will be called after attempted execution of a DevTools protocol method.
+     *
+     * @param browser the originating browser instance
+     * @param messageId the ID that identifies the originating method call
+     * @param success if the method succeeded, |success| will be true and |result| will be a JSON
+     *        object containing the method call result. If the method call failed, |success| will
+     *        be false and |result| will be a JSON object describing the error.
+     * @param result method call result or an error
+     */
+    void onDevToolsMethodResult(CefBrowser browser, int messageId, boolean success, String result);
+
+    /**
+     * Method that will be called on receipt of a DevTools protocol event.
+     *
+     * @param browser the originating browser instance
+     * @param method the method name
+     * @param parameters the event data
+     */
+    void onDevToolsEvent(CefBrowser browser, String method, String parameters);
+}
diff --git a/java/org/cef/browser/CefFrame.java b/java/org/cef/browser/CefFrame.java
index 3a2393fb..a64b4ed9 100644
--- a/java/org/cef/browser/CefFrame.java
+++ b/java/org/cef/browser/CefFrame.java
@@ -14,11 +14,11 @@ public interface CefFrame {
     void dispose();
 
     /**
-     * Returns the globally unique identifier for this frame or < 0 if the
+     * Returns the globally unique identifier for this frame or an empty string if the
      * underlying frame does not yet exist.
      * @return The frame identifier
      */
-    long getIdentifier();
+    String getIdentifier();
 
     /**
      * Emits the URL currently loaded in this frame.
@@ -98,4 +98,9 @@ public interface CefFrame {
      * Execute paste in this frame.
      */
     public void paste();
-}
\ No newline at end of file
+
+    /**
+     * Execute selectAll in this frame.
+     */
+    public void selectAll();
+}
diff --git a/java/org/cef/browser/CefFrame_N.java b/java/org/cef/browser/CefFrame_N.java
index 8e129f1a..0bd1c6af 100644
--- a/java/org/cef/browser/CefFrame_N.java
+++ b/java/org/cef/browser/CefFrame_N.java
@@ -30,12 +30,12 @@ public void dispose() {
     }
 
     @Override
-    public long getIdentifier() {
+    public String getIdentifier() {
         try {
             return N_GetIdentifier(getNativeRef(null));
         } catch (UnsatisfiedLinkError ule) {
             ule.printStackTrace();
-            return -1;
+            return null;
         }
     }
 
@@ -148,8 +148,16 @@ public void paste() {
         }
     }
 
+    public void selectAll() {
+        try {
+            N_SelectAll(getNativeRef(null));
+        } catch (UnsatisfiedLinkError ule) {
+            ule.printStackTrace();
+        }
+    }
+
     private final native void N_Dispose(long self);
-    private final native long N_GetIdentifier(long self);
+    private final native String N_GetIdentifier(long self);
     private final native String N_GetURL(long self);
     private final native String N_GetName(long self);
     private final native boolean N_IsMain(long self);
@@ -162,4 +170,5 @@ public void paste() {
     private final native void N_Cut(long self);
     private final native void N_Copy(long self);
     private final native void N_Paste(long self);
+    private final native void N_SelectAll(long self);
 }
diff --git a/java/org/cef/browser/CefPaintEvent.java b/java/org/cef/browser/CefPaintEvent.java
new file mode 100644
index 00000000..aed9af31
--- /dev/null
+++ b/java/org/cef/browser/CefPaintEvent.java
@@ -0,0 +1,51 @@
+// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+package org.cef.browser;
+
+import java.awt.*;
+import java.nio.ByteBuffer;
+
+public class CefPaintEvent {
+    private final CefBrowser browser;
+    private final boolean popup;
+    private final Rectangle[] dirtyRects;
+    private final ByteBuffer renderedFrame;
+    private final int width;
+    private final int height;
+
+    public CefPaintEvent(CefBrowser browser, boolean popup, Rectangle[] dirtyRects,
+            ByteBuffer renderedFrame, int width, int height) {
+        this.browser = browser;
+        this.popup = popup;
+        this.dirtyRects = dirtyRects;
+        this.renderedFrame = renderedFrame;
+        this.width = width;
+        this.height = height;
+    }
+
+    public CefBrowser getBrowser() {
+        return browser;
+    }
+
+    public boolean getPopup() {
+        return popup;
+    }
+
+    public Rectangle[] getDirtyRects() {
+        return dirtyRects;
+    }
+
+    public ByteBuffer getRenderedFrame() {
+        return renderedFrame;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+}
\ No newline at end of file
diff --git a/java/org/cef/browser/CefRegistration.java b/java/org/cef/browser/CefRegistration.java
new file mode 100644
index 00000000..11051404
--- /dev/null
+++ b/java/org/cef/browser/CefRegistration.java
@@ -0,0 +1,24 @@
+// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+package org.cef.browser;
+
+/**
+ * Used internally by {@link CefDevToolsClient}.
+ * <p>
+ * Handle to observer registration, As long as this object is alive, the observer will stay
+ * registered.
+ */
+abstract class CefRegistration {
+    /**
+     * Removes the native reference from an unused object.
+     */
+    public abstract void dispose();
+
+    @Override
+    public void finalize() throws Throwable {
+        dispose();
+        super.finalize();
+    }
+}
diff --git a/java/org/cef/browser/CefRegistration_N.java b/java/org/cef/browser/CefRegistration_N.java
new file mode 100644
index 00000000..a7defd13
--- /dev/null
+++ b/java/org/cef/browser/CefRegistration_N.java
@@ -0,0 +1,33 @@
+// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+package org.cef.browser;
+
+import org.cef.callback.CefNative;
+
+class CefRegistration_N extends CefRegistration implements CefNative {
+    // Used internally to store a pointer to the CEF object.
+    private long N_CefHandle = 0;
+
+    @Override
+    public void setNativeRef(String identifier, long nativeRef) {
+        N_CefHandle = nativeRef;
+    }
+
+    @Override
+    public long getNativeRef(String identifier) {
+        return N_CefHandle;
+    }
+
+    @Override
+    public void dispose() {
+        try {
+            N_Dispose(N_CefHandle);
+        } catch (UnsatisfiedLinkError ule) {
+            ule.printStackTrace();
+        }
+    }
+
+    private final native void N_Dispose(long self);
+}
diff --git a/java/org/cef/handler/CefAppHandler.java b/java/org/cef/handler/CefAppHandler.java
index 095e4747..b6ede710 100644
--- a/java/org/cef/handler/CefAppHandler.java
+++ b/java/org/cef/handler/CefAppHandler.java
@@ -72,4 +72,23 @@ public interface CefAppHandler {
      * currently pending scheduled call should be cancelled.
      */
     public void onScheduleMessagePumpWork(long delay_ms);
+
+    /**
+     * Implement this method to provide app-specific behavior when an already
+     * running app is relaunched with the same CefSettings.root_cache_path value.
+     * For example, activate an existing app window or create a new app window.
+     * |command_line| will be read-only. Do not keep a reference to
+     * |command_line| outside of this method. Return true if the relaunch is
+     * handled or false for default relaunch behavior. Default behavior will
+     * create a new default styled Chrome window.
+     *
+     * To avoid cache corruption only a single app instance is allowed to run for
+     * a given CefSettings.root_cache_path value. On relaunch the app checks a
+     * process singleton lock and then forwards the new launch arguments to the
+     * already running app process before exiting early. Client apps should
+     * therefore check the CefInitialize() return value for early exit before
+     * proceeding.
+     */
+    public boolean onAlreadyRunningAppRelaunch(
+            CefCommandLine command_line, String current_directory);
 }
diff --git a/java/org/cef/handler/CefAppHandlerAdapter.java b/java/org/cef/handler/CefAppHandlerAdapter.java
index d74eee48..1d0bc15b 100644
--- a/java/org/cef/handler/CefAppHandlerAdapter.java
+++ b/java/org/cef/handler/CefAppHandlerAdapter.java
@@ -32,9 +32,10 @@ public void onBeforeCommandLineProcessing(String process_type, CefCommandLine co
                     continue;
                 }
                 // Arguments with '--', '-' and, on Windows, '/' prefixes are considered switches.
-                int switchCnt = arg.startsWith("--")
-                        ? 2
-                        : arg.startsWith("/") ? 1 : arg.startsWith("-") ? 1 : 0;
+                int switchCnt = arg.startsWith("--") ? 2
+                        : arg.startsWith("/")        ? 1
+                        : arg.startsWith("-")        ? 1
+                                                     : 0;
                 switch (switchCnt) {
                     case 2:
                         // An argument of "--" will terminate switch parsing with all subsequent
@@ -88,4 +89,11 @@ public void onContextInitialized() {
     public void onScheduleMessagePumpWork(long delay_ms) {
         CefApp.getInstance().doMessageLoopWork(delay_ms);
     }
+
+    @Override
+    public boolean onAlreadyRunningAppRelaunch(
+            CefCommandLine command_line, String current_directory) {
+        // The default implementation does nothing
+        return false;
+    }
 }
diff --git a/java/org/cef/handler/CefDisplayHandler.java b/java/org/cef/handler/CefDisplayHandler.java
index 0affefc5..5913794e 100644
--- a/java/org/cef/handler/CefDisplayHandler.java
+++ b/java/org/cef/handler/CefDisplayHandler.java
@@ -28,6 +28,13 @@ public interface CefDisplayHandler {
      */
     public void onTitleChange(CefBrowser browser, String title);
 
+    /**
+     * Browser fullscreen mode changed.
+     * @param browser The browser generating the event.
+     * @param fullscreen True if fullscreen mode is on.
+     */
+    public void OnFullscreenModeChange(CefBrowser browser, boolean fullscreen);
+
     /**
      * About to display a tooltip.
      * @param browser The browser generating the event.
diff --git a/java/org/cef/handler/CefDisplayHandlerAdapter.java b/java/org/cef/handler/CefDisplayHandlerAdapter.java
index 80ab96b6..302ae6b0 100644
--- a/java/org/cef/handler/CefDisplayHandlerAdapter.java
+++ b/java/org/cef/handler/CefDisplayHandlerAdapter.java
@@ -24,6 +24,11 @@ public void onTitleChange(CefBrowser browser, String title) {
         return;
     }
 
+    @Override
+    public void OnFullscreenModeChange(CefBrowser browser, boolean fullscreen) {
+        return;
+    }
+
     @Override
     public boolean onTooltip(CefBrowser browser, String text) {
         return false;
diff --git a/java/org/cef/handler/CefLoadHandler.java b/java/org/cef/handler/CefLoadHandler.java
index 37d5a3e8..af50686e 100644
--- a/java/org/cef/handler/CefLoadHandler.java
+++ b/java/org/cef/handler/CefLoadHandler.java
@@ -187,12 +187,8 @@ enum ErrorCode {
         ERR_INVALID_HTTP_RESPONSE(-370),
         ERR_CONTENT_DECODING_INIT_FAILED(-371),
         ERR_HTTP2_RST_STREAM_NO_ERROR_RECEIVED(-372),
-        ERR_HTTP2_PUSHED_STREAM_NOT_AVAILABLE(-373),
-        ERR_HTTP2_CLAIMED_PUSHED_STREAM_RESET_BY_SERVER(-374),
         ERR_TOO_MANY_RETRIES(-375),
         ERR_HTTP2_STREAM_CLOSED(-376),
-        ERR_HTTP2_CLIENT_REFUSED_STREAM(-377),
-        ERR_HTTP2_PUSHED_RESPONSE_DOES_NOT_MATCH(-378),
         ERR_HTTP_RESPONSE_CODE_FAILURE(-379),
         ERR_QUIC_CERT_ROOT_NOT_KNOWN(-380),
         ERR_QUIC_GOAWAY_REQUEST_CAN_BE_RETRIED(-381),
diff --git a/java/org/cef/handler/CefRenderHandler.java b/java/org/cef/handler/CefRenderHandler.java
index 0a94bb2f..258df884 100644
--- a/java/org/cef/handler/CefRenderHandler.java
+++ b/java/org/cef/handler/CefRenderHandler.java
@@ -5,11 +5,13 @@
 package org.cef.handler;
 
 import org.cef.browser.CefBrowser;
+import org.cef.browser.CefPaintEvent;
 import org.cef.callback.CefDragData;
 
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.nio.ByteBuffer;
+import java.util.function.Consumer;
 
 /**
  * Implement this interface to handle events when window rendering is disabled.
@@ -65,6 +67,24 @@ public interface CefRenderHandler {
     public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects,
             ByteBuffer buffer, int width, int height);
 
+    /**
+     * Add provided listener.
+     * @param listener Code that gets executed after a frame was rendered.
+     */
+    public void addOnPaintListener(Consumer<CefPaintEvent> listener);
+
+    /**
+     * Remove existing listeners and replace with provided listener.
+     * @param listener Code that gets executed after a frame was rendered.
+     */
+    public void setOnPaintListener(Consumer<CefPaintEvent> listener);
+
+    /**
+     * Remove provided listener.
+     * @param listener Code that gets executed after a frame was rendered.
+     */
+    public void removeOnPaintListener(Consumer<CefPaintEvent> listener);
+
     /**
      * Handle cursor changes.
      * @param browser The browser generating the event.
diff --git a/java/tests/detailed/BrowserFrame.java b/java/tests/detailed/BrowserFrame.java
deleted file mode 100644
index 25beacf3..00000000
--- a/java/tests/detailed/BrowserFrame.java
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2018 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed;
-
-import org.cef.CefApp;
-import org.cef.browser.CefBrowser;
-import org.cef.handler.CefLifeSpanHandlerAdapter;
-
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-
-import javax.swing.JFrame;
-import javax.swing.SwingUtilities;
-
-public class BrowserFrame extends JFrame {
-    private volatile boolean isClosed_ = false;
-    private CefBrowser browser_ = null;
-    private static int browserCount_ = 0;
-    private Runnable afterParentChangedAction_ = null;
-
-    public BrowserFrame() {
-        this(null);
-    }
-
-    public BrowserFrame(String title) {
-        super(title);
-
-        // Browser window closing works as follows:
-        //   1. Clicking the window X button calls WindowAdapter.windowClosing.
-        //   2. WindowAdapter.windowClosing calls CefBrowser.close(false).
-        //   3. CEF calls CefLifeSpanHandler.doClose() which calls CefBrowser.doClose()
-        //      which returns true (canceling the close).
-        //   4. CefBrowser.doClose() triggers another call to WindowAdapter.windowClosing.
-        //   5. WindowAdapter.windowClosing calls CefBrowser.close(true).
-        //   6. For windowed browsers CEF destroys the native window handle. For OSR
-        //      browsers CEF calls CefLifeSpanHandler.doClose() which calls
-        //      CefBrowser.doClose() again which returns false (allowing the close).
-        //   7. CEF calls CefLifeSpanHandler.onBeforeClose and the browser is destroyed.
-        //
-        // On macOS pressing Cmd+Q results in a call to CefApp.handleBeforeTerminate
-        // which calls CefBrowser.close(true) for each existing browser. CEF then calls
-        // CefLifeSpanHandler.onBeforeClose and the browser is destroyed.
-        //
-        // Application shutdown works as follows:
-        //   1. CefLifeSpanHandler.onBeforeClose calls CefApp.getInstance().dispose()
-        //      when the last browser window is destroyed.
-        //   2. CefAppHandler.stateHasChanged terminates the application by calling
-        //      System.exit(0) when the state changes to CefAppState.TERMINATED.
-        addWindowListener(new WindowAdapter() {
-            @Override
-            public void windowClosing(WindowEvent e) {
-                if (browser_ == null) {
-                    // If there's no browser we can dispose immediately.
-                    isClosed_ = true;
-                    System.out.println("BrowserFrame.windowClosing Frame.dispose");
-                    dispose();
-                    return;
-                }
-
-                boolean isClosed = isClosed_;
-
-                if (isClosed) {
-                    // Cause browser.doClose() to return false so that OSR browsers
-                    // can close.
-                    browser_.setCloseAllowed();
-                }
-
-                // Results in another call to this method.
-                System.out.println("BrowserFrame.windowClosing CefBrowser.close(" + isClosed + ")");
-                browser_.close(isClosed);
-                if (!isClosed_) {
-                    isClosed_ = true;
-                }
-                if (isClosed) {
-                    // Dispose after the 2nd call to this method.
-                    System.out.println("BrowserFrame.windowClosing Frame.dispose");
-                    dispose();
-                }
-            }
-        });
-    }
-
-    public void setBrowser(CefBrowser browser) {
-        if (browser_ == null) browser_ = browser;
-
-        browser_.getClient().removeLifeSpanHandler();
-        browser_.getClient().addLifeSpanHandler(new CefLifeSpanHandlerAdapter() {
-            @Override
-            public void onAfterCreated(CefBrowser browser) {
-                System.out.println("BrowserFrame.onAfterCreated id=" + browser.getIdentifier());
-                browserCount_++;
-            }
-
-            @Override
-            public void onAfterParentChanged(CefBrowser browser) {
-                System.out.println(
-                        "BrowserFrame.onAfterParentChanged id=" + browser.getIdentifier());
-                if (afterParentChangedAction_ != null) {
-                    SwingUtilities.invokeLater(afterParentChangedAction_);
-                    afterParentChangedAction_ = null;
-                }
-            }
-
-            @Override
-            public boolean doClose(CefBrowser browser) {
-                boolean result = browser.doClose();
-                System.out.println("BrowserFrame.doClose id=" + browser.getIdentifier()
-                        + " CefBrowser.doClose=" + result);
-                return result;
-            }
-
-            @Override
-            public void onBeforeClose(CefBrowser browser) {
-                System.out.println("BrowserFrame.onBeforeClose id=" + browser.getIdentifier());
-                if (--browserCount_ == 0) {
-                    System.out.println("BrowserFrame.onBeforeClose CefApp.dispose");
-                    CefApp.getInstance().dispose();
-                }
-            }
-        });
-    }
-
-    public void removeBrowser(Runnable r) {
-        System.out.println("BrowserFrame.removeBrowser");
-        afterParentChangedAction_ = r;
-        // The removeNotify() notification should be sent as a result of calling remove().
-        // However, it isn't in all cases so we do it manually here.
-        browser_ = null;
-    }
-
-    public CefBrowser getBrowser() {
-        return browser_;
-    }
-}
diff --git a/java/tests/detailed/MainFrame.java b/java/tests/detailed/MainFrame.java
deleted file mode 100644
index 5b1efeb5..00000000
--- a/java/tests/detailed/MainFrame.java
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed;
-
-import org.cef.CefApp;
-import org.cef.CefApp.CefVersion;
-import org.cef.CefClient;
-import org.cef.CefSettings;
-import org.cef.CefSettings.ColorType;
-import org.cef.OS;
-import org.cef.browser.CefBrowser;
-import org.cef.browser.CefFrame;
-import org.cef.browser.CefMessageRouter;
-import org.cef.browser.CefRequestContext;
-import org.cef.handler.CefDisplayHandlerAdapter;
-import org.cef.handler.CefFocusHandlerAdapter;
-import org.cef.handler.CefLoadHandlerAdapter;
-import org.cef.handler.CefRequestContextHandlerAdapter;
-import org.cef.network.CefCookieManager;
-
-import java.awt.BorderLayout;
-import java.awt.KeyboardFocusManager;
-import java.awt.event.FocusAdapter;
-import java.awt.event.FocusEvent;
-import java.io.File;
-import java.lang.Thread.UncaughtExceptionHandler;
-
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-
-import tests.detailed.dialog.DownloadDialog;
-import tests.detailed.handler.AppHandler;
-import tests.detailed.handler.ContextMenuHandler;
-import tests.detailed.handler.DragHandler;
-import tests.detailed.handler.JSDialogHandler;
-import tests.detailed.handler.KeyboardHandler;
-import tests.detailed.handler.MessageRouterHandler;
-import tests.detailed.handler.MessageRouterHandlerEx;
-import tests.detailed.handler.RequestHandler;
-import tests.detailed.ui.ControlPanel;
-import tests.detailed.ui.MenuBar;
-import tests.detailed.ui.StatusPanel;
-import tests.detailed.util.DataUri;
-
-public class MainFrame extends BrowserFrame {
-    private static final long serialVersionUID = -2295538706810864538L;
-    public static void main(String[] args) {
-        // Perform startup initialization on platforms that require it.
-        if (!CefApp.startup(args)) {
-            System.out.println("Startup initialization failed!");
-            return;
-        }
-
-        // OSR mode is enabled by default on Linux.
-        // and disabled by default on Windows and Mac OS X.
-        boolean osrEnabledArg = false;
-        boolean transparentPaintingEnabledArg = false;
-        boolean createImmediately = false;
-        for (String arg : args) {
-            arg = arg.toLowerCase();
-            if (arg.equals("--off-screen-rendering-enabled")) {
-                osrEnabledArg = true;
-            } else if (arg.equals("--transparent-painting-enabled")) {
-                transparentPaintingEnabledArg = true;
-            } else if (arg.equals("--create-immediately")) {
-                createImmediately = true;
-            }
-        }
-
-        System.out.println("Offscreen rendering " + (osrEnabledArg ? "enabled" : "disabled"));
-
-        // MainFrame keeps all the knowledge to display the embedded browser
-        // frame.
-        final MainFrame frame = new MainFrame(
-                osrEnabledArg, transparentPaintingEnabledArg, createImmediately, args);
-        frame.setSize(800, 600);
-        frame.setVisible(true);
-    }
-
-    private final CefClient client_;
-    private String errorMsg_ = "";
-    private ControlPanel control_pane_;
-    private StatusPanel status_panel_;
-    private boolean browserFocus_ = true;
-    private boolean osr_enabled_;
-    private boolean transparent_painting_enabled_;
-
-    public MainFrame(boolean osrEnabled, boolean transparentPaintingEnabled,
-            boolean createImmediately, String[] args) {
-        this.osr_enabled_ = osrEnabled;
-        this.transparent_painting_enabled_ = transparentPaintingEnabled;
-
-        CefApp myApp;
-        if (CefApp.getState() != CefApp.CefAppState.INITIALIZED) {
-            // 1) CefApp is the entry point for JCEF. You can pass
-            //    application arguments to it, if you want to handle any
-            //    chromium or CEF related switches/attributes in
-            //    the native world.
-            CefSettings settings = new CefSettings();
-            settings.windowless_rendering_enabled = osrEnabled;
-            // try to load URL "about:blank" to see the background color
-            settings.background_color = settings.new ColorType(100, 255, 242, 211);
-            myApp = CefApp.getInstance(args, settings);
-
-            CefVersion version = myApp.getVersion();
-            System.out.println("Using:\n" + version);
-
-            //    We're registering our own AppHandler because we want to
-            //    add an own schemes (search:// and client://) and its corresponding
-            //    protocol handlers. So if you enter "search:something on the web", your
-            //    search request "something on the web" is forwarded to www.google.com
-            CefApp.addAppHandler(new AppHandler(args));
-        } else {
-            myApp = CefApp.getInstance();
-        }
-
-        //    By calling the method createClient() the native part
-        //    of JCEF/CEF will be initialized and an  instance of
-        //    CefClient will be created. You can create one to many
-        //    instances of CefClient.
-        client_ = myApp.createClient();
-
-        // 2) You have the ability to pass different handlers to your
-        //    instance of CefClient. Each handler is responsible to
-        //    deal with different informations (e.g. keyboard input).
-        //
-        //    For each handler (with more than one method) adapter
-        //    classes exists. So you don't need to override methods
-        //    you're not interested in.
-        DownloadDialog downloadDialog = new DownloadDialog(this);
-        client_.addContextMenuHandler(new ContextMenuHandler(this));
-        client_.addDownloadHandler(downloadDialog);
-        client_.addDragHandler(new DragHandler());
-        client_.addJSDialogHandler(new JSDialogHandler());
-        client_.addKeyboardHandler(new KeyboardHandler());
-        client_.addRequestHandler(new RequestHandler(this));
-
-        //    Beside the normal handler instances, we're registering a MessageRouter
-        //    as well. That gives us the opportunity to reply to JavaScript method
-        //    calls (JavaScript binding). We're using the default configuration, so
-        //    that the JavaScript binding methods "cefQuery" and "cefQueryCancel"
-        //    are used.
-        CefMessageRouter msgRouter = CefMessageRouter.create();
-        msgRouter.addHandler(new MessageRouterHandler(), true);
-        msgRouter.addHandler(new MessageRouterHandlerEx(client_), false);
-        client_.addMessageRouter(msgRouter);
-
-        // 2.1) We're overriding CefDisplayHandler as nested anonymous class
-        //      to update our address-field, the title of the panel as well
-        //      as for updating the status-bar on the bottom of the browser
-        client_.addDisplayHandler(new CefDisplayHandlerAdapter() {
-            @Override
-            public void onAddressChange(CefBrowser browser, CefFrame frame, String url) {
-                control_pane_.setAddress(browser, url);
-            }
-            @Override
-            public void onTitleChange(CefBrowser browser, String title) {
-                setTitle(title);
-            }
-            @Override
-            public void onStatusMessage(CefBrowser browser, String value) {
-                status_panel_.setStatusText(value);
-            }
-        });
-
-        // 2.2) To disable/enable navigation buttons and to display a prgress bar
-        //      which indicates the load state of our website, we're overloading
-        //      the CefLoadHandler as nested anonymous class. Beside this, the
-        //      load handler is responsible to deal with (load) errors as well.
-        //      For example if you navigate to a URL which does not exist, the
-        //      browser will show up an error message.
-        client_.addLoadHandler(new CefLoadHandlerAdapter() {
-            @Override
-            public void onLoadingStateChange(CefBrowser browser, boolean isLoading,
-                    boolean canGoBack, boolean canGoForward) {
-                control_pane_.update(browser, isLoading, canGoBack, canGoForward);
-                status_panel_.setIsInProgress(isLoading);
-
-                if (!isLoading && !errorMsg_.isEmpty()) {
-                    browser.loadURL(DataUri.create("text/html", errorMsg_));
-                    errorMsg_ = "";
-                }
-            }
-
-            @Override
-            public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode,
-                    String errorText, String failedUrl) {
-                if (errorCode != ErrorCode.ERR_NONE && errorCode != ErrorCode.ERR_ABORTED) {
-                    errorMsg_ = "<html><head>";
-                    errorMsg_ += "<title>Error while loading</title>";
-                    errorMsg_ += "</head><body>";
-                    errorMsg_ += "<h1>" + errorCode + "</h1>";
-                    errorMsg_ += "<h3>Failed to load " + failedUrl + "</h3>";
-                    errorMsg_ += "<p>" + (errorText == null ? "" : errorText) + "</p>";
-                    errorMsg_ += "</body></html>";
-                    browser.stopLoad();
-                }
-            }
-        });
-
-        // Create the browser.
-        CefBrowser browser = client_.createBrowser(
-                "http://www.google.com", osrEnabled, null);
-        setBrowser(browser);
-
-        // Set up the UI for this example implementation.
-        JPanel contentPanel = createContentPanel();
-        getContentPane().add(contentPanel, BorderLayout.CENTER);
-
-        // Clear focus from the browser when the address field gains focus.
-        control_pane_.getAddressField().addFocusListener(new FocusAdapter() {
-            @Override
-            public void focusGained(FocusEvent e) {
-                if (!browserFocus_) return;
-                browserFocus_ = false;
-                KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
-                control_pane_.getAddressField().requestFocus();
-            }
-        });
-
-        // Clear focus from the address field when the browser gains focus.
-        client_.addFocusHandler(new CefFocusHandlerAdapter() {
-            @Override
-            public void onGotFocus(CefBrowser browser) {
-                if (browserFocus_) return;
-                browserFocus_ = true;
-                KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
-                browser.setFocus(true);
-            }
-
-            @Override
-            public void onTakeFocus(CefBrowser browser, boolean next) {
-                browserFocus_ = false;
-            }
-        });
-
-        if (createImmediately) browser.createImmediately();
-
-        // Add the browser to the UI.
-
-        MenuBar menuBar = new MenuBar(
-                this, browser, control_pane_, downloadDialog, CefCookieManager.getGlobalManager());
-
-        menuBar.addBookmark("Binding Test", "client://tests/binding_test.html");
-        menuBar.addBookmark("Binding Test 2", "client://tests/binding_test2.html");
-        menuBar.addBookmark("Download Test", "https://cef-builds.spotifycdn.com/index.html");
-        menuBar.addBookmark("Login Test (username:pumpkin, password:pie)",
-                "http://www.colostate.edu/~ric/protect/your.html");
-        menuBar.addBookmark("Certificate-error Test", "https://www.k2go.de");
-        menuBar.addBookmark("Resource-Handler Test", "http://www.foo.bar/");
-        menuBar.addBookmark("Resource-Handler Set Error Test", "http://seterror.test/");
-        menuBar.addBookmark(
-                "Scheme-Handler Test 1: (scheme \"client\")", "client://tests/handler.html");
-        menuBar.addBookmark(
-                "Scheme-Handler Test 2: (scheme \"search\")", "search://do a barrel roll/");
-        menuBar.addBookmark("Spellcheck Test", "client://tests/spellcheck.html");
-        menuBar.addBookmark("LocalStorage Test", "client://tests/localstorage.html");
-        menuBar.addBookmark("Transparency Test", "client://tests/transparency.html");
-        menuBar.addBookmarkSeparator();
-        menuBar.addBookmark(
-                "javachromiumembedded", "https://bitbucket.org/chromiumembedded/java-cef");
-        menuBar.addBookmark("chromiumembedded", "https://bitbucket.org/chromiumembedded/cef");
-        setJMenuBar(menuBar);
-    }
-
-    private JPanel createContentPanel() {
-        JPanel contentPanel = new JPanel(new BorderLayout());
-        control_pane_ = new ControlPanel(getBrowser());
-        status_panel_ = new StatusPanel();
-        contentPanel.add(control_pane_, BorderLayout.NORTH);
-        contentPanel.add(status_panel_, BorderLayout.SOUTH);
-        return contentPanel;
-    }
-
-    public boolean isOsrEnabled() {
-        return osr_enabled_;
-    }
-
-    public boolean isTransparentPaintingEnabled() {
-        return transparent_painting_enabled_;
-    }
-}
diff --git a/java/tests/detailed/dialog/CertErrorDialog.java b/java/tests/detailed/dialog/CertErrorDialog.java
deleted file mode 100644
index 4c78ea79..00000000
--- a/java/tests/detailed/dialog/CertErrorDialog.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.dialog;
-
-import org.cef.callback.CefCallback;
-import org.cef.handler.CefLoadHandler.ErrorCode;
-
-import java.awt.Frame;
-
-import javax.swing.JOptionPane;
-
-public class CertErrorDialog implements Runnable {
-    private final Frame owner_;
-    private final ErrorCode cert_error_;
-    private final String request_url_;
-    private final CefCallback callback_;
-
-    public CertErrorDialog(
-            Frame owner, ErrorCode cert_error, String request_url, CefCallback callback) {
-        owner_ = owner;
-        cert_error_ = cert_error;
-        request_url_ = request_url;
-        callback_ = callback;
-    }
-
-    @Override
-    public void run() {
-        int dialogResult = JOptionPane.showConfirmDialog(owner_,
-                "An certificate error (" + cert_error_ + ") occurreed "
-                        + "while requesting\n" + request_url_ + "\nDo you want to proceed anyway?",
-                "Certificate error", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE);
-        if (dialogResult == JOptionPane.YES_OPTION) {
-            callback_.Continue();
-        } else {
-            callback_.cancel();
-        }
-    }
-}
diff --git a/java/tests/detailed/dialog/CookieManagerDialog.java b/java/tests/detailed/dialog/CookieManagerDialog.java
deleted file mode 100644
index 279ebbf2..00000000
--- a/java/tests/detailed/dialog/CookieManagerDialog.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.dialog;
-
-import org.cef.callback.CefCookieVisitor;
-import org.cef.misc.BoolRef;
-import org.cef.network.CefCookie;
-import org.cef.network.CefCookieManager;
-
-import java.awt.BorderLayout;
-import java.awt.Frame;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.Date;
-import java.util.Vector;
-
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.table.AbstractTableModel;
-
-@SuppressWarnings("serial")
-public class CookieManagerDialog extends JDialog {
-    private static int testCookieId = 1;
-    private final CefCookieManager manager;
-    private final CookieTableModel tblModel = new CookieTableModel();
-
-    public CookieManagerDialog(Frame owner, String title, CefCookieManager cookieManager) {
-        super(owner, title, false);
-        setLayout(new BorderLayout());
-        setSize(800, 600);
-        manager = cookieManager;
-
-        JTable cookieTable = new JTable(tblModel);
-        cookieTable.setFillsViewportHeight(true);
-
-        JPanel controlPanel = new JPanel();
-        controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS));
-        JButton delButton = new JButton("Delete cookies");
-        delButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                tblModel.removeCookies();
-            }
-        });
-        controlPanel.add(delButton);
-
-        JButton testCreateCookie = new JButton("Add test cookie");
-        testCreateCookie.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                Date now = new Date();
-                Date expires = new Date(now.getTime() + 86400000);
-                String name = "testNo" + testCookieId++;
-                CefCookie cookie = new CefCookie(name, "testCookie", ".test.cookie", "/", false,
-                        true, now, now, true, expires);
-                if (manager.setCookie("http://my.test.cookie", cookie)) {
-                    tblModel.visit(cookie, 1, 1, new BoolRef());
-                }
-            }
-        });
-        controlPanel.add(testCreateCookie);
-
-        JButton doneButton = new JButton("Done");
-        doneButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                setVisible(false);
-            }
-        });
-        controlPanel.add(doneButton);
-
-        add(new JScrollPane(cookieTable));
-        add(controlPanel, BorderLayout.SOUTH);
-
-        if (manager == null) throw new NullPointerException("Cookie manager is null");
-        manager.visitAllCookies(tblModel);
-    }
-
-    private class CookieTableModel extends AbstractTableModel implements CefCookieVisitor {
-        private final String[] columnNames;
-        private Vector<Object[]> rowData = new Vector<>();
-
-        public CookieTableModel() {
-            super();
-            columnNames = new String[] {"Name", "Value", "Domain", "Path", "Secure", "HTTP only",
-                    "Created", "Last Access", "Expires"};
-        }
-
-        // add an entry to the table
-        @Override
-        public boolean visit(CefCookie cookie, int count, int total, BoolRef delete) {
-            Object[] entry = {cookie.name, cookie.value, cookie.domain, cookie.path,
-                    new Boolean(cookie.secure), new Boolean(cookie.httponly), cookie.creation,
-                    cookie.lastAccess, cookie.expires};
-            int row = rowData.size();
-            rowData.addElement(entry);
-            fireTableRowsInserted(row, row);
-
-            return true;
-        }
-
-        public void removeCookies() {
-            int cnt = rowData.size();
-            if (cnt > 0) {
-                rowData.clear();
-                manager.deleteCookies("", "");
-                fireTableRowsDeleted(0, cnt - 1);
-            }
-        }
-
-        @Override
-        public int getRowCount() {
-            return rowData.size();
-        }
-
-        @Override
-        public int getColumnCount() {
-            return columnNames.length;
-        }
-
-        @Override
-        public String getColumnName(int column) {
-            return columnNames[column];
-        }
-
-        @Override
-        public Class<?> getColumnClass(int columnIndex) {
-            if (rowData.size() > 0) return rowData.get(0)[columnIndex].getClass();
-            return Object.class;
-        }
-
-        @Override
-        public boolean isCellEditable(int rowIndex, int columnIndex) {
-            return false;
-        }
-
-        @Override
-        public Object getValueAt(int rowIndex, int columnIndex) {
-            return rowData.get(rowIndex)[columnIndex];
-        }
-    }
-}
diff --git a/java/tests/detailed/dialog/DevToolsDialog.java b/java/tests/detailed/dialog/DevToolsDialog.java
deleted file mode 100644
index 74a3a766..00000000
--- a/java/tests/detailed/dialog/DevToolsDialog.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.dialog;
-
-import org.cef.browser.CefBrowser;
-
-import java.awt.BorderLayout;
-import java.awt.Frame;
-import java.awt.Point;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-
-import javax.swing.JDialog;
-
-@SuppressWarnings("serial")
-public class DevToolsDialog extends JDialog {
-    private final CefBrowser devTools_;
-    public DevToolsDialog(Frame owner, String title, CefBrowser browser) {
-        this(owner, title, browser, null);
-    }
-
-    public DevToolsDialog(Frame owner, String title, CefBrowser browser, Point inspectAt) {
-        super(owner, title, false);
-
-        setLayout(new BorderLayout());
-        setSize(800, 600);
-        setLocation(owner.getLocation().x + 20, owner.getLocation().y + 20);
-
-        devTools_ = browser.getDevTools(inspectAt);
-
-        addComponentListener(new ComponentAdapter() {
-            @Override
-            public void componentHidden(ComponentEvent e) {
-                dispose();
-            }
-        });
-    }
-
-    @Override
-    public void dispose() {
-        devTools_.close(true);
-        super.dispose();
-    }
-}
diff --git a/java/tests/detailed/dialog/DownloadDialog.java b/java/tests/detailed/dialog/DownloadDialog.java
deleted file mode 100644
index f9717a50..00000000
--- a/java/tests/detailed/dialog/DownloadDialog.java
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.dialog;
-
-import org.cef.browser.CefBrowser;
-import org.cef.callback.CefBeforeDownloadCallback;
-import org.cef.callback.CefDownloadItem;
-import org.cef.callback.CefDownloadItemCallback;
-import org.cef.handler.CefDownloadHandler;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Frame;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-
-@SuppressWarnings("serial")
-public class DownloadDialog extends JDialog implements CefDownloadHandler {
-    private final Frame owner_;
-    private final Map<Integer, DownloadObject> downloadObjects_ =
-            new HashMap<Integer, DownloadObject>();
-    private final JPanel downloadPanel_ = new JPanel();
-    private final DownloadDialog dialog_;
-
-    public DownloadDialog(Frame owner) {
-        super(owner, "Downloads", false);
-        setVisible(false);
-        setSize(400, 300);
-
-        owner_ = owner;
-        dialog_ = this;
-        downloadPanel_.setLayout(new BoxLayout(downloadPanel_, BoxLayout.Y_AXIS));
-        add(downloadPanel_);
-    }
-
-    private class DownloadObject extends JPanel {
-        private boolean isHidden_ = true;
-        private final int identifier_;
-        private JLabel fileName_ = new JLabel();
-        private JLabel status_ = new JLabel();
-        private JButton dlAbort_ = new JButton();
-        private JButton dlRemoveEntry_ = new JButton("x");
-        private CefDownloadItemCallback callback_;
-        private Color bgColor_;
-
-        DownloadObject(CefDownloadItem downloadItem, String suggestedName) {
-            super();
-            setOpaque(true);
-            setLayout(new BorderLayout());
-            setMaximumSize(new Dimension(dialog_.getWidth() - 10, 80));
-            identifier_ = downloadItem.getId();
-            bgColor_ = identifier_ % 2 == 0 ? Color.WHITE : Color.YELLOW;
-            setBackground(bgColor_);
-
-            fileName_.setText(suggestedName);
-            add(fileName_, BorderLayout.NORTH);
-
-            status_.setAlignmentX(LEFT_ALIGNMENT);
-            add(status_, BorderLayout.CENTER);
-
-            JPanel controlPane = new JPanel();
-            controlPane.setLayout(new BoxLayout(controlPane, BoxLayout.X_AXIS));
-            controlPane.setOpaque(true);
-            controlPane.setBackground(bgColor_);
-            dlAbort_.setText("Abort");
-            dlAbort_.setEnabled(false);
-            dlAbort_.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(ActionEvent e) {
-                    if (callback_ != null) {
-                        fileName_.setText("ABORTED - " + fileName_.getText());
-                        callback_.cancel();
-                    }
-                }
-            });
-            controlPane.add(dlAbort_);
-
-            dlRemoveEntry_.setEnabled(false);
-            dlRemoveEntry_.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(ActionEvent e) {
-                    DownloadObject removed = downloadObjects_.remove(identifier_);
-                    if (removed != null) {
-                        downloadPanel_.remove(removed);
-                        dialog_.repaint();
-                    }
-                }
-            });
-            controlPane.add(dlRemoveEntry_);
-            add(controlPane, BorderLayout.SOUTH);
-
-            update(downloadItem, null);
-        }
-
-        // The method humanReadableByteCount() is based on
-        // http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
-        String humanReadableByteCount(long bytes) {
-            int unit = 1024;
-            if (bytes < unit) return bytes + " B";
-
-            int exp = (int) (Math.log(bytes) / Math.log(unit));
-            String pre = "" + ("kMGTPE").charAt(exp - 1);
-            return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
-        }
-
-        void update(CefDownloadItem downloadItem, CefDownloadItemCallback callback) {
-            int percentComplete = downloadItem.getPercentComplete();
-            String rcvBytes = humanReadableByteCount(downloadItem.getReceivedBytes());
-            String totalBytes = humanReadableByteCount(downloadItem.getTotalBytes());
-            String speed = humanReadableByteCount(downloadItem.getCurrentSpeed()) + "it/s";
-
-            if (downloadItem.getReceivedBytes() >= 5 && isHidden_) {
-                dialog_.setVisible(true);
-                dialog_.toFront();
-                owner_.toBack();
-                isHidden_ = false;
-            }
-            Runtime.getRuntime().runFinalization();
-
-            callback_ = callback;
-            status_.setText(rcvBytes + " of " + totalBytes + " - " + percentComplete + "%"
-                    + " - " + speed);
-            dlAbort_.setEnabled(downloadItem.isInProgress());
-            dlRemoveEntry_.setEnabled(!downloadItem.isInProgress() || downloadItem.isCanceled()
-                    || downloadItem.isComplete());
-            if (!downloadItem.isInProgress() && !downloadItem.isCanceled()
-                    && !downloadItem.isComplete()) {
-                fileName_.setText("FAILED - " + fileName_.getText());
-                callback.cancel();
-            }
-        }
-    }
-
-    @Override
-    public void onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem,
-            String suggestedName, CefBeforeDownloadCallback callback) {
-        callback.Continue(suggestedName, true);
-
-        DownloadObject dlObject = new DownloadObject(downloadItem, suggestedName);
-        downloadObjects_.put(downloadItem.getId(), dlObject);
-        downloadPanel_.add(dlObject);
-    }
-
-    @Override
-    public void onDownloadUpdated(
-            CefBrowser browser, CefDownloadItem downloadItem, CefDownloadItemCallback callback) {
-        DownloadObject dlObject = downloadObjects_.get(downloadItem.getId());
-        if (dlObject == null) return;
-        dlObject.update(downloadItem, callback);
-    }
-}
diff --git a/java/tests/detailed/dialog/PasswordDialog.java b/java/tests/detailed/dialog/PasswordDialog.java
deleted file mode 100644
index 61662f48..00000000
--- a/java/tests/detailed/dialog/PasswordDialog.java
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.dialog;
-
-import org.cef.callback.CefAuthCallback;
-
-import java.awt.Frame;
-import java.awt.GridLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPasswordField;
-import javax.swing.JTextField;
-
-@SuppressWarnings("serial")
-public class PasswordDialog extends JDialog implements Runnable {
-    private final JTextField username_ = new JTextField(20);
-    private final JPasswordField password_ = new JPasswordField(20);
-    private final CefAuthCallback callback_;
-
-    public PasswordDialog(Frame owner, CefAuthCallback callback) {
-        super(owner, "Authentication required", true);
-        callback_ = callback;
-        setSize(400, 100);
-        setLayout(new GridLayout(0, 2));
-        add(new JLabel("Username:"));
-        add(username_);
-        add(new JLabel("Password:"));
-        add(password_);
-
-        JButton abortButton = new JButton("Abort");
-        abortButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                callback_.cancel();
-                setVisible(false);
-                dispose();
-            }
-        });
-        add(abortButton);
-
-        JButton okButton = new JButton("OK");
-        okButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                if (username_.getText().isEmpty()) return;
-                String password = new String(password_.getPassword());
-                callback_.Continue(username_.getText(), password);
-                setVisible(false);
-                dispose();
-            }
-        });
-        add(okButton);
-    }
-
-    @Override
-    public void run() {
-        setVisible(true);
-    }
-}
diff --git a/java/tests/detailed/dialog/SearchDialog.java b/java/tests/detailed/dialog/SearchDialog.java
deleted file mode 100644
index 88838c36..00000000
--- a/java/tests/detailed/dialog/SearchDialog.java
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.dialog;
-
-import org.cef.browser.CefBrowser;
-
-import java.awt.BorderLayout;
-import java.awt.Frame;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.Box;
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-
-@SuppressWarnings("serial")
-public class SearchDialog extends JDialog {
-    private final CefBrowser browser_;
-    private final JTextField searchField_ = new JTextField(30);
-    private final JCheckBox caseCheckBox_ = new JCheckBox("Case sensitive");
-    private final JButton prevButton_ = new JButton("Prev");
-    private final JButton nextButton_ = new JButton("Next");
-
-    public SearchDialog(Frame owner, CefBrowser browser) {
-        super(owner, "Find...", false);
-        browser_ = browser;
-
-        setLayout(new BorderLayout());
-        setSize(400, 100);
-
-        JPanel searchPanel = new JPanel();
-        searchPanel.setLayout(new BoxLayout(searchPanel, BoxLayout.X_AXIS));
-        searchPanel.add(Box.createHorizontalStrut(5));
-        searchPanel.add(new JLabel("Search:"));
-        searchPanel.add(searchField_);
-
-        JPanel controlPanel = new JPanel();
-        controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS));
-        controlPanel.add(Box.createHorizontalStrut(5));
-
-        JButton searchButton = new JButton("Search");
-        searchButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                if (searchField_.getText() == null || searchField_.getText().isEmpty()) return;
-
-                setTitle("Find \"" + searchField_.getText() + "\"");
-                boolean matchCase = caseCheckBox_.isSelected();
-                browser_.find(searchField_.getText(), true, matchCase, false);
-                prevButton_.setEnabled(true);
-                nextButton_.setEnabled(true);
-            }
-        });
-        controlPanel.add(searchButton);
-
-        prevButton_.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                boolean matchCase = caseCheckBox_.isSelected();
-                setTitle("Find \"" + searchField_.getText() + "\"");
-                browser_.find(searchField_.getText(), false, matchCase, true);
-            }
-        });
-        prevButton_.setEnabled(false);
-        controlPanel.add(prevButton_);
-
-        nextButton_.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                boolean matchCase = caseCheckBox_.isSelected();
-                setTitle("Find \"" + searchField_.getText() + "\"");
-                browser_.find(searchField_.getText(), true, matchCase, true);
-            }
-        });
-        nextButton_.setEnabled(false);
-        controlPanel.add(nextButton_);
-
-        controlPanel.add(Box.createHorizontalStrut(50));
-
-        JButton doneButton = new JButton("Done");
-        doneButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                setVisible(false);
-                dispose();
-            }
-        });
-        controlPanel.add(doneButton);
-
-        add(searchPanel, BorderLayout.NORTH);
-        add(caseCheckBox_);
-        add(controlPanel, BorderLayout.SOUTH);
-    }
-
-    @Override
-    public void dispose() {
-        browser_.stopFinding(true);
-        super.dispose();
-    }
-}
diff --git a/java/tests/detailed/dialog/ShowTextDialog.java b/java/tests/detailed/dialog/ShowTextDialog.java
deleted file mode 100644
index 70813046..00000000
--- a/java/tests/detailed/dialog/ShowTextDialog.java
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.dialog;
-
-import org.cef.callback.CefStringVisitor;
-
-import java.awt.BorderLayout;
-import java.awt.Frame;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextArea;
-
-@SuppressWarnings("serial")
-public class ShowTextDialog extends JDialog implements CefStringVisitor {
-    private final JTextArea textArea_ = new JTextArea();
-
-    public ShowTextDialog(Frame owner, String title) {
-        super(owner, title, false);
-        setLayout(new BorderLayout());
-        setSize(800, 600);
-
-        JPanel controlPanel = new JPanel();
-        controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS));
-        JButton doneButton = new JButton("Done");
-        doneButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                setVisible(false);
-                dispose();
-            }
-        });
-        controlPanel.add(doneButton);
-
-        add(new JScrollPane(textArea_));
-        add(controlPanel, BorderLayout.SOUTH);
-    }
-
-    @Override
-    public void visit(String string) {
-        if (!isVisible()) {
-            setVisible(true);
-        }
-        textArea_.append(string);
-    }
-}
diff --git a/java/tests/detailed/dialog/UrlRequestDialog.java b/java/tests/detailed/dialog/UrlRequestDialog.java
deleted file mode 100644
index b1cc175e..00000000
--- a/java/tests/detailed/dialog/UrlRequestDialog.java
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.dialog;
-
-import org.cef.network.CefPostData;
-import org.cef.network.CefPostDataElement;
-import org.cef.network.CefRequest;
-import org.cef.network.CefRequest.CefUrlRequestFlags;
-
-import java.awt.BorderLayout;
-import java.awt.Frame;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.GridLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.Vector;
-
-import javax.swing.BorderFactory;
-import javax.swing.ButtonGroup;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JDialog;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JRadioButton;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.JTextField;
-import javax.swing.SwingUtilities;
-import javax.swing.table.AbstractTableModel;
-
-@SuppressWarnings("serial")
-public class UrlRequestDialog extends JDialog {
-    private final Vector<JRadioButton> requestMethods = new Vector<>();
-    private final Map<JCheckBox, Integer> requestFlags = new HashMap<>();
-    private final TableModel headerTblModel = new TableModel(true);
-    private final TableModel postDataModel = new TableModel(false);
-    private final JTextField urlField;
-    private final JTextField cookieUrl;
-    private final Frame owner_;
-
-    private CefRequest createRequest() {
-        String url = urlField.getText();
-        if (url.isEmpty() || url.trim().equalsIgnoreCase("http://")) {
-            SwingUtilities.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                    JOptionPane.showMessageDialog(owner_,
-                            "Please specify at least an URL. Otherwise the CefRequest is invalid");
-                }
-            });
-            return null;
-        }
-
-        CefRequest request = CefRequest.create();
-        if (request == null) return null;
-
-        String firstPartyForCookie = cookieUrl.getText();
-        if (firstPartyForCookie.isEmpty() || firstPartyForCookie.trim().equalsIgnoreCase("http://"))
-            firstPartyForCookie = url;
-
-        String method = "GET";
-        for (int i = 0; i < requestMethods.size(); i++) {
-            JRadioButton button = requestMethods.get(i);
-            if (button.isSelected()) {
-                method = button.getText();
-                break;
-            }
-        }
-
-        CefPostData postData = null;
-        int postDataRows = postDataModel.getRowCount();
-        if (postDataRows > 0) {
-            postData = CefPostData.create();
-        } else if (method.equalsIgnoreCase("POST") || method.equalsIgnoreCase("PUT")) {
-            SwingUtilities.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                    JOptionPane.showMessageDialog(
-                            owner_, "The methods POST and PUT require at least one row of data.");
-                }
-            });
-            return null;
-        }
-
-        if (postData != null) {
-            for (int i = 0; i < postDataRows; i++) {
-                String value = (String) postDataModel.getValueAt(i, 0);
-                if (value.trim().isEmpty()) continue;
-
-                CefPostDataElement elem = CefPostDataElement.create();
-                if (elem != null) {
-                    File f = new File(value);
-                    if (f.isFile()) {
-                        elem.setToFile(value);
-                    } else {
-                        byte[] byteStr = value.getBytes();
-                        elem.setToBytes(byteStr.length, byteStr);
-                    }
-                    postData.addElement(elem);
-                }
-            }
-        }
-
-        Map<String, String> headerMap = null;
-        int headerRows = headerTblModel.getRowCount();
-        if (headerRows > 0) {
-            headerMap = new HashMap<>();
-            for (int i = 0; i < headerRows; i++) {
-                String key = (String) headerTblModel.getValueAt(i, 0);
-                String value = (String) headerTblModel.getValueAt(i, 1);
-                if (key.trim().isEmpty()) continue;
-
-                headerMap.put(key, value);
-            }
-        }
-
-        int flags = 0;
-        Set<Entry<JCheckBox, Integer>> entrySet = requestFlags.entrySet();
-        for (Entry<JCheckBox, Integer> entry : entrySet) {
-            if (entry.getKey().isSelected()) {
-                flags |= entry.getValue();
-            }
-        }
-
-        request.set(url, method, postData, headerMap);
-        request.setFirstPartyForCookies(firstPartyForCookie);
-        request.setFlags(flags);
-        return request;
-    }
-
-    public UrlRequestDialog(Frame owner, String title) {
-        super(owner, title, false);
-        setSize(1200, 600);
-        setLayout(new BorderLayout());
-
-        owner_ = owner;
-
-        // URL for the request
-        urlField = new JTextField("http://");
-        JPanel urlPanel = createPanelWithTitle("Request URL", 1, 0);
-        urlPanel.add(urlField);
-
-        // URL for the cookies
-        cookieUrl = new JTextField("http://");
-        JPanel cookiePanel = createPanelWithTitle("Cookie-URL", 1, 0);
-        cookiePanel.add(cookieUrl);
-
-        // Radio buttons for the request method
-        ButtonGroup requestModeGrp = new ButtonGroup();
-        JPanel requestModePanel = createPanelWithTitle("HTTP Request Mode", 1, 0);
-        addRequestMode(requestModePanel, requestModeGrp, "GET", true);
-        addRequestMode(requestModePanel, requestModeGrp, "HEAD", false);
-        addRequestMode(requestModePanel, requestModeGrp, "POST", false);
-        addRequestMode(requestModePanel, requestModeGrp, "PUT", false);
-        addRequestMode(requestModePanel, requestModeGrp, "DELETE", false);
-
-        // Checkboxes for the flags
-        JPanel flagsPanel = createPanelWithTitle("Flags", 0, 1);
-        addRequestFlag(flagsPanel, "Skip cache", CefUrlRequestFlags.UR_FLAG_SKIP_CACHE,
-                "If set the cache will be skipped when handling the request", false);
-        addRequestFlag(flagsPanel, "Allow cached credentials",
-                CefUrlRequestFlags.UR_FLAG_ALLOW_CACHED_CREDENTIALS,
-                "If set user name, password, and cookies may be sent with the request, "
-                        + "and cookies may be saved from the response.",
-                false);
-        addRequestFlag(flagsPanel, "Report Upload Progress",
-                CefUrlRequestFlags.UR_FLAG_REPORT_UPLOAD_PROGRESS,
-                "If set upload progress events will be generated when a request has a body", false);
-        addRequestFlag(flagsPanel, "Report RawHeaders",
-                CefUrlRequestFlags.UR_FLAG_REPORT_RAW_HEADERS,
-                "If set the headers sent and received for the request will be recorded", false);
-        addRequestFlag(flagsPanel, "No download data", CefUrlRequestFlags.UR_FLAG_NO_DOWNLOAD_DATA,
-                "If set the CefURLRequestClient.onDownloadData method will not be called", false);
-        addRequestFlag(flagsPanel, "No retry on 5xx", CefUrlRequestFlags.UR_FLAG_NO_RETRY_ON_5XX,
-                "If set 5XX redirect errors will be propagated to the observer instead of automatically re-tried.",
-                false);
-
-        // Table for header values
-        JPanel headerValues = createPanelWithTable("Header Values", headerTblModel);
-        headerTblModel.addEntry("User-Agent", "Mozilla/5.0 JCEF Example Agent");
-        headerTblModel.addEntry("Accept",
-                "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
-
-        // Table for post-data
-        JPanel postData = createPanelWithTable("Post Data", postDataModel);
-
-        // Create view
-        JPanel headerPanel = new JPanel(new GridBagLayout());
-        GridBagConstraints c = new GridBagConstraints();
-        c.fill = GridBagConstraints.HORIZONTAL;
-        c.weightx = 0.5;
-        c.gridx = 0;
-        c.gridy = 0;
-        headerPanel.add(urlPanel, c);
-        c.gridx = 1;
-        headerPanel.add(cookiePanel, c);
-        c.gridx = 0;
-        c.gridy = 1;
-        c.gridwidth = 2;
-        c.weightx = 0.0;
-        headerPanel.add(requestModePanel, c);
-
-        JPanel centerPanel = new JPanel(new GridLayout(2, 0));
-        centerPanel.add(headerValues);
-        centerPanel.add(postData);
-
-        JButton abortButton = new JButton("Abort");
-        abortButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                setVisible(false);
-                dispose();
-            }
-        });
-
-        JButton sendButton = new JButton("Send");
-        sendButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                CefRequest request = createRequest();
-                if (request == null) return;
-
-                UrlRequestDialogReply handleRequest =
-                        new UrlRequestDialogReply(owner_, getTitle() + " - Result");
-                handleRequest.send(request);
-                handleRequest.setVisible(true);
-                setVisible(false);
-                dispose();
-            }
-        });
-
-        JPanel bottomPanel = new JPanel(new GridLayout(0, 2));
-        bottomPanel.add(abortButton);
-        bottomPanel.add(sendButton);
-
-        add(headerPanel, BorderLayout.PAGE_START);
-        add(flagsPanel, BorderLayout.LINE_START);
-        add(centerPanel, BorderLayout.CENTER);
-        add(bottomPanel, BorderLayout.PAGE_END);
-    }
-
-    private void addRequestMode(
-            JPanel panel, ButtonGroup buttonGrp, String requestMode, boolean selected) {
-        JRadioButton button = new JRadioButton(requestMode, selected);
-        buttonGrp.add(button);
-        panel.add(button);
-        requestMethods.addElement(button);
-    }
-
-    private void addRequestFlag(
-            JPanel panel, String flag, int value, String tooltip, boolean selected) {
-        JCheckBox checkBox = new JCheckBox(flag, selected);
-        checkBox.setToolTipText(tooltip);
-        panel.add(checkBox);
-        requestFlags.put(checkBox, value);
-    }
-
-    private JPanel createPanelWithTitle(String title, int rows, int cols) {
-        JPanel result = new JPanel(new GridLayout(rows, cols));
-        result.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(title),
-                BorderFactory.createEmptyBorder(10, 10, 10, 10)));
-        return result;
-    }
-
-    private JPanel createPanelWithTable(String title, TableModel tblModel) {
-        final TableModel localTblModel = tblModel;
-        JPanel result = new JPanel(new BorderLayout());
-        result.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(title),
-                BorderFactory.createEmptyBorder(10, 10, 10, 10)));
-
-        JTable table = new JTable(tblModel);
-        table.setFillsViewportHeight(true);
-        JScrollPane scrollPane = new JScrollPane(table);
-
-        JPanel buttonPane = new JPanel(new GridLayout(0, 2));
-        JButton addButton = new JButton("Add entry");
-        addButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                localTblModel.newDefaultEntry();
-            }
-        });
-        buttonPane.add(addButton);
-
-        JButton delButton = new JButton("Remove entry");
-        delButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                localTblModel.removeSelected();
-            }
-        });
-        buttonPane.add(delButton);
-
-        result.add(scrollPane, BorderLayout.CENTER);
-        result.add(buttonPane, BorderLayout.PAGE_END);
-
-        return result;
-    }
-
-    private class TableModel extends AbstractTableModel {
-        private final String[] columnNames;
-        private Vector<Object[]> rowData = new Vector<>();
-        private final boolean hasKeyColumn_;
-
-        public TableModel(boolean hasKeyColumn) {
-            super();
-            hasKeyColumn_ = hasKeyColumn;
-            if (hasKeyColumn)
-                columnNames = new String[] {"Key", "Value", ""};
-            else
-                columnNames = new String[] {"Value", ""};
-        }
-
-        public void newDefaultEntry() {
-            int row = rowData.size();
-            if (hasKeyColumn_) {
-                Object[] rowEntry = {"key", "value", new Boolean(false)};
-                rowData.addElement(rowEntry);
-            } else {
-                Object[] rowEntry = {"value", new Boolean(false)};
-                rowData.addElement(rowEntry);
-            }
-            fireTableRowsInserted(row, row);
-        }
-
-        public void removeSelected() {
-            int idx = hasKeyColumn_ ? 2 : 1;
-            for (int i = 0; i < rowData.size(); ++i) {
-                if ((Boolean) rowData.get(i)[idx]) {
-                    rowData.remove(i);
-                    fireTableRowsDeleted(i, i);
-                    i--;
-                }
-            }
-        }
-
-        public void addEntry(String key, String value) {
-            int row = rowData.size();
-            if (hasKeyColumn_) {
-                Object[] rowEntry = {key, value, new Boolean(false)};
-                rowData.addElement(rowEntry);
-            } else {
-                Object[] rowEntry = {value, new Boolean(false)};
-                rowData.addElement(rowEntry);
-            }
-            fireTableRowsInserted(row, row);
-        }
-
-        @Override
-        public int getRowCount() {
-            return rowData.size();
-        }
-
-        @Override
-        public int getColumnCount() {
-            return columnNames.length;
-        }
-
-        @Override
-        public String getColumnName(int column) {
-            return columnNames[column];
-        }
-
-        @Override
-        public Class<?> getColumnClass(int columnIndex) {
-            if (rowData.size() > 0) return rowData.get(0)[columnIndex].getClass();
-            return Object.class;
-        }
-
-        @Override
-        public boolean isCellEditable(int rowIndex, int columnIndex) {
-            return true;
-        }
-
-        @Override
-        public Object getValueAt(int rowIndex, int columnIndex) {
-            return rowData.get(rowIndex)[columnIndex];
-        }
-
-        @Override
-        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
-            rowData.get(rowIndex)[columnIndex] = aValue;
-            fireTableCellUpdated(rowIndex, columnIndex);
-        }
-    }
-}
diff --git a/java/tests/detailed/dialog/UrlRequestDialogReply.java b/java/tests/detailed/dialog/UrlRequestDialogReply.java
deleted file mode 100644
index 861388d3..00000000
--- a/java/tests/detailed/dialog/UrlRequestDialogReply.java
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.dialog;
-
-import org.cef.callback.CefAuthCallback;
-import org.cef.callback.CefURLRequestClient;
-import org.cef.network.CefRequest;
-import org.cef.network.CefResponse;
-import org.cef.network.CefURLRequest;
-import org.cef.network.CefURLRequest.Status;
-
-import java.awt.BorderLayout;
-import java.awt.Frame;
-import java.awt.GridLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.ByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
-
-import javax.swing.BorderFactory;
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextArea;
-import javax.swing.SwingUtilities;
-
-@SuppressWarnings("serial")
-public class UrlRequestDialogReply extends JDialog implements CefURLRequestClient {
-    private long nativeRef_ = 0;
-    private final JLabel statusLabel_ = new JLabel("HTTP-Request status: ");
-    private final JTextArea sentRequest_ = new JTextArea();
-    private final JTextArea repliedResult_ = new JTextArea();
-    private final JButton cancelButton_ = new JButton("Cancel");
-    private CefURLRequest urlRequest_ = null;
-    private final Frame owner_;
-    private ByteArrayOutputStream byteStream_ = new ByteArrayOutputStream();
-
-    public UrlRequestDialogReply(Frame owner, String title) {
-        super(owner, title, false);
-        setLayout(new BorderLayout());
-        setSize(800, 600);
-
-        owner_ = owner;
-
-        JPanel controlPanel = new JPanel();
-        controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS));
-        JButton doneButton = new JButton("Done");
-        doneButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                urlRequest_.dispose();
-                setVisible(false);
-                dispose();
-            }
-        });
-        controlPanel.add(doneButton);
-
-        cancelButton_.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                if (urlRequest_ != null) {
-                    urlRequest_.cancel();
-                }
-            }
-        });
-        cancelButton_.setEnabled(false);
-        controlPanel.add(cancelButton_);
-
-        JPanel requestPane = createPanelWithTitle("Sent HTTP-Request", 1, 0);
-        requestPane.add(new JScrollPane(sentRequest_));
-
-        JPanel replyPane = createPanelWithTitle("Reply from the server", 1, 0);
-        replyPane.add(new JScrollPane(repliedResult_));
-
-        JPanel contentPane = new JPanel(new GridLayout(2, 0));
-        contentPane.add(requestPane);
-        contentPane.add(replyPane);
-
-        add(statusLabel_, BorderLayout.PAGE_START);
-        add(contentPane, BorderLayout.CENTER);
-        add(controlPanel, BorderLayout.PAGE_END);
-    }
-
-    private JPanel createPanelWithTitle(String title, int rows, int cols) {
-        JPanel result = new JPanel(new GridLayout(rows, cols));
-        result.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(title),
-                BorderFactory.createEmptyBorder(10, 10, 10, 10)));
-        return result;
-    }
-
-    public void send(CefRequest request) {
-        if (request == null) {
-            statusLabel_.setText("HTTP-Request status: FAILED");
-            sentRequest_.append("Can't send CefRequest because it is NULL");
-            cancelButton_.setEnabled(false);
-            return;
-        }
-
-        urlRequest_ = CefURLRequest.create(request, this);
-        if (urlRequest_ == null) {
-            statusLabel_.setText("HTTP-Request status: FAILED");
-            sentRequest_.append("Can't send CefRequest because creation of CefURLRequest failed.");
-            repliedResult_.append(
-                    "The native code (CEF) returned a NULL-Pointer for CefURLRequest.");
-            cancelButton_.setEnabled(false);
-        } else {
-            sentRequest_.append(request.toString());
-            cancelButton_.setEnabled(true);
-            updateStatus("", false);
-        }
-    }
-
-    private void updateStatus(final String updateMsg, final boolean printByteStream) {
-        final Status status = urlRequest_.getRequestStatus();
-        Runnable runnable = new Runnable() {
-            @Override
-            public void run() {
-                statusLabel_.setText("HTTP-Request status: " + status);
-                if (status != Status.UR_UNKNOWN && status != Status.UR_IO_PENDING) {
-                    cancelButton_.setEnabled(false);
-                }
-                repliedResult_.append(updateMsg);
-                if (printByteStream) {
-                    try {
-                        repliedResult_.append("\n\n" + byteStream_.toString("UTF-8"));
-                    } catch (UnsupportedEncodingException e) {
-                        repliedResult_.append("\n\n" + byteStream_.toString());
-                    }
-                }
-            }
-        };
-
-        if (SwingUtilities.isEventDispatchThread()) {
-            runnable.run();
-        } else {
-            SwingUtilities.invokeLater(runnable);
-        }
-    }
-
-    // CefURLRequestClient
-
-    @Override
-    public void setNativeRef(String identifer, long nativeRef) {
-        nativeRef_ = nativeRef;
-    }
-
-    @Override
-    public long getNativeRef(String identifer) {
-        return nativeRef_;
-    }
-
-    @Override
-    public void onRequestComplete(CefURLRequest request) {
-        String updateStr = "onRequestCompleted\n\n";
-        CefResponse response = request.getResponse();
-        boolean isText = response.getHeaderByName("Content-Type").startsWith("text");
-        updateStr += response.toString();
-        updateStatus(updateStr, isText);
-    }
-
-    @Override
-    public void onUploadProgress(CefURLRequest request, int current, int total) {
-        updateStatus("onUploadProgress: " + current + "/" + total + " bytes\n", false);
-    }
-
-    @Override
-    public void onDownloadProgress(CefURLRequest request, int current, int total) {
-        updateStatus("onDownloadProgress: " + current + "/" + total + " bytes\n", false);
-    }
-
-    @Override
-    public void onDownloadData(CefURLRequest request, byte[] data, int data_length) {
-        byteStream_.write(data, 0, data_length);
-        updateStatus("onDownloadData: " + data_length + " bytes\n", false);
-    }
-
-    @Override
-    public boolean getAuthCredentials(boolean isProxy, String host, int port, String realm,
-            String scheme, CefAuthCallback callback) {
-        SwingUtilities.invokeLater(new PasswordDialog(owner_, callback));
-        return true;
-    }
-}
diff --git a/java/tests/detailed/handler/AppHandler.java b/java/tests/detailed/handler/AppHandler.java
deleted file mode 100644
index 45ec49bb..00000000
--- a/java/tests/detailed/handler/AppHandler.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.handler;
-
-import org.cef.CefApp;
-import org.cef.CefApp.CefAppState;
-import org.cef.browser.CefBrowser;
-import org.cef.browser.CefFrame;
-import org.cef.callback.CefSchemeHandlerFactory;
-import org.cef.callback.CefSchemeRegistrar;
-import org.cef.handler.CefAppHandlerAdapter;
-import org.cef.handler.CefResourceHandler;
-import org.cef.network.CefRequest;
-
-public class AppHandler extends CefAppHandlerAdapter {
-    // We're registering our own schemes to demonstrate how to use
-    // CefAppHandler.onRegisterCustomSchemes() in combination with
-    // CefApp.registerSchemeHandlerFactory().
-    public AppHandler(String[] args) {
-        super(args);
-    }
-
-    // (1) First of all we have to register our custom schemes by implementing
-    //     the method "onRegisterCustomSchemes. The scheme names are added by
-    //     calling CefSchemeRegistrar.addCustomScheme.
-    @Override
-    public void onRegisterCustomSchemes(CefSchemeRegistrar registrar) {
-        if (registrar.addCustomScheme(
-                    SearchSchemeHandler.scheme, true, false, false, false, true, false, false)) {
-            System.out.println("Added scheme " + SearchSchemeHandler.scheme + "://");
-        }
-        if (registrar.addCustomScheme(
-                    ClientSchemeHandler.scheme, true, false, false, false, true, false, false)) {
-            System.out.println("Added scheme " + ClientSchemeHandler.scheme + "://");
-        }
-    }
-
-    // (2) At the next step we have to register a SchemeHandlerFactory which is
-    //     called if an user enters our registered scheme.
-    //
-    //     This is done via the CefApp.registerSchemeHandlerFactory() method.
-    //     A good place to call this function is from
-    //     CefAppHandler.onContextInitialized().
-    //
-    //     The empty |domain_name| value will cause the factory to match all
-    //     domain names. A set |domain_name| will only be valid for the entered
-    //     domain.
-    @Override
-    public void onContextInitialized() {
-        CefApp cefApp = CefApp.getInstance();
-        cefApp.registerSchemeHandlerFactory(
-                SearchSchemeHandler.scheme, SearchSchemeHandler.domain, new SchemeHandlerFactory());
-        cefApp.registerSchemeHandlerFactory(
-                ClientSchemeHandler.scheme, ClientSchemeHandler.domain, new SchemeHandlerFactory());
-    }
-
-    // (3) The SchemeHandlerFactory creates a new ResourceHandler instance for each
-    //     request the user has send to the browser. The ResourceHandler is the
-    //     responsible class to process and return the result of a received
-    //     request.
-    private class SchemeHandlerFactory implements CefSchemeHandlerFactory {
-        @Override
-        public CefResourceHandler create(
-                CefBrowser browser, CefFrame frame, String schemeName, CefRequest request) {
-            if (schemeName.equals(SearchSchemeHandler.scheme))
-                return new SearchSchemeHandler(browser);
-            else if (schemeName.equals(ClientSchemeHandler.scheme))
-                return new ClientSchemeHandler();
-            return null;
-        }
-    }
-
-    @Override
-    public void stateHasChanged(CefAppState state) {
-        System.out.println("AppHandler.stateHasChanged: " + state);
-        if (state == CefAppState.TERMINATED) System.exit(0);
-    }
-}
diff --git a/java/tests/detailed/handler/ClientSchemeHandler.java b/java/tests/detailed/handler/ClientSchemeHandler.java
deleted file mode 100644
index 2ee156ff..00000000
--- a/java/tests/detailed/handler/ClientSchemeHandler.java
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.handler;
-
-import org.cef.callback.CefCallback;
-import org.cef.handler.CefResourceHandlerAdapter;
-import org.cef.misc.IntRef;
-import org.cef.misc.StringRef;
-import org.cef.network.CefRequest;
-import org.cef.network.CefResponse;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * The example for the second scheme with domain handling is a more
- * complex example and is taken from the parent project CEF. Please
- * see CEF: "cefclient/scheme_test.cpp" for futher details
- */
-public class ClientSchemeHandler extends CefResourceHandlerAdapter {
-    public static final String scheme = "client";
-    public static final String domain = "tests";
-
-    private byte[] data_;
-    private String mime_type_;
-    private int offset_ = 0;
-
-    public ClientSchemeHandler() {
-        super();
-    }
-
-    @Override
-    public synchronized boolean processRequest(CefRequest request, CefCallback callback) {
-        boolean handled = false;
-        String url = request.getURL();
-        if (url.indexOf("handler.html") != -1) {
-            // Build the response html
-            String html;
-            html = "<html><head><title>Client Scheme Handler</title></head>"
-                    + "<body bgcolor=\"white\">"
-                    + "This contents of this page page are served by the "
-                    + "ClientSchemeHandler class handling the client:// protocol."
-                    + "<br/>You should see an image:"
-                    + "<br/><img src=\"client://tests/logo.png\"><pre>";
-
-            // Output a string representation of the request
-            html += request.toString();
-
-            html += "</pre><br/>Try the test form:"
-                    + "<form method=\"POST\" action=\"handler.html\">"
-                    + "<input type=\"text\" name=\"field1\">"
-                    + "<input type=\"text\" name=\"field2\">"
-                    + "<input type=\"submit\">"
-                    + "</form></body></html>";
-
-            data_ = html.getBytes();
-
-            handled = true;
-            // Set the resulting mime type
-            mime_type_ = "text/html";
-        } else if (url.endsWith(".png")) {
-            handled = loadContent(url.substring(url.lastIndexOf('/') + 1));
-            mime_type_ = "image/png";
-        } else if (url.endsWith(".html")) {
-            handled = loadContent(url.substring(url.lastIndexOf('/') + 1));
-            mime_type_ = "text/html";
-            if (!handled) {
-                String html = "<html><head><title>Error 404</title></head>";
-                html += "<body><h1>Error 404</h1>";
-                html += "File  " + url.substring(url.lastIndexOf('/') + 1) + " ";
-                html += "does not exist</body></html>";
-                data_ = html.getBytes();
-                handled = true;
-            }
-        }
-
-        if (handled) {
-            // Indicate the headers are available.
-            callback.Continue();
-            return true;
-        }
-
-        return false;
-    }
-
-    @Override
-    public void getResponseHeaders(
-            CefResponse response, IntRef response_length, StringRef redirectUrl) {
-        response.setMimeType(mime_type_);
-        response.setStatus(200);
-
-        // Set the resulting response length
-        response_length.set(data_.length);
-    }
-
-    @Override
-    public synchronized boolean readResponse(
-            byte[] data_out, int bytes_to_read, IntRef bytes_read, CefCallback callback) {
-        boolean has_data = false;
-
-        if (offset_ < data_.length) {
-            // Copy the next block of data into the buffer.
-            int transfer_size = Math.min(bytes_to_read, (data_.length - offset_));
-            System.arraycopy(data_, offset_, data_out, 0, transfer_size);
-            offset_ += transfer_size;
-
-            bytes_read.set(transfer_size);
-            has_data = true;
-        } else {
-            offset_ = 0;
-            bytes_read.set(0);
-        }
-
-        return has_data;
-    }
-
-    private boolean loadContent(String resName) {
-        InputStream inStream = getClass().getResourceAsStream(resName);
-        if (inStream != null) {
-            try {
-                ByteArrayOutputStream outFile = new ByteArrayOutputStream();
-                int readByte = -1;
-                while ((readByte = inStream.read()) >= 0) outFile.write(readByte);
-                data_ = outFile.toByteArray();
-                return true;
-            } catch (IOException e) {
-            }
-        }
-        return false;
-    }
-}
diff --git a/java/tests/detailed/handler/ContextMenuHandler.java b/java/tests/detailed/handler/ContextMenuHandler.java
deleted file mode 100644
index c18c76b8..00000000
--- a/java/tests/detailed/handler/ContextMenuHandler.java
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.handler;
-
-import org.cef.browser.CefBrowser;
-import org.cef.browser.CefFrame;
-import org.cef.callback.CefContextMenuParams;
-import org.cef.callback.CefMenuModel;
-import org.cef.callback.CefMenuModel.MenuId;
-import org.cef.handler.CefContextMenuHandler;
-
-import java.awt.Frame;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Vector;
-
-import tests.detailed.dialog.SearchDialog;
-import tests.detailed.dialog.ShowTextDialog;
-
-public class ContextMenuHandler implements CefContextMenuHandler {
-    private final Frame owner_;
-    private Map<Integer, String> suggestions_ = new HashMap<Integer, String>();
-
-    public ContextMenuHandler(Frame owner) {
-        owner_ = owner;
-    }
-
-    @Override
-    public void onBeforeContextMenu(
-            CefBrowser browser, CefFrame frame, CefContextMenuParams params, CefMenuModel model) {
-        model.clear();
-
-        // Navigation menu
-        model.addItem(MenuId.MENU_ID_BACK, "Back");
-        model.setEnabled(MenuId.MENU_ID_BACK, browser.canGoBack());
-
-        model.addItem(MenuId.MENU_ID_FORWARD, "Forward");
-        model.setEnabled(MenuId.MENU_ID_FORWARD, browser.canGoForward());
-
-        model.addSeparator();
-        model.addItem(MenuId.MENU_ID_FIND, "Find...");
-        if (params.hasImageContents() && params.getSourceUrl() != null)
-            model.addItem(MenuId.MENU_ID_USER_FIRST, "Download Image...");
-        model.addItem(MenuId.MENU_ID_VIEW_SOURCE, "View Source...");
-
-        Vector<String> suggestions = new Vector<String>();
-        params.getDictionarySuggestions(suggestions);
-
-        // Spell checking menu
-        model.addSeparator();
-        if (suggestions.size() == 0) {
-            model.addItem(MenuId.MENU_ID_NO_SPELLING_SUGGESTIONS, "No suggestions");
-            model.setEnabled(MenuId.MENU_ID_NO_SPELLING_SUGGESTIONS, false);
-            return;
-        }
-
-        int id = MenuId.MENU_ID_SPELLCHECK_SUGGESTION_0;
-        for (String suggestedWord : suggestions) {
-            model.addItem(id, suggestedWord);
-            suggestions_.put(id, suggestedWord);
-            if (++id > MenuId.MENU_ID_SPELLCHECK_SUGGESTION_LAST) break;
-        }
-    }
-
-    @Override
-    public boolean onContextMenuCommand(CefBrowser browser, CefFrame frame,
-            CefContextMenuParams params, int commandId, int eventFlags) {
-        switch (commandId) {
-            case MenuId.MENU_ID_VIEW_SOURCE:
-                ShowTextDialog visitor =
-                        new ShowTextDialog(owner_, "Source of \"" + browser.getURL() + "\"");
-                browser.getSource(visitor);
-                return true;
-            case MenuId.MENU_ID_FIND:
-                SearchDialog search = new SearchDialog(owner_, browser);
-                search.setVisible(true);
-                return true;
-            case MenuId.MENU_ID_USER_FIRST:
-                browser.startDownload(params.getSourceUrl());
-                return true;
-            default:
-                if (commandId >= MenuId.MENU_ID_SPELLCHECK_SUGGESTION_0) {
-                    String newWord = suggestions_.get(commandId);
-                    if (newWord != null) {
-                        System.err.println(
-                                "replacing " + params.getMisspelledWord() + " with " + newWord);
-                        browser.replaceMisspelling(newWord);
-                        return true;
-                    }
-                }
-                return false;
-        }
-    }
-
-    @Override
-    public void onContextMenuDismissed(CefBrowser browser, CefFrame frame) {
-        suggestions_.clear();
-    }
-}
diff --git a/java/tests/detailed/handler/DragHandler.java b/java/tests/detailed/handler/DragHandler.java
deleted file mode 100644
index ee7d36aa..00000000
--- a/java/tests/detailed/handler/DragHandler.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.handler;
-
-import org.cef.browser.CefBrowser;
-import org.cef.callback.CefDragData;
-import org.cef.handler.CefDragHandler;
-
-public class DragHandler implements CefDragHandler {
-    @Override
-    public boolean onDragEnter(CefBrowser browser, CefDragData dragData, int mask) {
-        System.out.println("DRAG:");
-        System.out.print("  flags:");
-        if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_COPY) != 0)
-            System.out.print(" COPY");
-        if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_LINK) != 0)
-            System.out.print(" LINK");
-        if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_GENERIC) != 0)
-            System.out.print(" GENERIC");
-        if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_PRIVATE) != 0)
-            System.out.print(" PRIVATE");
-        if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_MOVE) != 0)
-            System.out.print(" MOVE");
-        if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_DELETE) != 0)
-            System.out.print(" DELETE");
-        System.out.println("\n  " + dragData);
-        return false;
-    }
-}
diff --git a/java/tests/detailed/handler/JSDialogHandler.java b/java/tests/detailed/handler/JSDialogHandler.java
deleted file mode 100644
index 417a55fb..00000000
--- a/java/tests/detailed/handler/JSDialogHandler.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.handler;
-
-import org.cef.browser.CefBrowser;
-import org.cef.callback.CefJSDialogCallback;
-import org.cef.handler.CefJSDialogHandlerAdapter;
-import org.cef.misc.BoolRef;
-
-public class JSDialogHandler extends CefJSDialogHandlerAdapter {
-    @Override
-    public boolean onJSDialog(CefBrowser browser, String origin_url, JSDialogType dialog_type,
-            String message_text, String default_prompt_text, CefJSDialogCallback callback,
-            BoolRef suppress_message) {
-        if (message_text.equalsIgnoreCase("Never displayed")) {
-            suppress_message.set(true);
-            System.out.println(
-                    "The " + dialog_type + " from origin \"" + origin_url + "\" was suppressed.");
-            System.out.println(
-                    "   The content of the suppressed dialog was: \"" + message_text + "\"");
-        }
-        return false;
-    }
-}
diff --git a/java/tests/detailed/handler/KeyboardHandler.java b/java/tests/detailed/handler/KeyboardHandler.java
deleted file mode 100644
index 350d0f3b..00000000
--- a/java/tests/detailed/handler/KeyboardHandler.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.handler;
-
-import org.cef.browser.CefBrowser;
-import org.cef.handler.CefKeyboardHandlerAdapter;
-
-public class KeyboardHandler extends CefKeyboardHandlerAdapter {
-    @Override
-    public boolean onKeyEvent(CefBrowser browser, CefKeyEvent event) {
-        if (!event.focus_on_editable_field && event.windows_key_code == 0x20) {
-            // Special handling for the space character when an input element does not
-            // have focus. Handling the event in OnPreKeyEvent() keeps the event from
-            // being processed in the renderer. If we instead handled the event in the
-            // OnKeyEvent() method the space key would cause the window to scroll in
-            // addition to showing the alert box.
-            if (event.type == CefKeyEvent.EventType.KEYEVENT_RAWKEYDOWN) {
-                browser.executeJavaScript("alert('You pressed the space bar!');", "", 0);
-            }
-            return true;
-        }
-        return false;
-    }
-}
diff --git a/java/tests/detailed/handler/MessageRouterHandler.java b/java/tests/detailed/handler/MessageRouterHandler.java
deleted file mode 100644
index 1d37c85a..00000000
--- a/java/tests/detailed/handler/MessageRouterHandler.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.handler;
-
-import org.cef.browser.CefBrowser;
-import org.cef.browser.CefFrame;
-import org.cef.callback.CefQueryCallback;
-import org.cef.handler.CefMessageRouterHandlerAdapter;
-
-public class MessageRouterHandler extends CefMessageRouterHandlerAdapter {
-    @Override
-    public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String request,
-            boolean persistent, CefQueryCallback callback) {
-        if (request.indexOf("BindingTest:") == 0) {
-            // Reverse the message and return it to the JavaScript caller.
-            String msg = request.substring(12);
-            callback.success(new StringBuilder(msg).reverse().toString());
-            return true;
-        }
-        // Not handled.
-        return false;
-    }
-}
diff --git a/java/tests/detailed/handler/MessageRouterHandlerEx.java b/java/tests/detailed/handler/MessageRouterHandlerEx.java
deleted file mode 100644
index bc4b780b..00000000
--- a/java/tests/detailed/handler/MessageRouterHandlerEx.java
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.handler;
-
-import org.cef.CefClient;
-import org.cef.browser.CefBrowser;
-import org.cef.browser.CefFrame;
-import org.cef.browser.CefMessageRouter;
-import org.cef.browser.CefMessageRouter.CefMessageRouterConfig;
-import org.cef.callback.CefQueryCallback;
-import org.cef.handler.CefMessageRouterHandlerAdapter;
-
-public class MessageRouterHandlerEx extends CefMessageRouterHandlerAdapter {
-    private final CefClient client_;
-    private final CefMessageRouterConfig config_ =
-            new CefMessageRouterConfig("myQuery", "myQueryAbort");
-    private CefMessageRouter router_ = null;
-
-    public MessageRouterHandlerEx(final CefClient client) {
-        client_ = client;
-    }
-
-    @Override
-    public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String request,
-            boolean persistent, CefQueryCallback callback) {
-        if (request.startsWith("hasExtension")) {
-            if (router_ != null)
-                callback.success("");
-            else
-                callback.failure(0, "");
-        } else if (request.startsWith("enableExt")) {
-            if (router_ != null) {
-                callback.failure(-1, "Already enabled");
-            } else {
-                router_ = CefMessageRouter.create(config_, new JavaVersionMessageRouter());
-                client_.addMessageRouter(router_);
-                callback.success("");
-            }
-        } else if (request.startsWith("disableExt")) {
-            if (router_ == null) {
-                callback.failure(-2, "Already disabled");
-            } else {
-                client_.removeMessageRouter(router_);
-                router_.dispose();
-                router_ = null;
-                callback.success("");
-            }
-        } else {
-            // not handled
-            return false;
-        }
-        return true;
-    }
-
-    private class JavaVersionMessageRouter extends CefMessageRouterHandlerAdapter {
-        @Override
-        public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String request,
-                boolean persistent, CefQueryCallback callback) {
-            if (request.startsWith("jcefJava")) {
-                callback.success(System.getProperty("java.version"));
-                return true;
-            }
-            return false;
-        };
-    }
-}
diff --git a/java/tests/detailed/handler/RequestHandler.java b/java/tests/detailed/handler/RequestHandler.java
deleted file mode 100644
index d80e1251..00000000
--- a/java/tests/detailed/handler/RequestHandler.java
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.handler;
-
-import org.cef.browser.CefBrowser;
-import org.cef.browser.CefFrame;
-import org.cef.callback.CefAuthCallback;
-import org.cef.callback.CefCallback;
-import org.cef.handler.CefLoadHandler.ErrorCode;
-import org.cef.handler.CefRequestHandler;
-import org.cef.handler.CefResourceHandler;
-import org.cef.handler.CefResourceRequestHandler;
-import org.cef.handler.CefResourceRequestHandlerAdapter;
-import org.cef.misc.BoolRef;
-import org.cef.network.CefPostData;
-import org.cef.network.CefPostDataElement;
-import org.cef.network.CefRequest;
-
-import java.awt.Frame;
-import java.util.HashMap;
-import java.util.Vector;
-
-import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
-
-import tests.detailed.dialog.CertErrorDialog;
-import tests.detailed.dialog.PasswordDialog;
-
-public class RequestHandler extends CefResourceRequestHandlerAdapter implements CefRequestHandler {
-    private final Frame owner_;
-
-    public RequestHandler(Frame owner) {
-        owner_ = owner;
-    }
-
-    @Override
-    public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request,
-            boolean user_gesture, boolean is_redirect) {
-        CefPostData postData = request.getPostData();
-        if (postData != null) {
-            Vector<CefPostDataElement> elements = new Vector<CefPostDataElement>();
-            postData.getElements(elements);
-            for (CefPostDataElement el : elements) {
-                int numBytes = el.getBytesCount();
-                if (numBytes <= 0) continue;
-
-                byte[] readBytes = new byte[numBytes];
-                if (el.getBytes(numBytes, readBytes) <= 0) continue;
-
-                String readString = new String(readBytes);
-                if (readString.indexOf("ignore") > -1) {
-                    SwingUtilities.invokeLater(new Runnable() {
-                        @Override
-                        public void run() {
-                            JOptionPane.showMessageDialog(owner_,
-                                    "The request was rejected because you've entered \"ignore\" into the form.");
-                        }
-                    });
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onOpenURLFromTab(
-            CefBrowser browser, CefFrame frame, String target_url, boolean user_gesture) {
-        return false;
-    }
-
-    @Override
-    public CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame,
-            CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator,
-            BoolRef disableDefaultHandling) {
-        return this;
-    }
-
-    @Override
-    public boolean onBeforeResourceLoad(CefBrowser browser, CefFrame frame, CefRequest request) {
-        // If you send a HTTP-POST request to http://www.google.com/
-        // google rejects your request because they don't allow HTTP-POST.
-        //
-        // This test extracts the value of the test form.
-        // (see "Show Form" entry within BrowserMenuBar)
-        // and sends its value as HTTP-GET request to Google.
-        if (request.getMethod().equalsIgnoreCase("POST")
-                && request.getURL().equals("http://www.google.com/")) {
-            String forwardTo = "http://www.google.com/#q=";
-            CefPostData postData = request.getPostData();
-            boolean sendAsGet = false;
-            if (postData != null) {
-                Vector<CefPostDataElement> elements = new Vector<CefPostDataElement>();
-                postData.getElements(elements);
-                for (CefPostDataElement el : elements) {
-                    int numBytes = el.getBytesCount();
-                    if (numBytes <= 0) continue;
-
-                    byte[] readBytes = new byte[numBytes];
-                    if (el.getBytes(numBytes, readBytes) <= 0) continue;
-
-                    String readString = new String(readBytes).trim();
-                    String[] stringPairs = readString.split("&");
-                    for (String s : stringPairs) {
-                        int startPos = s.indexOf('=');
-                        if (s.startsWith("searchFor"))
-                            forwardTo += s.substring(startPos + 1);
-                        else if (s.startsWith("sendAsGet")) {
-                            sendAsGet = true;
-                        }
-                    }
-                }
-                if (sendAsGet) postData.removeElements();
-            }
-            if (sendAsGet) {
-                request.setFlags(0);
-                request.setMethod("GET");
-                request.setURL(forwardTo);
-                request.setFirstPartyForCookies(forwardTo);
-                HashMap<String, String> headerMap = new HashMap<>();
-                request.getHeaderMap(headerMap);
-                headerMap.remove("Content-Type");
-                headerMap.remove("Origin");
-                request.setHeaderMap(headerMap);
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public CefResourceHandler getResourceHandler(
-            CefBrowser browser, CefFrame frame, CefRequest request) {
-        // the non existing domain "foo.bar" is handled by the ResourceHandler implementation
-        // E.g. if you try to load the URL http://www.foo.bar, you'll be forwarded
-        // to the ResourceHandler class.
-        if (request.getURL().endsWith("foo.bar/")) {
-            return new ResourceHandler();
-        }
-
-        if (request.getURL().endsWith("seterror.test/")) {
-            return new ResourceSetErrorHandler();
-        }
-
-        return null;
-    }
-
-    @Override
-    public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy,
-            String host, int port, String realm, String scheme, CefAuthCallback callback) {
-        SwingUtilities.invokeLater(new PasswordDialog(owner_, callback));
-        return true;
-    }
-
-    @Override
-    public boolean onCertificateError(
-            CefBrowser browser, ErrorCode cert_error, String request_url, CefCallback callback) {
-        SwingUtilities.invokeLater(new CertErrorDialog(owner_, cert_error, request_url, callback));
-        return true;
-    }
-
-    @Override
-    public void onRenderProcessTerminated(CefBrowser browser, TerminationStatus status) {
-        System.out.println("render process terminated: " + status);
-    }
-}
diff --git a/java/tests/detailed/handler/ResourceHandler.java b/java/tests/detailed/handler/ResourceHandler.java
deleted file mode 100644
index 4a36e0ee..00000000
--- a/java/tests/detailed/handler/ResourceHandler.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package tests.detailed.handler;
-
-import org.cef.callback.CefCallback;
-import org.cef.handler.CefLoadHandler;
-import org.cef.handler.CefResourceHandlerAdapter;
-import org.cef.misc.IntRef;
-import org.cef.misc.StringRef;
-import org.cef.network.CefRequest;
-import org.cef.network.CefResponse;
-
-import java.nio.ByteBuffer;
-
-public class ResourceHandler extends CefResourceHandlerAdapter {
-    private int startPos = 0;
-    private static final String html = new String("<html>\n"
-            + "  <head>\n"
-            + "    <title>ResourceHandler Test</title>\n"
-            + "  </head>\n"
-            + "  <body>\n"
-            + "    <h1>ResourceHandler Test</h1>\n"
-            + "    <p>You have entered the URL: http://www.foo.bar. This page is generated by the application itself and<br/>\n"
-            + "       no HTTP request was sent to the internet.\n"
-            + "    <p>See class <u>tests.handler.ResourceHandler</u> and the <u>RequestHandler</u> implementation for details.</p>\n"
-            + "  </body>\n"
-            + "</html>");
-
-    @Override
-    public boolean processRequest(CefRequest request, CefCallback callback) {
-        System.out.println("processRequest: " + request);
-
-        startPos = 0;
-        callback.Continue();
-        return true;
-    }
-
-    @Override
-    public void getResponseHeaders(
-            CefResponse response, IntRef response_length, StringRef redirectUrl) {
-        System.out.println("getResponseHeaders: " + response);
-
-        response_length.set(html.length());
-        response.setMimeType("text/html");
-        response.setStatus(200);
-    }
-
-    @Override
-    public boolean readResponse(
-            byte[] data_out, int bytes_to_read, IntRef bytes_read, CefCallback callback) {
-        int length = html.length();
-        if (startPos >= length) return false;
-
-        // Extract up to bytes_to_read bytes from the html data
-        int endPos = startPos + bytes_to_read;
-        String dataToSend =
-                (endPos > length) ? html.substring(startPos) : html.substring(startPos, endPos);
-
-        // Copy extracted bytes into data_out and set the read length
-        // to bytes_read.
-        ByteBuffer result = ByteBuffer.wrap(data_out);
-        result.put(dataToSend.getBytes());
-        bytes_read.set(dataToSend.length());
-
-        startPos = endPos;
-        return true;
-    }
-
-    @Override
-    public void cancel() {
-        System.out.println("cancel");
-        startPos = 0;
-    }
-}
diff --git a/java/tests/detailed/handler/ResourceSetErrorHandler.java b/java/tests/detailed/handler/ResourceSetErrorHandler.java
deleted file mode 100644
index bc3dd129..00000000
--- a/java/tests/detailed/handler/ResourceSetErrorHandler.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package tests.detailed.handler;
-
-import org.cef.callback.CefCallback;
-import org.cef.handler.CefLoadHandler.ErrorCode;
-import org.cef.handler.CefResourceHandlerAdapter;
-import org.cef.misc.IntRef;
-import org.cef.misc.StringRef;
-import org.cef.network.CefRequest;
-import org.cef.network.CefResponse;
-
-public class ResourceSetErrorHandler extends CefResourceHandlerAdapter {
-    @Override
-    public boolean processRequest(CefRequest request, CefCallback callback) {
-        System.out.println("processRequest: " + request);
-        callback.Continue();
-        return true;
-    }
-
-    @Override
-    public void getResponseHeaders(
-            CefResponse response, IntRef response_length, StringRef redirectUrl) {
-        response.setError(ErrorCode.ERR_NOT_IMPLEMENTED);
-        System.out.println("getResponseHeaders: " + response);
-    }
-}
\ No newline at end of file
diff --git a/java/tests/detailed/handler/SearchSchemeHandler.java b/java/tests/detailed/handler/SearchSchemeHandler.java
deleted file mode 100644
index 8a5c80e1..00000000
--- a/java/tests/detailed/handler/SearchSchemeHandler.java
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.handler;
-
-import org.cef.browser.CefBrowser;
-import org.cef.callback.CefCallback;
-import org.cef.handler.CefResourceHandlerAdapter;
-import org.cef.network.CefRequest;
-
-/**
- * In this case we create a new CefRequest object with
- * http://www.google.com/#q=<entered value without scheme search>
- * as target and forward it to the CefBrowser instance.
- * The "search://"-request is aborted by returning false.
- */
-public class SearchSchemeHandler extends CefResourceHandlerAdapter {
-    public static final String scheme = "search";
-    public static final String domain = "";
-
-    private final CefBrowser browser_;
-
-    public SearchSchemeHandler(CefBrowser browser) {
-        browser_ = browser;
-    }
-
-    @Override
-    public boolean processRequest(CefRequest request, CefCallback callback) {
-        // cut away "scheme://"
-        String requestUrl = request.getURL();
-        String newUrl = requestUrl.substring(scheme.length() + 3);
-        // cut away a trailing "/" if any
-        if (newUrl.indexOf('/') == newUrl.length() - 1) {
-            newUrl = newUrl.substring(0, newUrl.length() - 1);
-        }
-        newUrl = "http://www.google.com/#q=" + newUrl;
-
-        CefRequest newRequest = CefRequest.create();
-        if (newRequest != null) {
-            newRequest.setMethod("GET");
-            newRequest.setURL(newUrl);
-            newRequest.setFirstPartyForCookies(newUrl);
-            browser_.loadRequest(newRequest);
-        }
-        return false;
-    }
-}
diff --git a/java/tests/detailed/handler/binding_test.html b/java/tests/detailed/handler/binding_test.html
deleted file mode 100644
index 9ee0775e..00000000
--- a/java/tests/detailed/handler/binding_test.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<html>
-<head>
-<title>Binding Test</title>
-<script language="JavaScript">
-
-// Send a query to the browser process.
-function sendMessage() {
-  // Results in a call to the OnQuery method in binding_test.cpp
-  window.cefQuery({
-    request: 'BindingTest:' + document.getElementById("message").value,
-    onSuccess: function(response) {
-      document.getElementById('result').value = 'Response: '+response;
-    },
-    onFailure: function(error_code, error_message) {}
-  });
-}
-</script>
-
-</head>
-<body bgcolor="white">
-<form>
-Message: <input type="text" id="message" value="My Message">
-<br/><input type="button" onclick="sendMessage();" value="Send Message">
-<br/>You should see the reverse of your message below:
-<br/><textarea rows="10" cols="40" id="result"></textarea>
-</form>
-</body>
-</html>
diff --git a/java/tests/detailed/handler/binding_test2.html b/java/tests/detailed/handler/binding_test2.html
deleted file mode 100644
index 8a61a96f..00000000
--- a/java/tests/detailed/handler/binding_test2.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<html>
-<head>
-<title>Binding Test - Part 2</title>
-<script language="JavaScript">
-
-function toggleButton() {
-  window.cefQuery({
-    request: 'hasExtension',
-    onSuccess: function(response) {
-      document.getElementById('jcefOn').disabled = true;
-      document.getElementById('jcefOff').disabled = false;
-    },
-    onFailure: function(error_code, error_message) {
-      document.getElementById('jcefOn').disabled = false;
-      document.getElementById('jcefOff').disabled = true;
-    }
-  });
-}
-
-function execute(cmd) {
-  window.cefQuery({
-    request: cmd,
-    onSuccess: function(response) {
-      location.reload();
-    },
-    onFailure: function(error_code, error_message) {
-      document.getElementById('result').value = 'Error: '+error_message;
-    }
-  });
-}
-
-function getJavaVersion() {
-  if ("myQuery" in window) {
-    window.myQuery({
-      request: 'jcefJava',
-      onSuccess: function(response) {
-        document.getElementById('result').value = 'Java Version: '+response;
-      },
-      onFailure: function(error_code, error_message) {
-        document.getElementById('result').value = 'Error: '+error_message;
-      }
-    });
-  } else {
-    document.getElementById('result').value = 'Error: myQuery isn\'t enabled';
-  }
-}
-
-</script>
-<head>
-
-<body bgcolor="white" onload="toggleButton()">
-
-<form>
-<h1>JavaScript Binding Test - Part 2</h1>
-<p>While this page was loaded, the JavaScript function
-<pre>window.cefRequest(request: 'hasExtension')</pre>
-was executed for enabling/disabling the buttons below.
-<br/>&nbsp;<br/>
-If you press "Enable myQuery", the JavaScript function
-<pre>window.cefRequest(request: 'enableExt')</pre>
-is executed. This causes Java to create a second instance of  
-<pre>CefMessageRouter</pre>
-In this case the name of the JavaScript query function is set to "myQuery" and
-<br/>a handler for the request 'jcefJava' is registered. Pressing the "Test" 
-<br/>button will execute the JavaScript code
-<pre>window.myRequest(request: 'jcefJava')</pre>
-which returns your current Java version on success or an error message in case
-<br/>of an error.
-</p>
-<p><b>Please note:</b> If you leave this page (myQuery enabled) and you return
-<br/>after a while - without closing the browser - the JavaScript binding is 
-<br/>still enabled.</p>
-Second message router: 
-<input type="button" id="jcefOn" value="Enable myQuery" onclick="execute('enableExt');" />
-<input type="button" id="jcefOff" value="Disable myQuery" onclick="execute('disableExt');" />
-<br/><input type="button" onclick="getJavaVersion();" value="Test"/>
-<input type="text" id="result" size="80" readonly />
-</form>
-</body>
-</html>
-
diff --git a/java/tests/detailed/handler/localstorage.html b/java/tests/detailed/handler/localstorage.html
deleted file mode 100644
index 87c6e68c..00000000
--- a/java/tests/detailed/handler/localstorage.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<html>
-<body bgcolor="white">
-<script language="JavaScript">
-var val = window.localStorage.getItem('val');
-function addLine() {
-  if(val == null)
-    val = '<br/>One Line.';
-  else
-    val += '<br/>Another Line.';
-  window.localStorage.setItem('val', val);
-  document.getElementById('out').innerHTML = val;
-}
-</script>
-Click the "Add Line" button to add a line or the "Clear" button to clear.<br/>
-This data will persist across sessions if a cache path was specified.<br/>
-<input type="button" value="Add Line" onClick="addLine();"/>
-<input type="button" value="Clear" onClick="window.localStorage.removeItem('val'); window.location.reload();"/>
-<div id="out"></div>
-<script language="JavaScript">
-if(val != null)
-  document.getElementById('out').innerHTML = val;
-</script>
-</body>
-</html>
diff --git a/java/tests/detailed/handler/logo.png b/java/tests/detailed/handler/logo.png
deleted file mode 100644
index a2a15f44..00000000
Binary files a/java/tests/detailed/handler/logo.png and /dev/null differ
diff --git a/java/tests/detailed/handler/spellcheck.html b/java/tests/detailed/handler/spellcheck.html
deleted file mode 100644
index 6334135a..00000000
--- a/java/tests/detailed/handler/spellcheck.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<html>
-<head>
-<title>Spellcheck Test</title>
-
-</head>
-<body bgcolor="white">
-The next paragraph contains some text to be validated against the spell-checker.
-<br/> Click into the following box. To replace a misspelled word use the
-right-mouse-click.<br/>
-<p contenteditable="true" spellcheck="true" style="background-color:#F6E3CE">
-This is a misspelled paragrapph. Withh maany errors<br/> Click into this bogx
-to ttest it.</p>
-</body>
-</html>
diff --git a/java/tests/detailed/handler/transparency.html b/java/tests/detailed/handler/transparency.html
deleted file mode 100644
index a8dd3b46..00000000
--- a/java/tests/detailed/handler/transparency.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-<title>Transparency Examples</title>
-<style type="text/css">
-body {
-font-family: Verdana, Arial;
-}
-img {
-opacity:0.4;
-}
-img:hover {
-opacity:1.0;
-}
-.box_white, .box_black {
-font-size: 14px;
-font-weight: bold;
-text-align: center;
-padding: 10px;
-display: inline-block;
-width: 100px;
-}
-.box_white {
-background-color: white;
-border: 2px solid black;
-color: black;
-}
-.box_black {
-background-color: black;
-border: 2px solid white;
-color: white;
-}
-.box_0 {
-opacity: 1.0;
-}
-.box_25 {
-opacity: 0.75;
-}
-.box_50 {
-opacity: 0.5;
-}
-.box_75 {
-opacity: 0.25;
-}
-.box_100 {
-opacity: 0;
-}
-</style>
-</head>
-<body>
-
-<h1>Image Transparency</h1>
-Hover over an image to make it fully opaque.<br>
-<img src="http://www.w3schools.com/css/klematis.jpg" width="150" height="113" alt="klematis" />
-<img src="http://www.w3schools.com/css/klematis2.jpg" width="150" height="113" alt="klematis" />
-
-<h1>Block Transparency</h1>
-<span class="box_white box_0">White 0%</span> <span class="box_white box_25">White 25%</span> <span class="box_white box_50">White 50%</span> <span class="box_white box_75">White 75%</span> <span class="box_white box_100">White 100%</span>
-<br>
-<span class="box_black box_0">Black 0%</span> <span class="box_black box_25">Black 25%</span> <span class="box_black box_50">Black 50%</span> <span class="box_black box_75">Black 75%</span> <span class="box_black box_100">Black 100%</span>
-
-</body>
-</html>
diff --git a/java/tests/detailed/ui/ControlPanel.java b/java/tests/detailed/ui/ControlPanel.java
deleted file mode 100644
index c3923dcc..00000000
--- a/java/tests/detailed/ui/ControlPanel.java
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.ui;
-
-import org.cef.OS;
-import org.cef.browser.CefBrowser;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import javax.swing.Box;
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-
-@SuppressWarnings("serial")
-public class ControlPanel extends JPanel {
-    private final JButton backButton_;
-    private final JButton forwardButton_;
-    private final JButton reloadButton_;
-    private final JTextField address_field_;
-    private final JLabel zoom_label_;
-    private double zoomLevel_ = 0;
-    private final CefBrowser browser_;
-
-    public ControlPanel(CefBrowser browser) {
-        assert browser != null;
-        browser_ = browser;
-
-        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
-
-        add(Box.createHorizontalStrut(5));
-        add(Box.createHorizontalStrut(5));
-
-        backButton_ = new JButton("Back");
-        backButton_.setFocusable(false);
-        backButton_.setAlignmentX(LEFT_ALIGNMENT);
-        backButton_.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.goBack();
-            }
-        });
-        add(backButton_);
-        add(Box.createHorizontalStrut(5));
-
-        forwardButton_ = new JButton("Forward");
-        forwardButton_.setFocusable(false);
-        forwardButton_.setAlignmentX(LEFT_ALIGNMENT);
-        forwardButton_.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.goForward();
-            }
-        });
-        add(forwardButton_);
-        add(Box.createHorizontalStrut(5));
-
-        reloadButton_ = new JButton("Reload");
-        reloadButton_.setFocusable(false);
-        reloadButton_.setAlignmentX(LEFT_ALIGNMENT);
-        reloadButton_.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                if (reloadButton_.getText().equalsIgnoreCase("reload")) {
-                    int mask = OS.isMacintosh() ? ActionEvent.META_MASK : ActionEvent.CTRL_MASK;
-                    if ((e.getModifiers() & mask) != 0) {
-                        System.out.println("Reloading - ignoring cached values");
-                        browser_.reloadIgnoreCache();
-                    } else {
-                        System.out.println("Reloading - using cached values");
-                        browser_.reload();
-                    }
-                } else {
-                    browser_.stopLoad();
-                }
-            }
-        });
-        add(reloadButton_);
-        add(Box.createHorizontalStrut(5));
-
-        JLabel addressLabel = new JLabel("Address:");
-        addressLabel.setAlignmentX(LEFT_ALIGNMENT);
-        add(addressLabel);
-        add(Box.createHorizontalStrut(5));
-
-        address_field_ = new JTextField(100);
-        address_field_.setAlignmentX(LEFT_ALIGNMENT);
-        address_field_.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.loadURL(getAddress());
-            }
-        });
-        add(address_field_);
-        add(Box.createHorizontalStrut(5));
-
-        JButton goButton = new JButton("Go");
-        goButton.setFocusable(false);
-        goButton.setAlignmentX(LEFT_ALIGNMENT);
-        goButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.loadURL(getAddress());
-            }
-        });
-        add(goButton);
-        add(Box.createHorizontalStrut(5));
-
-        JButton minusButton = new JButton("-");
-        minusButton.setFocusable(false);
-        minusButton.setAlignmentX(CENTER_ALIGNMENT);
-        minusButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.setZoomLevel(--zoomLevel_);
-                zoom_label_.setText(new Double(zoomLevel_).toString());
-            }
-        });
-        add(minusButton);
-
-        zoom_label_ = new JLabel("0.0");
-        add(zoom_label_);
-
-        JButton plusButton = new JButton("+");
-        plusButton.setFocusable(false);
-        plusButton.setAlignmentX(CENTER_ALIGNMENT);
-        plusButton.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.setZoomLevel(++zoomLevel_);
-                zoom_label_.setText(new Double(zoomLevel_).toString());
-            }
-        });
-        add(plusButton);
-    }
-
-    public void update(
-            CefBrowser browser, boolean isLoading, boolean canGoBack, boolean canGoForward) {
-        if (browser == browser_) {
-            backButton_.setEnabled(canGoBack);
-            forwardButton_.setEnabled(canGoForward);
-            reloadButton_.setText(isLoading ? "Abort" : "Reload");
-        }
-    }
-
-    public String getAddress() {
-        String address = address_field_.getText();
-        // If the URI format is unknown "new URI" will throw an
-        // exception. In this case we interpret the value of the
-        // address field as search request. Therefore we simply add
-        // the "search" scheme.
-        try {
-            address = address.replaceAll(" ", "%20");
-            URI test = new URI(address);
-            if (test.getScheme() != null) return address;
-            if (test.getHost() != null && test.getPath() != null) return address;
-            String specific = test.getSchemeSpecificPart();
-            if (specific.indexOf('.') == -1)
-                throw new URISyntaxException(specific, "No dot inside domain");
-        } catch (URISyntaxException e1) {
-            address = "search://" + address;
-        }
-        return address;
-    }
-
-    public void setAddress(CefBrowser browser, String address) {
-        if (browser == browser_) address_field_.setText(address);
-    }
-
-    public JTextField getAddressField() {
-        return address_field_;
-    }
-}
diff --git a/java/tests/detailed/ui/MenuBar.java b/java/tests/detailed/ui/MenuBar.java
deleted file mode 100644
index a6fe40bc..00000000
--- a/java/tests/detailed/ui/MenuBar.java
+++ /dev/null
@@ -1,553 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.ui;
-
-import org.cef.CefApp;
-import org.cef.CefClient;
-import org.cef.OS;
-import org.cef.browser.CefBrowser;
-import org.cef.callback.CefPdfPrintCallback;
-import org.cef.callback.CefRunFileDialogCallback;
-import org.cef.callback.CefStringVisitor;
-import org.cef.handler.CefDialogHandler.FileDialogMode;
-import org.cef.misc.CefPdfPrintSettings;
-import org.cef.network.CefCookieManager;
-import org.cef.network.CefRequest;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.Container;
-import java.awt.Dimension;
-import java.awt.FlowLayout;
-import java.awt.Frame;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.util.Vector;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-
-import javax.swing.ImageIcon;
-import javax.swing.JButton;
-import javax.swing.JFileChooser;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JLayeredPane;
-import javax.swing.JMenu;
-import javax.swing.JMenuBar;
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JRootPane;
-import javax.swing.SwingUtilities;
-
-import tests.detailed.BrowserFrame;
-import tests.detailed.MainFrame;
-import tests.detailed.dialog.CookieManagerDialog;
-import tests.detailed.dialog.DevToolsDialog;
-import tests.detailed.dialog.DownloadDialog;
-import tests.detailed.dialog.SearchDialog;
-import tests.detailed.dialog.ShowTextDialog;
-import tests.detailed.dialog.UrlRequestDialog;
-import tests.detailed.util.DataUri;
-
-@SuppressWarnings("serial")
-public class MenuBar extends JMenuBar {
-    class SaveAs implements CefStringVisitor {
-        private PrintWriter fileWriter_;
-
-        public SaveAs(String fName) throws FileNotFoundException, UnsupportedEncodingException {
-            fileWriter_ = new PrintWriter(fName, "UTF-8");
-        }
-
-        @Override
-        public void visit(String string) {
-            fileWriter_.write(string);
-            fileWriter_.close();
-        }
-    }
-
-    private final MainFrame owner_;
-    private final CefBrowser browser_;
-    private String last_selected_file_ = "";
-    private final JMenu bookmarkMenu_;
-    private final ControlPanel control_pane_;
-    private final DownloadDialog downloadDialog_;
-    private final CefCookieManager cookieManager_;
-    private boolean reparentPending_ = false;
-
-    public MenuBar(MainFrame owner, CefBrowser browser, ControlPanel control_pane,
-            DownloadDialog downloadDialog, CefCookieManager cookieManager) {
-        owner_ = owner;
-        browser_ = browser;
-        control_pane_ = control_pane;
-        downloadDialog_ = downloadDialog;
-        cookieManager_ = cookieManager;
-
-        setEnabled(browser_ != null);
-
-        JMenu fileMenu = new JMenu("File");
-
-        JMenuItem openFileItem = new JMenuItem("Open file...");
-        openFileItem.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent arg0) {
-                JFileChooser fc = new JFileChooser(new File(last_selected_file_));
-                // Show open dialog; this method does not return until the dialog is closed.
-                fc.showOpenDialog(owner_);
-                File selectedFile = fc.getSelectedFile();
-                if (selectedFile != null) {
-                    last_selected_file_ = selectedFile.getAbsolutePath();
-                    browser_.loadURL("file:///" + selectedFile.getAbsolutePath());
-                }
-            }
-        });
-        fileMenu.add(openFileItem);
-
-        JMenuItem openFileDialog = new JMenuItem("Save as...");
-        openFileDialog.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                CefRunFileDialogCallback callback = new CefRunFileDialogCallback() {
-                    @Override
-                    public void onFileDialogDismissed(Vector<String> filePaths) {
-                        if (!filePaths.isEmpty()) {
-                            try {
-                                SaveAs saveContent = new SaveAs(filePaths.get(0));
-                                browser_.getSource(saveContent);
-                            } catch (FileNotFoundException | UnsupportedEncodingException e) {
-                                browser_.executeJavaScript("alert(\"Can't save file\");",
-                                        control_pane_.getAddress(), 0);
-                            }
-                        }
-                    }
-                };
-                browser_.runFileDialog(FileDialogMode.FILE_DIALOG_SAVE, owner_.getTitle(),
-                        "index.html", null, 0, callback);
-            }
-        });
-        fileMenu.add(openFileDialog);
-
-        JMenuItem printItem = new JMenuItem("Print...");
-        printItem.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.print();
-            }
-        });
-        fileMenu.add(printItem);
-
-        JMenuItem printToPdfItem = new JMenuItem("Print to PDF");
-        printToPdfItem.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                JFileChooser fc = new JFileChooser();
-                fc.showSaveDialog(owner_);
-                File selectedFile = fc.getSelectedFile();
-                if (selectedFile != null) {
-                    CefPdfPrintSettings pdfSettings = new CefPdfPrintSettings();
-                    pdfSettings.display_header_footer = true;
-                    // letter page size
-                    pdfSettings.paper_width = 8.5;
-                    pdfSettings.paper_height = 11;
-                    browser.printToPDF(
-                            selectedFile.getAbsolutePath(), pdfSettings, new CefPdfPrintCallback() {
-                                @Override
-                                public void onPdfPrintFinished(String path, boolean ok) {
-                                    SwingUtilities.invokeLater(new Runnable() {
-                                        @Override
-                                        public void run() {
-                                            if (ok) {
-                                                JOptionPane.showMessageDialog(owner_,
-                                                        "PDF saved to " + path, "Success",
-                                                        JOptionPane.INFORMATION_MESSAGE);
-                                            } else {
-                                                JOptionPane.showMessageDialog(owner_, "PDF failed",
-                                                        "Failed", JOptionPane.ERROR_MESSAGE);
-                                            }
-                                        }
-                                    });
-                                }
-                            });
-                }
-            }
-        });
-        fileMenu.add(printToPdfItem);
-
-        JMenuItem searchItem = new JMenuItem("Search...");
-        searchItem.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                new SearchDialog(owner_, browser_).setVisible(true);
-            }
-        });
-        fileMenu.add(searchItem);
-
-        fileMenu.addSeparator();
-
-        JMenuItem viewSource = new JMenuItem("View source");
-        viewSource.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.viewSource();
-            }
-        });
-        fileMenu.add(viewSource);
-
-        JMenuItem getSource = new JMenuItem("Get source...");
-        getSource.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                ShowTextDialog visitor = new ShowTextDialog(
-                        owner_, "Source of \"" + control_pane_.getAddress() + "\"");
-                browser_.getSource(visitor);
-            }
-        });
-        fileMenu.add(getSource);
-
-        JMenuItem getText = new JMenuItem("Get text...");
-        getText.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                ShowTextDialog visitor = new ShowTextDialog(
-                        owner_, "Content of \"" + control_pane_.getAddress() + "\"");
-                browser_.getText(visitor);
-            }
-        });
-        fileMenu.add(getText);
-
-        fileMenu.addSeparator();
-
-        JMenuItem showDownloads = new JMenuItem("Show Downloads");
-        showDownloads.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                downloadDialog_.setVisible(true);
-            }
-        });
-        fileMenu.add(showDownloads);
-
-        JMenuItem showCookies = new JMenuItem("Show Cookies");
-        showCookies.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                CookieManagerDialog cookieManager =
-                        new CookieManagerDialog(owner_, "Cookie Manager", cookieManager_);
-                cookieManager.setVisible(true);
-            }
-        });
-        fileMenu.add(showCookies);
-
-        fileMenu.addSeparator();
-
-        JMenuItem exitItem = new JMenuItem("Exit");
-        exitItem.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                owner_.dispatchEvent(new WindowEvent(owner_, WindowEvent.WINDOW_CLOSING));
-            }
-        });
-        fileMenu.add(exitItem);
-
-        bookmarkMenu_ = new JMenu("Bookmarks");
-
-        JMenuItem addBookmarkItem = new JMenuItem("Add bookmark");
-        addBookmarkItem.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                addBookmark(owner_.getTitle(), control_pane_.getAddress());
-            }
-        });
-        bookmarkMenu_.add(addBookmarkItem);
-        bookmarkMenu_.addSeparator();
-
-        JMenu testMenu = new JMenu("Tests");
-
-        JMenuItem testJSItem = new JMenuItem("JavaScript alert");
-        testJSItem.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.executeJavaScript("alert('Hello World');", control_pane_.getAddress(), 1);
-            }
-        });
-        testMenu.add(testJSItem);
-
-        JMenuItem jsAlertItem = new JMenuItem("JavaScript alert (will be suppressed)");
-        jsAlertItem.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.executeJavaScript("alert('Never displayed');", "http://dontshow.me", 1);
-            }
-        });
-        testMenu.add(jsAlertItem);
-
-        JMenuItem testShowText = new JMenuItem("Show Text");
-        testShowText.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.loadURL(DataUri.create(
-                        "text/html", "<html><body><h1>Hello World</h1></body></html>"));
-            }
-        });
-        testMenu.add(testShowText);
-
-        JMenuItem showForm = new JMenuItem("RequestHandler Test");
-        showForm.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                String form = "<html><head><title>RequestHandler test</title></head>";
-                form += "<body><h1>RequestHandler test</h1>";
-                form += "<form action=\"http://www.google.com/\" method=\"post\">";
-                form += "<input type=\"text\" name=\"searchFor\"/>";
-                form += "<input type=\"submit\"/><br/>";
-                form += "<input type=\"checkbox\" name=\"sendAsGet\"> Use GET instead of POST";
-                form += "<p>This form tries to send the content of the text field as HTTP-POST request to http://www.google.com.</p>";
-                form += "<h2>Testcase 1</h2>";
-                form += "Try to enter the word <b>\"ignore\"</b> into the text field and press \"submit\".<br />";
-                form += "The request will be rejected by the application.";
-                form += "<p>See implementation of <u>tests.RequestHandler.onBeforeBrowse(CefBrowser, CefRequest, boolean)</u> for details</p>";
-                form += "<h2>Testcase 2</h2>";
-                form += "Due Google doesn't allow the POST method, the server replies with a 405 error.</br>";
-                form += "If you activate the checkbox \"Use GET instead of POST\", the application will change the POST request into a GET request.";
-                form += "<p>See implementation of <u>tests.RequestHandler.onBeforeResourceLoad(CefBrowser, CefRequest)</u> for details</p>";
-                form += "</form>";
-                form += "</body></html>";
-                browser_.loadURL(DataUri.create("text/html", form));
-            }
-        });
-        testMenu.add(showForm);
-
-        JMenuItem httpRequest = new JMenuItem("Manual HTTP request");
-        httpRequest.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                String searchFor = JOptionPane.showInputDialog(owner_, "Search on google:");
-                if (searchFor != null && !searchFor.isEmpty()) {
-                    CefRequest myRequest = CefRequest.create();
-                    myRequest.setMethod("GET");
-                    myRequest.setURL("http://www.google.com/#q=" + searchFor);
-                    myRequest.setFirstPartyForCookies("http://www.google.com/#q=" + searchFor);
-                    browser_.loadRequest(myRequest);
-                }
-            }
-        });
-        testMenu.add(httpRequest);
-
-        JMenuItem showInfo = new JMenuItem("Show Info");
-        showInfo.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                String info = "<html><head><title>Browser status</title></head>";
-                info += "<body><h1>Browser status</h1><table border=\"0\">";
-                info += "<tr><td>CanGoBack</td><td>" + browser_.canGoBack() + "</td></tr>";
-                info += "<tr><td>CanGoForward</td><td>" + browser_.canGoForward() + "</td></tr>";
-                info += "<tr><td>IsLoading</td><td>" + browser_.isLoading() + "</td></tr>";
-                info += "<tr><td>isPopup</td><td>" + browser_.isPopup() + "</td></tr>";
-                info += "<tr><td>hasDocument</td><td>" + browser_.hasDocument() + "</td></tr>";
-                info += "<tr><td>Url</td><td>" + browser_.getURL() + "</td></tr>";
-                info += "<tr><td>Zoom-Level</td><td>" + browser_.getZoomLevel() + "</td></tr>";
-                info += "</table></body></html>";
-                String js = "var x=window.open(); x.document.open(); x.document.write('" + info
-                        + "'); x.document.close();";
-                browser_.executeJavaScript(js, "", 0);
-            }
-        });
-        testMenu.add(showInfo);
-
-        final JMenuItem showDevTools = new JMenuItem("Show DevTools");
-        showDevTools.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                DevToolsDialog devToolsDlg = new DevToolsDialog(owner_, "DEV Tools", browser_);
-                devToolsDlg.addComponentListener(new ComponentAdapter() {
-                    @Override
-                    public void componentHidden(ComponentEvent e) {
-                        showDevTools.setEnabled(true);
-                    }
-                });
-                devToolsDlg.setVisible(true);
-                showDevTools.setEnabled(false);
-            }
-        });
-        testMenu.add(showDevTools);
-
-        JMenuItem testURLRequest = new JMenuItem("URL Request");
-        testURLRequest.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                UrlRequestDialog dlg = new UrlRequestDialog(owner_, "URL Request Test");
-                dlg.setVisible(true);
-            }
-        });
-        testMenu.add(testURLRequest);
-
-        JMenuItem reparent = new JMenuItem("Reparent");
-        reparent.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                final BrowserFrame newFrame = new BrowserFrame("New Window");
-                newFrame.setLayout(new BorderLayout());
-                final JButton reparentButton = new JButton("Reparent <");
-                reparentButton.addActionListener(new ActionListener() {
-                    @Override
-                    public void actionPerformed(ActionEvent e) {
-                        if (reparentPending_) return;
-                        reparentPending_ = true;
-
-                        if (reparentButton.getText().equals("Reparent <")) {
-                            owner_.removeBrowser(new Runnable() {
-                                public void run() {
-                                    newFrame.setBrowser(browser_);
-                                    reparentButton.setText("Reparent >");
-                                    reparentPending_ = false;
-                                }
-                            });
-                        } else {
-                            newFrame.removeBrowser(new Runnable() {
-                                public void run() {
-                                    JRootPane rootPane = (JRootPane) owner_.getComponent(0);
-                                    Container container = rootPane.getContentPane();
-                                    JPanel panel = (JPanel) container.getComponent(0);
-                                    owner_.setBrowser(browser_);
-                                    owner_.revalidate();
-                                    reparentButton.setText("Reparent <");
-                                    reparentPending_ = false;
-                                }
-                            });
-                        }
-                    }
-                });
-                newFrame.add(reparentButton, BorderLayout.NORTH);
-                newFrame.setSize(400, 400);
-                newFrame.setVisible(true);
-            }
-        });
-        testMenu.add(reparent);
-
-        JMenuItem newwindow = new JMenuItem("New window");
-        newwindow.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                final MainFrame frame = new MainFrame(OS.isLinux(), false, false, null);
-                frame.setSize(800, 600);
-                frame.setVisible(true);
-            }
-        });
-        testMenu.add(newwindow);
-
-        JMenuItem screenshotSync = new JMenuItem("Screenshot (on AWT thread, native res)");
-        screenshotSync.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                long start = System.nanoTime();
-                CompletableFuture<BufferedImage> shot = browser.createScreenshot(true);
-                System.out.println("Took screenshot from the AWT event thread in "
-                        + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " msecs");
-                try {
-                    displayScreenshot(shot.get());
-                } catch (InterruptedException | ExecutionException exc) {
-                    // cannot happen, future is already resolved in this case
-                }
-            }
-        });
-        screenshotSync.setEnabled(owner.isOsrEnabled());
-        testMenu.add(screenshotSync);
-
-        JMenuItem screenshotSyncScaled = new JMenuItem("Screenshot (on AWT thread, scaled)");
-        screenshotSyncScaled.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                long start = System.nanoTime();
-                CompletableFuture<BufferedImage> shot = browser.createScreenshot(false);
-                System.out.println("Took screenshot from the AWT event thread in "
-                        + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " msecs");
-                try {
-                    displayScreenshot(shot.get());
-                } catch (InterruptedException | ExecutionException exc) {
-                    // cannot happen, future is already resolved in this case
-                }
-            }
-        });
-        screenshotSyncScaled.setEnabled(owner.isOsrEnabled());
-        testMenu.add(screenshotSyncScaled);
-
-        JMenuItem screenshotAsync = new JMenuItem("Screenshot (from other thread, scaled)");
-        screenshotAsync.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                long start = System.nanoTime();
-                CompletableFuture<BufferedImage> shot = browser.createScreenshot(false);
-                shot.thenAccept((image) -> {
-                    System.out.println("Took screenshot asynchronously in "
-                            + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " msecs");
-                    SwingUtilities.invokeLater(new Runnable() {
-                        @Override
-                        public void run() {
-                            displayScreenshot(image);
-                        }
-                    });
-                });
-            }
-        });
-        screenshotAsync.setEnabled(owner.isOsrEnabled());
-        testMenu.add(screenshotAsync);
-
-        add(fileMenu);
-        add(bookmarkMenu_);
-        add(testMenu);
-    }
-
-    public void addBookmark(String name, String URL) {
-        if (bookmarkMenu_ == null) return;
-
-        // Test if the bookmark already exists. If yes, update URL
-        Component[] entries = bookmarkMenu_.getMenuComponents();
-        for (Component itemEntry : entries) {
-            if (!(itemEntry instanceof JMenuItem)) continue;
-
-            JMenuItem item = (JMenuItem) itemEntry;
-            if (item.getText().equals(name)) {
-                item.setActionCommand(URL);
-                return;
-            }
-        }
-
-        JMenuItem menuItem = new JMenuItem(name);
-        menuItem.setActionCommand(URL);
-        menuItem.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.loadURL(e.getActionCommand());
-            }
-        });
-        bookmarkMenu_.add(menuItem);
-        validate();
-    }
-
-    private void displayScreenshot(BufferedImage aScreenshot) {
-        JFrame frame = new JFrame("Screenshot");
-        ImageIcon image = new ImageIcon();
-        image.setImage(aScreenshot);
-        frame.setLayout(new FlowLayout());
-        JLabel label = new JLabel(image);
-        label.setPreferredSize(new Dimension(aScreenshot.getWidth(), aScreenshot.getHeight()));
-        frame.add(label);
-        frame.setVisible(true);
-        frame.pack();
-    }
-
-    public void addBookmarkSeparator() {
-        bookmarkMenu_.addSeparator();
-    }
-}
diff --git a/java/tests/detailed/ui/StatusPanel.java b/java/tests/detailed/ui/StatusPanel.java
deleted file mode 100644
index 6f9026ed..00000000
--- a/java/tests/detailed/ui/StatusPanel.java
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.ui;
-
-import java.awt.Dimension;
-
-import javax.swing.Box;
-import javax.swing.BoxLayout;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JProgressBar;
-
-@SuppressWarnings("serial")
-public class StatusPanel extends JPanel {
-    private final JProgressBar progressBar_;
-    private final JLabel status_field_;
-
-    public StatusPanel() {
-        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
-
-        add(Box.createHorizontalStrut(5));
-        add(Box.createHorizontalStrut(5));
-
-        progressBar_ = new JProgressBar();
-        Dimension progressBarSize = progressBar_.getMaximumSize();
-        progressBarSize.width = 100;
-        progressBar_.setMinimumSize(progressBarSize);
-        progressBar_.setMaximumSize(progressBarSize);
-        add(progressBar_);
-        add(Box.createHorizontalStrut(5));
-
-        status_field_ = new JLabel("Info");
-        status_field_.setAlignmentX(LEFT_ALIGNMENT);
-        add(status_field_);
-        add(Box.createHorizontalStrut(5));
-        add(Box.createVerticalStrut(21));
-    }
-
-    public void setIsInProgress(boolean inProgress) {
-        progressBar_.setIndeterminate(inProgress);
-    }
-
-    public void setStatusText(String text) {
-        status_field_.setText(text);
-    }
-}
diff --git a/java/tests/detailed/util/DataUri.java b/java/tests/detailed/util/DataUri.java
deleted file mode 100644
index 895ad858..00000000
--- a/java/tests/detailed/util/DataUri.java
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.detailed.util;
-
-/**
- * Utility class for creating data: URIs that can be passed to CefBrowser.loadURL.
- */
-public class DataUri {
-    public static String create(String mimeType, String contents) {
-        return "data:" + mimeType + ";base64,"
-                + java.util.Base64.getEncoder().encodeToString(contents.getBytes());
-    }
-};
diff --git a/java/tests/junittests/DisplayHandlerTest.java b/java/tests/junittests/DisplayHandlerTest.java
deleted file mode 100644
index 81b873af..00000000
--- a/java/tests/junittests/DisplayHandlerTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.junittests;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import org.cef.browser.CefBrowser;
-import org.cef.browser.CefFrame;
-import org.cef.handler.CefDisplayHandlerAdapter;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-
-// Test the DisplayHandler implementation.
-@ExtendWith(TestSetupExtension.class)
-class DisplayHandlerTest {
-    private final String testUrl_ = "http://test.com/test.html";
-    private final String testContent_ =
-            "<html><head><title>Test Title</title></head><body>Test!</body></html>";
-
-    private boolean gotCallback_ = false;
-
-    @Test
-    void onTitleChange() {
-        TestFrame frame = new TestFrame() {
-            @Override
-            protected void setupTest() {
-                client_.addDisplayHandler(new CefDisplayHandlerAdapter() {
-                    @Override
-                    public void onTitleChange(CefBrowser browser, String title) {
-                        assertFalse(gotCallback_);
-                        gotCallback_ = true;
-                        assertEquals("Test Title", title);
-                        terminateTest();
-                    }
-                });
-
-                addResource(testUrl_, testContent_, "text/html");
-
-                createBrowser(testUrl_);
-
-                super.setupTest();
-            }
-        };
-
-        frame.awaitCompletion();
-
-        assertTrue(gotCallback_);
-    }
-
-    @Test
-    void onAddressChange() {
-        TestFrame frame = new TestFrame() {
-            @Override
-            protected void setupTest() {
-                client_.addDisplayHandler(new CefDisplayHandlerAdapter() {
-                    @Override
-                    public void onAddressChange(CefBrowser browser, CefFrame frame, String url) {
-                        assertFalse(gotCallback_);
-                        gotCallback_ = true;
-                        assertEquals(url, testUrl_);
-                        terminateTest();
-                    }
-                });
-
-                addResource(testUrl_, testContent_, "text/html");
-
-                createBrowser(testUrl_);
-
-                super.setupTest();
-            }
-        };
-
-        frame.awaitCompletion();
-
-        assertTrue(gotCallback_);
-    }
-}
diff --git a/java/tests/junittests/DragDataTest.java b/java/tests/junittests/DragDataTest.java
deleted file mode 100644
index bd904309..00000000
--- a/java/tests/junittests/DragDataTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.junittests;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import org.cef.callback.CefDragData;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-
-import java.util.Vector;
-
-// Test the TestFrame implementation.
-@ExtendWith(TestSetupExtension.class)
-class DragDataTest {
-    @Test
-    void createEmpty() {
-        CefDragData dragData = CefDragData.create();
-        assertNotNull(dragData);
-        assertFalse(dragData.isReadOnly());
-
-        assertFalse(dragData.isLink());
-        assertFalse(dragData.isFile());
-        assertTrue(dragData.isFragment()); // Default state.
-
-        assertEquals("", dragData.getLinkURL());
-        assertEquals("", dragData.getLinkTitle());
-        assertEquals("", dragData.getLinkMetadata());
-        assertEquals("", dragData.getFragmentText());
-        assertEquals("", dragData.getFragmentHtml());
-        assertEquals("", dragData.getFragmentBaseURL());
-        assertEquals(0, dragData.getFileContents(null));
-        assertEquals("", dragData.getFileName());
-        assertFalse(dragData.getFileNames(null));
-
-        // Explicit cleanup to avoid memory leaks.
-        dragData.dispose();
-    }
-
-    @Test
-    void createLink() {
-        CefDragData dragData = CefDragData.create();
-        assertNotNull(dragData);
-        assertFalse(dragData.isReadOnly());
-
-        final String linkURL = "http://test.com/test.html";
-        dragData.setLinkURL(linkURL);
-        assertEquals(linkURL, dragData.getLinkURL());
-
-        final String linkTitle = "Test Title";
-        dragData.setLinkTitle(linkTitle);
-        assertEquals(linkTitle, dragData.getLinkTitle());
-
-        final String linkMetadata = "something";
-        dragData.setLinkMetadata(linkMetadata);
-        assertEquals(linkMetadata, dragData.getLinkMetadata());
-
-        assertTrue(dragData.isLink());
-        assertFalse(dragData.isFile());
-        assertFalse(dragData.isFragment());
-
-        // Explicit cleanup to avoid memory leaks.
-        dragData.dispose();
-    }
-
-    @Test
-    void createFile() {
-        CefDragData dragData = CefDragData.create();
-        assertNotNull(dragData);
-        assertFalse(dragData.isReadOnly());
-
-        final String path1 = "/path/to/file1.txt";
-        final String path2 = "/path/to/file2.txt";
-
-        dragData.addFile(path1, "File 1");
-        dragData.addFile(path2, "File 2");
-
-        Vector<String> fileNames = new Vector<>();
-        assertTrue(dragData.getFileNames(fileNames));
-
-        assertEquals(2, fileNames.size());
-        assertEquals(path1, fileNames.get(0));
-        assertEquals(path2, fileNames.get(1));
-
-        assertFalse(dragData.isLink());
-        assertTrue(dragData.isFile());
-        assertFalse(dragData.isFragment());
-
-        // Explicit cleanup to avoid memory leaks.
-        dragData.dispose();
-    }
-
-    @Test
-    void createFragment() {
-        CefDragData dragData = CefDragData.create();
-        assertNotNull(dragData);
-        assertFalse(dragData.isReadOnly());
-
-        final String fragmentText = "something";
-        dragData.setFragmentText(fragmentText);
-        assertEquals(fragmentText, dragData.getFragmentText());
-
-        final String fragmentHtml = "<span>something</span>";
-        dragData.setFragmentHtml(fragmentHtml);
-        assertEquals(fragmentHtml, dragData.getFragmentHtml());
-
-        final String fragmentBaseURL = "http://test.com/test.html";
-        dragData.setFragmentBaseURL(fragmentBaseURL);
-        assertEquals(fragmentBaseURL, dragData.getFragmentBaseURL());
-
-        assertFalse(dragData.isLink());
-        assertFalse(dragData.isFile());
-        assertTrue(dragData.isFragment());
-
-        // Explicit cleanup to avoid memory leaks.
-        dragData.dispose();
-    }
-
-    @Test
-    void cloneObject() {
-        CefDragData dragData = CefDragData.create();
-        assertNotNull(dragData);
-        assertFalse(dragData.isReadOnly());
-
-        final String fragmentText = "something";
-        final String fragmentBaseURL = "http://test.com/test.html";
-        dragData.setFragmentText(fragmentText);
-        dragData.setFragmentBaseURL(fragmentBaseURL);
-
-        CefDragData dragData2 = dragData.clone();
-        assertFalse(dragData2.isReadOnly());
-        assertEquals(fragmentText, dragData2.getFragmentText());
-        assertEquals(fragmentBaseURL, dragData2.getFragmentBaseURL());
-
-        assertFalse(dragData2.isLink());
-        assertFalse(dragData2.isFile());
-        assertTrue(dragData2.isFragment());
-
-        // Explicit cleanup to avoid memory leaks.
-        dragData.dispose();
-        dragData2.dispose();
-    }
-
-    @Test
-    void disposeObject() {
-        CefDragData dragData = CefDragData.create();
-        assertNotNull(dragData);
-        assertFalse(dragData.isReadOnly());
-
-        final String fragmentText = "something";
-        dragData.setFragmentText(fragmentText);
-        assertEquals(fragmentText, dragData.getFragmentText());
-
-        // Explicit cleanup to avoid memory leaks.
-        // After dispose() the Java object is no longer backed by a CEF object.
-        dragData.dispose();
-
-        assertEquals(null, dragData.getFragmentText());
-    }
-}
diff --git a/java/tests/junittests/TestFrame.java b/java/tests/junittests/TestFrame.java
deleted file mode 100644
index bdbc26a9..00000000
--- a/java/tests/junittests/TestFrame.java
+++ /dev/null
@@ -1,297 +0,0 @@
-// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.junittests;
-
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-
-import static tests.junittests.TestSetupContext.debugPrint;
-
-import org.cef.CefApp;
-import org.cef.CefClient;
-import org.cef.browser.CefBrowser;
-import org.cef.browser.CefFrame;
-import org.cef.callback.CefAuthCallback;
-import org.cef.callback.CefCallback;
-import org.cef.handler.CefCookieAccessFilter;
-import org.cef.handler.CefLifeSpanHandler;
-import org.cef.handler.CefLoadHandler;
-import org.cef.handler.CefRequestHandler;
-import org.cef.handler.CefResourceHandler;
-import org.cef.handler.CefResourceRequestHandler;
-import org.cef.misc.BoolRef;
-import org.cef.misc.StringRef;
-import org.cef.network.CefRequest;
-import org.cef.network.CefRequest.TransitionType;
-import org.cef.network.CefResponse;
-import org.cef.network.CefURLRequest;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import java.util.HashMap;
-import java.util.concurrent.CountDownLatch;
-
-import javax.swing.JFrame;
-
-// Base class for browsers that run tests.
-class TestFrame extends JFrame implements CefLifeSpanHandler, CefLoadHandler, CefRequestHandler,
-                                          CefResourceRequestHandler {
-    private static final long serialVersionUID = -5570653778104813836L;
-    private boolean isClosed_ = false;
-    private CountDownLatch countdown_ = new CountDownLatch(1);
-
-    // Resources that have been populated for the test.
-    private class ResourceContent {
-        String content;
-        String mimeType;
-        HashMap<String, String> headerMap;
-    }
-    private HashMap<String, ResourceContent> resourceMap_ = null;
-
-    protected final CefClient client_;
-    protected CefBrowser browser_ = null;
-
-    TestFrame() {
-        client_ = CefApp.getInstance().createClient();
-        assertNotNull(client_);
-
-        // Browser window closing works as follows:
-        //   1. Sending WindowEvent.WINDOW_CLOSING calls WindowAdapter.windowClosing.
-        //   2. WindowAdapter.windowClosing calls CefBrowser.close(false).
-        //   3. CEF calls CefLifeSpanHandler.doClose() which calls CefBrowser.doClose()
-        //      which returns true (canceling the close).
-        //   4. CefBrowser.doClose() triggers another call to WindowAdapter.windowClosing.
-        //   5. WindowAdapter.windowClosing calls CefBrowser.close(true).
-        //   6. For windowed browsers CEF destroys the native window handle. For OSR
-        //      browsers CEF calls CefLifeSpanHandler.doClose() which calls
-        //      CefBrowser.doClose() again which returns false (allowing the close).
-        //   7. CEF calls CefLifeSpanHandler.onBeforeClose and the browser is destroyed.
-        addWindowListener(new WindowAdapter() {
-            @Override
-            public void windowClosing(WindowEvent e) {
-                boolean isClosed = isClosed_;
-
-                if (isClosed) {
-                    // Cause browser.doClose() to return false so that OSR browsers
-                    // can close.
-                    browser_.setCloseAllowed();
-                }
-
-                // Results in another call to this method.
-                if (debugPrint())
-                    System.out.println("windowClosing CefBrowser.close(" + isClosed + ")");
-                browser_.close(isClosed);
-                if (!isClosed_) {
-                    isClosed_ = true;
-                }
-                if (isClosed) {
-                    // Dispose after the 2nd call to this method.
-                    if (debugPrint()) System.out.println("windowClosing Frame.dispose");
-                    dispose();
-                }
-            }
-        });
-
-        client_.addLifeSpanHandler(this);
-        client_.addLoadHandler(this);
-        client_.addRequestHandler(this);
-
-        setupTest();
-    }
-
-    protected void createBrowser(String startURL) {
-        assertNull(browser_);
-        browser_ = client_.createBrowser(startURL, false /* isTransparent */);
-        assertNotNull(browser_);
-
-        pack();
-        setSize(800, 600);
-        setVisible(true);
-    }
-
-    // Override this method to perform test setup.
-    protected void setupTest() {}
-
-    // Override this method to perform test cleanup.
-    protected void cleanupTest() {
-        if (debugPrint()) System.out.println("cleanupTest");
-        client_.dispose();
-        // Allow the test to complete.
-        countdown_.countDown();
-    }
-
-    // Call this method to terminate the test by dispatching a window close event.
-    protected final void terminateTest() {
-        if (debugPrint()) System.out.println("terminateTest");
-        if (!isClosed_) {
-            dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
-        }
-    }
-
-    // Block until the test completes.
-    public final void awaitCompletion() {
-        try {
-            countdown_.await();
-        } catch (InterruptedException e) {
-        }
-        if (debugPrint()) System.out.println("awaitCompletion returned");
-    }
-
-    protected void addResource(String url, String content, String mimeType) {
-        addResource(url, content, mimeType, null);
-    }
-
-    // Add a resource that will be returned via getResourceHandler().
-    protected void addResource(
-            String url, String content, String mimeType, HashMap<String, String> headerMap) {
-        if (resourceMap_ == null) resourceMap_ = new HashMap<>();
-
-        assertNull(resourceMap_.get(url));
-
-        ResourceContent rc = new ResourceContent();
-        rc.content = content;
-        rc.mimeType = mimeType;
-        rc.headerMap = headerMap;
-
-        resourceMap_.put(url, rc);
-    }
-
-    // CefLifeSpanHandler methods:
-
-    @Override
-    public void onAfterCreated(CefBrowser browser) {
-        if (debugPrint()) System.out.println("onAfterCreated id=" + browser.getIdentifier());
-    }
-
-    @Override
-    public boolean onBeforePopup(
-            CefBrowser browser, CefFrame frame, String target_url, String target_frame_name) {
-        return false;
-    }
-
-    @Override
-    public void onAfterParentChanged(CefBrowser browser) {}
-
-    @Override
-    public boolean doClose(CefBrowser browser) {
-        boolean result = browser.doClose();
-        if (debugPrint()) {
-            System.out.println(
-                    "doClose id=" + browser.getIdentifier() + " CefBrowser.doClose=" + result);
-        }
-        return result;
-    }
-
-    @Override
-    public void onBeforeClose(CefBrowser browser) {
-        if (debugPrint()) System.out.println("onBeforeClose id=" + browser.getIdentifier());
-        cleanupTest();
-    }
-
-    // CefLoadHandler methods:
-
-    @Override
-    public void onLoadingStateChange(
-            CefBrowser browser, boolean isLoading, boolean canGoBack, boolean canGoForward) {}
-
-    @Override
-    public void onLoadStart(CefBrowser browser, CefFrame frame, TransitionType transitionType) {}
-
-    @Override
-    public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) {}
-
-    @Override
-    public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode,
-            String errorText, String failedUrl) {}
-
-    // CefRequestHandler methods:
-
-    @Override
-    public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request,
-            boolean user_gesture, boolean is_redirect) {
-        return false;
-    }
-
-    @Override
-    public boolean onOpenURLFromTab(
-            CefBrowser browser, CefFrame frame, String target_url, boolean user_gesture) {
-        return false;
-    }
-
-    @Override
-    public CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame,
-            CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator,
-            BoolRef disableDefaultHandling) {
-        return this;
-    }
-
-    @Override
-    public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy,
-            String host, int port, String realm, String scheme, CefAuthCallback callback) {
-        return false;
-    }
-
-    @Override
-    public boolean onCertificateError(CefBrowser browser, CefLoadHandler.ErrorCode cert_error,
-            String request_url, CefCallback callback) {
-        return false;
-    }
-
-    @Override
-    public void onRenderProcessTerminated(CefBrowser browser, TerminationStatus status) {}
-
-    // CefResourceRequestHandler methods:
-
-    @Override
-    public CefCookieAccessFilter getCookieAccessFilter(
-            CefBrowser browser, CefFrame frame, CefRequest request) {
-        return null;
-    }
-
-    @Override
-    public boolean onBeforeResourceLoad(CefBrowser browser, CefFrame frame, CefRequest request) {
-        return false;
-    }
-
-    @Override
-    public CefResourceHandler getResourceHandler(
-            CefBrowser browser, CefFrame frame, CefRequest request) {
-        if (resourceMap_ != null) {
-            String url = request.getURL();
-
-            // Ignore the query component, if any.
-            int idx = url.indexOf('?');
-            if (idx > 0) url = url.substring(0, idx);
-
-            ResourceContent rc = resourceMap_.get(url);
-            if (rc != null) {
-                if (debugPrint()) System.out.println("Found resource for: " + url);
-                return new TestResourceHandler(rc.content, rc.mimeType, rc.headerMap);
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public void onResourceRedirect(CefBrowser browser, CefFrame frame, CefRequest request,
-            CefResponse response, StringRef new_url) {}
-
-    @Override
-    public boolean onResourceResponse(
-            CefBrowser browser, CefFrame frame, CefRequest request, CefResponse response) {
-        return false;
-    }
-
-    @Override
-    public void onResourceLoadComplete(CefBrowser browser, CefFrame frame, CefRequest request,
-            CefResponse response, CefURLRequest.Status status, long receivedContentLength) {}
-
-    @Override
-    public void onProtocolExecution(
-            CefBrowser browser, CefFrame frame, CefRequest request, BoolRef allowOsExecution) {}
-}
diff --git a/java/tests/junittests/TestFrameTest.java b/java/tests/junittests/TestFrameTest.java
deleted file mode 100644
index e8f36c16..00000000
--- a/java/tests/junittests/TestFrameTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.junittests;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import org.cef.browser.CefBrowser;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-
-// Test the TestFrame implementation.
-@ExtendWith(TestSetupExtension.class)
-class TestFrameTest {
-    private boolean gotSetupTest_ = false;
-    private boolean gotCleanupTest_ = false;
-    private boolean gotLoadingStateChange_ = false;
-
-    @Test
-    void minimal() {
-        final String testUrl = "http://test.com/test.html";
-        TestFrame frame = new TestFrame() {
-            @Override
-            protected void setupTest() {
-                assertFalse(gotSetupTest_);
-                gotSetupTest_ = true;
-
-                addResource(testUrl, "<html><body>Test!</body></html>", "text/html");
-
-                createBrowser(testUrl);
-
-                super.setupTest();
-            }
-
-            @Override
-            protected void cleanupTest() {
-                assertFalse(gotCleanupTest_);
-                gotCleanupTest_ = true;
-
-                super.cleanupTest();
-            }
-
-            @Override
-            public void onLoadingStateChange(CefBrowser browser, boolean isLoading,
-                    boolean canGoBack, boolean canGoForward) {
-                if (!isLoading) {
-                    assertFalse(gotLoadingStateChange_);
-                    gotLoadingStateChange_ = true;
-                    terminateTest();
-                }
-            }
-        };
-
-        frame.awaitCompletion();
-
-        assertTrue(gotSetupTest_);
-        assertTrue(gotLoadingStateChange_);
-        assertTrue(gotCleanupTest_);
-    }
-}
diff --git a/java/tests/junittests/TestResourceHandler.java b/java/tests/junittests/TestResourceHandler.java
deleted file mode 100644
index 23594f4f..00000000
--- a/java/tests/junittests/TestResourceHandler.java
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.junittests;
-
-import org.cef.callback.CefCallback;
-import org.cef.handler.CefResourceHandlerAdapter;
-import org.cef.misc.IntRef;
-import org.cef.misc.StringRef;
-import org.cef.network.CefRequest;
-import org.cef.network.CefResponse;
-
-import java.nio.ByteBuffer;
-import java.util.HashMap;
-
-class TestResourceHandler extends CefResourceHandlerAdapter {
-    private int offset_ = 0;
-    private final String content_;
-    private final String mimeType_;
-    private final HashMap<String, String> headerMap_;
-
-    TestResourceHandler(String content, String mimeType, HashMap<String, String> headerMap) {
-        content_ = content;
-        mimeType_ = mimeType;
-        headerMap_ = headerMap;
-    }
-
-    @Override
-    public boolean processRequest(CefRequest request, CefCallback callback) {
-        callback.Continue();
-        return true;
-    }
-
-    @Override
-    public void getResponseHeaders(
-            CefResponse response, IntRef response_length, StringRef redirectUrl) {
-        response_length.set(content_.length());
-        response.setMimeType(mimeType_);
-        response.setStatus(200);
-
-        if (headerMap_ != null) {
-            HashMap<String, String> headerMap = new HashMap<>();
-            response.getHeaderMap(headerMap);
-            headerMap.putAll(headerMap_);
-            response.setHeaderMap(headerMap);
-        }
-    }
-
-    @Override
-    public boolean readResponse(
-            byte[] data_out, int bytes_to_read, IntRef bytes_read, CefCallback callback) {
-        int length = content_.length();
-        if (offset_ >= length) return false;
-
-        // Extract up to |bytes_to_read| bytes from |content_|.
-        int endPos = offset_ + bytes_to_read;
-        String dataToSend = (endPos > length) ? content_.substring(offset_)
-                                              : content_.substring(offset_, endPos);
-
-        // Copy extracted bytes into |data_out| and set the read length to |bytes_read|.
-        ByteBuffer result = ByteBuffer.wrap(data_out);
-        result.put(dataToSend.getBytes());
-        bytes_read.set(dataToSend.length());
-
-        offset_ = endPos;
-        return true;
-    }
-}
diff --git a/java/tests/junittests/TestSetupContext.java b/java/tests/junittests/TestSetupContext.java
deleted file mode 100644
index 758fbffc..00000000
--- a/java/tests/junittests/TestSetupContext.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.junittests;
-
-import org.junit.jupiter.api.extension.ExtensionContext;
-
-import java.util.Optional;
-
-// Stores global test setup state for access from package classes.
-class TestSetupContext {
-    private static boolean debugPrint_ = false;
-
-    // Debug print statements may be enabled via `--config debugPrint=true`.
-    static boolean debugPrint() {
-        return debugPrint_;
-    }
-
-    // Initialize from global configuration parameters.
-    static void initialize(ExtensionContext context) {
-        Optional<String> debugPrint = context.getConfigurationParameter("debugPrint");
-        if (debugPrint.isPresent() && debugPrint.get().equalsIgnoreCase("true")) {
-            debugPrint_ = true;
-        }
-    }
-}
diff --git a/java/tests/junittests/TestSetupExtension.java b/java/tests/junittests/TestSetupExtension.java
deleted file mode 100644
index 66887719..00000000
--- a/java/tests/junittests/TestSetupExtension.java
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.junittests;
-
-import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;
-
-import org.cef.CefApp;
-import org.cef.CefApp.CefAppState;
-import org.cef.CefSettings;
-import org.cef.handler.CefAppHandlerAdapter;
-import org.junit.jupiter.api.extension.BeforeAllCallback;
-import org.junit.jupiter.api.extension.ExtensionContext;
-
-import java.util.concurrent.CountDownLatch;
-
-// All test cases must install this extension for CEF to be properly initialized
-// and shut down.
-//
-// For example:
-//
-//   @ExtendWith(TestSetupExtension.class)
-//   class FooTest {
-//        @Test
-//        void testCaseThatRequiresCEF() {}
-//   }
-//
-// This code is based on https://stackoverflow.com/a/51556718.
-public class TestSetupExtension
-        implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {
-    private static boolean initialized_ = false;
-    private static CountDownLatch countdown_ = new CountDownLatch(1);
-
-    @Override
-    public void beforeAll(ExtensionContext context) {
-        if (!initialized_) {
-            initialized_ = true;
-            initialize(context);
-        }
-    }
-
-    // Executed before any tests are run.
-    private void initialize(ExtensionContext context) {
-        TestSetupContext.initialize(context);
-
-        if (TestSetupContext.debugPrint()) {
-            System.out.println("TestSetupExtension.initialize");
-        }
-
-        // Register a callback hook for when the root test context is shut down.
-        context.getRoot().getStore(GLOBAL).put("jcef_test_setup", this);
-
-        // Perform startup initialization on platforms that require it.
-        if (!CefApp.startup(null)) {
-            System.out.println("Startup initialization failed!");
-            return;
-        }
-
-        CefApp.addAppHandler(new CefAppHandlerAdapter(null) {
-            @Override
-            public void stateHasChanged(org.cef.CefApp.CefAppState state) {
-                if (state == CefAppState.TERMINATED) {
-                    // Signal completion of CEF shutdown.
-                    countdown_.countDown();
-                }
-            }
-        });
-
-        // Initialize the singleton CefApp instance.
-        CefSettings settings = new CefSettings();
-        CefApp.getInstance(settings);
-    }
-
-    // Executed after all tests have completed.
-    @Override
-    public void close() {
-        if (TestSetupContext.debugPrint()) {
-            System.out.println("TestSetupExtension.close");
-        }
-
-        CefApp.getInstance().dispose();
-
-        // Wait for CEF shutdown to complete.
-        try {
-            countdown_.await();
-        } catch (InterruptedException e) {
-        }
-    }
-}
diff --git a/java/tests/simple/MainFrame.java b/java/tests/simple/MainFrame.java
deleted file mode 100644
index 822c4c8f..00000000
--- a/java/tests/simple/MainFrame.java
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-
-package tests.simple;
-
-import org.cef.CefApp;
-import org.cef.CefApp.CefAppState;
-import org.cef.CefClient;
-import org.cef.CefSettings;
-import org.cef.OS;
-import org.cef.browser.CefBrowser;
-import org.cef.browser.CefFrame;
-import org.cef.handler.CefAppHandlerAdapter;
-import org.cef.handler.CefDisplayHandlerAdapter;
-import org.cef.handler.CefFocusHandlerAdapter;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.KeyboardFocusManager;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.FocusAdapter;
-import java.awt.event.FocusEvent;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-
-import javax.swing.JFrame;
-import javax.swing.JTextField;
-
-/**
- * This is a simple example application using JCEF.
- * It displays a JFrame with a JTextField at its top and a CefBrowser in its
- * center. The JTextField is used to enter and assign an URL to the browser UI.
- * No additional handlers or callbacks are used in this example.
- *
- * The number of used JCEF classes is reduced (nearly) to its minimum and should
- * assist you to get familiar with JCEF.
- *
- * For a more feature complete example have also a look onto the example code
- * within the package "tests.detailed".
- */
-public class MainFrame extends JFrame {
-    private static final long serialVersionUID = -5570653778104813836L;
-    private final JTextField address_;
-    private final CefApp cefApp_;
-    private final CefClient client_;
-    private final CefBrowser browser_;
-    private boolean browserFocus_ = true;
-
-    /**
-     * To display a simple browser window, it suffices completely to create an
-     * instance of the class CefBrowser and to assign its UI component to your
-     * application (e.g. to your content pane).
-     * But to be more verbose, this CTOR keeps an instance of each object on the
-     * way to the browser UI.
-     */
-    private MainFrame(String startURL, boolean useOSR, boolean isTransparent) {
-        // (1) The entry point to JCEF is always the class CefApp. There is only one
-        //     instance per application and therefore you have to call the method
-        //     "getInstance()" instead of a CTOR.
-        //
-        //     CefApp is responsible for the global CEF context. It loads all
-        //     required native libraries, initializes CEF accordingly, starts a
-        //     background task to handle CEF's message loop and takes care of
-        //     shutting down CEF after disposing it.
-        CefApp.addAppHandler(new CefAppHandlerAdapter(null) {
-            @Override
-            public void stateHasChanged(org.cef.CefApp.CefAppState state) {
-                // Shutdown the app if the native CEF part is terminated
-                if (state == CefAppState.TERMINATED) System.exit(0);
-            }
-        });
-        CefSettings settings = new CefSettings();
-        settings.windowless_rendering_enabled = useOSR;
-        cefApp_ = CefApp.getInstance(settings);
-
-        // (2) JCEF can handle one to many browser instances simultaneous. These
-        //     browser instances are logically grouped together by an instance of
-        //     the class CefClient. In your application you can create one to many
-        //     instances of CefClient with one to many CefBrowser instances per
-        //     client. To get an instance of CefClient you have to use the method
-        //     "createClient()" of your CefApp instance. Calling an CTOR of
-        //     CefClient is not supported.
-        //
-        //     CefClient is a connector to all possible events which come from the
-        //     CefBrowser instances. Those events could be simple things like the
-        //     change of the browser title or more complex ones like context menu
-        //     events. By assigning handlers to CefClient you can control the
-        //     behavior of the browser. See tests.detailed.MainFrame for an example
-        //     of how to use these handlers.
-        client_ = cefApp_.createClient();
-
-        // (3) One CefBrowser instance is responsible to control what you'll see on
-        //     the UI component of the instance. It can be displayed off-screen
-        //     rendered or windowed rendered. To get an instance of CefBrowser you
-        //     have to call the method "createBrowser()" of your CefClient
-        //     instances.
-        //
-        //     CefBrowser has methods like "goBack()", "goForward()", "loadURL()",
-        //     and many more which are used to control the behavior of the displayed
-        //     content. The UI is held within a UI-Compontent which can be accessed
-        //     by calling the method "getUIComponent()" on the instance of CefBrowser.
-        //     The UI component is inherited from a java.awt.Component and therefore
-        //     it can be embedded into any AWT UI.
-        browser_ = client_.createBrowser(startURL, isTransparent);
-
-        // (4) For this minimal browser, we need only a text field to enter an URL
-        //     we want to navigate to and a CefBrowser window to display the content
-        //     of the URL. To respond to the input of the user, we're registering an
-        //     anonymous ActionListener. This listener is performed each time the
-        //     user presses the "ENTER" key within the address field.
-        //     If this happens, the entered value is passed to the CefBrowser
-        //     instance to be loaded as URL.
-        address_ = new JTextField(startURL, 100);
-        address_.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                browser_.loadURL(address_.getText());
-            }
-        });
-
-        // Update the address field when the browser URL changes.
-        client_.addDisplayHandler(new CefDisplayHandlerAdapter() {
-            @Override
-            public void onAddressChange(CefBrowser browser, CefFrame frame, String url) {
-                address_.setText(url);
-            }
-        });
-
-        // Clear focus from the browser when the address field gains focus.
-        address_.addFocusListener(new FocusAdapter() {
-            @Override
-            public void focusGained(FocusEvent e) {
-                if (!browserFocus_) return;
-                browserFocus_ = false;
-                KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
-                address_.requestFocus();
-            }
-        });
-
-        // Clear focus from the address field when the browser gains focus.
-        client_.addFocusHandler(new CefFocusHandlerAdapter() {
-            @Override
-            public void onGotFocus(CefBrowser browser) {
-                if (browserFocus_) return;
-                browserFocus_ = true;
-                KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
-                browser.setFocus(true);
-            }
-
-            @Override
-            public void onTakeFocus(CefBrowser browser, boolean next) {
-                browserFocus_ = false;
-            }
-        });
-
-        // (5) All UI components are assigned to the default content pane of this
-        //     JFrame and afterwards the frame is made visible to the user.
-        getContentPane().add(address_, BorderLayout.NORTH);
-        pack();
-        setSize(800, 600);
-        setVisible(true);
-
-        // (6) To take care of shutting down CEF accordingly, it's important to call
-        //     the method "dispose()" of the CefApp instance if the Java
-        //     application will be closed. Otherwise you'll get asserts from CEF.
-        addWindowListener(new WindowAdapter() {
-            @Override
-            public void windowClosing(WindowEvent e) {
-                CefApp.getInstance().dispose();
-                dispose();
-            }
-        });
-    }
-
-    public static void main(String[] args) {
-        // Perform startup initialization on platforms that require it.
-        if (!CefApp.startup(args)) {
-            System.out.println("Startup initialization failed!");
-            return;
-        }
-
-        // The simple example application is created as anonymous class and points
-        // to Google as the very first loaded page. Windowed rendering mode is used by
-        // default. If you want to test OSR mode set |useOsr| to true and recompile.
-        boolean useOsr = false;
-        new MainFrame("http://www.google.com", useOsr, false);
-    }
-}
diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt
index 0368b692..70e88f40 100644
--- a/native/CMakeLists.txt
+++ b/native/CMakeLists.txt
@@ -54,6 +54,8 @@ set(JCEF_SRCS
   CefPrintSettings_N.h
   CefQueryCallback_N.cpp
   CefQueryCallback_N.h
+  CefRegistration_N.cpp
+  CefRegistration_N.h
   CefRequest_N.cpp
   CefRequest_N.h
   CefCallback_N.cpp
@@ -83,6 +85,8 @@ set(JCEF_SRCS
   cookie_visitor.cpp
   cookie_visitor.h
   critical_wait.h
+  devtools_message_observer.cpp
+  devtools_message_observer.h
   dialog_handler.cpp
   dialog_handler.h
   display_handler.cpp
@@ -95,6 +99,8 @@ set(JCEF_SRCS
   drag_handler.h
   focus_handler.cpp
   focus_handler.h
+  int_callback.cpp
+  int_callback.h
   jcef_version.h
   jni_scoped_helpers.h
   jni_scoped_helpers.cpp
diff --git a/native/CefBrowser_N.cpp b/native/CefBrowser_N.cpp
index f7f17cd8..fbc2d6c4 100644
--- a/native/CefBrowser_N.cpp
+++ b/native/CefBrowser_N.cpp
@@ -6,12 +6,15 @@
 
 #include "include/base/cef_callback.h"
 #include "include/cef_browser.h"
+#include "include/cef_parser.h"
 #include "include/cef_task.h"
 #include "include/wrapper/cef_closure_task.h"
 
 #include "browser_process_handler.h"
 #include "client_handler.h"
 #include "critical_wait.h"
+#include "devtools_message_observer.h"
+#include "int_callback.h"
 #include "jni_util.h"
 #include "life_span_handler.h"
 #include "pdf_print_callback.h"
@@ -893,24 +896,30 @@ struct JNIObjectsForCreate {
   ScopedJNIObjectGlobal jparentBrowser;
   ScopedJNIObjectGlobal jclientHandler;
   ScopedJNIObjectGlobal url;
+  ScopedJNIObjectGlobal canvas;
   ScopedJNIObjectGlobal jcontext;
   ScopedJNIObjectGlobal jinspectAt;
+  ScopedJNIObjectGlobal jbrowserSettings;
 
   JNIObjectsForCreate(JNIEnv* env,
                       jobject _jbrowser,
                       jobject _jparentBrowser,
                       jobject _jclientHandler,
                       jstring _url,
+                      jobject _canvas,
                       jobject _jcontext,
-                      jobject _jinspectAt)
+                      jobject _jinspectAt,
+                      jobject _browserSettings)
       :
 
         jbrowser(env, _jbrowser),
         jparentBrowser(env, _jparentBrowser),
         jclientHandler(env, _jclientHandler),
         url(env, _url),
+        canvas(env, _canvas),
         jcontext(env, _jcontext),
-        jinspectAt(env, _jinspectAt) {}
+        jinspectAt(env, _jinspectAt),
+        jbrowserSettings(env, _browserSettings) {}
 };
 
 void create(std::shared_ptr<JNIObjectsForCreate> objs,
@@ -938,6 +947,13 @@ void create(std::shared_ptr<JNIObjectsForCreate> objs,
     settings.background_color = CefColorSetARGB(255, 255, 255, 255);
   }
 
+  ScopedJNIClass cefBrowserSettings(env, "org/cef/CefBrowserSettings");
+  if (cefBrowserSettings != nullptr &&
+      objs->jbrowserSettings != nullptr) {  // Dev-tools settings are null
+     GetJNIFieldInt(env, cefBrowserSettings, objs->jbrowserSettings,
+                     "windowless_frame_rate", &settings.windowless_frame_rate);
+  }
+
   CefRefPtr<CefBrowser> browserObj;
   CefString strUrl = GetJNIString(env, static_cast<jstring>(objs->url.get()));
 
@@ -994,6 +1010,26 @@ void getZoomLevel(CefRefPtr<CefBrowserHost> host,
   }
 }
 
+void executeDevToolsMethod(CefRefPtr<CefBrowserHost> host,
+                           const CefString& method,
+                           const CefString& parametersAsJson,
+                           CefRefPtr<IntCallback> callback) {
+  CefRefPtr<CefDictionaryValue> parameters = nullptr;
+  if (!parametersAsJson.empty()) {
+    CefRefPtr<CefValue> value = CefParseJSON(
+        parametersAsJson, cef_json_parser_options_t::JSON_PARSER_RFC);
+
+    if (!value || value->GetType() != VTYPE_DICTIONARY) {
+      callback->onComplete(0);
+      return;
+    }
+
+    parameters = value->GetDictionary();
+  }
+
+  callback->onComplete(host->ExecuteDevToolsMethod(0, method, parameters));
+}
+
 // Removed because we don't care about when the native parent window changes.
 // This fixes a compile issue on macOS - ds58
 //void OnAfterParentChanged(CefRefPtr<CefBrowser> browser) {
@@ -1014,21 +1050,6 @@ void getZoomLevel(CefRefPtr<CefBrowserHost> host,
 //  }
 //}
 
-jobject NewJNILongVector(JNIEnv* env, const std::vector<int64_t>& vals) {
-  ScopedJNIObjectLocal jvector(env, "java/util/Vector");
-  if (!jvector)
-    return nullptr;
-
-  std::vector<int64_t>::const_iterator iter;
-  for (iter = vals.begin(); iter != vals.end(); ++iter) {
-    ScopedJNIObjectLocal argument(
-        env, NewJNIObject(env, "java/lang/Long", "(J)V", (jlong)*iter));
-    JNI_CALL_VOID_METHOD(env, jvector, "addElement", "(Ljava/lang/Object;)V",
-                         argument.get());
-  }
-  return jvector.Release();
-}
-
 CefPdfPrintSettings GetJNIPdfPrintSettings(JNIEnv* env, jobject obj) {
   CefString tmp;
   CefPdfPrintSettings settings;
@@ -1099,6 +1120,16 @@ CefPdfPrintSettings GetJNIPdfPrintSettings(JNIEnv* env, jobject obj) {
   return settings;
 }
 
+// JNI CefRegistration object.
+class ScopedJNIRegistration : public ScopedJNIObject<CefRegistration> {
+ public:
+  ScopedJNIRegistration(JNIEnv* env, CefRefPtr<CefRegistration> obj)
+      : ScopedJNIObject<CefRegistration>(env,
+                                         obj,
+                                         "org/cef/browser/CefRegistration_N",
+                                         "CefRegistration") {}
+};
+
 }  // namespace
 
 JNIEXPORT jboolean JNICALL
@@ -1109,9 +1140,12 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv* env,
                                                     jstring url,
                                                     jboolean osr,
                                                     jboolean transparent,
-                                                    jobject jcontext) {
-  std::shared_ptr<JNIObjectsForCreate> objs(new JNIObjectsForCreate(
-      env, jbrowser, nullptr, jclientHandler, url, jcontext, nullptr));
+                                                    jobject canvas,
+                                                    jobject jcontext,
+                                                    jobject browserSettings) {
+  std::shared_ptr<JNIObjectsForCreate> objs(
+      new JNIObjectsForCreate(env, jbrowser, nullptr, jclientHandler, url,
+                              canvas, jcontext, nullptr, browserSettings));
   if (CefCurrentlyOn(TID_UI)) {
     create(objs, windowHandle, osr, transparent);
   } else {
@@ -1129,10 +1163,11 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv* env,
                                                      jlong windowHandle,
                                                      jboolean osr,
                                                      jboolean transparent,
+                                                     jobject canvas,
                                                      jobject inspect) {
   std::shared_ptr<JNIObjectsForCreate> objs(
       new JNIObjectsForCreate(env, jbrowser, jparent, jclientHandler, nullptr,
-                              nullptr, inspect));
+                              canvas, nullptr, inspect, nullptr));
   if (CefCurrentlyOn(TID_UI)) {
     create(objs, windowHandle, osr, transparent);
   } else {
@@ -1142,6 +1177,52 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv* env,
   return JNI_FALSE;  // set asynchronously
 }
 
+JNIEXPORT void JNICALL
+Java_org_cef_browser_CefBrowser_1N_N_1ExecuteDevToolsMethod(
+    JNIEnv* env,
+    jobject jbrowser,
+    jstring method,
+    jstring parametersAsJson,
+    jobject jcallback) {
+  CefRefPtr<IntCallback> callback = new IntCallback(env, jcallback);
+
+  CefRefPtr<CefBrowser> browser = GetJNIBrowser(env, jbrowser);
+  if (!browser.get()) {
+    callback->onComplete(0);
+    return;
+  }
+
+  CefString strMethod = GetJNIString(env, method);
+  CefString strParametersAsJson = GetJNIString(env, parametersAsJson);
+
+  if (CefCurrentlyOn(TID_UI)) {
+    executeDevToolsMethod(browser->GetHost(), strMethod, strParametersAsJson,
+                          callback);
+  } else {
+    CefPostTask(TID_UI,
+                base::BindOnce(executeDevToolsMethod, browser->GetHost(),
+                               strMethod, strParametersAsJson, callback));
+  }
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_cef_browser_CefBrowser_1N_N_1AddDevToolsMessageObserver(
+    JNIEnv* env,
+    jobject jbrowser,
+    jobject jobserver) {
+  CefRefPtr<CefBrowser> browser =
+      JNI_GET_BROWSER_OR_RETURN(env, jbrowser, NULL);
+
+  CefRefPtr<DevToolsMessageObserver> observer =
+      new DevToolsMessageObserver(env, jobserver);
+
+  CefRefPtr<CefRegistration> registration =
+      browser->GetHost()->AddDevToolsMessageObserver(observer);
+
+  ScopedJNIRegistration jregistration(env, registration);
+  return jregistration.Release();
+}
+
 JNIEXPORT jlong JNICALL
 Java_org_cef_browser_CefBrowser_1N_N_1GetWindowHandle(JNIEnv* env,
                                                       jobject obj,
@@ -1237,11 +1318,12 @@ Java_org_cef_browser_CefBrowser_1N_N_1GetFocusedFrame(JNIEnv* env,
 }
 
 JNIEXPORT jobject JNICALL
-Java_org_cef_browser_CefBrowser_1N_N_1GetFrame(JNIEnv* env,
-                                               jobject obj,
-                                               jlong identifier) {
+Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByIdentifier(JNIEnv* env,
+                                                           jobject obj,
+                                                           jstring identifier) {
   CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr);
-  CefRefPtr<CefFrame> frame = browser->GetFrame(identifier);
+  CefRefPtr<CefFrame> frame =
+      browser->GetFrameByIdentifier(GetJNIString(env, identifier));
   if (!frame)
     return nullptr;
   ScopedJNIFrame jframe(env, frame);
@@ -1249,11 +1331,11 @@ Java_org_cef_browser_CefBrowser_1N_N_1GetFrame(JNIEnv* env,
 }
 
 JNIEXPORT jobject JNICALL
-Java_org_cef_browser_CefBrowser_1N_N_1GetFrame2(JNIEnv* env,
-                                                jobject obj,
-                                                jstring name) {
+Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByName(JNIEnv* env,
+                                                     jobject obj,
+                                                     jstring name) {
   CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr);
-  CefRefPtr<CefFrame> frame = browser->GetFrame(GetJNIString(env, name));
+  CefRefPtr<CefFrame> frame = browser->GetFrameByName(GetJNIString(env, name));
   if (!frame)
     return nullptr;
   ScopedJNIFrame jframe(env, frame);
@@ -1270,9 +1352,9 @@ JNIEXPORT jobject JNICALL
 Java_org_cef_browser_CefBrowser_1N_N_1GetFrameIdentifiers(JNIEnv* env,
                                                           jobject obj) {
   CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr);
-  std::vector<int64_t> identifiers;
+  std::vector<CefString> identifiers;
   browser->GetFrameIdentifiers(identifiers);
-  return NewJNILongVector(env, identifiers);
+  return NewJNIStringVector(env, identifiers);
 }
 
 JNIEXPORT jobject JNICALL
@@ -1994,3 +2076,38 @@ Java_org_cef_browser_CefBrowser_1N_N_1NotifyMoveOrResizeStarted(JNIEnv* env,
   }
 #endif
 }
+
+JNIEXPORT void JNICALL
+Java_org_cef_browser_CefBrowser_1N_N_1SetWindowlessFrameRate(JNIEnv* env,
+                                                             jobject jbrowser,
+                                                             jint frameRate) {
+  CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, jbrowser);
+  CefRefPtr<CefBrowserHost> host = browser->GetHost();
+  host->SetWindowlessFrameRate(frameRate);
+}
+
+void getWindowlessFrameRate(CefRefPtr<CefBrowserHost> host,
+                            CefRefPtr<IntCallback> callback) {
+  callback->onComplete((jint)host->GetWindowlessFrameRate());
+}
+
+JNIEXPORT void JNICALL
+Java_org_cef_browser_CefBrowser_1N_N_1GetWindowlessFrameRate(
+    JNIEnv* env,
+    jobject jbrowser,
+    jobject jintCallback) {
+  CefRefPtr<IntCallback> callback = new IntCallback(env, jintCallback);
+
+  CefRefPtr<CefBrowser> browser = GetJNIBrowser(env, jbrowser);
+  if (!browser.get()) {
+    callback->onComplete(0);
+    return;
+  }
+
+  CefRefPtr<CefBrowserHost> host = browser->GetHost();
+  if (CefCurrentlyOn(TID_UI)) {
+    getWindowlessFrameRate(host, callback);
+  } else {
+    CefPostTask(TID_UI, base::BindOnce(getWindowlessFrameRate, host, callback));
+  }
+}
diff --git a/native/CefBrowser_N.h b/native/CefBrowser_N.h
index bd0fd0d0..c2e4af9b 100644
--- a/native/CefBrowser_N.h
+++ b/native/CefBrowser_N.h
@@ -11,7 +11,7 @@ extern "C" {
  * Class:     org_cef_browser_CefBrowser_N
  * Method:    N_CreateBrowser
  * Signature:
- * (Lorg/cef/handler/CefClientHandler;JLjava/lang/String;ZZLjava/awt/Component;Lorg/cef/browser/CefRequestContext;)Z
+ * (Lorg/cef/handler/CefClientHandler;JLjava/lang/String;ZZLjava/awt/Component;Lorg/cef/browser/CefRequestContext;Lorg/cef/CefBrowserSettings;)Z
  */
 JNIEXPORT jboolean JNICALL
 Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv*,
@@ -21,6 +21,8 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv*,
                                                     jstring,
                                                     jboolean,
                                                     jboolean,
+                                                    jobject,
+                                                    jobject,
                                                     jobject);
 
 /*
@@ -39,6 +41,30 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv*,
                                                      jboolean,
                                                      jobject);
 
+/*
+ * Class:     org_cef_browser_CefBrowser_N
+ * Method:    N_ExecuteDevToolsMethod
+ * Signature:
+ * (Ljava/lang/String;Ljava/lang/String;Lorg/cef/browser/CefBrowser_N/IntCallback;)V
+ */
+JNIEXPORT void JNICALL
+Java_org_cef_browser_CefBrowser_1N_N_1ExecuteDevToolsMethod(JNIEnv*,
+                                                            jobject,
+                                                            jstring,
+                                                            jstring,
+                                                            jobject);
+
+/*
+ * Class:     org_cef_browser_CefBrowser_N
+ * Method:    N_AddDevToolsMessageObserver
+ * Signature:
+ * (Lorg/cef/browser/CefDevToolsMessageObserver;)Lorg/cef/browser/CefRegistration;
+ */
+JNIEXPORT jobject JNICALL
+Java_org_cef_browser_CefBrowser_1N_N_1AddDevToolsMessageObserver(JNIEnv*,
+                                                                 jobject,
+                                                                 jobject);
+
 /*
  * Class:     org_cef_browser_CefBrowser_N
  * Method:    N_GetWindowHandle
@@ -151,6 +177,24 @@ Java_org_cef_browser_CefBrowser_1N_N_1GetFrame(JNIEnv*, jobject, jlong);
 JNIEXPORT jobject JNICALL
 Java_org_cef_browser_CefBrowser_1N_N_1GetFrame2(JNIEnv*, jobject, jstring);
 
+/*
+ * Class:     org_cef_browser_CefBrowser_N
+ * Method:    N_GetFrameByIdentifier
+ * Signature: (Ljava/lang/String;)Lorg/cef/browser/CefFrame;
+ */
+JNIEXPORT jobject JNICALL
+Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByIdentifier(JNIEnv*,
+                                                           jobject,
+                                                           jstring);
+
+/*
+ * Class:     org_cef_browser_CefBrowser_N
+ * Method:    N_GetFrameByName
+ * Signature: (Ljava/lang/String;)Lorg/cef/browser/CefFrame;
+ */
+JNIEXPORT jobject JNICALL
+Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByName(JNIEnv*, jobject, jstring);
+
 /*
  * Class:     org_cef_browser_CefBrowser_N
  * Method:    N_GetFrameIdentifiers
@@ -346,7 +390,7 @@ Java_org_cef_browser_CefBrowser_1N_N_1PrintToPDF(JNIEnv*,
 /*
  * Class:     org_cef_browser_CefBrowser_N
  * Method:    N_Find
- * Signature: (ILjava/lang/String;ZZZ)V
+ * Signature: (Ljava/lang/String;ZZZ)V
  */
 JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1Find(JNIEnv*,
                                                                   jobject,
@@ -507,7 +551,37 @@ JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1UpdateUI(JNIEnv*,
 JNIEXPORT void JNICALL
 Java_org_cef_browser_CefBrowser_1N_N_1NotifyMoveOrResizeStarted(JNIEnv*,
                                                                 jobject);
+/*
+ * Class:     org_cef_browser_CefBrowser_N
+ * Method:    N_SetWindowlessFrameRate
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL
+Java_org_cef_browser_CefBrowser_1N_N_1SetWindowlessFrameRate(JNIEnv*,
+                                                             jobject,
+                                                             jint);
 
+/*
+ * Class:     org_cef_browser_CefBrowser_N
+ * Method:    N_GetWindowlessFrameRate
+ * Signature: (Lorg/cef/browser/CefBrowser_N/IntCallback;)V
+ */
+JNIEXPORT void JNICALL
+Java_org_cef_browser_CefBrowser_1N_N_1GetWindowlessFrameRate(JNIEnv*,
+                                                             jobject,
+                                                             jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class org_cef_browser_CefBrowser_N_IntCallback */
+
+#ifndef _Included_org_cef_browser_CefBrowser_N_IntCallback
+#define _Included_org_cef_browser_CefBrowser_N_IntCallback
+#ifdef __cplusplus
+extern "C" {
+#endif
 #ifdef __cplusplus
 }
 #endif
diff --git a/native/CefFileDialogCallback_N.h b/native/CefFileDialogCallback_N.h
index 1f11dae9..1da3ded8 100644
--- a/native/CefFileDialogCallback_N.h
+++ b/native/CefFileDialogCallback_N.h
@@ -10,13 +10,12 @@ extern "C" {
 /*
  * Class:     org_cef_callback_CefFileDialogCallback_N
  * Method:    N_Continue
- * Signature: (JILjava/util/Vector;)V
+ * Signature: (JLjava/util/Vector;)V
  */
 JNIEXPORT void JNICALL
 Java_org_cef_callback_CefFileDialogCallback_1N_N_1Continue(JNIEnv*,
                                                            jobject,
                                                            jlong,
-                                                           jint,
                                                            jobject);
 
 /*
diff --git a/native/CefFrame_N.cpp b/native/CefFrame_N.cpp
index 3fc93790..cab338ed 100644
--- a/native/CefFrame_N.cpp
+++ b/native/CefFrame_N.cpp
@@ -27,14 +27,14 @@ JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Dispose(JNIEnv* env,
   ClearSelf(env, obj);
 }
 
-JNIEXPORT jlong JNICALL
+JNIEXPORT jstring JNICALL
 Java_org_cef_browser_CefFrame_1N_N_1GetIdentifier(JNIEnv* env,
                                                   jobject obj,
                                                   jlong self) {
   CefRefPtr<CefFrame> frame = GetSelf(self);
   if (!frame)
-    return (jlong)-1;
-  return (jlong)frame->GetIdentifier();
+    return nullptr;
+  return NewJNIString(env, frame->GetIdentifier());
 }
 
 JNIEXPORT jstring JNICALL
@@ -164,3 +164,14 @@ JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Paste(JNIEnv* env,
 
   frame->Paste();
 }
+
+JNIEXPORT void JNICALL
+Java_org_cef_browser_CefFrame_1N_N_1SelectAll(JNIEnv* env,
+                                              jobject obj,
+                                              jlong self) {
+  CefRefPtr<CefFrame> frame = GetSelf(self);
+  if (!frame)
+    return;
+
+  frame->SelectAll();
+}
diff --git a/native/CefFrame_N.h b/native/CefFrame_N.h
index e1f6b459..a1568181 100644
--- a/native/CefFrame_N.h
+++ b/native/CefFrame_N.h
@@ -19,9 +19,9 @@ JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Dispose(JNIEnv*,
 /*
  * Class:     org_cef_browser_CefFrame_N
  * Method:    N_GetIdentifier
- * Signature: (J)J
+ * Signature: (J)Ljava/lang/String;
  */
-JNIEXPORT jlong JNICALL
+JNIEXPORT jstring JNICALL
 Java_org_cef_browser_CefFrame_1N_N_1GetIdentifier(JNIEnv*, jobject, jlong);
 
 /*
@@ -135,6 +135,15 @@ JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Paste(JNIEnv*,
                                                                  jobject,
                                                                  jlong);
 
+/*
+ * Class:     org_cef_browser_CefFrame_N
+ * Method:    N_SelectAll
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1SelectAll(JNIEnv*,
+                                                                     jobject,
+                                                                     jlong);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/native/CefRegistration_N.cpp b/native/CefRegistration_N.cpp
new file mode 100644
index 00000000..dc23751d
--- /dev/null
+++ b/native/CefRegistration_N.cpp
@@ -0,0 +1,14 @@
+// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+#include "CefRegistration_N.h"
+#include "include/cef_registration.h"
+#include "jni_scoped_helpers.h"
+
+JNIEXPORT void JNICALL
+Java_org_cef_browser_CefRegistration_1N_N_1Dispose(JNIEnv* env,
+                                                   jobject obj,
+                                                   jlong self) {
+  SetCefForJNIObject<CefRegistration>(env, obj, NULL, "CefRegistration");
+}
diff --git a/native/CefRegistration_N.h b/native/CefRegistration_N.h
new file mode 100644
index 00000000..9747b04b
--- /dev/null
+++ b/native/CefRegistration_N.h
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_cef_browser_CefRegistration_N */
+
+#ifndef _Included_org_cef_browser_CefRegistration_N
+#define _Included_org_cef_browser_CefRegistration_N
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_cef_browser_CefRegistration_N
+ * Method:    N_Dispose
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_org_cef_browser_CefRegistration_1N_N_1Dispose(JNIEnv*, jobject, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/native/browser_process_handler.cpp b/native/browser_process_handler.cpp
index 38c8fdca..ad583e87 100644
--- a/native/browser_process_handler.cpp
+++ b/native/browser_process_handler.cpp
@@ -50,6 +50,31 @@ void BrowserProcessHandler::OnScheduleMessagePumpWork(int64_t delay_ms) {
                        delay_ms);
 }
 
+bool BrowserProcessHandler::OnAlreadyRunningAppRelaunch(
+    CefRefPtr<CefCommandLine> command_line,
+    const CefString& current_directory) {
+  if (!handle_)
+    return false;
+
+  ScopedJNIEnv env;
+  if (!env)
+    return false;
+
+  ScopedJNIObject<CefCommandLine> jcommandLine(
+      env, command_line, "org/cef/callback/CefCommandLine_N", "CefCommandLine");
+  jcommandLine.SetTemporary();
+  ScopedJNIString jcurrentDirectory(env, current_directory);
+
+  jboolean jresult = 0;
+
+  JNI_CALL_BOOLEAN_METHOD(
+      jresult, env, handle_, "onAlreadyRunningAppRelaunch",
+      "(Lorg/cef/callback/CefCommandLine;Ljava/lang/String;)Z",
+      jcommandLine.get(), jcurrentDirectory.get());
+
+  return jresult;
+}
+
 // static
 CefRefPtr<CefListValue> BrowserProcessHandler::GetMessageRouterConfigs() {
   int idx = 0;
diff --git a/native/browser_process_handler.h b/native/browser_process_handler.h
index 260ebd66..8bbf29e3 100644
--- a/native/browser_process_handler.h
+++ b/native/browser_process_handler.h
@@ -34,6 +34,8 @@ class BrowserProcessHandler : public CefBrowserProcessHandler {
 
   void OnContextInitialized() override;
   void OnScheduleMessagePumpWork(int64_t delay_ms) override;
+  bool OnAlreadyRunningAppRelaunch(CefRefPtr<CefCommandLine> command_line,
+                                   const CefString& current_directory) override;
 
   static CefRefPtr<CefListValue> GetMessageRouterConfigs();
   static void AddMessageRouterConfig(const CefMessageRouterConfig& cfg);
diff --git a/native/context.cpp b/native/context.cpp
index b47a3956..1e4020c1 100644
--- a/native/context.cpp
+++ b/native/context.cpp
@@ -44,6 +44,11 @@ CefSettings GetJNISettings(JNIEnv* env, jobject obj) {
     CefString(&settings.cache_path) = tmp;
     tmp.clear();
   }
+  if (GetJNIFieldString(env, cls, obj, "root_cache_path", &tmp) &&
+      !tmp.empty()) {
+    CefString(&settings.root_cache_path) = tmp;
+    tmp.clear();
+  }
   GetJNIFieldBoolean(env, cls, obj, "persist_session_cookies",
                      &settings.persist_session_cookies);
   if (GetJNIFieldString(env, cls, obj, "user_agent", &tmp) && !tmp.empty()) {
diff --git a/native/devtools_message_observer.cpp b/native/devtools_message_observer.cpp
new file mode 100644
index 00000000..84a47fbf
--- /dev/null
+++ b/native/devtools_message_observer.cpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+#include "devtools_message_observer.h"
+
+#include "jni_util.h"
+
+DevToolsMessageObserver::DevToolsMessageObserver(JNIEnv* env, jobject observer)
+    : handle_(env, observer) {}
+
+void DevToolsMessageObserver::OnDevToolsMethodResult(
+    CefRefPtr<CefBrowser> browser,
+    int message_id,
+    bool success,
+    const void* result,
+    size_t result_size) {
+  ScopedJNIEnv env;
+  if (!env)
+    return;
+
+  ScopedJNIBrowser jbrowser(env, browser);
+  std::string strResult(static_cast<const char*>(result), result_size);
+  JNI_CALL_VOID_METHOD(
+      env, handle_, "onDevToolsMethodResult",
+      "(Lorg/cef/browser/CefBrowser;IZLjava/lang/String;)V", jbrowser.get(),
+      message_id, success ? JNI_TRUE : JNI_FALSE, NewJNIString(env, strResult));
+}
+
+void DevToolsMessageObserver::OnDevToolsEvent(CefRefPtr<CefBrowser> browser,
+                                              const CefString& method,
+                                              const void* params,
+                                              size_t params_size) {
+  ScopedJNIEnv env;
+  if (!env)
+    return;
+  ScopedJNIBrowser jbrowser(env, browser);
+
+  std::string strParams(static_cast<const char*>(params), params_size);
+  JNI_CALL_VOID_METHOD(
+      env, handle_, "onDevToolsEvent",
+      "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;Ljava/lang/String;)V",
+      jbrowser.get(), NewJNIString(env, method), NewJNIString(env, strParams));
+}
diff --git a/native/devtools_message_observer.h b/native/devtools_message_observer.h
new file mode 100644
index 00000000..19e34bb9
--- /dev/null
+++ b/native/devtools_message_observer.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+#ifndef JCEF_NATIVE_DEVTOOLS_MESSAGE_OBSERVER_H_
+#define JCEF_NATIVE_DEVTOOLS_MESSAGE_OBSERVER_H_
+#pragma once
+
+#include <jni.h>
+#include "include/cef_devtools_message_observer.h"
+
+#include "jni_scoped_helpers.h"
+
+// DevToolsMessageObserver implementation.
+class DevToolsMessageObserver : public CefDevToolsMessageObserver {
+ public:
+  DevToolsMessageObserver(JNIEnv* env, jobject observer);
+
+  // CefDevToolsMessageObserver methods
+  virtual void OnDevToolsMethodResult(CefRefPtr<CefBrowser> browser,
+                                      int message_id,
+                                      bool success,
+                                      const void* result,
+                                      size_t result_size) override;
+  virtual void OnDevToolsEvent(CefRefPtr<CefBrowser> browser,
+                               const CefString& method,
+                               const void* params,
+                               size_t params_size) override;
+
+ protected:
+  ScopedJNIObjectGlobal handle_;
+
+  // Include the default reference counting implementation.
+  IMPLEMENT_REFCOUNTING(DevToolsMessageObserver);
+};
+
+#endif  // JCEF_NATIVE_DEVTOOLS_MESSAGE_OBSERVER_H_
diff --git a/native/display_handler.cpp b/native/display_handler.cpp
index 60874291..13dcd9de 100644
--- a/native/display_handler.cpp
+++ b/native/display_handler.cpp
@@ -41,6 +41,18 @@ void DisplayHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
                        jbrowser.get(), jtitle.get());
 }
 
+void DisplayHandler::OnFullscreenModeChange(CefRefPtr<CefBrowser> browser,
+                                            bool fullscreen) {
+  ScopedJNIEnv env;
+  if (!env)
+    return;
+
+  ScopedJNIBrowser jbrowser(env, browser);
+  JNI_CALL_VOID_METHOD(env, handle_, "OnFullscreenModeChange",
+                       "(Lorg/cef/browser/CefBrowser;Z)V", jbrowser.get(),
+                       (jboolean)fullscreen);
+}
+
 bool DisplayHandler::OnTooltip(CefRefPtr<CefBrowser> browser, CefString& text) {
   ScopedJNIEnv env;
   if (!env)
diff --git a/native/display_handler.h b/native/display_handler.h
index 3b015b62..30615fdb 100644
--- a/native/display_handler.h
+++ b/native/display_handler.h
@@ -23,6 +23,8 @@ class DisplayHandler : public CefDisplayHandler {
                        const CefString& url) override;
   void OnTitleChange(CefRefPtr<CefBrowser> browser,
                      const CefString& title) override;
+  void OnFullscreenModeChange(CefRefPtr<CefBrowser> browser,
+                              bool fullscreen) override;
   bool OnTooltip(CefRefPtr<CefBrowser> browser, CefString& text) override;
   void OnStatusMessage(CefRefPtr<CefBrowser> browser,
                        const CefString& value) override;
diff --git a/native/int_callback.cpp b/native/int_callback.cpp
new file mode 100644
index 00000000..a45471a4
--- /dev/null
+++ b/native/int_callback.cpp
@@ -0,0 +1,20 @@
+// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+#include "int_callback.h"
+
+#include "jni_scoped_helpers.h"
+#include "jni_util.h"
+#include "util.h"
+
+IntCallback::IntCallback(JNIEnv* env, jobject jcallback)
+    : handle_(env, jcallback) {}
+
+void IntCallback::onComplete(int value) {
+  ScopedJNIEnv env;
+  if (!env)
+    return;
+
+  JNI_CALL_VOID_METHOD(env, handle_, "onComplete", "(I)V", (jint)value);
+}
diff --git a/native/int_callback.h b/native/int_callback.h
new file mode 100644
index 00000000..6437479c
--- /dev/null
+++ b/native/int_callback.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+#ifndef JCEF_NATIVE_INT_CALLBACK_H_
+#define JCEF_NATIVE_INT_CALLBACK_H_
+#pragma once
+
+#include <jni.h>
+
+#include "jni_scoped_helpers.h"
+
+// Callback for returning int primatives. The methods of
+// this class will be called on the browser process UI thread.
+class IntCallback : public virtual CefBaseRefCounted {
+ public:
+  IntCallback(JNIEnv* env, jobject jcallback);
+
+  virtual void onComplete(int value);
+
+ protected:
+  ScopedJNIObjectGlobal handle_;
+
+  // Include the default reference counting implementation.
+  IMPLEMENT_REFCOUNTING(IntCallback);
+};
+
+#endif  // JCEF_NATIVE_INT_CALLBACK_H_
diff --git a/native/jni_util.cpp b/native/jni_util.cpp
index 9aacfd59..ef5e6559 100644
--- a/native/jni_util.cpp
+++ b/native/jni_util.cpp
@@ -632,18 +632,10 @@ jobject NewJNIErrorCode(JNIEnv* env, cef_errorcode_t errorCode) {
                ERR_CONTENT_DECODING_INIT_FAILED, jerrorCode);
       JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode",
                ERR_HTTP2_RST_STREAM_NO_ERROR_RECEIVED, jerrorCode);
-      JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode",
-               ERR_HTTP2_PUSHED_STREAM_NOT_AVAILABLE, jerrorCode);
-      JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode",
-               ERR_HTTP2_CLAIMED_PUSHED_STREAM_RESET_BY_SERVER, jerrorCode);
       JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode",
                ERR_TOO_MANY_RETRIES, jerrorCode);
       JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode",
                ERR_HTTP2_STREAM_CLOSED, jerrorCode);
-      JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode",
-               ERR_HTTP2_CLIENT_REFUSED_STREAM, jerrorCode);
-      JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode",
-               ERR_HTTP2_PUSHED_RESPONSE_DOES_NOT_MATCH, jerrorCode);
       JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode",
                ERR_HTTP_RESPONSE_CODE_FAILURE, jerrorCode);
       JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode",
diff --git a/native/request_handler.cpp b/native/request_handler.cpp
index 9d6b89e3..26d50dbd 100644
--- a/native/request_handler.cpp
+++ b/native/request_handler.cpp
@@ -120,8 +120,8 @@ bool RequestHandler::GetAuthCredentials(CefRefPtr<CefBrowser> browser,
   ScopedJNIBrowser jbrowser(env, browser);
   ScopedJNIString joriginUrl(env, origin_url);
   ScopedJNIString jhost(env, host);
-  ScopedJNIString jrealm(env, host);
-  ScopedJNIString jscheme(env, host);
+  ScopedJNIString jrealm(env, realm);
+  ScopedJNIString jscheme(env, scheme);
   ScopedJNIAuthCallback jcallback(env, callback);
   jboolean jresult = JNI_FALSE;
 
diff --git a/tools/make_all_jni_headers.bat b/tools/make_all_jni_headers.bat
index 3f101d3a..ecb1dee0 100644
--- a/tools/make_all_jni_headers.bat
+++ b/tools/make_all_jni_headers.bat
@@ -37,6 +37,7 @@ call make_jni_header.bat %1 org.cef.callback.CefQueryCallback_N
 call make_jni_header.bat %1 org.cef.callback.CefSchemeRegistrar_N
 call make_jni_header.bat %1 org.cef.handler.CefClientHandler
 call make_jni_header.bat %1 org.cef.misc.CefPrintSettings_N
+call make_jni_header.bat %1 org.cef.browser.CefRegistration_N
 call make_jni_header.bat %1 org.cef.network.CefCookieManager_N
 call make_jni_header.bat %1 org.cef.network.CefPostData_N
 call make_jni_header.bat %1 org.cef.network.CefPostDataElement_N