diff --git a/.gitignore b/.gitignore index e7bc7d07..dcaa1219 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,4 @@ Thumbs.db /tools/buildtools/linux64/clang-format /tools/buildtools/mac/clang-format /tools/buildtools/win/clang-format.exe +/target/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f7cc449..d98e7c93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,14 +130,20 @@ set_property(GLOBAL PROPERTY OS_FOLDERS ON) # Specify the CEF distribution version. if(NOT DEFINED CEF_VERSION) - set(CEF_VERSION "100.0.14+g4e5ba66+chromium-100.0.4896.75") + set(CEF_VERSION "141.0.10+g1d65b0d+chromium-141.0.7390.123") endif() # Determine the platform. if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") if("${PROJECT_ARCH}" STREQUAL "arm64") set(CEF_PLATFORM "macosarm64") + elseif("${PROJECT_ARCH}" STREQUAL "x86_64") + set(CEF_PLATFORM "macosx64") + elseif("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "arm64") + set(PROJECT_ARCH "arm64") + set(CEF_PLATFORM "macosarm64") else() + set(PROJECT_ARCH "x86_64") set(CEF_PLATFORM "macosx64") endif() elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") @@ -192,6 +198,20 @@ endif() message(STATUS "Using Python: ${PYTHON_EXECUTABLE}") +# +# Enactor custom tweak. +# + +# In order to fix the macos compilation issue with latest xcode +# cef_mac.h line 63 has been commented. This modified file should be copied from the enactor folder + +if(OS_MACOSX) + message("MacOS copy cef_mac.h...") + execute_process( + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_SOURCE_DIR}/enactor/cef_mac.h + ${CEF_ROOT}/include/internal/cef_mac.h) +endif() # # Java configuration. @@ -258,12 +278,19 @@ file(COPY "${CEF_ROOT}/README.txt" DESTINATION "${CMAKE_BINARY_DIR}") if(OS_WINDOWS) set(GS_PLATFORM "win32") set(GS_HASHPATH "win/clang-format.exe.sha1") + set(GS_OUTPATH "win/clang-format.exe") elseif(OS_MACOSX) set(GS_PLATFORM "darwin") - set(GS_HASHPATH "mac/clang-format.sha1") + if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "arm64") + set(GS_HASHPATH "mac/clang-format.arm64.sha1") + else() + set(GS_HASHPATH "mac/clang-format.x64.sha1") + endif() + set(GS_OUTPATH "mac/clang-format") elseif(OS_LINUX) set(GS_PLATFORM "linux*") set(GS_HASHPATH "linux64/clang-format.sha1") + set(GS_OUTPATH "linux64/clang-format") endif() message(STATUS "Downloading clang-format from Google Storage...") @@ -275,6 +302,7 @@ execute_process( "--no_auth" "--bucket" "chromium-clang-format" "-s" "tools/buildtools/${GS_HASHPATH}" + "-o" "tools/buildtools/${GS_OUTPATH}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} RESULT_VARIABLE EXECUTE_RV ) @@ -302,3 +330,14 @@ message(STATUS "Python executable: ${PYTHON_EXECUTABLE}") message(STATUS "Java directory: ${JAVA_DIR}") message(STATUS "JNI libraries: ${JNI_LIBRARIES}") message(STATUS "JNI include directories: ${JNI_INCLUDE_DIRS}") + +# Enactor manifest generation + +string(REGEX REPLACE ".*chromium-([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+).*" "\\1" + CMAKE_CHROMIUM_VERSION "${CEF_VERSION}") + +set(xml_path "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/manifest.xml") +set(chromium.version "${CMAKE_CHROMIUM_VERSION}") +set(jcef.version "${JCEF_VERSION}") +configure_file("manifest.xml.in" "manifest.xml") + diff --git a/README.md b/README.md index b0f854d4..ea351ea3 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ The Java Chromium Embedded Framework (JCEF) is a simple framework for embedding * Building JCEF - https://bitbucket.org/chromiumembedded/java-cef/wiki/BranchesAndBuilding * Support Forum - http://magpcss.org/ceforum/viewforum.php?f=17 +* Issue Tracker - https://github.com/chromiumembedded/java-cef/issues * Downloads - https://github.com/jcefmaven/jcefbuild * Maven/Gradle Artifacts - https://github.com/jcefmaven/jcefmaven * Donations - http://www.magpcss.org/ceforum/donate.php @@ -29,7 +30,7 @@ The JCEF project is an extension of the Chromium Embedded Framework (CEF) projec JCEF is still very much a work in progress. Some ways that you can help out: -\- Vote for issues in the [JCEF issue tracker](https://bitbucket.org/chromiumembedded/java-cef/issues?status=new&status=open) that are important to you. This helps with development prioritization. +\- Vote for issues in the [JCEF issue tracker](https://github.com/chromiumembedded/java-cef/issues) that are important to you. This helps with development prioritization. \- Report any bugs that you find or feature requests that are important to you. Make sure to first search for existing issues before creating new ones. Please use the [JCEF Forum](http://magpcss.org/ceforum/viewforum.php?f=17) and not the issue tracker for usage questions. Each JCEF issue should: @@ -40,7 +41,7 @@ JCEF is still very much a work in progress. Some ways that you can help out: \- Write unit tests for new or existing functionality. -\- Pull requests and patches are welcome. View open issues in the [JCEF issue tracker](https://bitbucket.org/chromiumembedded/java-cef/issues?status=new&status=open) or search for TODO(cef) in the source code for ideas. +\- Pull requests and patches are welcome. View open issues in the [JCEF issue tracker](https://github.com/chromiumembedded/java-cef/issues) or search for TODO(cef) in the source code for ideas. If you would like to contribute source code changes to JCEF please follow the below guidelines: @@ -51,4 +52,4 @@ If you would like to contribute source code changes to JCEF please follow the be * Be submitted against the current [JCEF master branch](https://bitbucket.org/chromiumembedded/java-cef/src/?at=master) unless explicitly fixing a bug in a CEF release branch. * Follow the style of existing JCEF source files. In general JCEF uses the [Chromium coding style](http://www.chromium.org/developers/coding-style). * Include new or modified unit tests as appropriate to the functionality. -* Not include unnecessary or unrelated changes. \ No newline at end of file +* Not include unnecessary or unrelated changes. diff --git a/assemble-linux.xml b/assemble-linux.xml new file mode 100644 index 00000000..f32ffb35 --- /dev/null +++ b/assemble-linux.xml @@ -0,0 +1,28 @@ + + + java-cef + + zip + + false + + + + ${basedir}/binary_distrib/${distribution.folder}/bin/lib/${distribution.folder} + + **/* + + + + + + ${basedir}/jcef_build/manifest.xml + + + + diff --git a/assemble-mac-os.xml b/assemble-mac-os.xml new file mode 100644 index 00000000..799bb8a4 --- /dev/null +++ b/assemble-mac-os.xml @@ -0,0 +1,28 @@ + + + java-cef + + zip + + false + + + + ${basedir}/jcef_build/native/Release + + **/* + + + + + + ${basedir}/jcef_build/manifest.xml + + + + diff --git a/assemble-striped-linux.xml b/assemble-striped-linux.xml new file mode 100644 index 00000000..88a34aa9 --- /dev/null +++ b/assemble-striped-linux.xml @@ -0,0 +1,35 @@ + + + java-cef + + zip + + false + + + + ${basedir}/binary_distrib/${distribution.folder}/bin/lib/${distribution.folder} + + * + strip/* + + + libcef.so + libEGL.so + libGLESv2.so + libjcef.so + + + + + + ${basedir}/jcef_build/manifest.xml + + + + diff --git a/assemble-windows.xml b/assemble-windows.xml new file mode 100644 index 00000000..87b45adb --- /dev/null +++ b/assemble-windows.xml @@ -0,0 +1,30 @@ + + + java-cef + + zip + + false + + + + + + ${basedir}/binary_distrib/${distribution.folder}/bin/lib/${distribution.folder} + + **/* + + + + + + ${basedir}/jcef_build/manifest.xml + + + + diff --git a/enactor/cef_mac.h b/enactor/cef_mac.h new file mode 100644 index 00000000..899eb94f --- /dev/null +++ b/enactor/cef_mac.h @@ -0,0 +1,115 @@ +// Copyright (c) 2010 Marshall A. Greenblatt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CEF_INCLUDE_INTERNAL_CEF_MAC_H_ +#define CEF_INCLUDE_INTERNAL_CEF_MAC_H_ +#pragma once + +#include "include/internal/cef_types_mac.h" +#include "include/internal/cef_types_wrappers.h" + +// Handle types. +#define CefCursorHandle cef_cursor_handle_t +#define CefEventHandle cef_event_handle_t +#define CefWindowHandle cef_window_handle_t + +/// +/// Class representing CefExecuteProcess arguments. +/// +class CefMainArgs : public cef_main_args_t { + public: + CefMainArgs() : cef_main_args_t{} {} + CefMainArgs(const cef_main_args_t& r) : cef_main_args_t(r) {} + CefMainArgs(int argc_arg, char** argv_arg) + : cef_main_args_t{argc_arg, argv_arg} {} +}; + +struct CefWindowInfoTraits { + typedef cef_window_info_t struct_type; + + static inline void init(struct_type* s) { s->size = sizeof(struct_type); } + + static inline void clear(struct_type* s) { + cef_string_clear(&s->window_name); + } + + static inline void set(const struct_type* src, + struct_type* target, + bool copy) { + cef_string_set(src->window_name.str, src->window_name.length, + &target->window_name, copy); + target->bounds = src->bounds; + target->hidden = src->hidden; + target->parent_view = src->parent_view; + target->windowless_rendering_enabled = src->windowless_rendering_enabled; + target->shared_texture_enabled = src->shared_texture_enabled; + target->external_begin_frame_enabled = src->external_begin_frame_enabled; + target->view = src->view; + target->runtime_style = src->runtime_style; + } +}; + +/// +/// Class representing window information. +/// +class CefWindowInfo : public CefStructBase { + public: + using base_type = CefStructBase; + using base_type::CefStructBase; + using base_type::operator=; + + /// + /// Create the browser as a child view. + /// + void SetAsChild(CefWindowHandle parent, const CefRect& bounds) { + parent_view = parent; + this->bounds = bounds; + hidden = false; + } + + /// + /// Create the browser using windowless (off-screen) rendering. No view + /// will be created for the browser and all rendering will occur via the + /// CefRenderHandler interface. The |parent| value will be used to identify + /// monitor info and to act as the parent view for dialogs, context menus, + /// etc. If |parent| is not provided then the main screen monitor will be used + /// and some functionality that requires a parent view may not function + /// correctly. In order to create windowless browsers the + /// CefSettings.windowless_rendering_enabled value must be set to true. + /// Transparent painting is enabled by default but can be disabled by setting + /// CefBrowserSettings.background_color to an opaque value. + /// + void SetAsWindowless(CefWindowHandle parent) { + windowless_rendering_enabled = true; + parent_view = parent; + runtime_style = CEF_RUNTIME_STYLE_ALLOY; + } +}; + +#endif // CEF_INCLUDE_INTERNAL_CEF_MAC_H_ diff --git a/java/org/cef/CefApp.java b/java/org/cef/CefApp.java index afd10f04..e623b834 100644 --- a/java/org/cef/CefApp.java +++ b/java/org/cef/CefApp.java @@ -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 @@ -424,7 +430,11 @@ public void run() { } } - if (N_Initialize(appHandler_, settings)) setState(CefAppState.INITIALIZED); + if (N_Initialize(appHandler_, settings)) { + setState(CefAppState.INITIALIZED); + } else { + setState(CefAppState.INITIALIZATION_FAILED); + } } }; if (SwingUtilities.isEventDispatchThread()) 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 f72b4d19..687be93d 100644 --- a/java/org/cef/CefClient.java +++ b/java/org/cef/CefClient.java @@ -4,11 +4,7 @@ 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.browser.*; import org.cef.callback.CefAuthCallback; import org.cef.callback.CefBeforeDownloadCallback; import org.cef.callback.CefCallback; @@ -60,6 +56,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Vector; +import java.util.function.Consumer; import javax.swing.SwingUtilities; @@ -141,7 +138,16 @@ public CefBrowser createBrowser(String url, boolean isOffscreenRendered, boolean CefRequestContext context) { if (isDisposed_) throw new IllegalStateException("Can't create browser. CefClient is disposed"); - return CefBrowserFactory.create(this, url, isOffscreenRendered, isTransparent, context); + return CefBrowserFactory.create( + this, url, isOffscreenRendered, isTransparent, context, null); + } + + 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, isOffscreenRendered, isTransparent, context, settings); } @Override @@ -274,11 +280,11 @@ public void removeDialogHandler() { @Override public boolean onFileDialog(CefBrowser browser, FileDialogMode mode, String title, - String defaultFilePath, Vector acceptFilters, int selectedAcceptFilter, - CefFileDialogCallback callback) { + String defaultFilePath, Vector acceptFilters, Vector acceptExtensions, + Vector acceptDescriptions, CefFileDialogCallback callback) { if (dialogHandler_ != null && browser != null) { return dialogHandler_.onFileDialog(browser, mode, title, defaultFilePath, acceptFilters, - selectedAcceptFilter, callback); + acceptExtensions, acceptDescriptions, callback); } return false; } @@ -306,6 +312,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) { @@ -360,10 +372,12 @@ public void removeDownloadHandler() { } @Override - public void onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem, + public boolean onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem, String suggestedName, CefBeforeDownloadCallback callback) { if (downloadHandler_ != null && browser != null) - downloadHandler_.onBeforeDownload(browser, downloadItem, suggestedName, callback); + return downloadHandler_.onBeforeDownload( + browser, downloadItem, suggestedName, callback); + return false; } @Override @@ -754,6 +768,15 @@ public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, realHandler.onPaint(browser, popup, dirtyRects, buffer, width, height); } + @Override + public void addOnPaintListener(Consumer listener) {} + + @Override + public void setOnPaintListener(Consumer listener) {} + + @Override + public void removeOnPaintListener(Consumer listener) {} + @Override public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y) { if (browser == null) return false; @@ -820,14 +843,6 @@ public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean return false; } - @Override - public boolean onQuotaRequest( - CefBrowser browser, String origin_url, long new_size, CefCallback callback) { - if (requestHandler_ != null && browser != null) - return requestHandler_.onQuotaRequest(browser, origin_url, new_size, callback); - return false; - } - @Override public boolean onCertificateError( CefBrowser browser, ErrorCode cert_error, String request_url, CefCallback callback) { @@ -837,8 +852,10 @@ public boolean onCertificateError( } @Override - public void onRenderProcessTerminated(CefBrowser browser, TerminationStatus status) { - if (requestHandler_ != null) requestHandler_.onRenderProcessTerminated(browser, status); + public void onRenderProcessTerminated( + CefBrowser browser, TerminationStatus status, int error_code, String error_string) { + if (requestHandler_ != null) + requestHandler_.onRenderProcessTerminated(browser, status, error_code, error_string); } // CefWindowHandler diff --git a/java/org/cef/CefSettings.java b/java/org/cef/CefSettings.java index 5d756d99..a08ff038 100644 --- a/java/org/cef/CefSettings.java +++ b/java/org/cef/CefSettings.java @@ -102,10 +102,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 @@ -181,15 +210,6 @@ public ColorType clone() { */ public String locales_dir_path = null; - /** - * Set to true to disable loading of pack files for resources and locales. - * A resource bundle handler must be provided for the browser and render - * processes via CefApp::GetResourceBundleHandler() if loading of pack files - * is disabled. Also configurable using the "disable-pack-loading" command- - * line switch. - */ - public boolean pack_loading_disabled = false; - /** * Set to a value between 1024 and 65535 to enable remote debugging on the * specified port. For example, if 8080 is specified the remote debugging URL @@ -199,6 +219,22 @@ public ColorType clone() { */ public int remote_debugging_port = 0; + /** + * Specify an ID to enable Chrome policy management via Platform and OS-user + * policies. On Windows, this is a registry key like + * "SOFTWARE\\Policies\\Google\\Chrome". On MacOS, this is a bundle ID like + * "com.google.Chrome". On Linux, this is an absolute directory path like + * "/etc/opt/chrome/policies". Only supported with Chrome style. See + * https://support.google.com/chrome/a/answer/9037717 for details. + * + * Chrome Browser Cloud Management integration, when enabled via the + * "enable-chrome-browser-cloud-management" command-line flag, will also use + * the specified ID. See https://support.google.com/chrome/a/answer/9116814 + * for details. + */ + public String chrome_policy_id; + + /** * The number of stack trace frames to capture for uncaught exceptions. * Specify a positive value to enable the CefV8ContextHandler:: @@ -239,6 +275,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; @@ -248,7 +285,7 @@ public CefSettings clone() { tmp.javascript_flags = javascript_flags; tmp.resources_dir_path = resources_dir_path; tmp.locales_dir_path = locales_dir_path; - tmp.pack_loading_disabled = pack_loading_disabled; + tmp.chrome_policy_id = chrome_policy_id; tmp.remote_debugging_port = remote_debugging_port; tmp.uncaught_exception_stack_size = uncaught_exception_stack_size; if (background_color != null) tmp.background_color = background_color.clone(); 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 14eeab26..29a6b0dc 100644 --- a/java/org/cef/browser/CefBrowser.java +++ b/java/org/cef/browser/CefBrowser.java @@ -49,6 +49,14 @@ public interface CefBrowser { */ public CefRenderHandler getRenderHandler(); + /** + * Retrieves the request context used by this browser instance. May be the + * global request context if this browser does not have a specific request + * context. + */ + public CefRequestContext getRequestContext(); + + /** * Get an implementation of CefWindowHandler if any. * @return An instance of CefWindowHandler or null. @@ -125,20 +133,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 getFrameIdentifiers(); + public Vector getFrameIdentifiers(); /** * Returns the names of all existing frames. @@ -337,18 +345,31 @@ 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 - * embedded within your UI. Only one instance per browser is available. + * Get an instance of the DevTools to be displayed in its own window. */ - public CefBrowser getDevTools(); + public void openDevTools(); /** - * Get an instance of the dev tools to be displayed in its own window or to be - * embedded within your UI. Only one instance per browser is available. + * Open an instance of the DevTools to be displayed in its own window. * * @param inspectAt a position in the UI which should be inspected. */ - public CefBrowser getDevTools(Point inspectAt); + public void openDevTools(Point inspectAt); + + /** + * Close the DevTools. + */ + public void closeDevTools(); + + /** + * 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 @@ -363,7 +384,7 @@ public void runFileDialog(FileDialogMode mode, String title, String defaultFileP *

* If executed on the AWT Event Thread, this returns an immediately resolved {@link * java.util.concurrent.CompletableFuture}. If executed from another thread, the {@link - * java.util.concurrent.CompletableFuture} returned is resolved as soon as the screenshot + * java.util.concurrent.CompletableFuture} returned is resolved as soon as the screenshot * has been taken (which must happen on the event thread). *

* The generated screenshot can either be returned as-is, containing all natively-rendered @@ -380,4 +401,26 @@ public void runFileDialog(FileDialogMode mode, String title, String defaultFileP * @throws UnsupportedOperationException if not supported */ public CompletableFuture 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 getWindowlessFrameRate(); } diff --git a/java/org/cef/browser/CefBrowserFactory.java b/java/org/cef/browser/CefBrowserFactory.java index 708d0f24..299dfcfb 100644 --- a/java/org/cef/browser/CefBrowserFactory.java +++ b/java/org/cef/browser/CefBrowserFactory.java @@ -4,6 +4,7 @@ package org.cef.browser; +import org.cef.CefBrowserSettings; import org.cef.CefClient; /** @@ -11,8 +12,9 @@ */ public class CefBrowserFactory { public static CefBrowser create(CefClient client, String url, boolean isOffscreenRendered, - boolean isTransparent, CefRequestContext context) { - if (isOffscreenRendered) return new CefBrowserOsr(client, url, isTransparent, context); - return new CefBrowserWr(client, url, context); + boolean isTransparent, CefRequestContext context, CefBrowserSettings settings) { + if (isOffscreenRendered) + return new CefBrowserOsr(client, url, isTransparent, context, settings); + return new CefBrowserWr(client, url, context, settings); } } diff --git a/java/org/cef/browser/CefBrowserOsr.java b/java/org/cef/browser/CefBrowserOsr.java index f0672f9b..b999b6ba 100644 --- a/java/org/cef/browser/CefBrowserOsr.java +++ b/java/org/cef/browser/CefBrowserOsr.java @@ -15,6 +15,7 @@ import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.util.GLBuffers; +import org.cef.CefBrowserSettings; import org.cef.CefClient; import org.cef.OS; import org.cef.callback.CefDragData; @@ -60,9 +61,11 @@ import java.util.Arrays; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; import javax.swing.MenuSelectionManager; import javax.swing.SwingUtilities; @@ -84,13 +87,18 @@ class CefBrowserOsr extends CefBrowser_N implements CefRenderHandler { private int depth_per_component = 8; private boolean isTransparent_; - CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context) { - this(client, url, transparent, context, null, null); + private CopyOnWriteArrayList> onPaintListeners = + new CopyOnWriteArrayList<>(); + + 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; renderer_ = new CefRenderer(transparent); createGLCanvas(); @@ -117,7 +125,7 @@ public CefRenderHandler getRenderHandler() { protected CefBrowser_N createDevToolsBrowser(CefClient client, String url, CefRequestContext context, CefBrowser_N parent, Point inspectAt) { return new CefBrowserOsr( - client, url, isTransparent_, context, (CefBrowserOsr) this, inspectAt); + client, url, isTransparent_, context, (CefBrowserOsr) this, inspectAt, null); } private synchronized long getWindowHandle() { @@ -354,6 +362,22 @@ public void onPopupSize(CefBrowser browser, Rectangle size) { renderer_.onPopupSize(size); } + @Override + public void addOnPaintListener(Consumer listener) { + onPaintListeners.add(listener); + } + + @Override + public void setOnPaintListener(Consumer listener) { + onPaintListeners.clear(); + onPaintListeners.add(listener); + } + + @Override + public void removeOnPaintListener(Consumer listener) { + onPaintListeners.remove(listener); + } + @Override public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height) { @@ -376,6 +400,13 @@ public void run() { canvas_.display(); } }); + if (!onPaintListeners.isEmpty()) { + CefPaintEvent paintEvent = + new CefPaintEvent(browser, popup, dirtyRects, buffer, width, height); + for (Consumer l : onPaintListeners) { + l.accept(paintEvent); + } + } } @Override @@ -401,11 +432,25 @@ protected void registerListeners() {} protected void unregisterListeners() {} }; + private static int getDndAction(int mask) { + // Default to copy if multiple operations are specified. + int action = DnDConstants.ACTION_NONE; + if ((mask & CefDragData.DragOperations.DRAG_OPERATION_COPY) + == CefDragData.DragOperations.DRAG_OPERATION_COPY) { + action = DnDConstants.ACTION_COPY; + } else if ((mask & CefDragData.DragOperations.DRAG_OPERATION_MOVE) + == CefDragData.DragOperations.DRAG_OPERATION_MOVE) { + action = DnDConstants.ACTION_MOVE; + } else if ((mask & CefDragData.DragOperations.DRAG_OPERATION_LINK) + == CefDragData.DragOperations.DRAG_OPERATION_LINK) { + action = DnDConstants.ACTION_LINK; + } + return action; + } + @Override public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y) { - int action = (mask & CefDragData.DragOperations.DRAG_OPERATION_MOVE) == 0 - ? DnDConstants.ACTION_COPY - : DnDConstants.ACTION_MOVE; + int action = getDndAction(mask); MouseEvent triggerEvent = new MouseEvent(canvas_, MouseEvent.MOUSE_DRAGGED, 0, 0, x, y, 0, false); DragGestureEvent ev = new DragGestureEvent( @@ -416,7 +461,7 @@ public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, new StringSelection(dragData.getFragmentText()), new DragSourceAdapter() { @Override public void dragDropEnd(DragSourceDropEvent dsde) { - dragSourceEndedAt(dsde.getLocation(), mask); + dragSourceEndedAt(dsde.getLocation(), action); dragSourceSystemDragEnded(); } }); diff --git a/java/org/cef/browser/CefBrowserWr.java b/java/org/cef/browser/CefBrowserWr.java index b142bc5c..677ddce7 100644 --- a/java/org/cef/browser/CefBrowserWr.java +++ b/java/org/cef/browser/CefBrowserWr.java @@ -4,6 +4,7 @@ package org.cef.browser; +import org.cef.CefBrowserSettings; import org.cef.CefClient; import org.cef.OS; import org.cef.handler.CefWindowHandler; @@ -166,14 +167,15 @@ public int getClickCount(int event, int button) { } }; - CefBrowserWr(CefClient client, String url, CefRequestContext context) { - this(client, url, context, null, null); + CefBrowserWr( + CefClient client, String url, CefRequestContext context, CefBrowserSettings settings) { + this(client, url, context, null, null, settings); } @SuppressWarnings("serial") private CefBrowserWr(CefClient client, String url, CefRequestContext context, - CefBrowserWr parent, Point inspectAt) { - super(client, url, context, parent, inspectAt); + CefBrowserWr parent, Point inspectAt, CefBrowserSettings settings) { + super(client, url, context, parent, inspectAt, settings); delayedUpdate_.setRepeats(false); // Disabling lightweight of popup menu is required because @@ -318,7 +320,7 @@ public CefWindowHandler getWindowHandler() { @Override protected CefBrowser_N createDevToolsBrowser(CefClient client, String url, CefRequestContext context, CefBrowser_N parent, Point inspectAt) { - return new CefBrowserWr(client, url, context, (CefBrowserWr) this, inspectAt); + return new CefBrowserWr(client, url, context, (CefBrowserWr) this, inspectAt, null); } private synchronized long getWindowHandle() { @@ -378,7 +380,7 @@ private void doUpdate() { } } else { synchronized (content_rect_) { - Rectangle bounds = component_.getBounds(); + Rectangle bounds = null != canvas_ ? canvas_.getBounds() : component_.getBounds(); content_rect_ = new Rectangle((int) (bounds.getX() * scaleFactor_), (int) (bounds.getY() * scaleFactor_), (int) (bounds.getWidth() * scaleFactor_), @@ -421,4 +423,16 @@ private boolean createBrowserIfRequired(boolean hasParent) { public CompletableFuture createScreenshot(boolean nativeResolution) { throw new UnsupportedOperationException("Unsupported for windowed rendering"); } + + @Override + public void setWindowlessFrameRate(int frameRate) { + throw new UnsupportedOperationException( + "You can only set windowless framerate on OSR browser"); + } + + @Override + public CompletableFuture getWindowlessFrameRate() { + throw new UnsupportedOperationException( + "You can only get windowless framerate on OSR browser"); + } } diff --git a/java/org/cef/browser/CefBrowser_N.java b/java/org/cef/browser/CefBrowser_N.java index 406d0256..c89e2968 100644 --- a/java/org/cef/browser/CefBrowser_N.java +++ b/java/org/cef/browser/CefBrowser_N.java @@ -4,8 +4,9 @@ package org.cef.browser; +import org.cef.CefBrowserSettings; import org.cef.CefClient; -import org.cef.browser.CefRequestContext; +import org.cef.browser.CefDevToolsClient.DevToolsException; import org.cef.callback.CefDragData; import org.cef.callback.CefNativeAdapter; import org.cef.callback.CefPdfPrintCallback; @@ -18,7 +19,6 @@ import org.cef.misc.CefPdfPrintSettings; import org.cef.network.CefRequest; -import java.awt.Canvas; import java.awt.Component; import java.awt.Point; import java.awt.Rectangle; @@ -28,6 +28,7 @@ import java.awt.event.MouseWheelEvent; import java.awt.event.WindowEvent; import java.util.Vector; +import java.util.concurrent.CompletableFuture; import javax.swing.SwingUtilities; @@ -44,26 +45,32 @@ abstract class CefBrowser_N extends CefNativeAdapter implements CefBrowser { private final CefRequestContext request_context_; 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() { return url_; } - protected CefRequestContext getRequestContext() { - return request_context_; + @Override + public CefRequestContext getRequestContext() { + return request_context_ != null ? request_context_ : CefRequestContext.getGlobalContext(); } protected CefBrowser_N getParentBrowser() { @@ -127,22 +134,52 @@ public synchronized void onBeforeClose() { if (request_context_ != null) request_context_.dispose(); if (parent_ != null) { parent_.closeDevTools(); - parent_.devTools_ = null; parent_ = null; } + if (devToolsClient_ != null) { + devToolsClient_.close(); + } + } + + @Override + public void openDevTools() { + openDevTools(null); } @Override - public CefBrowser getDevTools() { - return getDevTools(null); + public synchronized void openDevTools(Point inspectAt) { + createDevToolsBrowser(client_, url_, request_context_, this, inspectAt).createImmediately(); } @Override - public synchronized CefBrowser getDevTools(Point inspectAt) { - if (devTools_ == null) { - devTools_ = createDevToolsBrowser(client_, url_, request_context_, this, inspectAt); + public synchronized CefDevToolsClient getDevToolsClient() { + if (!isPending_ || isClosing_ || isClosed_) { + return null; + } + if (devToolsClient_ == null || devToolsClient_.isClosed()) { + devToolsClient_ = new CefDevToolsClient(this); } - return devTools_; + return devToolsClient_; + } + + CompletableFuture executeDevToolsMethod(String method, String parametersAsJson) { + CompletableFuture 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, @@ -155,8 +192,8 @@ protected void createBrowser(CefClientHandler clientHandler, long windowHandle, boolean osr, boolean transparent, Component canvas, CefRequestContext context) { if (getNativeRef("CefBrowser") == 0 && !isPending_) { try { - N_CreateBrowser( - clientHandler, windowHandle, url, osr, transparent, canvas, context); + N_CreateBrowser(clientHandler, windowHandle, url, osr, transparent, canvas, context, + settings_); } catch (UnsatisfiedLinkError err) { err.printStackTrace(); } @@ -310,9 +347,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; @@ -320,9 +357,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; @@ -330,7 +367,7 @@ public CefFrame getFrame(String name) { } @Override - public Vector getFrameIdentifiers() { + public Vector getFrameIdentifiers() { try { return N_GetFrameIdentifiers(); } catch (UnsatisfiedLinkError ule) { @@ -379,6 +416,7 @@ public boolean hasDocument() { return false; } + @Override public void viewSource() { try { N_ViewSource(); @@ -387,6 +425,7 @@ public void viewSource() { } } + @Override public void getSource(CefStringVisitor visitor) { try { N_GetSource(visitor); @@ -395,6 +434,7 @@ public void getSource(CefStringVisitor visitor) { } } + @Override public void getText(CefStringVisitor visitor) { try { N_GetText(visitor); @@ -550,7 +590,8 @@ public void stopFinding(boolean clearSelection) { } } - protected final void closeDevTools() { + @Override + public void closeDevTools() { try { N_CloseDevTools(); } catch (UnsatisfiedLinkError ule) { @@ -751,11 +792,38 @@ protected final void notifyMoveOrResizeStarted() { } } + public void setWindowlessFrameRate(int frameRate) { + try { + N_SetWindowlessFrameRate(frameRate); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public CompletableFuture getWindowlessFrameRate() { + final CompletableFuture 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, Component canvas, - CefRequestContext context); + CefRequestContext context, CefBrowserSettings settings); private final native boolean N_CreateDevTools(CefBrowser parent, CefClientHandler clientHandler, 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(); @@ -768,9 +836,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 N_GetFrameIdentifiers(); + private final native CefFrame N_GetFrameByIdentifier(String identifier); + private final native CefFrame N_GetFrameByName(String name); + private final native Vector N_GetFrameIdentifiers(); private final native Vector N_GetFrameNames(); private final native int N_GetFrameCount(); private final native boolean N_IsPopup(); @@ -814,4 +882,6 @@ private final native void N_DragTargetDragEnter( 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> queuedCommands_ = + Collections.synchronizedMap(new HashMap<>()); + private final Set 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 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 getQueuedCommand(Integer messageId) { + return queuedCommands_.computeIfAbsent(messageId, key -> new CompletableFuture<>()); + } + + /** + * Execute a method call over the DevTools protocol. See the DevTools protocol documentation + * for details of supported methods and the expected syntax for parameters. + * + *

If an error occurs the returned future is completed exceptionally, otherwise its value is + * asynchronously set to the method result. + * + *

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 executeDevToolsMethod(String method) { + return executeDevToolsMethod(method, null); + } + + /** + * Execute a method call over the DevTools protocol. See the DevTools protocol documentation + * for details of supported methods and the expected syntax for parameters. + * + *

If an error occurs the returned future is completed exceptionally, otherwise its value is + * asynchronously set to the method result. + * + *

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 executeDevToolsMethod(String method, String parametersAsJson) { + if (isClosed()) { + CompletableFuture 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}. + *

+ * 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}. + *

+ * 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/browser/CefRequestContext.java b/java/org/cef/browser/CefRequestContext.java index 26fa66aa..f6998eb1 100644 --- a/java/org/cef/browser/CefRequestContext.java +++ b/java/org/cef/browser/CefRequestContext.java @@ -6,6 +6,9 @@ import org.cef.handler.CefRequestContextHandler; +import java.util.HashMap; +import java.util.Map; + /** * A request context provides request handling for a set of related browser * objects. A request context is specified when creating a new browser object @@ -50,4 +53,48 @@ public static final CefRequestContext createContext(CefRequestContextHandler han * Returns the handler for this context if any. */ public abstract CefRequestContextHandler getHandler(); + + /** + * Returns true if a preference with the specified |name| exists. + *

+ * This method must be called on the browser process UI thread, otherwise it will always return + * false. It is easiest to ensure the correct calling thread by using a callback method invoked + * by the browser process UI thread, such as CefLifeSpanHandler.onAfterCreated(CefBrowser), to + * configure the preferences. + */ + public abstract boolean hasPreference(String name); + + /** + * Returns the value for the preference with the specified |name|. Returns + * NULL if the preference does not exist. + * This method must be called on the browser process UI thread, otherwise it will always return + * null. + */ + public abstract Object getPreference(String name); + + /** + * Returns all preferences as a dictionary. If |includeDefaults| is true then + * preferences currently at their default value will be included. The returned + * object can be modified but modifications will not persist. This method must + * be called on the browser process UI thread, otherwise it will always return null. + */ + public abstract Map getAllPreferences(boolean includeDefaults); + + /** + * Returns true if the preference with the specified |name| can be modified + * using setPreference. As one example preferences set via the command-line + * usually cannot be modified. This method must be called on the browser + * process UI thread, otherwise it will always return false. + */ + public abstract boolean canSetPreference(String name); + + /** + * Set the |value| associated with preference |name|. Returns null if the + * value is set successfully, an error string otherwise. If |value| is NULL the + * preference will be restored to its default value. If setting the preference + * fails then a detailed description of the problem will be returned. + * This method must be called on the browser process UI thread, otherwise it will always return + * an error string. + */ + public abstract String setPreference(String name, Object value); } diff --git a/java/org/cef/browser/CefRequestContext_N.java b/java/org/cef/browser/CefRequestContext_N.java index 622a9ab5..eafdf013 100644 --- a/java/org/cef/browser/CefRequestContext_N.java +++ b/java/org/cef/browser/CefRequestContext_N.java @@ -6,6 +6,10 @@ import org.cef.callback.CefNative; import org.cef.handler.CefRequestContextHandler; +import org.cef.misc.StringRef; + +import java.util.HashMap; +import java.util.Map; class CefRequestContext_N extends CefRequestContext implements CefNative { // Used internally to store a pointer to the CEF object. @@ -73,6 +77,55 @@ public boolean isGlobal() { return false; } + @Override + public boolean hasPreference(String name) { + try { + return N_HasPreference(name); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public Object getPreference(String name) { + try { + return N_GetPreference(name); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public Map getAllPreferences(boolean includeDefaults) { + try { + return N_GetAllPreferences(includeDefaults); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return new HashMap(); + } + + @Override + public boolean canSetPreference(String name) { + try { + return N_CanSetPreference(name); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public String setPreference(String name, Object value) { + try { + return N_SetPreference(name, value); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return ule.getMessage(); + } + } @Override public CefRequestContextHandler getHandler() { return handler; @@ -83,4 +136,13 @@ private final static native CefRequestContext_N N_CreateContext( CefRequestContextHandler handler); private final native boolean N_IsGlobal(); private final native void N_CefRequestContext_DTOR(); + + // ------------------------------------------------------------------------- + // ADDED: Missing native declarations to fix compilation error + // ------------------------------------------------------------------------- + private final native boolean N_HasPreference(String name); + private final native Object N_GetPreference(String name); + private final native Map N_GetAllPreferences(boolean includeDefaults); + private final native boolean N_CanSetPreference(String name); + private final native String N_SetPreference(String name, Object value); } diff --git a/java/org/cef/callback/CefDragData.java b/java/org/cef/callback/CefDragData.java index 0d13029f..25a55471 100644 --- a/java/org/cef/callback/CefDragData.java +++ b/java/org/cef/callback/CefDragData.java @@ -127,6 +127,12 @@ public static final CefDragData create() { */ public abstract boolean getFileNames(Vector names); + /** + * Retrieve the list of file paths that are being dragged into the browser + * window. + */ + public abstract boolean getFilePaths(Vector paths); + /** * Set the link URL that is being dragged. * @param url The link URL to be set. diff --git a/java/org/cef/callback/CefDragData_N.java b/java/org/cef/callback/CefDragData_N.java index 9f6e0fee..e56867d1 100644 --- a/java/org/cef/callback/CefDragData_N.java +++ b/java/org/cef/callback/CefDragData_N.java @@ -179,6 +179,16 @@ public boolean getFileNames(Vector names) { return false; } + @Override + public boolean getFilePaths(Vector paths) { + try { + return N_GetFilePaths(N_CefHandle, paths); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + public void setLinkURL(String url) { try { N_SetLinkURL(N_CefHandle, url); @@ -259,6 +269,7 @@ public void addFile(String path, String displayName) { private final native int N_GetFileContents(long self, OutputStream writer); private final native String N_GetFileName(long self); private final native boolean N_GetFileNames(long self, Vector names); + private final native boolean N_GetFilePaths(long self, Vector paths); private final native void N_SetLinkURL(long self, String url); private final native void N_SetLinkTitle(long self, String title); private final native void N_SetLinkMetadata(long self, String data); diff --git a/java/org/cef/callback/CefFileDialogCallback.java b/java/org/cef/callback/CefFileDialogCallback.java index 1bbb0b3c..edc06c30 100644 --- a/java/org/cef/callback/CefFileDialogCallback.java +++ b/java/org/cef/callback/CefFileDialogCallback.java @@ -15,11 +15,9 @@ public interface CefFileDialogCallback { * a single value or a list of values depending on the dialog mode. An empty * value is treated the same as calling Cancel(). * - * @param selectedAcceptFilter 0-based index of the value selected from the - * accept filters array passed to CefDialogHandler::OnFileDialog. * @param filePaths list of selected file paths or an empty list. */ - public void Continue(int selectedAcceptFilter, Vector filePaths); + public void Continue(Vector filePaths); /** * Cancel the file selection. diff --git a/java/org/cef/callback/CefFileDialogCallback_N.java b/java/org/cef/callback/CefFileDialogCallback_N.java index de3d5410..770ed97b 100644 --- a/java/org/cef/callback/CefFileDialogCallback_N.java +++ b/java/org/cef/callback/CefFileDialogCallback_N.java @@ -16,9 +16,9 @@ protected void finalize() throws Throwable { } @Override - public void Continue(int selectedAcceptFilter, Vector filePaths) { + public void Continue(Vector filePaths) { try { - N_Continue(getNativeRef(null), selectedAcceptFilter, filePaths); + N_Continue(getNativeRef(null), filePaths); } catch (UnsatisfiedLinkError ule) { ule.printStackTrace(); } @@ -33,7 +33,6 @@ public void Cancel() { } } - private final native void N_Continue( - long self, int selectedAcceptFilter, Vector filePaths); + private final native void N_Continue(long self, Vector filePaths); private final native void N_Cancel(long self); } diff --git a/java/org/cef/callback/CefPdfPrintCallback.java b/java/org/cef/callback/CefPdfPrintCallback.java index 7bedd5c9..cd484042 100644 --- a/java/org/cef/callback/CefPdfPrintCallback.java +++ b/java/org/cef/callback/CefPdfPrintCallback.java @@ -9,7 +9,6 @@ * will be called on the browser process UI thread. */ public interface CefPdfPrintCallback { - /** * Method that will be executed when the PDF printing has completed. |path| * is the output path. |ok| will be true if the printing completed @@ -18,5 +17,4 @@ public interface CefPdfPrintCallback { * @param ok True if printing completed or false otherwise. */ public abstract void onPdfPrintFinished(String path, boolean ok); - } diff --git a/java/org/cef/callback/CefResourceReadCallback.java b/java/org/cef/callback/CefResourceReadCallback.java new file mode 100644 index 00000000..fb762430 --- /dev/null +++ b/java/org/cef/callback/CefResourceReadCallback.java @@ -0,0 +1,25 @@ +// 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.callback; + +/** + * Callback interface used for asynchronous resource reading. + */ +public interface CefResourceReadCallback { + /** + * Callback for asynchronous continuation of Read(). If |bytes_read| == 0 + * the response will be considered complete. If |bytes_read| > 0 then Read() + * will be called again until the request is complete (based on either the + * result or the expected content length). If |bytes_read| < 0 then the + * request will fail and the |bytes_read| value will be treated as the error + * code. + */ + void Continue(int bytes_read); + + /** + * Returns the byte buffer to write data into before calling #Continue(int). + */ + public byte[] getBuffer(); +} \ No newline at end of file diff --git a/java/org/cef/callback/CefResourceReadCallback_N.java b/java/org/cef/callback/CefResourceReadCallback_N.java new file mode 100644 index 00000000..1efaa8e4 --- /dev/null +++ b/java/org/cef/callback/CefResourceReadCallback_N.java @@ -0,0 +1,46 @@ +// 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.callback; + +class CefResourceReadCallback_N extends CefNativeAdapter implements CefResourceReadCallback { + // The native buffer where to copy the data to. + private long N_NativeBufferRef; + + // The Java buffer which the application is expected to fill with data. + private byte[] N_JavaBuffer; + + CefResourceReadCallback_N() {} + + @Override + protected void finalize() throws Throwable { + super.finalize(); + } + + public void setBufferRefs(long nativeBufferRef, byte[] javaBuffer) { + N_NativeBufferRef = nativeBufferRef; + N_JavaBuffer = javaBuffer; + } + + @Override + public byte[] getBuffer() { + return N_JavaBuffer; + } + + @Override + public void Continue(int bytes_read) { + try { + if (N_NativeBufferRef != 0 && N_JavaBuffer != null) { + N_Continue(getNativeRef(null), bytes_read, N_NativeBufferRef, N_JavaBuffer); + N_NativeBufferRef = 0; + N_JavaBuffer = null; + } + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Continue( + long self, int bytes_read, long nativeBufferRef, byte[] javaBuffer); +} \ No newline at end of file diff --git a/java/org/cef/callback/CefResourceSkipCallback.java b/java/org/cef/callback/CefResourceSkipCallback.java new file mode 100644 index 00000000..420af6f2 --- /dev/null +++ b/java/org/cef/callback/CefResourceSkipCallback.java @@ -0,0 +1,18 @@ +// 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.callback; + +/** + * Callback interface used for asynchronous resource skipping. + */ +public interface CefResourceSkipCallback { + /** + * Callback for asynchronous continuation of Skip(). If |bytes_skipped| > 0 + * then either Skip() will be called again until the requested number of + * bytes have been skipped or the request will proceed. If |bytes_skipped| + * <= 0 the request will fail with ERR_REQUEST_RANGE_NOT_SATISFIABLE. + */ + void Continue(long bytes_skipped); +} \ No newline at end of file diff --git a/java/org/cef/callback/CefResourceSkipCallback_N.java b/java/org/cef/callback/CefResourceSkipCallback_N.java new file mode 100644 index 00000000..19c84299 --- /dev/null +++ b/java/org/cef/callback/CefResourceSkipCallback_N.java @@ -0,0 +1,25 @@ + +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.callback; + +class CefResourceSkipCallback_N extends CefNativeAdapter implements CefResourceSkipCallback { + CefResourceSkipCallback_N() {} + + @Override + protected void finalize() throws Throwable { + super.finalize(); + } + + @Override + public void Continue(long bytes_skipped) { + try { + N_Continue(getNativeRef(null), bytes_skipped); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Continue(long self, long bytes_skipped); +} \ No newline at end of file diff --git a/java/org/cef/callback/CefRunFileDialogCallback.java b/java/org/cef/callback/CefRunFileDialogCallback.java index 21c96dac..9d7381a0 100644 --- a/java/org/cef/callback/CefRunFileDialogCallback.java +++ b/java/org/cef/callback/CefRunFileDialogCallback.java @@ -4,9 +4,10 @@ package org.cef.callback; -import java.util.Vector; import org.cef.browser.CefBrowser; +import java.util.Vector; + /** * Callback interface for CefBrowserHost::RunFileDialog. The methods of this * class will be called on the browser process UI thread. @@ -18,9 +19,7 @@ public interface CefRunFileDialogCallback { * depending on the dialog mode. If the selection was cancelled filePaths * will be empty. * - * @param selectedAcceptFilter 0-based index of the value selected from - * the accept filters array passed to CefBrowserHost::RunFileDialog. * @param filePaths list of file paths or empty list. */ - void onFileDialogDismissed(int selectedAcceptFilter, Vector filePaths); + void onFileDialogDismissed(Vector filePaths); } diff --git a/java/org/cef/callback/CefSchemeRegistrar.java b/java/org/cef/callback/CefSchemeRegistrar.java index d4fcb4f2..f59263c3 100644 --- a/java/org/cef/callback/CefSchemeRegistrar.java +++ b/java/org/cef/callback/CefSchemeRegistrar.java @@ -62,7 +62,7 @@ public interface CefSchemeRegistrar { * If |isCspBypassing| is true the scheme can bypass Content-Security-Policy * (CSP) checks. This value should be false in most cases where |isStandard| * is true. - * + * * If |is_fetch_enabled| is true the scheme can perform Fetch API requests. * * This function may be called on any thread. It should only be called once 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..9947b74c 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 @@ -47,11 +48,13 @@ public void onBeforeCommandLineProcessing(String process_type, CefCommandLine co case 1: { // Switches can optionally have a value specified using the '=' delimiter // (e.g. "-switch=value"). - String[] switchVals = arg.substring(switchCnt).split("="); - if (switchVals.length == 2) { - command_line.appendSwitchWithValue(switchVals[0], switchVals[1]); + String switchStr = arg.substring(switchCnt); + int index = switchStr.indexOf('='); + if (index > 0) { + command_line.appendSwitchWithValue( + switchStr.substring(0, index), switchStr.substring(index + 1)); } else { - command_line.appendSwitch(switchVals[0]); + command_line.appendSwitch(switchStr); } break; } @@ -88,4 +91,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/CefDialogHandler.java b/java/org/cef/handler/CefDialogHandler.java index 4e9a9d65..dffc6b11 100644 --- a/java/org/cef/handler/CefDialogHandler.java +++ b/java/org/cef/handler/CefDialogHandler.java @@ -20,6 +20,7 @@ public interface CefDialogHandler { enum FileDialogMode { FILE_DIALOG_OPEN, //!< Requires that the file exists before allowing the user to pick it. FILE_DIALOG_OPEN_MULTIPLE, //!< Like Open, but allows picking multiple files to open. + FILE_DIALOG_OPEN_FOLDER, FILE_DIALOG_SAVE //!< Allows picking a nonexistent file, and prompts to overwrite if the //! file already exists. } @@ -38,14 +39,17 @@ enum FileDialogMode { * "image/*"), (b) individual file extensions (e.g. ".txt" or ".png"), or (c) * combined description and file extension delimited using "|" and ";" (e.g. * "Image Types|.png;.gif;.jpg"). - * @param selectedAcceptFilter is the 0-based index of the filter that should - * be selected by default. + * @param acceptExtensions provides the semicolon-delimited expansion of MIME + * types to file extensions (if known, or empty string otherwise). + * @param acceptDescriptions provides the descriptions for MIME types (if known, + * or empty string otherwise). For example, the "image/*" mime type might + * have extensions ".png;.jpg;.bmp;..." and description "Image Files". * @param callback is a callback handler for handling own file dialogs. * * @return To display a custom dialog return true and execute callback. * To display the default dialog return false. */ public boolean onFileDialog(CefBrowser browser, FileDialogMode mode, String title, - String defaultFilePath, Vector acceptFilters, int selectedAcceptFilter, - CefFileDialogCallback callback); + String defaultFilePath, Vector acceptFilters, Vector acceptExtensions, + Vector acceptDescriptions, CefFileDialogCallback callback); } diff --git a/java/org/cef/handler/CefDisplayHandler.java b/java/org/cef/handler/CefDisplayHandler.java index 0affefc5..f2a828eb 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..90d22d50 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/CefDownloadHandler.java b/java/org/cef/handler/CefDownloadHandler.java index 66ea49a4..3f0ee6f2 100644 --- a/java/org/cef/handler/CefDownloadHandler.java +++ b/java/org/cef/handler/CefDownloadHandler.java @@ -15,9 +15,11 @@ */ public interface CefDownloadHandler { /** - * Called before a download begins. By default the download will be canceled. - * Execute callback either asynchronously or in this method to continue the download - * if desired. + * Called before a download begins. Return true and execute |callback| either + * asynchronously or in this method to continue or cancel the download. + * Return false to proceed with default handling (cancel with Alloy style, + * download shelf with Chrome style). Do not keep a reference to + * downloadItem outside of this method. * * @param browser The desired browser. * @param downloadItem The item to be downloaded. Do not keep a reference to it outside this @@ -25,7 +27,7 @@ public interface CefDownloadHandler { * @param suggestedName is the suggested name for the download file. * @param callback start the download by calling the Continue method */ - public void onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem, + public boolean onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem, String suggestedName, CefBeforeDownloadCallback callback); /** diff --git a/java/org/cef/handler/CefDownloadHandlerAdapter.java b/java/org/cef/handler/CefDownloadHandlerAdapter.java index 8b1f46aa..f0311637 100644 --- a/java/org/cef/handler/CefDownloadHandlerAdapter.java +++ b/java/org/cef/handler/CefDownloadHandlerAdapter.java @@ -16,8 +16,10 @@ */ public abstract class CefDownloadHandlerAdapter implements CefDownloadHandler { @Override - public void onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem, - String suggestedName, CefBeforeDownloadCallback callback) {} + public boolean onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem, + String suggestedName, CefBeforeDownloadCallback callback) { + return false; + } @Override public void onDownloadUpdated( diff --git a/java/org/cef/handler/CefLoadHandler.java b/java/org/cef/handler/CefLoadHandler.java index ba7e5038..4f0bb831 100644 --- a/java/org/cef/handler/CefLoadHandler.java +++ b/java/org/cef/handler/CefLoadHandler.java @@ -40,7 +40,6 @@ enum ErrorCode { ERR_NETWORK_CHANGED(-21), ERR_BLOCKED_BY_ADMINISTRATOR(-22), ERR_SOCKET_IS_CONNECTED(-23), - ERR_BLOCKED_ENROLLMENT_CHECK_PENDING(-24), ERR_UPLOAD_STREAM_REWIND_NOT_SUPPORTED(-25), ERR_CONTEXT_SHUT_DOWN(-26), ERR_BLOCKED_BY_RESPONSE(-27), @@ -188,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), @@ -218,13 +213,6 @@ enum ErrorCode { ERR_INVALID_WEB_BUNDLE(-505), ERR_TRUST_TOKEN_OPERATION_FAILED(-506), ERR_TRUST_TOKEN_OPERATION_SUCCESS_WITHOUT_SENDING_REQUEST(-507), - ERR_FTP_FAILED(-601), - ERR_FTP_SERVICE_UNAVAILABLE(-602), - ERR_FTP_TRANSFER_ABORTED(-603), - ERR_FTP_FILE_BUSY(-604), - ERR_FTP_SYNTAX_ERROR(-605), - ERR_FTP_COMMAND_NOT_SUPPORTED(-606), - ERR_FTP_BAD_COMMAND_SEQUENCE(-607), ERR_PKCS12_IMPORT_BAD_PASSWORD(-701), ERR_PKCS12_IMPORT_FAILED(-702), ERR_IMPORT_CA_CERT_NOT_CA(-703), 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 listener); + + /** + * Remove existing listeners and replace with provided listener. + * @param listener Code that gets executed after a frame was rendered. + */ + public void setOnPaintListener(Consumer listener); + + /** + * Remove provided listener. + * @param listener Code that gets executed after a frame was rendered. + */ + public void removeOnPaintListener(Consumer listener); + /** * Handle cursor changes. * @param browser The browser generating the event. diff --git a/java/org/cef/handler/CefRequestHandler.java b/java/org/cef/handler/CefRequestHandler.java index 8f5f26f9..22ba60dc 100644 --- a/java/org/cef/handler/CefRequestHandler.java +++ b/java/org/cef/handler/CefRequestHandler.java @@ -24,7 +24,10 @@ enum TerminationStatus { TS_ABNORMAL_TERMINATION, //!< Non-zero exit status. TS_PROCESS_WAS_KILLED, //!< SIGKILL or task manager kill. TS_PROCESS_CRASHED, //!< Segmentation fault. - TS_PROCESS_OOM //!< Out of memory. + TS_PROCESS_OOM, //!< Out of memory. + TS_LAUNCH_FAILED, //!< Failed to launch. + TS_INTEGRITY_FAILURE, //!< Integrity check failed. + TS_NUM_VALUES } /** @@ -103,20 +106,6 @@ CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy, String host, int port, String realm, String scheme, CefAuthCallback callback); - /** - * Called on the IO thread when JavaScript requests a specific storage quota size via the - * webkitStorageInfo.requestQuota function. - * - * @param browser The corresponding browser. - * @param origin_url Origin of the page making the request. - * @param new_size Requested quota size in bytes. - * @param callback Call CefCallback.Continue() either in this method or at a later time - * to grant or deny the request. - * @return True to handle the request (callback must be executed) or false to cancel. - */ - boolean onQuotaRequest( - CefBrowser browser, String origin_url, long new_size, CefCallback callback); - /** * Called on the UI thread to handle requests for URLs with an invalid SSL certificate. If * "ignore-certificate-errors" command-line switch is set all invalid certificates will be @@ -137,6 +126,9 @@ boolean onCertificateError(CefBrowser browser, CefLoadHandler.ErrorCode cert_err * Called on the browser process UI thread when the render process terminates unexpectedly. * @param browser The corresponding browser. * @param status Indicates how the process was terminated. + * @param error_code The process error code. + * @param error_string A string description of the error. */ - void onRenderProcessTerminated(CefBrowser browser, TerminationStatus status); + void onRenderProcessTerminated( + CefBrowser browser, TerminationStatus status, int error_code, String error_string); } diff --git a/java/org/cef/handler/CefRequestHandlerAdapter.java b/java/org/cef/handler/CefRequestHandlerAdapter.java index 02736748..a6c04ef6 100644 --- a/java/org/cef/handler/CefRequestHandlerAdapter.java +++ b/java/org/cef/handler/CefRequestHandlerAdapter.java @@ -44,12 +44,6 @@ public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean return false; } - @Override - public boolean onQuotaRequest( - CefBrowser browser, String origin_url, long new_size, CefCallback callback) { - return false; - } - @Override public boolean onCertificateError( CefBrowser browser, ErrorCode cert_error, String request_url, CefCallback callback) { @@ -57,5 +51,6 @@ public boolean onCertificateError( } @Override - public void onRenderProcessTerminated(CefBrowser browser, TerminationStatus status) {} + public void onRenderProcessTerminated( + CefBrowser browser, TerminationStatus status, int error_code, String error_string) {} } diff --git a/java/org/cef/handler/CefResourceHandler.java b/java/org/cef/handler/CefResourceHandler.java index 72f9f30d..8574c700 100644 --- a/java/org/cef/handler/CefResourceHandler.java +++ b/java/org/cef/handler/CefResourceHandler.java @@ -5,15 +5,21 @@ package org.cef.handler; import org.cef.callback.CefCallback; +import org.cef.callback.CefResourceReadCallback; +import org.cef.callback.CefResourceSkipCallback; +import org.cef.misc.BoolRef; import org.cef.misc.IntRef; +import org.cef.misc.LongRef; import org.cef.misc.StringRef; import org.cef.network.CefCookie; import org.cef.network.CefRequest; import org.cef.network.CefResponse; /** - * Implement this interface to handle custom resource requests. The methods of - * this class will always be called on the IO thread. + * Implement this interface to handle custom resource requests. This interface is a "new" API and an + * old API in one: the deprecated methods are part of the old API. The new API allows for parallel + * processing of requests, because it does not channel all reads through a dedicated IO thread, and + * it allows for skipping of bytes as part of handling Range requests. */ public interface CefResourceHandler { /** @@ -23,9 +29,22 @@ public interface CefResourceHandler { * @param callback Callback to continue or cancel the request. * @return True to handle the request and call CefCallback.Continue() once the response header * information is available. + * * @deprecated Use open() instead */ boolean processRequest(CefRequest request, CefCallback callback); + /** + * Open the response stream. This and related (getResponseHeaders, read, skip) methods will be + * called in sequence but not from a dedicated thread.

For backwards compatibility set + * |handleRequest| to false and return false and the processRequest() method will be called. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @param handleRequest Set to true to handle/cancel the request immediately + * @param callback Callback to continue or cancel the request at a later time + * @return True to handle the request + */ + boolean open(CefRequest request, BoolRef handleRequest, CefCallback callback); + /** * Retrieve response header information. If the response length is not known set * |responseLength| to -1 and readResponse() will be called until it returns false. If the @@ -49,9 +68,42 @@ public interface CefResourceHandler { * @param bytesRead Number of bytes written to the buffer. * @param callback Callback to execute if data will be available asynchronously. * @return True if more data is or will be available. + * * @deprecated Use read() instead */ boolean readResponse(byte[] dataOut, int bytesToRead, IntRef bytesRead, CefCallback callback); + /** + * Read response data. If data is available immediately copy up to |bytesToRead| bytes into + * |dataOut|, set |bytesRead| to the number of bytes copied, and return true. To read the data + * at a later time store |dataOut|, set |bytesRead| to 0, return true and call the callback when + * the data is available. To indicate response completion set |bytesRead| to 0 and return false. + * To indicate failure set |bytesRead| to <0 (e.g. -2 for ERR_FAILED) and return false.

For + * backwards compatibility set |bytesRead| to -1 and return false and the readResponse() method + * will be called. + * @param dataOut Write data to this buffer. Buffer remains valid until either an immediate + * response is delivered (return true) or the callback is called later when data is + * available (return false). + * @param bytesToRead Size of the buffer. + * @param bytesRead Number of bytes written to the buffer. + * @param callback Callback to execute if data will be available asynchronously. + * @return True if more data is or will be available. + */ + boolean read( + byte[] dataOut, int bytesToRead, IntRef bytesRead, CefResourceReadCallback callback); + + /** + * Skip response data when requested by a Range header. Skip over and discard |bytesToSkip| + * bytes of response data. If data is available immediately set |bytesSkipped| to the number of + * bytes skipped and return true. To read the data at a later time set |bytesSkipped| to 0, + * return true and execute |callback| when the data is available. To indicate failure set + * |bytesSkipped| to < 0 (e.g. -2 for ERR_FAILED) and return false. + * @param bytesToSkip Number of bytes to skip. + * @param bytesSkipped Number of bytes skipped. + * @param callback Callback to execute if data will be skipped asynchronously. + */ + boolean skip(long bytesToSkip, LongRef bytesSkipped, CefResourceSkipCallback callback); + + /** * Request processing has been canceled. */ diff --git a/java/org/cef/handler/CefResourceHandlerAdapter.java b/java/org/cef/handler/CefResourceHandlerAdapter.java index 9458bb2b..8e6935e6 100644 --- a/java/org/cef/handler/CefResourceHandlerAdapter.java +++ b/java/org/cef/handler/CefResourceHandlerAdapter.java @@ -6,6 +6,10 @@ import org.cef.callback.CefCallback; import org.cef.misc.IntRef; +import org.cef.callback.CefResourceReadCallback; +import org.cef.callback.CefResourceSkipCallback; +import org.cef.misc.BoolRef; +import org.cef.misc.LongRef; import org.cef.misc.StringRef; import org.cef.network.CefCookie; import org.cef.network.CefRequest; @@ -22,6 +26,13 @@ public boolean processRequest(CefRequest request, CefCallback callback) { return false; } + @Override + public boolean open(CefRequest request, BoolRef handleRequest, CefCallback callback) { + // Enables backwards compatibility by default by calling processRequest. + handleRequest.set(false); + return false; + } + @Override public void getResponseHeaders( CefResponse response, IntRef responseLength, StringRef redirectUrl) {} @@ -32,6 +43,20 @@ public boolean readResponse( return false; } + @Override + public boolean read( + byte[] dataOut, int bytesToRead, IntRef bytesRead, CefResourceReadCallback callback) { + // Enables backwards compatibility by default by calling readResponse. + bytesRead.set(-1); + return false; + } + + @Override + public boolean skip(long bytesToSkip, LongRef bytesSkipped, CefResourceSkipCallback callback) { + bytesSkipped.set(-2); + return false; + } + @Override public void cancel() {} } diff --git a/java/org/cef/handler/CefWindowHandler.java b/java/org/cef/handler/CefWindowHandler.java index eeda8dac..c0bc0f13 100644 --- a/java/org/cef/handler/CefWindowHandler.java +++ b/java/org/cef/handler/CefWindowHandler.java @@ -1,42 +1,42 @@ -// Copyright (c) 2015 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.handler; - -import java.awt.Rectangle; - -import org.cef.browser.CefBrowser; - -/** - * Implement this interface to handle events if window rendering is enabled. - * - */ -public interface CefWindowHandler { - /** - * Retrieve the view rectangle. - * @param browser The browser generating the event. - * @return The view rectangle. - */ - public Rectangle getRect(CefBrowser browser); - - /** - * Implement this method to handle mouse events on Windows. - * - * The method is called in case of the following events: - * MOUSE_MOVED, MOUSE_PRESSED, MOUSE_RELEASED and MOUSE_WHEEL for a - * horizontal wheel movement. - * - * @param browser The browser generating the event. - * @param event A mouse event like MouseEvent.MOUSE_MOVED. - * @param screenX The absolute X position on the screen. - * @param screenY The absolute Y position on the screen. - * @param modifier The modifier keys down during event (e.g. Shift, Ctrl). - * @param button An integer indicating which mouse button state changed. - * If parameter event is set to MouseEvent.MOUSE_WHEEL, the value of this - * parameter specifies the rotation indicator (negative value for left scroll - * and positive value for right scroll). - */ - public void onMouseEvent( - CefBrowser browser, int event, int screenX, int screenY, int modifier, int button); -} +// Copyright (c) 2015 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.handler; + +import org.cef.browser.CefBrowser; + +import java.awt.Rectangle; + +/** + * Implement this interface to handle events if window rendering is enabled. + * + */ +public interface CefWindowHandler { + /** + * Retrieve the view rectangle. + * @param browser The browser generating the event. + * @return The view rectangle. + */ + public Rectangle getRect(CefBrowser browser); + + /** + * Implement this method to handle mouse events on Windows. + * + * The method is called in case of the following events: + * MOUSE_MOVED, MOUSE_PRESSED, MOUSE_RELEASED and MOUSE_WHEEL for a + * horizontal wheel movement. + * + * @param browser The browser generating the event. + * @param event A mouse event like MouseEvent.MOUSE_MOVED. + * @param screenX The absolute X position on the screen. + * @param screenY The absolute Y position on the screen. + * @param modifier The modifier keys down during event (e.g. Shift, Ctrl). + * @param button An integer indicating which mouse button state changed. + * If parameter event is set to MouseEvent.MOUSE_WHEEL, the value of this + * parameter specifies the rotation indicator (negative value for left scroll + * and positive value for right scroll). + */ + public void onMouseEvent( + CefBrowser browser, int event, int screenX, int screenY, int modifier, int button); +} diff --git a/java/org/cef/handler/CefWindowHandlerAdapter.java b/java/org/cef/handler/CefWindowHandlerAdapter.java index 1e6ad6bd..839c0c7d 100644 --- a/java/org/cef/handler/CefWindowHandlerAdapter.java +++ b/java/org/cef/handler/CefWindowHandlerAdapter.java @@ -1,25 +1,25 @@ -// Copyright (c) 2015 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.handler; - -import java.awt.Rectangle; - -import org.cef.browser.CefBrowser; - -/** - * An abstract adapter class for receiving windowed render events. - * The methods in this class are empty. - * This class exists as convenience for creating handler objects. - */ -public abstract class CefWindowHandlerAdapter implements CefWindowHandler { - @Override - public Rectangle getRect(CefBrowser browser) { - return new Rectangle(0, 0, 0, 0); - } - - @Override - public void onMouseEvent( - CefBrowser browser, int event, int screenX, int screenY, int modifier, int button) {} -} +// Copyright (c) 2015 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.handler; + +import org.cef.browser.CefBrowser; + +import java.awt.Rectangle; + +/** + * An abstract adapter class for receiving windowed render events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefWindowHandlerAdapter implements CefWindowHandler { + @Override + public Rectangle getRect(CefBrowser browser) { + return new Rectangle(0, 0, 0, 0); + } + + @Override + public void onMouseEvent( + CefBrowser browser, int event, int screenX, int screenY, int modifier, int button) {} +} diff --git a/java/org/cef/misc/CefPdfPrintSettings.java b/java/org/cef/misc/CefPdfPrintSettings.java index 554c2925..a014d81c 100644 --- a/java/org/cef/misc/CefPdfPrintSettings.java +++ b/java/org/cef/misc/CefPdfPrintSettings.java @@ -15,97 +15,128 @@ public enum MarginType { // No margins NONE, - // Minimum margins. - MINIMUM, - // Custom margins using the values from CefPdfPrintSettings CUSTOM } /** - * Set to true to print headers and footers or false to not print - * headers and footers. + * Set to true for landscape mode or false for portrait mode. */ - public boolean header_footer_enabled; + public boolean landscape; /** - * Page title to display in the header. Only used if header_footer_enabled - * is set to true. + * Set to true to print background graphics or false to not print + * background graphics. */ - public String header_footer_title; + public boolean print_background; /** - * URL to display in the footer. Only used if header_footer_enabled is set - * to true. + * The percentage to scale the PDF by before printing (e.g. .5 is 50%). + * If this value is less than or equal to zero the default value of 1.0 + * will be used. */ - public String header_footer_url; + public double scale; /** - * Set to true for landscape mode or false for portrait mode. + * Output paper size in inches. If either of these values is less than or + * equal to zero then the default paper size (letter, 8.5 x 11 inches) will + * be used. */ - public boolean landscape; + public double paper_width; + public double paper_height; /** - * Set to true to print background graphics or false to not print - * background graphics. + * Set to true to prefer page size as defined by css. Defaults to false + * in which case the content will be scaled to fit the paper size. */ - public boolean backgrounds_enabled; + public boolean prefer_css_page_size; /** - * Output page size in microns (1 millimeter = 1000 microns). If either of these - * values is less than or equal to zero then the default paper size will be - * used as returned by the print_handler. A4 is 210 x 297 mm which would - * be 210000 x 297000 microns. US Letter is 215.9 x 279.4 mm which would - * be 215900 x 279400 microns. + * Margin type. */ - public int page_width; - public int page_height; + public MarginType margin_type; /** - * Set to true to print the selection only or false to print all. + * Margins in inches. Only used if margin_type is set to CUSTOM. */ - public boolean selection_only; + public double margin_top; + public double margin_right; + public double margin_bottom; + public double margin_left; /** - * The percentage to scale the PDF by before printing (e.g. 50 is 50%). - * If this value is less than or equal to zero the default value of 100 - * will be used. + * Paper ranges to print, one based, e.g., '1-5, 8, 11-13'. Pages are printed + * in the document order, not in the order specified, and no more than once. + * Defaults to empty string, which implies the entire document is printed. + * The page numbers are quietly capped to actual page count of the document, + * and ranges beyond the end of the document are ignored. If this results in + * no pages to print, an error is reported. It is an error to specify a range + * with start greater than end. + */ + public String page_ranges; + + /** + * Set to true to print headers and footers or false to not print + * headers and footers. Modify header_template and/or footer_template to + * customize the display. */ - public int scale_factor; + public boolean display_header_footer; /** - * Margins in points. Only used if |margin_type| is set to - * PDF_PRINT_MARGIN_CUSTOM. + * HTML template for the print header. Only displayed if + * |display_header_footer| is true (1). Should be valid HTML markup with + * the following classes used to inject printing values into them: + * + * - date: formatted print date + * - title: document title + * - url: document location + * - pageNumber: current page number + * - totalPages: total pages in the document + * + * For example, "" would generate a span containing + * the title. */ - public int margin_top; - public int margin_right; - public int margin_bottom; - public int margin_left; + public String header_template; /** - * Margin type. + * HTML template for the print footer. Only displayed if + * |display_header_footer| is true (1). Uses the same format as + * |header_template|. */ - public MarginType margin_type; + public String footer_template; + + /** + * Whether or not to generate tagged (accessible) PDF. + */ + public boolean generate_tagged_pdf; + + /** + * Whether or not to embed the document outline into the PDF. + */ + public boolean generate_document_outline; public CefPdfPrintSettings() {} @Override public CefPdfPrintSettings clone() { CefPdfPrintSettings tmp = new CefPdfPrintSettings(); - tmp.header_footer_enabled = this.header_footer_enabled; - tmp.header_footer_title = this.header_footer_title; - tmp.header_footer_url = this.header_footer_url; tmp.landscape = this.landscape; - tmp.backgrounds_enabled = this.backgrounds_enabled; - tmp.page_width = this.page_width; - tmp.page_height = this.page_height; - tmp.selection_only = this.selection_only; - tmp.scale_factor = this.scale_factor; + tmp.print_background = this.print_background; + tmp.scale = this.scale; + tmp.paper_width = this.paper_width; + tmp.paper_height = this.paper_height; + tmp.prefer_css_page_size = this.prefer_css_page_size; + tmp.margin_type = this.margin_type; tmp.margin_top = this.margin_top; - tmp.margin_right = this.margin_right; tmp.margin_bottom = this.margin_bottom; + tmp.margin_right = this.margin_right; tmp.margin_left = this.margin_left; - tmp.margin_type = this.margin_type; + tmp.page_ranges = this.page_ranges; + tmp.display_header_footer = this.display_header_footer; + tmp.header_template = this.header_template; + tmp.footer_template = this.footer_template; + tmp.generate_tagged_pdf = this.generate_tagged_pdf; + tmp.generate_document_outline = this.generate_document_outline; return tmp; } } diff --git a/java/org/cef/misc/LongRef.java b/java/org/cef/misc/LongRef.java new file mode 100644 index 00000000..02cd3ce9 --- /dev/null +++ b/java/org/cef/misc/LongRef.java @@ -0,0 +1,26 @@ +// 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.misc; + +/** + * Helper class for passing long values by reference. + */ +public class LongRef { + private long value_; + + public LongRef() {} + + public LongRef(long value) { + value_ = value; + } + + public void set(long value) { + value_ = value; + } + + public long get() { + return value_; + } +} \ No newline at end of file diff --git a/java/org/cef/network/CefPostDataElement.java b/java/org/cef/network/CefPostDataElement.java index f8a209b3..576e940d 100644 --- a/java/org/cef/network/CefPostDataElement.java +++ b/java/org/cef/network/CefPostDataElement.java @@ -16,6 +16,7 @@ public static enum Type { PDE_TYPE_EMPTY, PDE_TYPE_BYTES, PDE_TYPE_FILE, + PDE_TYPE_NUM_VALUES, } // This CTOR can't be called directly. Call method create() instead. diff --git a/java/org/cef/network/CefRequest.java b/java/org/cef/network/CefRequest.java index 47e38e92..5ce64451 100644 --- a/java/org/cef/network/CefRequest.java +++ b/java/org/cef/network/CefRequest.java @@ -41,6 +41,7 @@ public enum ResourceType { RT_NAVIGATION_PRELOAD_MAIN_FRAME, //!< A main-frame service worker navigation preload //!< request. RT_NAVIGATION_PRELOAD_SUB_FRAME, //!< A sub-frame service worker navigation preload request. + RT_NUM_VALUES, } /** @@ -317,7 +318,7 @@ public enum ReferrerPolicy { /** * Always the last value in this enumeration. */ - REFERRER_POLICY_LAST_VALUE + REFERRER_POLICY_NUM_VALUES } // This CTOR can't be called directly. Call method create() instead. diff --git a/java/tests/detailed/BrowserFrame.java b/java/tests/detailed/BrowserFrame.java index aa955f7f..dedcd1f8 100644 --- a/java/tests/detailed/BrowserFrame.java +++ b/java/tests/detailed/BrowserFrame.java @@ -4,15 +4,16 @@ 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; -import org.cef.CefApp; -import org.cef.browser.CefBrowser; -import org.cef.handler.CefLifeSpanHandlerAdapter; - public class BrowserFrame extends JFrame { private volatile boolean isClosed_ = false; private CefBrowser browser_ = null; diff --git a/java/tests/detailed/MainFrame.java b/java/tests/detailed/MainFrame.java index f13b321d..7377a2d1 100644 --- a/java/tests/detailed/MainFrame.java +++ b/java/tests/detailed/MainFrame.java @@ -6,6 +6,7 @@ import org.cef.CefApp; import org.cef.CefApp.CefVersion; +import org.cef.CefBrowserSettings; import org.cef.CefClient; import org.cef.CefSettings; import org.cef.CefSettings.ColorType; @@ -21,6 +22,8 @@ import org.cef.network.CefCookieManager; import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.GraphicsConfiguration; import java.awt.KeyboardFocusManager; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; @@ -29,6 +32,7 @@ import javax.swing.JFrame; import javax.swing.JPanel; +import javax.swing.SwingUtilities; import tests.detailed.dialog.DownloadDialog; import tests.detailed.handler.AppHandler; @@ -58,6 +62,7 @@ public static void main(String[] args) { boolean osrEnabledArg = false; boolean transparentPaintingEnabledArg = false; boolean createImmediately = false; + int windowless_frame_rate = 0; for (String arg : args) { arg = arg.toLowerCase(); if (arg.equals("--off-screen-rendering-enabled")) { @@ -66,6 +71,8 @@ public static void main(String[] args) { transparentPaintingEnabledArg = true; } else if (arg.equals("--create-immediately")) { createImmediately = true; + } else if (arg.equals("--windowless-frame-rate-60")) { + windowless_frame_rate = 60; } } @@ -73,10 +80,21 @@ public static void main(String[] args) { // MainFrame keeps all the knowledge to display the embedded browser // frame. - final MainFrame frame = new MainFrame( - osrEnabledArg, transparentPaintingEnabledArg, createImmediately, args); + final MainFrame frame = new MainFrame(osrEnabledArg, transparentPaintingEnabledArg, + createImmediately, windowless_frame_rate, args); frame.setSize(800, 600); frame.setVisible(true); + + if (osrEnabledArg && windowless_frame_rate != 0) { + frame.getBrowser().getWindowlessFrameRate().thenAccept( + framerate -> System.out.println("Framerate is:" + framerate)); + + frame.getBrowser().setWindowlessFrameRate(2); + frame.getBrowser().getWindowlessFrameRate().thenAccept( + framerate -> System.out.println("Framerate is:" + framerate)); + + frame.getBrowser().setWindowlessFrameRate(windowless_frame_rate); + } } private final CefClient client_; @@ -86,9 +104,11 @@ public static void main(String[] args) { private boolean browserFocus_ = true; private boolean osr_enabled_; private boolean transparent_painting_enabled_; + private JPanel contentPanel_; + private JFrame fullscreenFrame_; public MainFrame(boolean osrEnabled, boolean transparentPaintingEnabled, - boolean createImmediately, String[] args) { + boolean createImmediately, int windowless_frame_rate, String[] args) { this.osr_enabled_ = osrEnabled; this.transparent_painting_enabled_ = transparentPaintingEnabled; @@ -163,6 +183,10 @@ public void onTitleChange(CefBrowser browser, String title) { public void onStatusMessage(CefBrowser browser, String value) { status_panel_.setStatusText(value); } + @Override + public void onFullscreenModeChange(CefBrowser browser, boolean fullscreen) { + setBrowserFullscreen(fullscreen); + } }); // 2.2) To disable/enable navigation buttons and to display a prgress bar @@ -175,19 +199,25 @@ public void onStatusMessage(CefBrowser browser, String value) { @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_ = ""; - } + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + 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) { + if (errorCode != ErrorCode.ERR_NONE && errorCode != ErrorCode.ERR_ABORTED + && frame == browser.getMainFrame()) { errorMsg_ = ""; errorMsg_ += "Error while loading"; errorMsg_ += ""; @@ -200,14 +230,17 @@ public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, } }); + CefBrowserSettings browserSettings = new CefBrowserSettings(); + browserSettings.windowless_frame_rate = windowless_frame_rate; + // Create the browser. - CefBrowser browser = client_.createBrowser( - "http://www.google.com", osrEnabled, transparentPaintingEnabled, null); + CefBrowser browser = client_.createBrowser("http://www.google.com", osrEnabled, + transparentPaintingEnabled, null, browserSettings); setBrowser(browser); // Set up the UI for this example implementation. - JPanel contentPanel = createContentPanel(); - getContentPane().add(contentPanel, BorderLayout.CENTER); + contentPanel_ = createContentPanel(); + getContentPane().add(contentPanel_, BorderLayout.CENTER); // Clear focus from the browser when the address field gains focus. control_pane_.getAddressField().addFocusListener(new FocusAdapter() { @@ -239,7 +272,7 @@ public void onTakeFocus(CefBrowser browser, boolean next) { if (createImmediately) browser.createImmediately(); // Add the browser to the UI. - contentPanel.add(getBrowser().getUIComponent(), BorderLayout.CENTER); + contentPanel_.add(getBrowser().getUIComponent(), BorderLayout.CENTER); MenuBar menuBar = new MenuBar( this, browser, control_pane_, downloadDialog, CefCookieManager.getGlobalManager()); @@ -259,6 +292,8 @@ public void onTakeFocus(CefBrowser browser, boolean next) { 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.addBookmark("Fullscreen Test", + "https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_fullscreen2"); menuBar.addBookmarkSeparator(); menuBar.addBookmark( "javachromiumembedded", "https://bitbucket.org/chromiumembedded/java-cef"); @@ -282,4 +317,33 @@ public boolean isOsrEnabled() { public boolean isTransparentPaintingEnabled() { return transparent_painting_enabled_; } + + public void setBrowserFullscreen(boolean fullscreen) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + Component browserUI = getBrowser().getUIComponent(); + if (fullscreen) { + if (fullscreenFrame_ == null) { + fullscreenFrame_ = new JFrame(); + fullscreenFrame_.setUndecorated(true); + fullscreenFrame_.setResizable(true); + } + GraphicsConfiguration gc = MainFrame.this.getGraphicsConfiguration(); + fullscreenFrame_.setBounds(gc.getBounds()); + gc.getDevice().setFullScreenWindow(fullscreenFrame_); + + contentPanel_.remove(browserUI); + fullscreenFrame_.add(browserUI); + fullscreenFrame_.setVisible(true); + fullscreenFrame_.validate(); + } else { + fullscreenFrame_.remove(browserUI); + fullscreenFrame_.setVisible(false); + contentPanel_.add(browserUI, BorderLayout.CENTER); + contentPanel_.validate(); + } + } + }); + } } diff --git a/java/tests/detailed/dialog/CookieManagerDialog.java b/java/tests/detailed/dialog/CookieManagerDialog.java index 40d120e9..279ebbf2 100644 --- a/java/tests/detailed/dialog/CookieManagerDialog.java +++ b/java/tests/detailed/dialog/CookieManagerDialog.java @@ -1,148 +1,148 @@ -// 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 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; - -import org.cef.callback.CefCookieVisitor; -import org.cef.misc.BoolRef; -import org.cef.network.CefCookie; -import org.cef.network.CefCookieManager; - -@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 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]; - } - } -} +// 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 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 fb811ea5..00000000 --- a/java/tests/detailed/dialog/DevToolsDialog.java +++ /dev/null @@ -1,47 +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 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; - -import org.cef.browser.CefBrowser; - -@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); - add(devTools_.getUIComponent()); - - 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 index ae9cf219..c3ffaeac 100644 --- a/java/tests/detailed/dialog/DownloadDialog.java +++ b/java/tests/detailed/dialog/DownloadDialog.java @@ -1,162 +1,164 @@ -// 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 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; - -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; - -@SuppressWarnings("serial") -public class DownloadDialog extends JDialog implements CefDownloadHandler { - private final Frame owner_; - private final Map downloadObjects_ = - new HashMap(); - 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); - } -} +// 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 downloadObjects_ = + new HashMap(); + 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 boolean 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); + + return true; + } + + @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 index 77444f16..61662f48 100644 --- a/java/tests/detailed/dialog/PasswordDialog.java +++ b/java/tests/detailed/dialog/PasswordDialog.java @@ -1,65 +1,65 @@ -// 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 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; - -import org.cef.callback.CefAuthCallback; - -@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); - } -} +// 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 index 536792fb..88838c36 100644 --- a/java/tests/detailed/dialog/SearchDialog.java +++ b/java/tests/detailed/dialog/SearchDialog.java @@ -1,107 +1,107 @@ -// 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 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; - -import org.cef.browser.CefBrowser; - -@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(); - } -} +// 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 index f19717a1..70813046 100644 --- a/java/tests/detailed/dialog/ShowTextDialog.java +++ b/java/tests/detailed/dialog/ShowTextDialog.java @@ -1,53 +1,53 @@ -// 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 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; - -import org.cef.callback.CefStringVisitor; - -@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); - } -} +// 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 index 3b190350..b1cc175e 100644 --- a/java/tests/detailed/dialog/UrlRequestDialog.java +++ b/java/tests/detailed/dialog/UrlRequestDialog.java @@ -4,6 +4,11 @@ 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; @@ -32,11 +37,6 @@ import javax.swing.SwingUtilities; import javax.swing.table.AbstractTableModel; -import org.cef.network.CefPostData; -import org.cef.network.CefPostDataElement; -import org.cef.network.CefRequest; -import org.cef.network.CefRequest.CefUrlRequestFlags; - @SuppressWarnings("serial") public class UrlRequestDialog extends JDialog { private final Vector requestMethods = new Vector<>(); diff --git a/java/tests/detailed/handler/ClientSchemeHandler.java b/java/tests/detailed/handler/ClientSchemeHandler.java index dccdb66a..c3e5ecbf 100644 --- a/java/tests/detailed/handler/ClientSchemeHandler.java +++ b/java/tests/detailed/handler/ClientSchemeHandler.java @@ -1,134 +1,138 @@ -// 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 java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -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; - -/** - * 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 = "Client Scheme Handler" - + "" - + "This contents of this page page are served by the " - + "ClientSchemeHandler class handling the client:// protocol." - + "
You should see an image:" - + "

";
-
-            // Output a string representation of the request
-            html += request.toString();
-
-            html += "

Try the test form:" - + "
" - + "" - + "" - + "" - + "
"; - - 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 = "Error 404"; - html += "

Error 404

"; - html += "File " + url.substring(url.lastIndexOf('/') + 1) + " "; - html += "does not exist"; - 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; - } -} +// 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.callback.CefResourceReadCallback; +import org.cef.handler.CefResourceHandlerAdapter; +import org.cef.misc.BoolRef; +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 open( + CefRequest request, BoolRef handleRequest, CefCallback callback) { + boolean handled = false; + String url = request.getURL(); + if (url.indexOf("handler.html") != -1) { + // Build the response html + String html; + html = "Client Scheme Handler" + + "" + + "This contents of this page page are served by the " + + "ClientSchemeHandler class handling the client:// protocol." + + "
You should see an image:" + + "
";
+
+            // Output a string representation of the request
+            html += request.toString();
+
+            html += "

Try the test form:" + + "
" + + "" + + "" + + "" + + "
"; + + 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 = "Error 404"; + html += "

Error 404

"; + html += "File " + url.substring(url.lastIndexOf('/') + 1) + " "; + html += "does not exist"; + data_ = html.getBytes(); + handled = true; + } + } + + // All requests are handled immediately + handleRequest.set(true); + + if (handled) { + 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 read(byte[] data_out, int bytes_to_read, IntRef bytes_read, + CefResourceReadCallback 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 index 6d52c29e..c18c76b8 100644 --- a/java/tests/detailed/handler/ContextMenuHandler.java +++ b/java/tests/detailed/handler/ContextMenuHandler.java @@ -4,11 +4,6 @@ package tests.detailed.handler; -import java.awt.Frame; -import java.util.HashMap; -import java.util.Map; -import java.util.Vector; - import org.cef.browser.CefBrowser; import org.cef.browser.CefFrame; import org.cef.callback.CefContextMenuParams; @@ -16,6 +11,11 @@ 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; diff --git a/java/tests/detailed/handler/KeyboardHandler.java b/java/tests/detailed/handler/KeyboardHandler.java index 350d0f3b..6785b550 100644 --- a/java/tests/detailed/handler/KeyboardHandler.java +++ b/java/tests/detailed/handler/KeyboardHandler.java @@ -20,6 +20,32 @@ public boolean onKeyEvent(CefBrowser browser, CefKeyEvent event) { browser.executeJavaScript("alert('You pressed the space bar!');", "", 0); } return true; + } else if (event.type == CefKeyEvent.EventType.KEYEVENT_RAWKEYDOWN && event.is_system_key) { + // CMD+[key] is not working on a Mac. + // This switch statement delegates the common keyboard shortcuts to the browser + switch (event.unmodified_character) { + case 'a': + browser.getFocusedFrame().selectAll(); + break; + case 'c': + browser.getFocusedFrame().copy(); + break; + case 'v': + browser.getFocusedFrame().paste(); + break; + case 'x': + browser.getFocusedFrame().cut(); + break; + case 'z': + browser.getFocusedFrame().undo(); + break; + case 'Z': + browser.getFocusedFrame().redo(); + break; + default: + return false; + } + return true; } return false; } diff --git a/java/tests/detailed/handler/RequestHandler.java b/java/tests/detailed/handler/RequestHandler.java index a8fb3204..44d102a5 100644 --- a/java/tests/detailed/handler/RequestHandler.java +++ b/java/tests/detailed/handler/RequestHandler.java @@ -153,12 +153,6 @@ public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean return true; } - @Override - public boolean onQuotaRequest( - CefBrowser browser, String origin_url, long new_size, CefCallback callback) { - return false; - } - @Override public boolean onCertificateError( CefBrowser browser, ErrorCode cert_error, String request_url, CefCallback callback) { @@ -167,7 +161,9 @@ public boolean onCertificateError( } @Override - public void onRenderProcessTerminated(CefBrowser browser, TerminationStatus status) { - System.out.println("render process terminated: " + status); + public void onRenderProcessTerminated( + CefBrowser browser, TerminationStatus status, int error_code, String error_string) { + System.out.println("render process terminated: " + status + " errorCode: " + error_code + + " errorString: " + error_string); } } diff --git a/java/tests/detailed/handler/ResourceHandler.java b/java/tests/detailed/handler/ResourceHandler.java index 968a2783..5bc55308 100644 --- a/java/tests/detailed/handler/ResourceHandler.java +++ b/java/tests/detailed/handler/ResourceHandler.java @@ -1,15 +1,17 @@ package tests.detailed.handler; -import java.nio.ByteBuffer; - import org.cef.callback.CefCallback; +import org.cef.callback.CefResourceReadCallback; import org.cef.handler.CefLoadHandler; import org.cef.handler.CefResourceHandlerAdapter; +import org.cef.misc.BoolRef; 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("\n" @@ -25,11 +27,11 @@ public class ResourceHandler extends CefResourceHandlerAdapter { + ""); @Override - public boolean processRequest(CefRequest request, CefCallback callback) { + public boolean open(CefRequest request, BoolRef handleRequest, CefCallback callback) { System.out.println("processRequest: " + request); startPos = 0; - callback.Continue(); + handleRequest.set(true); return true; } @@ -44,8 +46,8 @@ public void getResponseHeaders( } @Override - public boolean readResponse( - byte[] data_out, int bytes_to_read, IntRef bytes_read, CefCallback callback) { + public boolean read(byte[] data_out, int bytes_to_read, IntRef bytes_read, + CefResourceReadCallback callback) { int length = html.length(); if (startPos >= length) return false; diff --git a/java/tests/detailed/handler/ResourceSetErrorHandler.java b/java/tests/detailed/handler/ResourceSetErrorHandler.java index bc3dd129..005cb702 100644 --- a/java/tests/detailed/handler/ResourceSetErrorHandler.java +++ b/java/tests/detailed/handler/ResourceSetErrorHandler.java @@ -3,6 +3,7 @@ import org.cef.callback.CefCallback; import org.cef.handler.CefLoadHandler.ErrorCode; import org.cef.handler.CefResourceHandlerAdapter; +import org.cef.misc.BoolRef; import org.cef.misc.IntRef; import org.cef.misc.StringRef; import org.cef.network.CefRequest; @@ -10,9 +11,9 @@ public class ResourceSetErrorHandler extends CefResourceHandlerAdapter { @Override - public boolean processRequest(CefRequest request, CefCallback callback) { + public boolean open(CefRequest request, BoolRef handleRequest, CefCallback callback) { System.out.println("processRequest: " + request); - callback.Continue(); + handleRequest.set(true); return true; } diff --git a/java/tests/detailed/handler/SearchSchemeHandler.java b/java/tests/detailed/handler/SearchSchemeHandler.java index 8a5c80e1..3f9b1e5b 100644 --- a/java/tests/detailed/handler/SearchSchemeHandler.java +++ b/java/tests/detailed/handler/SearchSchemeHandler.java @@ -7,6 +7,7 @@ import org.cef.browser.CefBrowser; import org.cef.callback.CefCallback; import org.cef.handler.CefResourceHandlerAdapter; +import org.cef.misc.BoolRef; import org.cef.network.CefRequest; /** @@ -26,7 +27,7 @@ public SearchSchemeHandler(CefBrowser browser) { } @Override - public boolean processRequest(CefRequest request, CefCallback callback) { + public boolean open(CefRequest request, BoolRef handleRequest, CefCallback callback) { // cut away "scheme://" String requestUrl = request.getURL(); String newUrl = requestUrl.substring(scheme.length() + 3); @@ -43,6 +44,7 @@ public boolean processRequest(CefRequest request, CefCallback callback) { newRequest.setFirstPartyForCookies(newUrl); browser_.loadRequest(newRequest); } + handleRequest.set(true); return false; } } diff --git a/java/tests/detailed/ui/ControlPanel.java b/java/tests/detailed/ui/ControlPanel.java index 87bfefed..c3923dcc 100644 --- a/java/tests/detailed/ui/ControlPanel.java +++ b/java/tests/detailed/ui/ControlPanel.java @@ -1,182 +1,182 @@ -// 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.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; - -import org.cef.OS; -import org.cef.browser.CefBrowser; - -@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_; - } -} +// 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 index f9494c2a..29ecc661 100644 --- a/java/tests/detailed/ui/MenuBar.java +++ b/java/tests/detailed/ui/MenuBar.java @@ -4,10 +4,9 @@ package tests.detailed.ui; -import org.cef.CefApp; -import org.cef.CefClient; import org.cef.OS; import org.cef.browser.CefBrowser; +import org.cef.browser.CefDevToolsClient; import org.cef.callback.CefPdfPrintCallback; import org.cef.callback.CefRunFileDialogCallback; import org.cef.callback.CefStringVisitor; @@ -21,12 +20,10 @@ 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.ComponentAdapter; +// import java.awt.event.ComponentEvent; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.io.File; @@ -40,10 +37,10 @@ import javax.swing.ImageIcon; import javax.swing.JButton; +import javax.swing.JCheckBoxMenuItem; 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; @@ -55,7 +52,7 @@ import tests.detailed.BrowserFrame; import tests.detailed.MainFrame; import tests.detailed.dialog.CookieManagerDialog; -import tests.detailed.dialog.DevToolsDialog; +// import tests.detailed.dialog.DevToolsDialog; import tests.detailed.dialog.DownloadDialog; import tests.detailed.dialog.SearchDialog; import tests.detailed.dialog.ShowTextDialog; @@ -65,7 +62,7 @@ @SuppressWarnings("serial") public class MenuBar extends JMenuBar { class SaveAs implements CefStringVisitor { - private PrintWriter fileWriter_; + private final PrintWriter fileWriter_; public SaveAs(String fName) throws FileNotFoundException, UnsupportedEncodingException { fileWriter_ = new PrintWriter(fName, "UTF-8"); @@ -86,6 +83,7 @@ public void visit(String string) { private final DownloadDialog downloadDialog_; private final CefCookieManager cookieManager_; private boolean reparentPending_ = false; + private CefDevToolsClient devToolsClient_; public MenuBar(MainFrame owner, CefBrowser browser, ControlPanel control_pane, DownloadDialog downloadDialog, CefCookieManager cookieManager) { @@ -121,8 +119,7 @@ public void actionPerformed(ActionEvent arg0) { public void actionPerformed(ActionEvent e) { CefRunFileDialogCallback callback = new CefRunFileDialogCallback() { @Override - public void onFileDialogDismissed( - int selectedAcceptFilter, Vector filePaths) { + public void onFileDialogDismissed(Vector filePaths) { if (!filePaths.isEmpty()) { try { SaveAs saveContent = new SaveAs(filePaths.get(0)); @@ -158,10 +155,10 @@ public void actionPerformed(ActionEvent e) { File selectedFile = fc.getSelectedFile(); if (selectedFile != null) { CefPdfPrintSettings pdfSettings = new CefPdfPrintSettings(); - pdfSettings.header_footer_enabled = true; - // A4 page size - pdfSettings.page_width = 210000; - pdfSettings.page_height = 297000; + 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 @@ -370,19 +367,42 @@ public void actionPerformed(ActionEvent e) { 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); + browser.openDevTools(); } }); testMenu.add(showDevTools); + JMenu devToolsProtocolMenu = new JMenu("DevTools Protocol"); + JMenuItem autoDarkMode = devToolsProtocolMenu.add(new JCheckBoxMenuItem("Auto Dark Mode")); + autoDarkMode.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Toggle the auto dark mode override + String params = String.format("{ \"enabled\": %s }", autoDarkMode.isSelected()); + executeDevToolsMethod("Emulation.setAutoDarkModeOverride", params); + } + }); + JMenuItem checkContrast = devToolsProtocolMenu.add(new JMenuItem("Check Contrast")); + checkContrast.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Check contrast, which usually triggers a series of Audits.issueAdded events + executeDevToolsMethod("Audits.checkContrast"); + } + }); + JMenuItem enableCSS = devToolsProtocolMenu.add(new JMenuItem("Enable CSS Agent")); + enableCSS.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Enable the CSS agent, which usually triggers a series of CSS.styleSheetAdded + // events. We can only enable the CSS agent if the DOM agent is enabled first, so we + // need to chain the two commands. + executeDevToolsMethod("DOM.enable") + .thenCompose(unused -> executeDevToolsMethod("CSS.enable")); + } + }); + testMenu.add(devToolsProtocolMenu); + JMenuItem testURLRequest = new JMenuItem("URL Request"); testURLRequest.addActionListener(new ActionListener() { @Override @@ -403,7 +423,9 @@ public void actionPerformed(ActionEvent e) { reparentButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (reparentPending_) return; + if (reparentPending_) { + return; + } reparentPending_ = true; if (reparentButton.getText().equals("Reparent <")) { @@ -442,7 +464,7 @@ public void run() { newwindow.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - final MainFrame frame = new MainFrame(OS.isLinux(), false, false, null); + final MainFrame frame = new MainFrame(OS.isLinux(), false, false, 0, null); frame.setSize(800, 600); frame.setVisible(true); } @@ -493,8 +515,7 @@ public void actionPerformed(ActionEvent e) { CompletableFuture shot = browser.createScreenshot(false); shot.thenAccept((image) -> { System.out.println("Took screenshot asynchronously in " - + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) - + " msecs"); + + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " msecs"); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { @@ -513,12 +534,16 @@ public void run() { } public void addBookmark(String name, String URL) { - if (bookmarkMenu_ == null) return; + 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; + if (!(itemEntry instanceof JMenuItem)) { + continue; + } JMenuItem item = (JMenuItem) itemEntry; if (item.getText().equals(name)) { @@ -551,6 +576,26 @@ private void displayScreenshot(BufferedImage aScreenshot) { frame.pack(); } + private CompletableFuture executeDevToolsMethod(String methodName) { + return executeDevToolsMethod(methodName, null); + } + + private CompletableFuture executeDevToolsMethod( + String methodName, String paramsAsJson) { + if (devToolsClient_ == null) { + devToolsClient_ = browser_.getDevToolsClient(); + devToolsClient_.addEventListener( + (method, json) -> System.out.println("CDP event " + method + ": " + json)); + } + + return devToolsClient_.executeDevToolsMethod(methodName, paramsAsJson) + .handle((error, json) -> { + System.out.println( + "CDP result of " + methodName + ": " + (error != null ? error : json)); + return null; + }); + } + public void addBookmarkSeparator() { bookmarkMenu_.addSeparator(); } diff --git a/java/tests/junittests/TestFrame.java b/java/tests/junittests/TestFrame.java index 78742d6b..eee36305 100644 --- a/java/tests/junittests/TestFrame.java +++ b/java/tests/junittests/TestFrame.java @@ -236,12 +236,6 @@ public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean return false; } - @Override - public boolean onQuotaRequest( - CefBrowser browser, String origin_url, long new_size, CefCallback callback) { - return false; - } - @Override public boolean onCertificateError(CefBrowser browser, CefLoadHandler.ErrorCode cert_error, String request_url, CefCallback callback) { @@ -249,7 +243,8 @@ public boolean onCertificateError(CefBrowser browser, CefLoadHandler.ErrorCode c } @Override - public void onRenderProcessTerminated(CefBrowser browser, TerminationStatus status) {} + public void onRenderProcessTerminated( + CefBrowser browser, TerminationStatus status, int error_code, String error_string) {} // CefResourceRequestHandler methods: diff --git a/java/tests/simple/MainFrame.java b/java/tests/simple/MainFrame.java index 7b2b21ab..44035d0d 100644 --- a/java/tests/simple/MainFrame.java +++ b/java/tests/simple/MainFrame.java @@ -17,6 +17,7 @@ import java.awt.BorderLayout; import java.awt.Component; +import java.awt.GraphicsConfiguration; import java.awt.KeyboardFocusManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -26,7 +27,9 @@ import java.awt.event.WindowEvent; import javax.swing.JFrame; +import javax.swing.JPanel; import javax.swing.JTextField; +import javax.swing.SwingUtilities; /** * This is a simple example application using JCEF. @@ -46,8 +49,9 @@ public class MainFrame extends JFrame { private final CefApp cefApp_; private final CefClient client_; private final CefBrowser browser_; - private final Component browerUI_; + private final Component browserUI_; private boolean browserFocus_ = true; + private JFrame fullscreenFrame_; /** * To display a simple browser window, it suffices completely to create an @@ -105,7 +109,7 @@ public void stateHasChanged(org.cef.CefApp.CefAppState state) { // The UI component is inherited from a java.awt.Component and therefore // it can be embedded into any AWT UI. browser_ = client_.createBrowser(startURL, useOSR, isTransparent); - browerUI_ = browser_.getUIComponent(); + browserUI_ = browser_.getUIComponent(); // (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 @@ -128,6 +132,10 @@ public void actionPerformed(ActionEvent e) { public void onAddressChange(CefBrowser browser, CefFrame frame, String url) { address_.setText(url); } + @Override + public void onFullscreenModeChange(CefBrowser browser, boolean fullscreen) { + setBrowserFullscreen(fullscreen); + } }); // Clear focus from the browser when the address field gains focus. @@ -160,7 +168,7 @@ public void onTakeFocus(CefBrowser browser, boolean next) { // (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); - getContentPane().add(browerUI_, BorderLayout.CENTER); + getContentPane().add(browserUI_, BorderLayout.CENTER); pack(); setSize(800, 600); setVisible(true); @@ -177,6 +185,34 @@ public void windowClosing(WindowEvent e) { }); } + public void setBrowserFullscreen(boolean fullscreen) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (fullscreen) { + if (fullscreenFrame_ == null) { + fullscreenFrame_ = new JFrame(); + fullscreenFrame_.setUndecorated(true); + fullscreenFrame_.setResizable(true); + } + GraphicsConfiguration gc = MainFrame.this.getGraphicsConfiguration(); + fullscreenFrame_.setBounds(gc.getBounds()); + gc.getDevice().setFullScreenWindow(fullscreenFrame_); + + getContentPane().remove(browserUI_); + fullscreenFrame_.add(browserUI_); + fullscreenFrame_.setVisible(true); + fullscreenFrame_.validate(); + } else { + fullscreenFrame_.remove(browserUI_); + fullscreenFrame_.setVisible(false); + getContentPane().add(browserUI_, BorderLayout.CENTER); + getContentPane().validate(); + } + } + }); + } + public static void main(String[] args) { // Perform startup initialization on platforms that require it. if (!CefApp.startup(args)) { diff --git a/manifest.xml.in b/manifest.xml.in new file mode 100644 index 00000000..3a22ae2b --- /dev/null +++ b/manifest.xml.in @@ -0,0 +1,5 @@ + + + ${chromium.version} + ${jcef.version} + \ No newline at end of file diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 6147d448..1f9030a2 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -54,12 +54,18 @@ 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 CefCallback_N.h CefRequestContext_N.cpp CefRequestContext_N.h + CefResourceReadCallback_N.cpp + CefResourceReadCallback_N.h + CefResourceSkipCallback_N.cpp + CefResourceSkipCallback_N.h CefResponse_N.cpp CefResponse_N.h CefSchemeRegistrar_N.cpp @@ -83,6 +89,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 @@ -93,6 +101,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 @@ -140,8 +150,6 @@ set(JCEF_SRCS set(JCEF_SRCS_LINUX critical_wait_posix.cpp jni_util_linux.cpp - signal_restore_posix.cpp - signal_restore_posix.h temp_window_x11.cc temp_window_x11.h util_linux.cpp @@ -149,8 +157,6 @@ set(JCEF_SRCS_LINUX ) set(JCEF_SRCS_MAC critical_wait_posix.cpp - signal_restore_posix.cpp - signal_restore_posix.h temp_window_mac.h temp_window_mac.mm util_mac.h @@ -216,9 +222,6 @@ SET_CEF_TARGET_OUT_DIR() # if(OS_LINUX) - # Find required libraries and update compiler/linker variables. - FIND_LINUX_LIBRARIES("gmodule-2.0 gtk+-2.0 gthread-2.0") - # Helper executable target. add_executable(${JCEF_HELPER_TARGET} ${JCEF_HELPER_SRCS}) SET_EXECUTABLE_TARGET_PROPERTIES(${JCEF_HELPER_TARGET}) @@ -257,16 +260,15 @@ if(OS_LINUX) COPY_FILES("${JCEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}") # TODO(jcef): Eliminate the symlink requirement once we figure out how. - # See https://bitbucket.org/chromiumembedded/java-cef/issues/137#comment-20535941 + # See https://github.com/chromiumembedded/java-cef/issues/137#issuecomment-1465038405 add_custom_command( TARGET ${JCEF_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "" COMMAND ${CMAKE_COMMAND} -E echo "*** Run the following commands manually to create necessary symlinks ***" - COMMAND ${CMAKE_COMMAND} -E echo "sudo ln -s ${CEF_RESOURCE_DIR}/icudtl.dat ${JAVA_DIR}/jre/bin/icudtl.dat" - COMMAND ${CMAKE_COMMAND} -E echo "sudo ln -s ${CEF_BINARY_DIR}/natives_blob.bin ${JAVA_DIR}/jre/bin/natives_blob.bin" - COMMAND ${CMAKE_COMMAND} -E echo "sudo ln -s ${CEF_BINARY_DIR}/snapshot_blob.bin ${JAVA_DIR}/jre/bin/snapshot_blob.bin" - COMMAND ${CMAKE_COMMAND} -E echo "sudo ln -s ${CEF_BINARY_DIR}/v8_context_snapshot.bin ${JAVA_DIR}/jre/bin/v8_context_snapshot.bin" + COMMAND ${CMAKE_COMMAND} -E echo "sudo ln -s ${CEF_RESOURCE_DIR}/icudtl.dat ${JAVA_DIR}/bin/icudtl.dat" + COMMAND ${CMAKE_COMMAND} -E echo "sudo ln -s ${CEF_BINARY_DIR}/snapshot_blob.bin ${JAVA_DIR}/bin/snapshot_blob.bin" + COMMAND ${CMAKE_COMMAND} -E echo "sudo ln -s ${CEF_BINARY_DIR}/v8_context_snapshot.bin ${JAVA_DIR}/bin/v8_context_snapshot.bin" COMMAND ${CMAKE_COMMAND} -E echo "" VERBATIM ) @@ -281,6 +283,28 @@ if(OS_MAC) # Avoid CMP0042 policy errors. set(CMAKE_MACOSX_RPATH 1) + + if(NOT DEFINED PROJECT_ARCH) + message(STATUS "PROJECT_ARCH not defined. Detecting machine architecture.") + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set(PROJECT_ARCH arm64) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64") + set(PROJECT_ARCH x86_64) + else() + message(FATAL_ERROR "Unsupported machine architecture: ${CMAKE_SYSTEM_PROCESSOR}. Please specify the target architecture using -DPROJECT_ARCH=") + endif() + endif() + + message(STATUS "Building for architecture: ${PROJECT_ARCH}") + + if(PROJECT_ARCH STREQUAL "x86_64") + set(CMAKE_OSX_ARCHITECTURES x86_64) + elseif(PROJECT_ARCH STREQUAL "arm64") + set(CMAKE_OSX_ARCHITECTURES arm64) + else() + message(FATAL_ERROR "Unsupported architecture: ${PROJECT_ARCH}") + endif() + # Avoid CMP0068 policy errors. if(POLICY CMP0068) cmake_policy(SET CMP0068 NEW) @@ -293,11 +317,6 @@ if(OS_MAC) set(EXECUTABLE_NAME "${JCEF_APP_NAME}") set(PRODUCT_NAME "${JCEF_APP_NAME}") - if(USE_SANDBOX) - # Logical target used to link the cef_sandbox library. - ADD_LOGICAL_TARGET("cef_sandbox_lib" "${CEF_SANDBOX_LIB_DEBUG}" "${CEF_SANDBOX_LIB_RELEASE}") - endif() - # JCEF library target. add_library(${JCEF_TARGET} SHARED ${JCEF_RESOURCES_SRCS} ${JCEF_SRCS}) SET_EXECUTABLE_TARGET_PROPERTIES(${JCEF_TARGET}) @@ -329,6 +348,14 @@ if(OS_MAC) COMMAND ${CMAKE_COMMAND} -E copy_directory "${CEF_BINARY_DIR}/Chromium Embedded Framework.framework" "${JCEF_APP}/Contents/Frameworks/Chromium Embedded Framework.framework" + # Helper apps look for libcef_sandbox.dylib at: + # "../../../Chromium Embedded Framework.framework/Libraries/libcef_sandbox.dylib" + # Create the directory structure and copy ONLY the sandbox library (not entire framework). + COMMAND ${CMAKE_COMMAND} -E make_directory + "${CEF_TARGET_OUT_DIR}/Chromium Embedded Framework.framework/Libraries" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CEF_BINARY_DIR}/Chromium Embedded Framework.framework/Libraries/libcef_sandbox.dylib" + "${CEF_TARGET_OUT_DIR}/Chromium Embedded Framework.framework/Libraries/libcef_sandbox.dylib" # Copy the JCEF library into the main app bindle. COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CEF_TARGET_OUT_DIR}/${JCEF_TARGET_LIBRARY}" @@ -368,10 +395,20 @@ if(OS_MAC) MACOSX_BUNDLE_INFO_PLIST ${_helper_info_plist} OUTPUT_NAME ${_helper_output_name} ) - - if(USE_SANDBOX) - target_link_libraries(${_helper_target} cef_sandbox_lib) - endif() + set_target_properties(${JCEF_TARGET} PROPERTIES + # XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ${ENACTOR_CODE_SIGN_IDENTITY} + XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${ENACTOR_DEVELOPMENT_TEAM} + # XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "YES" + # XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--deep" + ) + set_target_properties(${JCEF_HELPER_TARGET} PROPERTIES + # XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ${ENACTOR_CODE_SIGN_IDENTITY} + XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${ENACTOR_DEVELOPMENT_TEAM} + # XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "YES" + # XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--deep" + ) # Add the Helper as a dependency of the main executable target. add_dependencies(${JCEF_TARGET} "${_helper_target}") diff --git a/native/CefApp.cpp b/native/CefApp.cpp index c1e2eef4..3adb6961 100644 --- a/native/CefApp.cpp +++ b/native/CefApp.cpp @@ -7,7 +7,7 @@ #include #include "include/cef_app.h" -#include "include/cef_version.h" +#include "include/cef_version_info.h" #include "context.h" #include "jcef_version.h" diff --git a/native/CefBrowser_N.cpp b/native/CefBrowser_N.cpp index 925626b2..db867329 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" @@ -899,6 +902,7 @@ struct JNIObjectsForCreate { ScopedJNIObjectGlobal canvas; ScopedJNIObjectGlobal jcontext; ScopedJNIObjectGlobal jinspectAt; + ScopedJNIObjectGlobal jbrowserSettings; JNIObjectsForCreate(JNIEnv* env, jobject _jbrowser, @@ -907,7 +911,8 @@ struct JNIObjectsForCreate { jstring _url, jobject _canvas, jobject _jcontext, - jobject _jinspectAt) + jobject _jinspectAt, + jobject _browserSettings) : jbrowser(env, _jbrowser), @@ -916,7 +921,8 @@ struct JNIObjectsForCreate { url(env, _url), canvas(env, _canvas), jcontext(env, _jcontext), - jinspectAt(env, _jinspectAt) {} + jinspectAt(env, _jinspectAt), + jbrowserSettings(env, _browserSettings) {} }; void create(std::shared_ptr objs, @@ -934,7 +940,29 @@ void create(std::shared_ptr objs, if (!lifeSpanHandler.get()) return; + CefRefPtr parentBrowser = + GetCefFromJNIObject(env, objs->jparentBrowser, "CefBrowser"); + CefWindowInfo windowInfo; + CefBrowserSettings settings; + + // If parentBrowser is set, we want to show the DEV-Tools for that browser. + // Since that cannot be an Alloy-style window, it cannot be integrated into + // Java UI but must be opened as a pop-up. + if (parentBrowser.get() != nullptr) { + CefPoint inspectAt; + if (objs->jinspectAt != nullptr) { + int x, y; + GetJNIPoint(env, objs->jinspectAt, &x, &y); + inspectAt.Set(x, y); + } + + parentBrowser->GetHost()->ShowDevTools(windowInfo, clientHandler.get(), + settings, inspectAt); + JNI_CALL_VOID_METHOD(env, objs->jbrowser, "notifyBrowserCreated", "()V"); + return; + } + if (osr == JNI_FALSE) { CefRect rect; CefRefPtr windowHandler = @@ -972,40 +1000,28 @@ void create(std::shared_ptr objs, windowInfo.SetAsWindowless((CefWindowHandle)windowHandle); } - CefBrowserSettings settings; - if (transparent == JNI_FALSE) { // Specify an opaque background color (white) to disable transparency. 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 browserObj; CefString strUrl = GetJNIString(env, static_cast(objs->url.get())); CefRefPtr context = GetCefFromJNIObject( env, objs->jcontext, "CefRequestContext"); - CefRefPtr parentBrowser = - GetCefFromJNIObject(env, objs->jparentBrowser, "CefBrowser"); - // Add a global ref that will be released in LifeSpanHandler::OnAfterCreated. jobject globalRef = env->NewGlobalRef(objs->jbrowser); lifeSpanHandler->registerJBrowser(globalRef); - // If parentBrowser is set, we want to show the DEV-Tools for that browser - if (parentBrowser.get() != nullptr) { - CefPoint inspectAt; - if (objs->jinspectAt != nullptr) { - int x, y; - GetJNIPoint(env, objs->jinspectAt, &x, &y); - inspectAt.Set(x, y); - } - parentBrowser->GetHost()->ShowDevTools(windowInfo, clientHandler.get(), - settings, inspectAt); - JNI_CALL_VOID_METHOD(env, objs->jbrowser, "notifyBrowserCreated", "()V"); - return; - } - CefRefPtr extra_info; auto router_configs = BrowserProcessHandler::GetMessageRouterConfigs(); if (router_configs) { @@ -1014,6 +1030,10 @@ void create(std::shared_ptr objs, extra_info->SetList("router_configs", router_configs); } + // JCEF requires Alloy runtime style for "normal" browsers in order for them + // to be integratable into Java UI. + windowInfo.runtime_style = CEF_RUNTIME_STYLE_ALLOY; + bool result = CefBrowserHost::CreateBrowser( windowInfo, clientHandler.get(), strUrl, settings, extra_info, context); if (!result) { @@ -1035,6 +1055,26 @@ void getZoomLevel(CefRefPtr host, } } +void executeDevToolsMethod(CefRefPtr host, + const CefString& method, + const CefString& parametersAsJson, + CefRefPtr callback) { + CefRefPtr parameters = nullptr; + if (!parametersAsJson.empty()) { + CefRefPtr 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)); +} + void OnAfterParentChanged(CefRefPtr browser) { if (!CefCurrentlyOn(TID_UI)) { CefPostTask(TID_UI, base::BindOnce(&OnAfterParentChanged, browser)); @@ -1053,21 +1093,6 @@ void OnAfterParentChanged(CefRefPtr browser) { } } -jobject NewJNILongVector(JNIEnv* env, const std::vector& vals) { - ScopedJNIObjectLocal jvector(env, "java/util/Vector"); - if (!jvector) - return nullptr; - - std::vector::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; @@ -1078,33 +1103,18 @@ CefPdfPrintSettings GetJNIPdfPrintSettings(JNIEnv* env, jobject obj) { if (!cls) return settings; - GetJNIFieldBoolean(env, cls, obj, "header_footer_enabled", - &settings.header_footer_enabled); - - if (GetJNIFieldString(env, cls, obj, "header_footer_title", &tmp) && - !tmp.empty()) { - CefString(&settings.header_footer_title) = tmp; - tmp.clear(); - } - - if (GetJNIFieldString(env, cls, obj, "header_footer_url", &tmp) && - !tmp.empty()) { - CefString(&settings.header_footer_url) = tmp; - tmp.clear(); - } - GetJNIFieldBoolean(env, cls, obj, "landscape", &settings.landscape); - GetJNIFieldBoolean(env, cls, obj, "backgrounds_enabled", - &settings.backgrounds_enabled); - - GetJNIFieldInt(env, cls, obj, "page_width", &settings.page_width); + GetJNIFieldBoolean(env, cls, obj, "print_background", + &settings.print_background); - GetJNIFieldInt(env, cls, obj, "page_height", &settings.page_height); + GetJNIFieldDouble(env, cls, obj, "scale", &settings.scale); - GetJNIFieldBoolean(env, cls, obj, "selection_only", &settings.selection_only); + GetJNIFieldDouble(env, cls, obj, "paper_width", &settings.paper_width); + GetJNIFieldDouble(env, cls, obj, "paper_height", &settings.paper_height); - GetJNIFieldInt(env, cls, obj, "scale_factor", &settings.scale_factor); + GetJNIFieldBoolean(env, cls, obj, "prefer_css_page_size", + &settings.prefer_css_page_size); jobject obj_margin_type = nullptr; if (GetJNIFieldObject(env, cls, obj, "margin_type", &obj_margin_type, @@ -1118,10 +1128,6 @@ CefPdfPrintSettings GetJNIPdfPrintSettings(JNIEnv* env, jobject obj) { "org/cef/misc/CefPdfPrintSettings$MarginType", "NONE")) { settings.margin_type = PDF_PRINT_MARGIN_NONE; - } else if (IsJNIEnumValue(env, margin_type, - "org/cef/misc/CefPdfPrintSettings$MarginType", - "MINIMUM")) { - settings.margin_type = PDF_PRINT_MARGIN_MINIMUM; } else if (IsJNIEnumValue(env, margin_type, "org/cef/misc/CefPdfPrintSettings$MarginType", "CUSTOM")) { @@ -1129,14 +1135,50 @@ CefPdfPrintSettings GetJNIPdfPrintSettings(JNIEnv* env, jobject obj) { } } - GetJNIFieldInt(env, cls, obj, "margin_top", &settings.margin_top); - GetJNIFieldInt(env, cls, obj, "margin_bottom", &settings.margin_bottom); - GetJNIFieldInt(env, cls, obj, "margin_right", &settings.margin_right); - GetJNIFieldInt(env, cls, obj, "margin_left", &settings.margin_left); + GetJNIFieldDouble(env, cls, obj, "margin_top", &settings.margin_top); + GetJNIFieldDouble(env, cls, obj, "margin_bottom", &settings.margin_bottom); + GetJNIFieldDouble(env, cls, obj, "margin_right", &settings.margin_right); + GetJNIFieldDouble(env, cls, obj, "margin_left", &settings.margin_left); + + if (GetJNIFieldString(env, cls, obj, "page_ranges", &tmp) && !tmp.empty()) { + CefString(&settings.page_ranges) = tmp; + tmp.clear(); + } + + GetJNIFieldBoolean(env, cls, obj, "display_header_footer", + &settings.display_header_footer); + + if (GetJNIFieldString(env, cls, obj, "header_template", &tmp) && + !tmp.empty()) { + CefString(&settings.header_template) = tmp; + tmp.clear(); + } + + if (GetJNIFieldString(env, cls, obj, "footer_template", &tmp) && + !tmp.empty()) { + CefString(&settings.footer_template) = tmp; + tmp.clear(); + } + + GetJNIFieldBoolean(env, cls, obj, "generate_tagged_pdf", + &settings.generate_tagged_pdf); + + GetJNIFieldBoolean(env, cls, obj, "generate_document_outline", + &settings.generate_document_outline); return settings; } +// JNI CefRegistration object. +class ScopedJNIRegistration : public ScopedJNIObject { + public: + ScopedJNIRegistration(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/browser/CefRegistration_N", + "CefRegistration") {} +}; + } // namespace JNIEXPORT jboolean JNICALL @@ -1148,9 +1190,11 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv* env, jboolean osr, jboolean transparent, jobject canvas, - jobject jcontext) { - std::shared_ptr objs(new JNIObjectsForCreate( - env, jbrowser, nullptr, jclientHandler, url, canvas, jcontext, nullptr)); + jobject jcontext, + jobject browserSettings) { + std::shared_ptr objs( + new JNIObjectsForCreate(env, jbrowser, nullptr, jclientHandler, url, + canvas, jcontext, nullptr, browserSettings)); if (CefCurrentlyOn(TID_UI)) { create(objs, windowHandle, osr, transparent); } else { @@ -1172,7 +1216,7 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv* env, jobject inspect) { std::shared_ptr objs( new JNIObjectsForCreate(env, jbrowser, jparent, jclientHandler, nullptr, - canvas, nullptr, inspect)); + canvas, nullptr, inspect, nullptr)); if (CefCurrentlyOn(TID_UI)) { create(objs, windowHandle, osr, transparent); } else { @@ -1182,6 +1226,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 callback = new IntCallback(env, jcallback); + + CefRefPtr 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 browser = + JNI_GET_BROWSER_OR_RETURN(env, jbrowser, NULL); + + CefRefPtr observer = + new DevToolsMessageObserver(env, jobserver); + + CefRefPtr 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, @@ -1277,11 +1367,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 browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr); - CefRefPtr frame = browser->GetFrame(identifier); + CefRefPtr frame = + browser->GetFrameByIdentifier(GetJNIString(env, identifier)); if (!frame) return nullptr; ScopedJNIFrame jframe(env, frame); @@ -1289,11 +1380,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 browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr); - CefRefPtr frame = browser->GetFrame(GetJNIString(env, name)); + CefRefPtr frame = browser->GetFrameByName(GetJNIString(env, name)); if (!frame) return nullptr; ScopedJNIFrame jframe(env, frame); @@ -1310,9 +1401,9 @@ JNIEXPORT jobject JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetFrameIdentifiers(JNIEnv* env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr); - std::vector identifiers; + std::vector identifiers; browser->GetFrameIdentifiers(identifiers); - return NewJNILongVector(env, identifiers); + return NewJNIStringVector(env, identifiers); } JNIEXPORT jobject JNICALL @@ -1440,7 +1531,6 @@ Java_org_cef_browser_CefBrowser_1N_N_1SetWindowVisibility(JNIEnv* env, } #endif } - JNIEXPORT jdouble JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetZoomLevel(JNIEnv* env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, 0.0); @@ -1490,6 +1580,10 @@ Java_org_cef_browser_CefBrowser_1N_N_1RunFileDialog(JNIEnv* env, "org/cef/handler/CefDialogHandler$FileDialogMode", "FILE_DIALOG_OPEN_MULTIPLE")) { mode = FILE_DIALOG_OPEN_MULTIPLE; + } else if (IsJNIEnumValue(env, jmode, + "org/cef/handler/CefDialogHandler$FileDialogMode", + "FILE_DIALOG_OPEN_FOLDER")) { + mode = FILE_DIALOG_OPEN_FOLDER; } else if (IsJNIEnumValue(env, jmode, "org/cef/handler/CefDialogHandler$FileDialogMode", "FILE_DIALOG_SAVE")) { @@ -1498,10 +1592,9 @@ Java_org_cef_browser_CefBrowser_1N_N_1RunFileDialog(JNIEnv* env, mode = FILE_DIALOG_OPEN; } - browser->GetHost()->RunFileDialog(mode, GetJNIString(env, jtitle), - GetJNIString(env, jdefaultFilePath), - accept_types, selectedAcceptFilter, - new RunFileDialogCallback(env, jcallback)); + browser->GetHost()->RunFileDialog( + mode, GetJNIString(env, jtitle), GetJNIString(env, jdefaultFilePath), + accept_types, new RunFileDialogCallback(env, jcallback)); } JNIEXPORT void JNICALL @@ -1609,7 +1702,7 @@ Java_org_cef_browser_CefBrowser_1N_N_1SendKeyEvent(JNIEnv* env, JNI_STATIC_DEFINE_INT(env, cls, KEY_TYPED); int event_type, modifiers; - char16 key_char; + char16_t key_char; if (!CallJNIMethodI_V(env, cls, key_event, "getID", &event_type) || !CallJNIMethodC_V(env, cls, key_event, "getKeyChar", &key_char) || !CallJNIMethodI_V(env, cls, key_event, "getModifiersEx", &modifiers)) { @@ -2071,3 +2164,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 browser = JNI_GET_BROWSER_OR_RETURN(env, jbrowser); + CefRefPtr host = browser->GetHost(); + host->SetWindowlessFrameRate(frameRate); +} + +void getWindowlessFrameRate(CefRefPtr host, + CefRefPtr callback) { + callback->onComplete((jint)host->GetWindowlessFrameRate()); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetWindowlessFrameRate( + JNIEnv* env, + jobject jbrowser, + jobject jintCallback) { + CefRefPtr callback = new IntCallback(env, jintCallback); + + CefRefPtr browser = GetJNIBrowser(env, jbrowser); + if (!browser.get()) { + callback->onComplete(0); + return; + } + + CefRefPtr 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 9e03d8ca..b0348d5d 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*, @@ -22,6 +22,7 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv*, jboolean, jboolean, jobject, + jobject, jobject); /* @@ -41,6 +42,30 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv*, jobject, 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 @@ -139,19 +164,21 @@ Java_org_cef_browser_CefBrowser_1N_N_1GetFocusedFrame(JNIEnv*, jobject); /* * Class: org_cef_browser_CefBrowser_N - * Method: N_GetFrame - * Signature: (J)Lorg/cef/browser/CefFrame; + * Method: N_GetFrameByIdentifier + * Signature: (Ljava/lang/String;)Lorg/cef/browser/CefFrame; */ JNIEXPORT jobject JNICALL -Java_org_cef_browser_CefBrowser_1N_N_1GetFrame(JNIEnv*, jobject, jlong); +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByIdentifier(JNIEnv*, + jobject, + jstring); /* * Class: org_cef_browser_CefBrowser_N - * Method: N_GetFrame2 + * Method: N_GetFrameByName * Signature: (Ljava/lang/String;)Lorg/cef/browser/CefFrame; */ JNIEXPORT jobject JNICALL -Java_org_cef_browser_CefBrowser_1N_N_1GetFrame2(JNIEnv*, jobject, jstring); +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByName(JNIEnv*, jobject, jstring); /* * Class: org_cef_browser_CefBrowser_N @@ -348,7 +375,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, @@ -520,6 +547,37 @@ 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/CefCookieManager_N.cpp b/native/CefCookieManager_N.cpp index ed279740..f029e293 100644 --- a/native/CefCookieManager_N.cpp +++ b/native/CefCookieManager_N.cpp @@ -33,7 +33,7 @@ CefCookie GetJNICookie(JNIEnv* env, jobject jcookie) { CefString value(&cookie.value); CefString domain(&cookie.domain); CefString path(&cookie.path); - CefTime creation, lastAccess, expires; + CefBaseTime creation, lastAccess, expires; GetJNIFieldString(env, cls, jcookie, "name", &name); GetJNIFieldString(env, cls, jcookie, "value", &value); diff --git a/native/CefDragData_N.cpp b/native/CefDragData_N.cpp index cf7e6c21..f9132087 100644 --- a/native/CefDragData_N.cpp +++ b/native/CefDragData_N.cpp @@ -190,6 +190,25 @@ Java_org_cef_callback_CefDragData_1N_N_1GetFileNames(JNIEnv* env, return JNI_TRUE; } +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFilePaths(JNIEnv* env, + jobject obj, + jlong self, + jobject jfilePaths) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return JNI_FALSE; + + std::vector filePaths; + if (!dragData->GetFilePaths(filePaths)) + return JNI_FALSE; + + for (size_t i = 0; i < filePaths.size(); ++i) { + AddJNIStringToVector(env, jfilePaths, filePaths.at(i)); + } + return JNI_TRUE; +} + JNIEXPORT void JNICALL Java_org_cef_callback_CefDragData_1N_N_1SetLinkURL(JNIEnv* env, jobject obj, diff --git a/native/CefFileDialogCallback_N.cpp b/native/CefFileDialogCallback_N.cpp index 6c042240..73cd4fce 100644 --- a/native/CefFileDialogCallback_N.cpp +++ b/native/CefFileDialogCallback_N.cpp @@ -22,19 +22,17 @@ void ClearSelf(JNIEnv* env, jobject obj) { } // namespace JNIEXPORT void JNICALL -Java_org_cef_callback_CefFileDialogCallback_1N_N_1Continue( - JNIEnv* env, - jobject obj, - jlong self, - jint selectedAcceptFilter, - jobject jFilePaths) { +Java_org_cef_callback_CefFileDialogCallback_1N_N_1Continue(JNIEnv* env, + jobject obj, + jlong self, + jobject jFilePaths) { CefRefPtr callback = GetSelf(self); if (!callback) return; std::vector filePaths; GetJNIStringVector(env, jFilePaths, filePaths); - callback->Continue(selectedAcceptFilter, filePaths); + callback->Continue(filePaths); ClearSelf(env, obj); } 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 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 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/CefMessageRouter_N.cpp b/native/CefMessageRouter_N.cpp index 2f524296..d8e3e3e9 100644 --- a/native/CefMessageRouter_N.cpp +++ b/native/CefMessageRouter_N.cpp @@ -109,12 +109,11 @@ Java_org_cef_browser_CefMessageRouter_1N_N_1RemoveHandler( }, msgRouter, routerHandler)); } - - + // Remove JNI reference on jrouterhandler added by the ScopedJNIObject SetCefForJNIObject(env, jrouterHandler, nullptr, "CefMessageRouterHandler"); - + return JNI_TRUE; } diff --git a/native/CefPostDataElement_N.cpp b/native/CefPostDataElement_N.cpp index a756107b..414e7a55 100644 --- a/native/CefPostDataElement_N.cpp +++ b/native/CefPostDataElement_N.cpp @@ -98,6 +98,8 @@ Java_org_cef_network_CefPostDataElement_1N_N_1GetType(JNIEnv* env, jtype); JNI_CASE(env, "org/cef/network/CefPostDataElement$Type", PDE_TYPE_FILE, jtype); + JNI_CASE(env, "org/cef/network/CefPostDataElement$Type", + PDE_TYPE_NUM_VALUES, jtype); } return jtype; } 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(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 +/* 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/CefRequestContext_N.cpp b/native/CefRequestContext_N.cpp index 3f22cfd5..db6b2dd4 100644 --- a/native/CefRequestContext_N.cpp +++ b/native/CefRequestContext_N.cpp @@ -56,6 +56,104 @@ Java_org_cef_browser_CefRequestContext_1N_N_1IsGlobal(JNIEnv* env, return context->IsGlobal() ? JNI_TRUE : JNI_FALSE; } +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1HasPreference(JNIEnv* env, + jobject obj, + jstring jname) { + CefRefPtr context = + GetCefFromJNIObject(env, obj, "CefRequestContext"); + if (!context.get()) + return JNI_FALSE; + + CefString name = GetJNIString(env, jname); + return context->HasPreference(name) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1GetPreference(JNIEnv* env, + jobject obj, + jstring jname) { + CefRefPtr context = + GetCefFromJNIObject(env, obj, "CefRequestContext"); + if (!context.get()) + return nullptr; + + CefString name = GetJNIString(env, jname); + CefRefPtr value = context->GetPreference(name); + if (!value) + return nullptr; + + return NewJNIObjectFromCefValue(env, value); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1GetAllPreferences( + JNIEnv* env, + jobject obj, + jboolean includeDefaults) { + CefRefPtr context = + GetCefFromJNIObject(env, obj, "CefRequestContext"); + if (!context.get()) + return nullptr; + + CefRefPtr value = + context->GetAllPreferences(includeDefaults == JNI_TRUE); + if (!value) + return nullptr; + + jobject jmap = NewJNIHashMap(env); + CefDictionaryValue::KeyList keys; + value->GetKeys(keys); + for (const CefString& key : keys) { + jstring jkey = NewJNIString(env, key); + jobject jvalue = NewJNIObjectFromCefValue(env, value->GetValue(key)); + JNI_CALL_VOID_METHOD( + env, jmap, "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", jkey, + jvalue); + } + return jmap; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1CanSetPreference(JNIEnv* env, + jobject obj, + jstring jname) { + CefRefPtr context = + GetCefFromJNIObject(env, obj, "CefRequestContext"); + if (!context.get()) + return JNI_FALSE; + + CefString name = GetJNIString(env, jname); + return context->CanSetPreference(name) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jstring JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1SetPreference(JNIEnv* env, + jobject obj, + jstring jname, + jobject jvalue) { + if (!CefCurrentlyOn(TID_UI)) + return NewJNIString(env, "called on invalid thread"); + + CefRefPtr context = + GetCefFromJNIObject(env, obj, "CefRequestContext"); + if (!context.get()) + return NewJNIString(env, "no request context"); + + CefString name = GetJNIString(env, jname); + CefRefPtr value = GetCefValueFromJNIObject(env, jvalue); + if (!value) + return NewJNIString(env, "no value to set"); + + CefString error; + bool result = context->SetPreference(name, value, error); + if (!result) + return NewJNIString(env, error); + + return nullptr; +} + JNIEXPORT void JNICALL Java_org_cef_browser_CefRequestContext_1N_N_1CefRequestContext_1DTOR( JNIEnv* env, diff --git a/native/CefRequest_N.cpp b/native/CefRequest_N.cpp index b92f2774..626a76e5 100644 --- a/native/CefRequest_N.cpp +++ b/native/CefRequest_N.cpp @@ -126,8 +126,8 @@ Java_org_cef_network_CefRequest_1N_N_1SetReferrer(JNIEnv* env, policy = REFERRER_POLICY_NO_REFERRER; } else if (IsJNIEnumValue(env, jpolicy, "org/cef/network/CefRequest$ReferrerPolicy", - "REFERRER_POLICY_LAST_VALUE")) { - policy = REFERRER_POLICY_LAST_VALUE; + "REFERRER_POLICY_NUM_VALUES")) { + policy = REFERRER_POLICY_NUM_VALUES; } } @@ -399,6 +399,8 @@ Java_org_cef_network_CefRequest_1N_N_1GetResourceType(JNIEnv* env, RT_NAVIGATION_PRELOAD_MAIN_FRAME, result); JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_NAVIGATION_PRELOAD_SUB_FRAME, result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_NUM_VALUES, + result); } return result; } diff --git a/native/CefResourceReadCallback_N.cpp b/native/CefResourceReadCallback_N.cpp new file mode 100644 index 00000000..4eebcda4 --- /dev/null +++ b/native/CefResourceReadCallback_N.cpp @@ -0,0 +1,49 @@ +// 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 "CefResourceReadCallback_N.h" +#include "include/cef_resource_handler.h" +#include "jni_scoped_helpers.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +void ClearSelf(JNIEnv* env, jobject obj) { + // Clear the reference added in ResourceHandler. + SetCefForJNIObject(env, obj, nullptr, + "CefResourceReadCallback"); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefResourceReadCallback_1N_N_1Continue( + JNIEnv* env, + jobject obj, + jlong self, + jint bytes_read, + jlong nativeBufferRef, + jbyteArray javaBuffer) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + + void* data_out = reinterpret_cast(nativeBufferRef); + + if (bytes_read > 0) { + jsize max_bytes = env->GetArrayLength(javaBuffer); + jbyte* jbyte = env->GetByteArrayElements(javaBuffer, nullptr); + if (jbyte) { + memmove(data_out, jbyte, + (bytes_read < max_bytes ? bytes_read : max_bytes)); + env->ReleaseByteArrayElements(javaBuffer, jbyte, JNI_ABORT); + } + } + + callback->Continue(bytes_read); + ClearSelf(env, obj); +} diff --git a/native/CefResourceReadCallback_N.h b/native/CefResourceReadCallback_N.h new file mode 100644 index 00000000..1a12bbfe --- /dev/null +++ b/native/CefResourceReadCallback_N.h @@ -0,0 +1,26 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefResourceReadCallback_N */ + +#ifndef _Included_org_cef_callback_CefResourceReadCallback_N +#define _Included_org_cef_callback_CefResourceReadCallback_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefResourceReadCallback_N + * Method: N_Continue + * Signature: (JI)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefResourceReadCallback_1N_N_1Continue(JNIEnv*, + jobject, + jlong, + jint, + jlong, + jbyteArray); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/native/CefResourceSkipCallback_N.cpp b/native/CefResourceSkipCallback_N.cpp new file mode 100644 index 00000000..9f2b20c4 --- /dev/null +++ b/native/CefResourceSkipCallback_N.cpp @@ -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. + +#include "CefResourceSkipCallback_N.h" +#include "include/cef_resource_handler.h" +#include "jni_scoped_helpers.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +void ClearSelf(JNIEnv* env, jobject obj) { + // Clear the reference added in ResourceHandler. + SetCefForJNIObject(env, obj, nullptr, + "CefResourceSkipCallback"); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefResourceSkipCallback_1N_N_1Continue( + JNIEnv* env, + jobject obj, + jlong self, + jlong bytes_skipped) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Continue(bytes_skipped); + ClearSelf(env, obj); +} diff --git a/native/CefResourceSkipCallback_N.h b/native/CefResourceSkipCallback_N.h new file mode 100644 index 00000000..2de2e119 --- /dev/null +++ b/native/CefResourceSkipCallback_N.h @@ -0,0 +1,24 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefResourceSkipCallback_N */ + +#ifndef _Included_org_cef_callback_CefResourceSkipCallback_N +#define _Included_org_cef_callback_CefResourceSkipCallback_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefResourceSkipCallback_N + * Method: N_Continue + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefResourceSkipCallback_1N_N_1Continue(JNIEnv*, + jobject, + jlong, + jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/native/browser_process_handler.cpp b/native/browser_process_handler.cpp index 1b410f46..ad583e87 100644 --- a/native/browser_process_handler.cpp +++ b/native/browser_process_handler.cpp @@ -38,7 +38,7 @@ void BrowserProcessHandler::OnContextInitialized() { JNI_CALL_VOID_METHOD(env, handle_, "onContextInitialized", "()V"); } -void BrowserProcessHandler::OnScheduleMessagePumpWork(int64 delay_ms) { +void BrowserProcessHandler::OnScheduleMessagePumpWork(int64_t delay_ms) { if (!handle_) return; @@ -50,6 +50,31 @@ void BrowserProcessHandler::OnScheduleMessagePumpWork(int64 delay_ms) { delay_ms); } +bool BrowserProcessHandler::OnAlreadyRunningAppRelaunch( + CefRefPtr command_line, + const CefString& current_directory) { + if (!handle_) + return false; + + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIObject 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 BrowserProcessHandler::GetMessageRouterConfigs() { int idx = 0; diff --git a/native/browser_process_handler.h b/native/browser_process_handler.h index ddd577e4..8bbf29e3 100644 --- a/native/browser_process_handler.h +++ b/native/browser_process_handler.h @@ -33,7 +33,9 @@ class BrowserProcessHandler : public CefBrowserProcessHandler { virtual ~BrowserProcessHandler(); void OnContextInitialized() override; - void OnScheduleMessagePumpWork(int64 delay_ms) override; + void OnScheduleMessagePumpWork(int64_t delay_ms) override; + bool OnAlreadyRunningAppRelaunch(CefRefPtr command_line, + const CefString& current_directory) override; static CefRefPtr GetMessageRouterConfigs(); static void AddMessageRouterConfig(const CefMessageRouterConfig& cfg); diff --git a/native/context.cpp b/native/context.cpp index 7f894ad9..ddb5c4eb 100644 --- a/native/context.cpp +++ b/native/context.cpp @@ -13,10 +13,6 @@ #include "util_mac.h" #endif -#if defined(OS_POSIX) -#include "signal_restore_posix.h" -#endif - namespace { Context* g_context = nullptr; @@ -24,6 +20,11 @@ Context* g_context = nullptr; CefSettings GetJNISettings(JNIEnv* env, jobject obj) { CefString tmp; CefSettings settings; + +#if defined(OS_POSIX) && !defined(OS_ANDROID) + settings.disable_signal_handlers = true; +#endif + if (!obj) return settings; @@ -44,6 +45,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()) { @@ -101,10 +107,13 @@ CefSettings GetJNISettings(JNIEnv* env, jobject obj) { CefString(&settings.locales_dir_path) = tmp; tmp.clear(); } - GetJNIFieldBoolean(env, cls, obj, "pack_loading_disabled", - &settings.pack_loading_disabled); GetJNIFieldInt(env, cls, obj, "remote_debugging_port", &settings.remote_debugging_port); + if (GetJNIFieldString(env, cls, obj, "chrome_policy_id", &tmp) && + !tmp.empty()) { + CefString(&settings.chrome_policy_id) = tmp; + tmp.clear(); + } GetJNIFieldInt(env, cls, obj, "uncaught_exception_stack_size", &settings.uncaught_exception_stack_size); jobject obj_col = nullptr; @@ -221,12 +230,6 @@ bool Context::Initialize(JNIEnv* env, new ClientApp(CefString(&settings.cache_path), env, appHandler)); bool res = false; -#if defined(OS_POSIX) - // CefInitialize will reset signal handlers. Backup/restore the original - // signal handlers to avoid crashes in the JVM (see issue #41). - BackupSignalHandlers(); -#endif - #if defined(OS_MACOSX) res = util_mac::CefInitializeOnMainThread(main_args, settings, client_app.get()); @@ -234,10 +237,6 @@ bool Context::Initialize(JNIEnv* env, res = CefInitialize(main_args, settings, client_app.get(), nullptr); #endif -#if defined(OS_POSIX) - RestoreSignalHandlers(); -#endif - return res; } 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 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(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 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(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 +#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 browser, + int message_id, + bool success, + const void* result, + size_t result_size) override; + virtual void OnDevToolsEvent(CefRefPtr 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/dialog_handler.cpp b/native/dialog_handler.cpp index d1f84fae..20221b5b 100644 --- a/native/dialog_handler.cpp +++ b/native/dialog_handler.cpp @@ -27,13 +27,15 @@ class ScopedJNIFileDialogCallback DialogHandler::DialogHandler(JNIEnv* env, jobject handler) : handle_(env, handler) {} -bool DialogHandler::OnFileDialog(CefRefPtr browser, - FileDialogMode mode, - const CefString& title, - const CefString& default_file_path, - const std::vector& accept_filters, - int selected_accept_filter, - CefRefPtr callback) { +bool DialogHandler::OnFileDialog( + CefRefPtr browser, + FileDialogMode mode, + const CefString& title, + const CefString& default_file_path, + const std::vector& accept_filters, + const std::vector& accept_extensions, + const std::vector& accept_descriptions, + CefRefPtr callback) { ScopedJNIEnv env; if (!env) return false; @@ -43,6 +45,10 @@ bool DialogHandler::OnFileDialog(CefRefPtr browser, ScopedJNIString jdefaultFilePath(env, default_file_path); ScopedJNIObjectLocal jacceptFilters(env, NewJNIStringVector(env, accept_filters)); + ScopedJNIObjectLocal jacceptExtensions( + env, NewJNIStringVector(env, accept_extensions)); + ScopedJNIObjectLocal jacceptDescriptions( + env, NewJNIStringVector(env, accept_descriptions)); ScopedJNIFileDialogCallback jcallback(env, callback); ScopedJNIObjectResult jmode(env); @@ -52,6 +58,8 @@ bool DialogHandler::OnFileDialog(CefRefPtr browser, FILE_DIALOG_OPEN, jmode); JNI_CASE(env, "org/cef/handler/CefDialogHandler$FileDialogMode", FILE_DIALOG_OPEN_MULTIPLE, jmode); + JNI_CASE(env, "org/cef/handler/CefDialogHandler$FileDialogMode", + FILE_DIALOG_OPEN_FOLDER, jmode); JNI_CASE(env, "org/cef/handler/CefDialogHandler$FileDialogMode", FILE_DIALOG_SAVE, jmode); } @@ -62,10 +70,11 @@ bool DialogHandler::OnFileDialog(CefRefPtr browser, env, handle_, "onFileDialog", "(Lorg/cef/browser/CefBrowser;Lorg/cef/handler/" "CefDialogHandler$FileDialogMode;Ljava/lang/String;Ljava/lang/" - "String;Ljava/util/Vector;ILorg/cef/callback/CefFileDialogCallback;)Z", + "String;Ljava/util/Vector;Ljava/util/Vector;Ljava/util/Vector;Lorg/cef/" + "callback/CefFileDialogCallback;)Z", Boolean, jreturn, jbrowser.get(), jmode.get(), jtitle.get(), - jdefaultFilePath.get(), jacceptFilters.get(), selected_accept_filter, - jcallback.get()); + jdefaultFilePath.get(), jacceptFilters.get(), jacceptExtensions.get(), + jacceptDescriptions.get(), jcallback.get()); if (jreturn == JNI_FALSE) { // If the Java method returns "false" the callback won't be used and diff --git a/native/dialog_handler.h b/native/dialog_handler.h index 7dabcf63..0a5411ee 100644 --- a/native/dialog_handler.h +++ b/native/dialog_handler.h @@ -22,7 +22,8 @@ class DialogHandler : public CefDialogHandler { const CefString& title, const CefString& default_file_path, const std::vector& accept_filters, - int selected_accept_filter, + const std::vector& accept_extensions, + const std::vector& accept_descriptions, CefRefPtr callback) override; protected: diff --git a/native/display_handler.cpp b/native/display_handler.cpp index cf088682..d2fcca8e 100644 --- a/native/display_handler.cpp +++ b/native/display_handler.cpp @@ -112,6 +112,18 @@ void DisplayHandler::OnTitleChange(CefRefPtr browser, jbrowser.get(), jtitle.get()); } +void DisplayHandler::OnFullscreenModeChange(CefRefPtr 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 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 browser, const CefString& title) override; + void OnFullscreenModeChange(CefRefPtr browser, + bool fullscreen) override; bool OnTooltip(CefRefPtr browser, CefString& text) override; void OnStatusMessage(CefRefPtr browser, const CefString& value) override; diff --git a/native/download_handler.cpp b/native/download_handler.cpp index f594d435..e0b37759 100644 --- a/native/download_handler.cpp +++ b/native/download_handler.cpp @@ -49,14 +49,14 @@ class ScopedJNIDownloadItemCallback DownloadHandler::DownloadHandler(JNIEnv* env, jobject handler) : handle_(env, handler) {} -void DownloadHandler::OnBeforeDownload( +bool DownloadHandler::OnBeforeDownload( CefRefPtr browser, CefRefPtr download_item, const CefString& suggested_name, CefRefPtr callback) { ScopedJNIEnv env; if (!env) - return; + return false; ScopedJNIBrowser jbrowser(env, browser); ScopedJNIDownloadItem jdownloadItem(env, download_item); @@ -64,12 +64,16 @@ void DownloadHandler::OnBeforeDownload( ScopedJNIString jsuggestedName(env, suggested_name); ScopedJNIBeforeDownloadCallback jcallback(env, callback); - JNI_CALL_VOID_METHOD( - env, handle_, "onBeforeDownload", + jboolean jresult = 0; + + JNI_CALL_BOOLEAN_METHOD( + jresult, env, handle_, "onBeforeDownload", "(Lorg/cef/browser/CefBrowser;Lorg/cef/callback/CefDownloadItem;" - "Ljava/lang/String;Lorg/cef/callback/CefBeforeDownloadCallback;)V", + "Ljava/lang/String;Lorg/cef/callback/CefBeforeDownloadCallback;)Z", jbrowser.get(), jdownloadItem.get(), jsuggestedName.get(), jcallback.get()); + + return jresult; } void DownloadHandler::OnDownloadUpdated( diff --git a/native/download_handler.h b/native/download_handler.h index d41ca492..adbaacbb 100644 --- a/native/download_handler.h +++ b/native/download_handler.h @@ -17,7 +17,7 @@ class DownloadHandler : public CefDownloadHandler { DownloadHandler(JNIEnv* env, jobject handler); // CefDownloadHandler methods - virtual void OnBeforeDownload( + virtual bool OnBeforeDownload( CefRefPtr browser, CefRefPtr download_item, const CefString& suggested_name, 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 + +#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_scoped_helpers.cpp b/native/jni_scoped_helpers.cpp index a518821a..23808da5 100644 --- a/native/jni_scoped_helpers.cpp +++ b/native/jni_scoped_helpers.cpp @@ -112,6 +112,14 @@ jobject NewJNIIntRef(JNIEnv* env, int initValue) { return jintRef.Release(); } +jobject NewJNILongRef(JNIEnv* env, int64_t initValue) { + ScopedJNIObjectLocal jlongRef(env, "org/cef/misc/LongRef"); + if (!jlongRef) + return nullptr; + SetJNILongRef(env, jlongRef, initValue); + return jlongRef.Release(); +} + jobject NewJNIStringRef(JNIEnv* env, const CefString& initValue) { ScopedJNIObjectLocal jstringRef(env, "org/cef/misc/StringRef"); if (!jstringRef) @@ -120,11 +128,13 @@ jobject NewJNIStringRef(JNIEnv* env, const CefString& initValue) { return jstringRef.Release(); } -jobject NewJNIDate(JNIEnv* env, const CefTime& time) { +jobject NewJNIDate(JNIEnv* env, const CefBaseTime& time) { ScopedJNIObjectLocal jdate(env, "java/util/Date"); if (!jdate) return nullptr; - double timestamp = time.GetDoubleT() * 1000; + CefTime cef_time; + cef_time_from_basetime(time, &cef_time); + double timestamp = cef_time.GetDoubleT() * 1000; JNI_CALL_VOID_METHOD(env, jdate, "setTime", "(J)V", (jlong)timestamp); return jdate.Release(); } @@ -294,7 +304,7 @@ ScopedJNIString::ScopedJNIString(JNIEnv* env, const std::string& str) DCHECK(jhandle_); } -ScopedJNIDate::ScopedJNIDate(JNIEnv* env, const CefTime& time) +ScopedJNIDate::ScopedJNIDate(JNIEnv* env, const CefBaseTime& time) : ScopedJNIBase(env) { jhandle_ = NewJNIDate(env, time); DCHECK(jhandle_); @@ -431,6 +441,24 @@ ScopedJNICallback::ScopedJNICallback(JNIEnv* env, CefRefPtr obj) "org/cef/callback/CefCallback_N", "CefCallback") {} +ScopedJNIResourceReadCallback::ScopedJNIResourceReadCallback( + JNIEnv* env, + CefRefPtr obj) + : ScopedJNIObject( + env, + obj, + "org/cef/callback/CefResourceReadCallback_N", + "CefResourceReadCallback") {} + +ScopedJNIResourceSkipCallback::ScopedJNIResourceSkipCallback( + JNIEnv* env, + CefRefPtr obj) + : ScopedJNIObject( + env, + obj, + "org/cef/callback/CefResourceSkipCallback_N", + "CefResourceSkipCallback") {} + ScopedJNIBoolRef::ScopedJNIBoolRef(JNIEnv* env, bool value) : ScopedJNIBase(env) { jhandle_ = NewJNIBoolRef(env, value); @@ -451,6 +479,16 @@ ScopedJNIIntRef::operator int() const { return GetJNIIntRef(env_, jhandle_); } +ScopedJNILongRef::ScopedJNILongRef(JNIEnv* env, int64_t value) + : ScopedJNIBase(env) { + jhandle_ = NewJNILongRef(env, value); + DCHECK(jhandle_); +} + +ScopedJNILongRef::operator int64_t() const { + return GetJNILongRef(env_, jhandle_); +} + ScopedJNIStringRef::ScopedJNIStringRef(JNIEnv* env, const CefString& value) : ScopedJNIBase(env) { jhandle_ = NewJNIStringRef(env, value); diff --git a/native/jni_scoped_helpers.h b/native/jni_scoped_helpers.h index 70be4d2b..3228abdc 100644 --- a/native/jni_scoped_helpers.h +++ b/native/jni_scoped_helpers.h @@ -684,7 +684,7 @@ class ScopedJNIString : public ScopedJNIBase { // JNI date. class ScopedJNIDate : public ScopedJNIBase { public: - ScopedJNIDate(JNIEnv* env, const CefTime& time); + ScopedJNIDate(JNIEnv* env, const CefBaseTime& time); }; // JNI cookie. @@ -822,6 +822,26 @@ class ScopedJNICallback : public ScopedJNIObject { ScopedJNICallback(JNIEnv* env, CefRefPtr obj = nullptr); }; +// JNI CefResourceReadCallback object. +class ScopedJNIResourceReadCallback + : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIResourceReadCallback( + JNIEnv* env, + CefRefPtr obj = nullptr); +}; + +// JNI CefResourceSkipCallback object. +class ScopedJNIResourceSkipCallback + : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIResourceSkipCallback( + JNIEnv* env, + CefRefPtr obj = nullptr); +}; + // JNI BoolRef object. class ScopedJNIBoolRef : public ScopedJNIBase { public: @@ -840,6 +860,15 @@ class ScopedJNIIntRef : public ScopedJNIBase { operator int() const; }; +// JNI LongRef object. +class ScopedJNILongRef : public ScopedJNIBase { + public: + ScopedJNILongRef(JNIEnv* env, int64_t value); + + // Implicit retrieval of the underlying value. + operator int64_t() const; + }; + // JNI StringRef object. class ScopedJNIStringRef : public ScopedJNIBase { public: diff --git a/native/jni_util.cpp b/native/jni_util.cpp index 3e086456..0b2fcfd0 100644 --- a/native/jni_util.cpp +++ b/native/jni_util.cpp @@ -9,6 +9,8 @@ #include "jni_scoped_helpers.h" +#include "include/cef_base.h" + namespace { JavaVM* g_jvm = nullptr; @@ -97,6 +99,12 @@ int GetJNIIntRef(JNIEnv* env, jobject jintRef) { return intRefRes; } +int64_t GetJNILongRef(JNIEnv* env, jobject jlongRef) { + jlong longRefRes = -1; + JNI_CALL_METHOD(env, jlongRef, "get", "()J", Long, longRefRes); + return longRefRes; +} + CefString GetJNIStringRef(JNIEnv* env, jobject jstringRef) { ScopedJNIStringResult str(env); JNI_CALL_METHOD(env, jstringRef, "get", "()Ljava/lang/String;", Object, str); @@ -112,6 +120,10 @@ void SetJNIIntRef(JNIEnv* env, jobject jintRef, int intValue) { JNI_CALL_VOID_METHOD(env, jintRef, "set", "(I)V", intValue); } +void SetJNILongRef(JNIEnv* env, jobject jlongRef, int64_t longValue) { + JNI_CALL_VOID_METHOD(env, jlongRef, "set", "(J)V", longValue); +} + void SetJNIStringRef(JNIEnv* env, jobject jstringRef, const CefString& stringValue) { @@ -268,6 +280,25 @@ void SetJNIStringMultiMap(JNIEnv* env, } } +void* GetJNIByteBufferData(JNIEnv* env, jobject jbyteBuffer) { + if (!jbyteBuffer) + return nullptr; + + void* data = nullptr; + jlong capacity = env->GetDirectBufferCapacity(jbyteBuffer); + if (capacity > 0) { + data = env->GetDirectBufferAddress(jbyteBuffer); + } + return data; +} + +size_t GetJNIByteBufferLength(JNIEnv* env, jobject jbyteBuffer) { + if (!jbyteBuffer) + return 0; + + return static_cast(env->GetDirectBufferCapacity(jbyteBuffer)); +} + CefMessageRouterConfig GetJNIMessageRouterConfig(JNIEnv* env, jobject jConfig) { CefMessageRouterConfig config; @@ -285,6 +316,127 @@ CefMessageRouterConfig GetJNIMessageRouterConfig(JNIEnv* env, jobject jConfig) { return config; } +CefRefPtr GetCefValueFromJNIObject(JNIEnv* env, jobject obj) { + if (!obj) + return nullptr; + + if (env->IsInstanceOf(obj, ScopedJNIClass(env, "java/lang/Boolean"))) { + return GetCefValueFromJNIBoolean(env, obj); + } else if (env->IsInstanceOf(obj, ScopedJNIClass(env, "java/lang/Integer"))) { + return GetCefValueFromJNIInteger(env, obj); + } else if (env->IsInstanceOf(obj, ScopedJNIClass(env, "java/lang/Double"))) { + return GetCefValueFromJNIDouble(env, obj); + } else if (env->IsInstanceOf(obj, ScopedJNIClass(env, "java/lang/String"))) { + return GetCefValueFromJNIString(env, obj); + } else if (env->IsInstanceOf(obj, + ScopedJNIClass(env, "java/nio/ByteBuffer"))) { + return GetCefValueFromJNIByteBuffer(env, obj); + } else if (env->IsInstanceOf(obj, ScopedJNIClass(env, "java/util/Map"))) { + return GetCefValueFromJNIMap(env, obj); + } else if (env->IsInstanceOf(obj, ScopedJNIClass(env, "java/util/List"))) { + return GetCefValueFromJNIList(env, obj); + } else { + return nullptr; + } +} + +CefRefPtr GetCefValueFromJNIBoolean(JNIEnv* env, const jobject& obj) { + CefRefPtr value = CefValue::Create(); + value->SetBool(GetJNIBoolean(env, obj)); + return value; +} + +CefRefPtr GetCefValueFromJNIInteger(JNIEnv* env, const jobject& obj) { + CefRefPtr value = CefValue::Create(); + value->SetInt(GetJNIInteger(env, obj)); + return value; +} + +CefRefPtr GetCefValueFromJNIDouble(JNIEnv* env, const jobject& obj) { + CefRefPtr value = CefValue::Create(); + value->SetDouble(GetJNIDouble(env, obj)); + return value; +} + +CefRefPtr GetCefValueFromJNIString(JNIEnv* env, const jobject& obj) { + CefRefPtr value = CefValue::Create(); + value->SetString(GetJNIString(env, static_cast(obj))); + return value; +} + +CefRefPtr GetCefValueFromJNIByteBuffer(JNIEnv* env, + const jobject& obj) { + CefRefPtr value = CefValue::Create(); + CefRefPtr binary = CefBinaryValue::Create( + GetJNIByteBufferData(env, obj), GetJNIByteBufferLength(env, obj)); + value->SetBinary(binary); + return value; +} + +CefRefPtr GetCefValueFromJNIMap(JNIEnv* env, const jobject& obj) { + CefRefPtr dict = CefDictionaryValue::Create(); + + ScopedJNIObjectResult entrySet(env); + JNI_CALL_METHOD(env, obj, "entrySet", "()Ljava/util/Set;", Object, entrySet); + + ScopedJNIObjectResult iterator(env); + JNI_CALL_METHOD(env, entrySet, "iterator", "()Ljava/util/Iterator;", Object, + iterator); + + jboolean hasNext = JNI_FALSE; + JNI_CALL_METHOD(env, iterator, "hasNext", "()Z", Boolean, hasNext); + + while (hasNext == JNI_TRUE) { + ScopedJNIObjectResult next(env); + JNI_CALL_METHOD(env, iterator, "next", "()Ljava/lang/Object;", Object, + next); + + ScopedJNIObjectResult entryKey(env); + JNI_CALL_METHOD(env, next, "getKey", "()Ljava/lang/Object;", Object, + entryKey); + CefString key = GetJNIString(env, static_cast(entryKey.get())); + + ScopedJNIObjectResult entryValue(env); + JNI_CALL_METHOD(env, next, "getValue", "()Ljava/lang/Object;", Object, + entryValue); + jobject jvalue = entryValue.get(); + CefRefPtr cef_value = GetCefValueFromJNIObject(env, jvalue); + dict->SetValue(key, cef_value); + + JNI_CALL_METHOD(env, iterator, "hasNext", "()Z", Boolean, hasNext); + } + + CefRefPtr value = CefValue::Create(); + return value; +} + +CefRefPtr GetCefValueFromJNIList(JNIEnv* env, const jobject& obj) { + CefRefPtr list = CefListValue::Create(); + + ScopedJNIObjectResult iterator(env); + JNI_CALL_METHOD(env, obj, "iterator", "()Ljava/util/Iterator;", Object, + iterator); + + jboolean hasNext = JNI_FALSE; + JNI_CALL_METHOD(env, iterator, "hasNext", "()Z", Boolean, hasNext); + + long index = 0; + while (hasNext == JNI_TRUE) { + ScopedJNIObjectResult next(env); + JNI_CALL_METHOD(env, iterator, "next", "()Ljava/lang/Object;", Object, + next); + jobject jvalue = next.get(); + CefRefPtr cef_value = GetCefValueFromJNIObject(env, jvalue); + list->SetValue(index, cef_value); + index++; + JNI_CALL_METHOD(env, iterator, "hasNext", "()Z", Boolean, hasNext); + } + + CefRefPtr value = CefValue::Create(); + value->SetList(list); + return value; +} + jobject NewJNIErrorCode(JNIEnv* env, cef_errorcode_t errorCode) { ScopedJNIObjectResult jerrorCode(env); switch (errorCode) { @@ -337,8 +489,6 @@ jobject NewJNIErrorCode(JNIEnv* env, cef_errorcode_t errorCode) { ERR_BLOCKED_BY_ADMINISTRATOR, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_SOCKET_IS_CONNECTED, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_BLOCKED_ENROLLMENT_CHECK_PENDING, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_UPLOAD_STREAM_REWIND_NOT_SUPPORTED, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", @@ -519,8 +669,6 @@ jobject NewJNIErrorCode(JNIEnv* env, cef_errorcode_t errorCode) { ERR_CERT_VALIDITY_TOO_LONG, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_CERTIFICATE_TRANSPARENCY_REQUIRED, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_CERT_SYMANTEC_LEGACY, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_CERT_KNOWN_INTERCEPTION_BLOCKED, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_CERT_END, @@ -633,18 +781,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", @@ -694,20 +834,6 @@ jobject NewJNIErrorCode(JNIEnv* env, cef_errorcode_t errorCode) { JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_TRUST_TOKEN_OPERATION_SUCCESS_WITHOUT_SENDING_REQUEST, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_FTP_FAILED, - jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_FTP_SERVICE_UNAVAILABLE, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_FTP_TRANSFER_ABORTED, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_FTP_FILE_BUSY, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_FTP_SYNTAX_ERROR, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_FTP_COMMAND_NOT_SUPPORTED, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_FTP_BAD_COMMAND_SEQUENCE, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_PKCS12_IMPORT_BAD_PASSWORD, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", @@ -758,6 +884,162 @@ jobject NewJNIErrorCode(JNIEnv* env, cef_errorcode_t errorCode) { return jerrorCode.Release(); } +jobject NewJNIBoolean(JNIEnv* env, const bool value) { + ScopedJNIClass cls(env, "java/lang/Boolean"); + if (!cls) + return nullptr; + + jmethodID method = + env->GetStaticMethodID(cls, "valueOf", "(Z)Ljava/lang/Boolean;"); + if (!method) + return nullptr; + + return env->CallStaticObjectMethod(cls, method, value ? JNI_TRUE : JNI_FALSE); +} + +jboolean GetJNIBoolean(JNIEnv* env, jobject obj) { + if (obj) { + jboolean value = JNI_FALSE; + JNI_CALL_METHOD(env, obj, "booleanValue", "()Z", Boolean, value); + return value; + } + return JNI_FALSE; +} + +jobject NewJNIInteger(JNIEnv* env, const int value) { + ScopedJNIClass cls(env, "java/lang/Integer"); + if (!cls) + return nullptr; + + jmethodID method = + env->GetStaticMethodID(cls, "valueOf", "(I)Ljava/lang/Integer;"); + if (!method) + return nullptr; + + return env->CallStaticObjectMethod(cls, method, value); +} + +jint GetJNIInteger(JNIEnv* env, jobject obj) { + if (obj) { + jint value = 0; + JNI_CALL_METHOD(env, obj, "intValue", "()I", Int, value); + return value; + } + return 0; +} + +jobject NewJNIDouble(JNIEnv* env, const double value) { + ScopedJNIClass cls(env, "java/lang/Double"); + if (!cls) + return nullptr; + + jmethodID method = + env->GetStaticMethodID(cls, "valueOf", "(D)Ljava/lang/Double;"); + if (!method) + return nullptr; + + return env->CallStaticObjectMethod(cls, method, value); +} + +jdouble GetJNIDouble(JNIEnv* env, jobject obj) { + if (obj) { + jdouble value = 0; + JNI_CALL_METHOD(env, obj, "doubleValue", "()D", Double, value); + return value; + } + return 0; +} + +jobject NewJNIByteBuffer(JNIEnv* env, const void* data, size_t size) { + ScopedJNIClass cls(env, "java/nio/ByteBuffer"); + if (!cls) + return nullptr; + + jmethodID method = + env->GetStaticMethodID(cls, "wrap", "([B)Ljava/nio/ByteBuffer;"); + if (!method) + return nullptr; + + jbyteArray array = env->NewByteArray((jsize)size); + if (!array) + return nullptr; + + env->SetByteArrayRegion(array, 0, (jsize)size, + reinterpret_cast(data)); + return env->CallStaticObjectMethod(cls, method, array); +} + +jobject NewJNIHashMap(JNIEnv* env) { + ScopedJNIClass cls(env, "java/util/HashMap"); + if (!cls) + return nullptr; + + jmethodID method = env->GetMethodID(cls, "", "()V"); + if (!method) + return nullptr; + + return env->NewObject(cls, method); +} + +jobject NewJNIArrayList(JNIEnv* env) { + ScopedJNIClass cls(env, "java/util/ArrayList"); + if (!cls) + return nullptr; + + jmethodID method = env->GetMethodID(cls, "", "()V"); + if (!method) + return nullptr; + + return env->NewObject(cls, method); +} + +jobject NewJNIObjectFromCefValue(JNIEnv* env, const CefRefPtr value) { + switch (value->GetType()) { + case VTYPE_NULL: + return nullptr; + case VTYPE_BOOL: + return NewJNIBoolean(env, value->GetBool()); + case VTYPE_INT: + return NewJNIInteger(env, value->GetInt()); + case VTYPE_DOUBLE: + return NewJNIDouble(env, value->GetDouble()); + case VTYPE_STRING: + return NewJNIString(env, value->GetString()); + case VTYPE_BINARY: + return NewJNIByteBuffer(env, value->GetBinary()->GetRawData(), + value->GetBinary()->GetSize()); + case VTYPE_DICTIONARY: { + jobject jmap = NewJNIHashMap(env); + CefRefPtr dict = value->GetDictionary(); + CefDictionaryValue::KeyList keys; + dict->GetKeys(keys); + for (const CefString& key : keys) { + jstring jkey = NewJNIString(env, key); + jobject jvalue = NewJNIObjectFromCefValue(env, dict->GetValue(key)); + JNI_CALL_VOID_METHOD( + env, jmap, "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", jkey, + jvalue); + } + return jmap; + } + case VTYPE_LIST: { + jobject jlist = NewJNIArrayList(env); + CefRefPtr list = value->GetList(); + const size_t size = list->GetSize(); + for (size_t i = 0; i < size; ++i) { + jobject jvalue = NewJNIObjectFromCefValue(env, list->GetValue(i)); + JNI_CALL_VOID_METHOD(env, jlist, "add", "(Ljava/lang/Object;)Z", + jvalue); + } + return jlist; + } + default: + NOTREACHED(); + return nullptr; + } +} + cef_errorcode_t GetJNIErrorCode(JNIEnv* env, jobject jerrorCode) { cef_errorcode_t errorCode = ERR_NONE; @@ -804,14 +1086,16 @@ bool GetJNIFieldDate(JNIEnv* env, jclass cls, jobject obj, const char* field_name, - CefTime* value) { + CefBaseTime* value) { jobject fieldobj = nullptr; if (GetJNIFieldObject(env, cls, obj, field_name, &fieldobj, "Ljava/util/Date;")) { ScopedJNIObjectLocal jdate(env, fieldobj); long timestamp = 0; JNI_CALL_METHOD(env, jdate, "getTime", "()J", Long, timestamp); - value->SetDoubleT((double)(timestamp / 1000)); + CefTime cef_time; + cef_time.SetDoubleT((double)(timestamp / 1000)); + cef_time_to_basetime(&cef_time, value); return true; } return false; @@ -946,7 +1230,7 @@ bool CallJNIMethodC_V(JNIEnv* env, jclass cls, jobject obj, const char* method_name, - char16* value) { + char16_t* value) { jmethodID methodID = env->GetMethodID(cls, method_name, "()C"); if (methodID) { *value = env->CallCharMethod(obj, methodID); diff --git a/native/jni_util.h b/native/jni_util.h index 34017ab5..6028427c 100644 --- a/native/jni_util.h +++ b/native/jni_util.h @@ -39,11 +39,13 @@ jobject NewJNIObject(JNIEnv* env, const char* class_name, const char* sig, ...); // Retrieve primitive reference values bool GetJNIBoolRef(JNIEnv* env, jobject jboolRef); int GetJNIIntRef(JNIEnv* env, jobject jintRef); +int64_t GetJNILongRef(JNIEnv* env, jobject jlongRef); CefString GetJNIStringRef(JNIEnv* env, jobject jstringRef); // Set primitive reference values void SetJNIBoolRef(JNIEnv* env, jobject jboolRef, bool boolValue); void SetJNIIntRef(JNIEnv* env, jobject jintRef, int intValue); +void SetJNILongRef(JNIEnv* env, jobject jlongRef, int64_t longValue); void SetJNIStringRef(JNIEnv* env, jobject jstringRef, const CefString& initValue); @@ -87,12 +89,38 @@ void SetJNIStringMultiMap(JNIEnv* env, jobject jheaderMap, const std::multimap& vals); +void* GetJNIByteBufferData(JNIEnv* env, jobject jbyteBuffer); +size_t GetJNIByteBufferLength(JNIEnv* env, jobject jbyteBuffer); + CefMessageRouterConfig GetJNIMessageRouterConfig(JNIEnv* env, jobject jConfig); +CefRefPtr GetCefValueFromJNIObject(JNIEnv* env, jobject obj); +CefRefPtr GetCefValueFromJNIBoolean(JNIEnv* env, const jobject& obj); +CefRefPtr GetCefValueFromJNIInteger(JNIEnv* env, const jobject& obj); +CefRefPtr GetCefValueFromJNIDouble(JNIEnv* env, const jobject& obj); +CefRefPtr GetCefValueFromJNIString(JNIEnv* env, const jobject& obj); +CefRefPtr GetCefValueFromJNIByteBuffer(JNIEnv* env, + const jobject& obj); +CefRefPtr GetCefValueFromJNIMap(JNIEnv* env, const jobject& obj); +CefRefPtr GetCefValueFromJNIList(JNIEnv* env, const jobject& obj); + // Create a new JNI error code. jobject NewJNIErrorCode(JNIEnv* env, cef_errorcode_t errorCode); cef_errorcode_t GetJNIErrorCode(JNIEnv* env, jobject jerrorCode); +jobject NewJNIBoolean(JNIEnv* env, const bool value); +jobject NewJNIInteger(JNIEnv* env, const int value); +jobject NewJNIDouble(JNIEnv* env, const double value); +jobject NewJNIByteBuffer(JNIEnv* env, const void* data, size_t size); +jobject NewJNIHashMap(JNIEnv* env); +jobject NewJNIArrayList(JNIEnv* env); + +jobject NewJNIObjectFromCefValue(JNIEnv* env, const CefRefPtr value); + +jboolean GetJNIBoolean(JNIEnv* env, jobject jbool); +jint GetJNIInteger(JNIEnv* env, jobject jint); +jdouble GetJNIDouble(JNIEnv* env, jobject jdouble); + bool GetJNIFieldObject(JNIEnv* env, jclass cls, jobject obj, @@ -110,7 +138,7 @@ bool GetJNIFieldDate(JNIEnv* env, jclass cls, jobject obj, const char* field_name, - CefTime* value); + CefBaseTime* value); bool GetJNIFieldBoolean(JNIEnv* env, jclass cls, @@ -173,7 +201,7 @@ bool CallJNIMethodC_V(JNIEnv* env, jclass cls, jobject obj, const char* method_name, - char16* value); + char16_t* value); // Rertieve the CefSize equivalent of a java.awt.Dimension. CefSize GetJNISize(JNIEnv* env, jobject obj); diff --git a/native/life_span_handler.cpp b/native/life_span_handler.cpp index ea41a700..aaa8c256 100644 --- a/native/life_span_handler.cpp +++ b/native/life_span_handler.cpp @@ -14,6 +14,7 @@ LifeSpanHandler::LifeSpanHandler(JNIEnv* env, jobject handler) // TODO(JCEF): Expose all parameters. bool LifeSpanHandler::OnBeforePopup(CefRefPtr browser, CefRefPtr frame, + int popup_id, const CefString& target_url, const CefString& target_frame_name, WindowOpenDisposition target_disposition, diff --git a/native/life_span_handler.h b/native/life_span_handler.h index bbe00022..97ef6e56 100644 --- a/native/life_span_handler.h +++ b/native/life_span_handler.h @@ -22,6 +22,7 @@ class LifeSpanHandler : public CefLifeSpanHandler { // CefLifeSpanHandler methods: virtual bool OnBeforePopup(CefRefPtr browser, CefRefPtr frame, + int popup_id, const CefString& target_url, const CefString& target_frame_name, WindowOpenDisposition target_disposition, diff --git a/native/message_router_handler.cpp b/native/message_router_handler.cpp index 5591c96f..793ccf7c 100644 --- a/native/message_router_handler.cpp +++ b/native/message_router_handler.cpp @@ -28,7 +28,7 @@ MessageRouterHandler::MessageRouterHandler(JNIEnv* env, jobject handler) bool MessageRouterHandler::OnQuery( CefRefPtr browser, CefRefPtr frame, - int64 query_id, + int64_t query_id, const CefString& request, bool persistent, CefRefPtr callback) { @@ -63,7 +63,7 @@ bool MessageRouterHandler::OnQuery( void MessageRouterHandler::OnQueryCanceled(CefRefPtr browser, CefRefPtr frame, - int64 query_id) { + int64_t query_id) { ScopedJNIEnv env; if (!env) return; diff --git a/native/message_router_handler.h b/native/message_router_handler.h index 56da5398..90b4ae77 100644 --- a/native/message_router_handler.h +++ b/native/message_router_handler.h @@ -21,13 +21,13 @@ class MessageRouterHandler : public CefMessageRouterBrowserSide::Handler, // CefMessageRouterHandler methods virtual bool OnQuery(CefRefPtr browser, CefRefPtr frame, - int64 query_id, + int64_t query_id, const CefString& request, bool persistent, CefRefPtr callback) override; virtual void OnQueryCanceled(CefRefPtr browser, CefRefPtr frame, - int64 query_id) override; + int64_t query_id) override; protected: ScopedJNIObjectGlobal handle_; diff --git a/native/request_handler.cpp b/native/request_handler.cpp index 35bc065a..24434451 100644 --- a/native/request_handler.cpp +++ b/native/request_handler.cpp @@ -120,8 +120,8 @@ bool RequestHandler::GetAuthCredentials(CefRefPtr 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; @@ -143,34 +143,6 @@ bool RequestHandler::GetAuthCredentials(CefRefPtr browser, return (jresult != JNI_FALSE); } -bool RequestHandler::OnQuotaRequest(CefRefPtr browser, - const CefString& origin_url, - int64 new_size, - CefRefPtr callback) { - ScopedJNIEnv env; - if (!env) - return false; - - ScopedJNIBrowser jbrowser(env, browser); - ScopedJNIString joriginUrl(env, origin_url); - ScopedJNICallback jcallback(env, callback); - jboolean jresult = JNI_FALSE; - - JNI_CALL_METHOD(env, handle_, "onQuotaRequest", - "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;" - "JLorg/cef/callback/CefCallback;)Z", - Boolean, jresult, jbrowser.get(), joriginUrl.get(), - (jlong)new_size, jcallback.get()); - - if (jresult == JNI_FALSE) { - // If the Java method returns "false" the callback won't be used and - // the reference can therefore be removed. - jcallback.SetTemporary(); - } - - return (jresult != JNI_FALSE); -} - bool RequestHandler::OnCertificateError(CefRefPtr browser, cef_errorcode_t cert_error, const CefString& request_url, @@ -203,7 +175,9 @@ bool RequestHandler::OnCertificateError(CefRefPtr browser, } void RequestHandler::OnRenderProcessTerminated(CefRefPtr browser, - TerminationStatus status) { + TerminationStatus status, + int error_code, + const CefString& error_string) { // Forward request to ClientHandler to make the message_router_ happy. CefRefPtr client = (ClientHandler*)browser->GetHost()->GetClient().get(); @@ -225,11 +199,20 @@ void RequestHandler::OnRenderProcessTerminated(CefRefPtr browser, TS_PROCESS_CRASHED, jstatus); JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", TS_PROCESS_OOM, jstatus); + JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", + TS_LAUNCH_FAILED, jstatus); + JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", + TS_INTEGRITY_FAILURE, jstatus); + JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", + TS_NUM_VALUES, jstatus); } - JNI_CALL_VOID_METHOD( - env, handle_, "onRenderProcessTerminated", - "(Lorg/cef/browser/CefBrowser;" - "Lorg/cef/handler/CefRequestHandler$TerminationStatus;)V", - jbrowser.get(), jstatus.get()); + ScopedJNIString jerrorString(env, error_string); + + JNI_CALL_VOID_METHOD(env, handle_, "onRenderProcessTerminated", + "(Lorg/cef/browser/CefBrowser;" + "Lorg/cef/handler/CefRequestHandler$TerminationStatus;" + "ILjava/lang/String;)V", + jbrowser.get(), jstatus.get(), error_code, + jerrorString.get()); } diff --git a/native/request_handler.h b/native/request_handler.h index cfca0097..9ee8356e 100644 --- a/native/request_handler.h +++ b/native/request_handler.h @@ -44,17 +44,15 @@ class RequestHandler : public CefRequestHandler { const CefString& realm, const CefString& scheme, CefRefPtr callback) override; - bool OnQuotaRequest(CefRefPtr browser, - const CefString& origin_url, - int64 new_size, - CefRefPtr callback) override; bool OnCertificateError(CefRefPtr browser, cef_errorcode_t cert_error, const CefString& request_url, CefRefPtr ssl_info, CefRefPtr callback) override; void OnRenderProcessTerminated(CefRefPtr browser, - TerminationStatus status) override; + TerminationStatus status, + int error_code, + const CefString& error_string) override; protected: ScopedJNIObjectGlobal handle_; diff --git a/native/resource_handler.cpp b/native/resource_handler.cpp index e4368701..9b4dbfcd 100644 --- a/native/resource_handler.cpp +++ b/native/resource_handler.cpp @@ -35,8 +35,37 @@ bool ResourceHandler::ProcessRequest(CefRefPtr request, return (jresult != JNI_FALSE); } +bool ResourceHandler::Open(CefRefPtr request, + bool& handle_request, + CefRefPtr callback) { +ScopedJNIEnv env; +if (!env) +return false; + +ScopedJNIRequest jrequest(env, request); +jrequest.SetTemporary(); +ScopedJNIBoolRef jhandleRequest(env, handle_request); +ScopedJNICallback jcallback(env, callback); +jboolean jresult = JNI_FALSE; + +JNI_CALL_METHOD(env, handle_, "open", +"(Lorg/cef/network/CefRequest;Lorg/cef/misc/BoolRef;Lorg/cef/" +"callback/CefCallback;)Z", +Boolean, jresult, jrequest.get(), jhandleRequest.get(), +jcallback.get()); + +if (jresult == JNI_FALSE) { +// If the Java method returns "false" the callback won't be used and +// the reference can therefore be removed. +jcallback.SetTemporary(); +} + +handle_request = jhandleRequest; + +return (jresult != JNI_FALSE); +} void ResourceHandler::GetResponseHeaders(CefRefPtr response, - int64& response_length, + int64_t& response_length, CefString& redirectUrl) { ScopedJNIEnv env; if (!env) @@ -44,7 +73,7 @@ void ResourceHandler::GetResponseHeaders(CefRefPtr response, ScopedJNIResponse jresponse(env, response); jresponse.SetTemporary(); - ScopedJNIIntRef jresponseLength(env, response_length); + ScopedJNIIntRef jresponseLength(env, (int)response_length); ScopedJNIStringRef jredirectUrl(env, redirectUrl); JNI_CALL_VOID_METHOD(env, handle_, "getResponseHeaders", @@ -94,6 +123,79 @@ bool ResourceHandler::ReadResponse(void* data_out, return result; } + +bool ResourceHandler::Read(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) { +ScopedJNIEnv env; +if (!env) +return false; + +ScopedJNIIntRef jbytesRead(env, bytes_read); +jbyteArray jbytes = env->NewByteArray(bytes_to_read); +ScopedJNIResourceReadCallback jcallback(env, callback); + +// This callback must retain a reference to the data_out buffer +JNI_CALL_VOID_METHOD(env, jcallback.get(), "setBufferRefs", "(J[B)V", +(jlong)data_out, jbytes); + +jboolean jresult = JNI_FALSE; + +JNI_CALL_METHOD( +env, handle_, "read", +"([BILorg/cef/misc/IntRef;Lorg/cef/callback/CefResourceReadCallback;)Z", +Boolean, jresult, jbytes, bytes_to_read, jbytesRead.get(), +jcallback.get()); + +bytes_read = jbytesRead; + +bool result = (jresult != JNI_FALSE); +if (!result || bytes_read > 0) { +// The callback won't be used and the reference can therefore be removed. +jcallback.SetTemporary(); +} + +if (bytes_read > 0) { +jbyte* jbyte = env->GetByteArrayElements(jbytes, nullptr); +if (jbyte) { +memmove(data_out, jbyte, +(bytes_read < bytes_to_read ? bytes_read : bytes_to_read)); +env->ReleaseByteArrayElements(jbytes, jbyte, JNI_ABORT); +} +} +env->DeleteLocalRef(jbytes); + +return result; +} + +bool ResourceHandler::Skip(int64_t bytes_to_skip, + int64_t& bytes_skipped, + CefRefPtr callback) { +ScopedJNIEnv env; +if (!env) +return false; + +ScopedJNILongRef jbytesSkipped(env, bytes_skipped); +ScopedJNIResourceSkipCallback jcallback(env, callback); +jboolean jresult = JNI_FALSE; + +JNI_CALL_METHOD( +env, handle_, "skip", +"(JLorg/cef/misc/LongRef;Lorg/cef/callback/CefResourceSkipCallback;)Z", +Boolean, jresult, bytes_to_skip, jbytesSkipped.get(), jcallback.get()); + +bytes_skipped = jbytesSkipped; + +bool result = (jresult != JNI_FALSE); +if (!result || bytes_skipped > 0) { +// The callback won't be used and the reference can therefore be removed. +jcallback.SetTemporary(); +} + +return result; +} + void ResourceHandler::Cancel() { ScopedJNIEnv env; if (!env) diff --git a/native/resource_handler.h b/native/resource_handler.h index 1ab822ee..0c5328c7 100644 --- a/native/resource_handler.h +++ b/native/resource_handler.h @@ -20,13 +20,23 @@ class ResourceHandler : public CefResourceHandler { // CefResourceHandler methods: bool ProcessRequest(CefRefPtr request, CefRefPtr callback) override; + bool Open(CefRefPtr request, + bool& handle_request, + CefRefPtr callback) override; void GetResponseHeaders(CefRefPtr response, - int64& response_length, + int64_t& response_length, CefString& redirectUrl) override; bool ReadResponse(void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr callback) override; + bool Read(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) override; + bool Skip(int64_t bytes_to_skip, + int64_t& bytes_skipped, + CefRefPtr callback) override; void Cancel() override; protected: diff --git a/native/resource_request_handler.cpp b/native/resource_request_handler.cpp index 27ddc739..c234c177 100644 --- a/native/resource_request_handler.cpp +++ b/native/resource_request_handler.cpp @@ -154,7 +154,7 @@ void ResourceRequestHandler::OnResourceLoadComplete( CefRefPtr request, CefRefPtr response, CefResourceRequestHandler::URLRequestStatus status, - int64 received_content_length) { + int64_t received_content_length) { ScopedJNIEnv env; if (!env) return; diff --git a/native/resource_request_handler.h b/native/resource_request_handler.h index c355ff97..54b24eb3 100644 --- a/native/resource_request_handler.h +++ b/native/resource_request_handler.h @@ -43,7 +43,7 @@ class ResourceRequestHandler : public CefResourceRequestHandler { CefRefPtr request, CefRefPtr response, URLRequestStatus status, - int64 received_content_length) override; + int64_t received_content_length) override; void OnProtocolExecution(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, diff --git a/native/run_file_dialog_callback.cpp b/native/run_file_dialog_callback.cpp index 2054fdeb..e7f946f7 100644 --- a/native/run_file_dialog_callback.cpp +++ b/native/run_file_dialog_callback.cpp @@ -12,7 +12,6 @@ RunFileDialogCallback::RunFileDialogCallback(JNIEnv* env, jobject jcallback) : handle_(env, jcallback) {} void RunFileDialogCallback::OnFileDialogDismissed( - int selected_accept_filter, const std::vector& file_paths) { ScopedJNIEnv env; if (!env) @@ -20,6 +19,5 @@ void RunFileDialogCallback::OnFileDialogDismissed( ScopedJNIObjectLocal jfilePaths(env, NewJNIStringVector(env, file_paths)); JNI_CALL_VOID_METHOD(env, handle_, "onFileDialogDismissed", - "(ILjava/util/Vector;)V", selected_accept_filter, - jfilePaths.get()); + "(Ljava/util/Vector;)V", jfilePaths.get()); } diff --git a/native/run_file_dialog_callback.h b/native/run_file_dialog_callback.h index ad043241..3f76b123 100644 --- a/native/run_file_dialog_callback.h +++ b/native/run_file_dialog_callback.h @@ -19,7 +19,6 @@ class RunFileDialogCallback : public CefRunFileDialogCallback { // RunFileDialogCallback methods virtual void OnFileDialogDismissed( - int selected_accept_filter, const std::vector& file_paths) override; protected: diff --git a/native/signal_restore_posix.cpp b/native/signal_restore_posix.cpp deleted file mode 100644 index 03d22496..00000000 --- a/native/signal_restore_posix.cpp +++ /dev/null @@ -1,38 +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. - -#include "signal_restore_posix.h" - -#include -#include - -// arraysize borrowed from base/macros.h -template -char (&ArraySizeHelper(T (&array)[N]))[N]; -#define arraysize(array) (sizeof(ArraySizeHelper(array))) - -namespace { - -const int signals_to_restore[] = {SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, - SIGFPE, SIGSEGV, SIGALRM, SIGTERM, SIGCHLD, - SIGBUS, SIGTRAP, SIGPIPE}; - -struct sigaction signal_handlers[arraysize(signals_to_restore)]; - -} // namespace - -void BackupSignalHandlers() { - struct sigaction sigact; - for (unsigned i = 0; i < arraysize(signals_to_restore); ++i) { - memset(&sigact, 0, sizeof(sigact)); - sigaction(signals_to_restore[i], nullptr, &sigact); - signal_handlers[i] = sigact; - } -} - -void RestoreSignalHandlers() { - for (unsigned i = 0; i < arraysize(signals_to_restore); ++i) { - sigaction(signals_to_restore[i], &signal_handlers[i], nullptr); - } -} diff --git a/native/signal_restore_posix.h b/native/signal_restore_posix.h deleted file mode 100644 index 830b361a..00000000 --- a/native/signal_restore_posix.h +++ /dev/null @@ -1,11 +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. - -#ifndef SIGNAL_RESTORE_POSIX_H -#define SIGNAL_RESTORE_POSIX_H - -void BackupSignalHandlers(); -void RestoreSignalHandlers(); - -#endif // SIGNAL_RESTORE_POSIX_H diff --git a/native/temp_window_mac.mm b/native/temp_window_mac.mm index 0c35a858..32794cc7 100644 --- a/native/temp_window_mac.mm +++ b/native/temp_window_mac.mm @@ -21,7 +21,7 @@ // Create a borderless non-visible 1x1 window. window_ = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) - styleMask:NSBorderlessWindowMask + styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:NO]; CHECK(window_); diff --git a/native/url_request_client.cpp b/native/url_request_client.cpp index 1ffc8e1c..2acc9cab 100644 --- a/native/url_request_client.cpp +++ b/native/url_request_client.cpp @@ -52,8 +52,8 @@ void URLRequestClient::OnRequestComplete(CefRefPtr request) { } void URLRequestClient::OnUploadProgress(CefRefPtr request, - int64 current, - int64 total) { + int64_t current, + int64_t total) { ScopedJNIEnv env; if (!env) return; @@ -64,8 +64,8 @@ void URLRequestClient::OnUploadProgress(CefRefPtr request, } void URLRequestClient::OnDownloadProgress(CefRefPtr request, - int64 current, - int64 total) { + int64_t current, + int64_t total) { ScopedJNIEnv env; if (!env) return; diff --git a/native/url_request_client.h b/native/url_request_client.h index 0a976e71..5b9dfc15 100644 --- a/native/url_request_client.h +++ b/native/url_request_client.h @@ -29,12 +29,12 @@ class URLRequestClient : public CefURLRequestClient { virtual void OnRequestComplete(CefRefPtr request) override; virtual void OnUploadProgress(CefRefPtr request, - int64 current, - int64 total) override; + int64_t current, + int64_t total) override; virtual void OnDownloadProgress(CefRefPtr request, - int64 current, - int64 total) override; + int64_t current, + int64_t total) override; virtual void OnDownloadData(CefRefPtr request, const void* data, diff --git a/native/util_linux.cpp b/native/util_linux.cpp index 706b4cf7..e04e9f88 100644 --- a/native/util_linux.cpp +++ b/native/util_linux.cpp @@ -23,12 +23,14 @@ void X_XMoveResizeWindow(unsigned long browserHandle, unsigned int height) { ::Display* xdisplay = (::Display*)TempWindow::GetDisplay(); XMoveResizeWindow(xdisplay, browserHandle, 0, 0, width, height); + XFlush(xdisplay); } void X_XReparentWindow(unsigned long browserHandle, unsigned long parentDrawable) { ::Display* xdisplay = (::Display*)TempWindow::GetDisplay(); XReparentWindow(xdisplay, browserHandle, parentDrawable, 0, 0); + XFlush(xdisplay); } void X_XSync(bool discard) { diff --git a/native/util_mac.mm b/native/util_mac.mm index 92a67a9a..f7da32aa 100644 --- a/native/util_mac.mm +++ b/native/util_mac.mm @@ -95,19 +95,19 @@ + (void)load { method_exchangeImplementations(originalTerm, swizzledTerm); g_mouse_monitor_ = [NSEvent - addLocalMonitorForEventsMatchingMask:(NSLeftMouseDownMask | - NSLeftMouseUpMask | - NSLeftMouseDraggedMask | - NSRightMouseDownMask | - NSRightMouseUpMask | - NSRightMouseDraggedMask | - NSOtherMouseDownMask | - NSOtherMouseUpMask | - NSOtherMouseDraggedMask | - NSScrollWheelMask | - NSMouseMovedMask | - NSMouseEnteredMask | - NSMouseExitedMask) + addLocalMonitorForEventsMatchingMask:(NSEventMaskLeftMouseDown | + NSEventMaskLeftMouseUp | + NSEventMaskLeftMouseDragged | + NSEventMaskRightMouseDown | + NSEventMaskRightMouseUp | + NSEventMaskRightMouseDragged | + NSEventMaskOtherMouseDown | + NSEventMaskOtherMouseUp | + NSEventMaskOtherMouseDragged | + NSEventMaskScrollWheel | + NSEventMaskMouseMoved | + NSEventMaskMouseEntered | + NSEventMaskMouseExited) handler:^(NSEvent* evt) { // Get corresponding CefWindowHandle of // Java-Canvas @@ -141,37 +141,37 @@ + (void)load { // Forward mouse event to browsers parent // (JCEF UI) switch ([evt type]) { - case NSLeftMouseDown: - case NSOtherMouseDown: - case NSRightMouseDown: + case NSEventTypeLeftMouseDown: + case NSEventTypeOtherMouseDown: + case NSEventTypeRightMouseDown: [[browser superview] mouseDown:evt]; return evt; - case NSLeftMouseUp: - case NSOtherMouseUp: - case NSRightMouseUp: + case NSEventTypeLeftMouseUp: + case NSEventTypeOtherMouseUp: + case NSEventTypeRightMouseUp: [[browser superview] mouseUp:evt]; return evt; - case NSLeftMouseDragged: - case NSOtherMouseDragged: - case NSRightMouseDragged: + case NSEventTypeLeftMouseDragged: + case NSEventTypeOtherMouseDragged: + case NSEventTypeRightMouseDragged: [[browser superview] mouseDragged:evt]; return evt; - case NSMouseMoved: + case NSEventTypeMouseMoved: [[browser superview] mouseMoved:evt]; return evt; - case NSMouseEntered: + case NSEventTypeMouseEntered: [[browser superview] mouseEntered:evt]; return evt; - case NSMouseExited: + case NSEventTypeMouseExited: [[browser superview] mouseExited:evt]; return evt; - case NSScrollWheel: + case NSEventTypeScrollWheel: [[browser superview] scrollWheel:evt]; return evt; diff --git a/native/write_handler.cpp b/native/write_handler.cpp index cc87920a..e73fd44f 100644 --- a/native/write_handler.cpp +++ b/native/write_handler.cpp @@ -42,12 +42,12 @@ size_t WriteHandler::Write(const void* ptr, size_t size, size_t n) { return rv; } -int WriteHandler::Seek(int64 offset, int whence) { +int WriteHandler::Seek(int64_t offset, int whence) { // not supported by Javas OutputStream return -1; } -int64 WriteHandler::Tell() { +int64_t WriteHandler::Tell() { return offset_; } diff --git a/native/write_handler.h b/native/write_handler.h index 50f85445..f9bd8542 100644 --- a/native/write_handler.h +++ b/native/write_handler.h @@ -21,8 +21,8 @@ class WriteHandler : public CefWriteHandler { // CefWriteHandler methods virtual size_t Write(const void* ptr, size_t size, size_t n) override; - virtual int Seek(int64 offset, int whence) override; - virtual int64 Tell() override; + virtual int Seek(int64_t offset, int whence) override; + virtual int64_t Tell() override; virtual int Flush() override; virtual bool MayBlock() override; diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..2ddf2f4f --- /dev/null +++ b/pom.xml @@ -0,0 +1,1103 @@ + + + 4.0.0 + com.enactor.core + java-cef + 1.0.0 + Java Chromium Embedded Framework + + 10 + 10 + https://dev.enactor.co.uk/artifactory/libs-release-local + https://dev.enactor.co.uk/artifactory/libs-snapshot-local + ${repository.url.release} + www.enactor.co.uk + true + false + ${cmake.download} + + + + ${repository.id} + www.enactor.co.uk-snapshots + ${repository.url.snapshot} + + + ${repository.id} + www.enactor.co.uk-releases + ${repository.url.release} + + + + + + maven-antrun-plugin + + + generate-resources + + run + + + + ${java.home} + + + + + + + pl.project13.maven + git-commit-id-plugin + + + get-the-git-infos + + revision + + validate + + + + ${project.basedir}/.git + + + + + + + com.googlecode.cmake-maven-project + cmake-maven-plugin + 3.7.2-b1 + + + pl.project13.maven + git-commit-id-plugin + 2.2.6 + + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + + + + + generate-windows + + + windows + + + + win64 + windows-amd64 + + + + + com.googlecode.cmake-maven-project + cmake-maven-plugin + + + cmake-generate-windows + + generate + + + ${basedir} + ${basedir}/jcef_build + Visual Studio 17 2022 + windows-x86_64 + + ${java.home} + + + + + + + + + + + + cmake-compile-windows + + compile + + + Release + ${basedir}/jcef_build + windows-x86_64 + + ${java.home} + + + + + + + maven-antrun-plugin + + + compile + package + + run + + + + + + + + + + + + + package + package + + run + + + + + + + + + + + + + + + maven-install-plugin + + + install-jogl-all + install + + install-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jogl-all.jar + com.enactor.core + jogl-all + ${project.version} + jar + + + + install-jogl-all-natives + install + + install-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jogl-all-natives-${distribution.arch}.jar + com.enactor.core + jogl-all-natives + ${project.version} + ${distribution.arch} + jar + + + + install-jcef + install + + install-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jcef.jar + com.enactor.core + jcef + ${project.version} + jar + + + + install-gluegen-rt + install + + install-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/gluegen-rt.jar + com.enactor.core + gluegen-rt + ${project.version} + jar + + + + install-gluegen-rt-natives + install + + install-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/gluegen-rt-natives-${distribution.arch}.jar + com.enactor.core + gluegen-rt-natives + ${project.version} + ${distribution.arch} + jar + + + + + + maven-assembly-plugin + + + package + + single + + + + + chromium-binaries-windows + + assemble-windows.xml + + false + + + + org.apache.maven.plugins + maven-deploy-plugin + + ${skip.deploy} + + + + deploy-jogl-all + deploy + + deploy-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jogl-all.jar + ${repository.id} + ${repository.url} + com.enactor.core + jogl-all + ${project.version} + jar + + + + deploy-jogl-all-natives + deploy + + deploy-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jogl-all-natives-${distribution.arch}.jar + ${repository.id} + ${repository.url} + com.enactor.core + jogl-all-natives + ${project.version} + ${distribution.arch} + jar + + + + deploy-jcef + deploy + + deploy-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jcef.jar + ${repository.id} + ${repository.url} + com.enactor.core + jcef + ${project.version} + jar + + + + deploy-gluegen-rt + deploy + + deploy-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/gluegen-rt.jar + ${repository.id} + ${repository.url} + com.enactor.core + gluegen-rt + ${project.version} + jar + + + + deploy-gluegen-rt-natives + deploy + + deploy-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/gluegen-rt-natives-${distribution.arch}.jar + ${repository.id} + ${repository.url} + com.enactor.core + gluegen-rt-natives + ${project.version} + ${distribution.arch} + jar + + + + deploy-native-binaries + deploy + + deploy-file + + + ${basedir}/target/chromium-binaries-windows.zip + ${repository.id} + ${repository.url} + com.enactor.chromium + windows-binaries + ${project.version} + zip + + + + + + + + + + generate-linux + + + unix + Linux + + + + linux64 + linux-amd64 + + + + + com.googlecode.cmake-maven-project + cmake-maven-plugin + + + cmake-generate-linux + + generate + + + ${basedir} + ${basedir}/jcef_build + Ninja + linux-x86_64 + + ${java.home} + + + + + + + + + + + cmake-compile-linux + + compile + + + Release + ${basedir}/jcef_build + linux-x86_64 + + ${java.home} + + + + + + + maven-antrun-plugin + + + compile + package + + run + + + + + + + + + + + + package + package + + run + + + + + + + + + + + + strip-binary + package + + run + + + + + + + + + + + + + + maven-install-plugin + + + install-jogl-all + install + + install-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jogl-all.jar + com.enactor.core + jogl-all + ${project.version} + jar + + + + install-jogl-all-natives + install + + install-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jogl-all-natives-${distribution.arch}.jar + com.enactor.core + jogl-all-natives + ${project.version} + ${distribution.arch} + jar + + + + install-jcef + install + + install-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jcef.jar + com.enactor.core + jcef + ${project.version} + jar + + + + install-gluegen-rt + install + + install-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/gluegen-rt.jar + com.enactor.core + gluegen-rt + ${project.version} + jar + + + + install-gluegen-rt-natives + install + + install-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/gluegen-rt-natives-${distribution.arch}.jar + com.enactor.core + gluegen-rt-natives + ${project.version} + ${distribution.arch} + jar + + + + + + maven-assembly-plugin + + + assemble-linux-binaries + package + + single + + + chromium-binaries-linux + + assemble-linux.xml + + false + + + + assemble-linux-striped-binaries + package + + single + + + chromium-binaries-linux-striped + + assemble-striped-linux.xml + + false + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + ${skip.deploy} + + + + deploy-jogl-all + deploy + + deploy-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jogl-all.jar + ${repository.id} + ${repository.url} + com.enactor.core + jogl-all + ${project.version} + jar + + + + deploy-jogl-all-natives + deploy + + deploy-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jogl-all-natives-${distribution.arch}.jar + ${repository.id} + ${repository.url} + com.enactor.core + jogl-all-natives + ${project.version} + ${distribution.arch} + jar + + + + deploy-jcef + none + + deploy-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/jcef.jar + ${repository.id} + ${repository.url} + com.enactor.core + jcef + ${project.version} + jar + + + + deploy-gluegen-rt + deploy + + deploy-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/gluegen-rt.jar + ${repository.id} + ${repository.url} + com.enactor.core + gluegen-rt + ${project.version} + jar + + + + deploy-gluegen-rt-natives + deploy + + deploy-file + + + ${basedir}/binary_distrib/${distribution.folder}/bin/gluegen-rt-natives-${distribution.arch}.jar + ${repository.id} + ${repository.url} + com.enactor.core + gluegen-rt-natives + ${project.version} + ${distribution.arch} + jar + + + + deploy-native-binaries + deploy + + deploy-file + + + ${basedir}/target/chromium-binaries-linux.zip + ${repository.id} + ${repository.url} + com.enactor.chromium + linux-binaries + ${project.version} + zip + + + + deploy-striped-native-binaries + deploy + + deploy-file + + + ${basedir}/target/chromium-binaries-linux-striped.zip + ${repository.id} + ${repository.url} + com.enactor.chromium + linux-striped-binaries + ${project.version} + zip + + + + + + + + + generate-mac-amd64 + + + mac + x86_64 + + + + macosx64 + macos-amd64 + + + + + com.googlecode.cmake-maven-project + cmake-maven-plugin + + + cmake-generate-mac + + generate + + + ${basedir} + ${basedir}/jcef_build + Xcode + mac-x86_64 + + + + + + + + + + + + + + + cmake-compile-mac + + compile + + + Release + ${basedir}/jcef_build + mac-x86_64 + + + + + + + + maven-antrun-plugin + + + package + package + + run + + + + + + + + + + + + + + maven-install-plugin + + + deploy-jcef + install + + install-file + + + ${basedir}/jcef_build/native/Release/jcef.jar/ + com.enactor.core + jcef + ${project.version} + jar + + + + deploy-jcef-test + install + + install-file + + + ${basedir}/jcef_build/native/Release/jcef-tests.jar/ + com.enactor.core + jcef-tests + ${project.version} + jar + + + + + + maven-assembly-plugin + + + package + + single + + + + + chromium-binaries-${distribution.arch} + + assemble-mac-os.xml + + false + + + + org.apache.maven.plugins + maven-deploy-plugin + + ${skip.deploy} + + + + deploy-jcef + deploy + + deploy-file + + + ${basedir}/jcef_build/native/Release/jcef.jar + ${repository.id} + ${repository.url} + com.enactor.core + jcef + ${project.version} + jar + + + + deploy-native-binaries + deploy + + deploy-file + + + ${basedir}/target/chromium-binaries-${distribution.arch}.zip + ${repository.id} + ${repository.url} + com.enactor.chromium + mac-binaries + ${project.version} + ${distribution.arch} + zip + + + + + + + + + generate-mac-arm64 + + + mac + arm64 + + + + macosx64 + macos-arm64 + + + + + com.googlecode.cmake-maven-project + cmake-maven-plugin + + + cmake-generate-mac + + generate + + + ${basedir} + ${basedir}/jcef_build + Xcode + mac-x86_64 + + + + + + + + + + + + + + + cmake-compile-mac + + compile + + + Release + ${basedir}/jcef_build + mac-x86_64 + + + + + + + + maven-antrun-plugin + + + package + package + + run + + + + + + + + + + + + + + maven-install-plugin + + + deploy-jcef + install + + install-file + + + ${basedir}/jcef_build/native/Release/jcef.jar/ + com.enactor.core + jcef + ${project.version} + jar + + + + deploy-jcef-test + install + + install-file + + + ${basedir}/jcef_build/native/Release/jcef-tests.jar/ + com.enactor.core + jcef-tests + ${project.version} + jar + + + + + + maven-assembly-plugin + + + package + + single + + + + + chromium-binaries-${distribution.arch} + + assemble-mac-os.xml + + false + + + + org.apache.maven.plugins + maven-deploy-plugin + + ${skip.deploy} + + + + deploy-jcef + deploy + + deploy-file + + + ${basedir}/jcef_build/native/Release/jcef.jar + ${repository.id} + ${repository.url} + com.enactor.core + jcef + ${project.version} + jar + + + + deploy-native-binaries + deploy + + deploy-file + + + ${basedir}/target/chromium-binaries-${distribution.arch}.zip + ${repository.id} + ${repository.url} + com.enactor.chromium + mac-binaries + ${project.version} + ${distribution.arch} + zip + + + + + + + + + + + + + org.jogamp.gluegen + gluegen-rt-main + 2.3.2 + + + org.jogamp.jogl + jogl-all-main + 2.3.2 + + org.apache.commons + commons-lang3 + 3.8.1 + + + org.apache.logging.log4j + log4j-api + 2.11.2 + + + org.apache.logging.log4j + log4j-core + 2.11.2 + + + diff --git a/strip_binaries.sh b/strip_binaries.sh new file mode 100644 index 00000000..893e9a42 --- /dev/null +++ b/strip_binaries.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# 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. + +if [ -z "$1" ]; then + echo "ERROR: Please specify a binaries path" +else + +mkdir $1/strip + +cp $1/libcef.so $1/strip/libcef.so +cp $1/libEGL.so $1/strip/libEGL.so +cp $1/libGLESv2.so $1/strip/libGLESv2.so +cp $1/libjcef.so $1/strip/libjcef.so + +strip -s $1/strip/libcef.so +strip -s $1/strip/libEGL.so +strip -s $1/strip/libGLESv2.so +strip -s $1/strip/libjcef.so +fi diff --git a/tools/buildtools/README.jcef b/tools/buildtools/README.jcef index c90189e4..298b17d1 100644 --- a/tools/buildtools/README.jcef +++ b/tools/buildtools/README.jcef @@ -1,8 +1,8 @@ Name: depot_tools Short Name: depot_tools URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git -Date: 11 Jan 2020 -Revision: 7a8bf9489 +Date: 21 Sep 2022 +Revision: 08bb5c487f License: BSD License File: LICENSE @@ -11,4 +11,3 @@ Select tools extracted from depot_tools. Local Modifications: - Remove dependency on vpython. -- Update gsutil version to 4.46. diff --git a/tools/buildtools/download_from_google_storage.py b/tools/buildtools/download_from_google_storage.py index 3f279545..fb3fb985 100644 --- a/tools/buildtools/download_from_google_storage.py +++ b/tools/buildtools/download_from_google_storage.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. - """Download files from Google Storage based on SHA1 sums.""" from __future__ import print_function @@ -45,9 +44,10 @@ 'aix7': 'aix', } - -class FileNotFoundError(IOError): - pass +if sys.version_info.major == 2: + # pylint: disable=redefined-builtin + class FileNotFoundError(IOError): + pass class InvalidFileError(IOError): @@ -78,12 +78,11 @@ class Gsutil(object): RETRY_BASE_DELAY = 5.0 RETRY_DELAY_MULTIPLE = 1.3 - def __init__(self, path, boto_path=None, version='4.46'): + def __init__(self, path, boto_path=None): if not os.path.exists(path): raise FileNotFoundError('GSUtil not found in %s' % path) self.path = path self.boto_path = boto_path - self.version = version def get_sub_env(self): env = os.environ.copy() @@ -100,12 +99,12 @@ def get_sub_env(self): return env def call(self, *args): - cmd = [sys.executable, self.path, '--force-version', self.version] + cmd = [sys.executable, self.path] cmd.extend(args) return subprocess2.call(cmd, env=self.get_sub_env()) def check_call(self, *args): - cmd = [sys.executable, self.path, '--force-version', self.version] + cmd = [sys.executable, self.path] cmd.extend(args) ((out, err), code) = subprocess2.communicate( cmd, @@ -129,7 +128,7 @@ def check_call(self, *args): def check_call_with_retries(self, *args): delay = self.RETRY_BASE_DELAY - for i in xrange(self.MAX_TRIES): + for i in range(self.MAX_TRIES): code, out, err = self.check_call(*args) if not code or i == self.MAX_TRIES - 1: break @@ -254,40 +253,59 @@ def _downloader_worker_thread(thread_num, q, force, base_url, continue extract_dir = output_filename[:-len('.tar.gz')] if os.path.exists(output_filename) and not force: - if not extract or os.path.exists(extract_dir): - if get_sha1(output_filename) == input_sha1_sum: - continue - # Check if file exists. + skip = get_sha1(output_filename) == input_sha1_sum + if extract: + # Additional condition for extract: + # 1) extract_dir must exist + # 2) .tmp flag file mustn't exist + if not os.path.exists(extract_dir): + out_q.put('%d> Extract dir %s does not exist, re-downloading...' % + (thread_num, extract_dir)) + skip = False + # .tmp file is created just before extraction and removed just after + # extraction. If such file exists, it means the process was terminated + # mid-extraction and therefore needs to be extracted again. + elif os.path.exists(extract_dir + '.tmp'): + out_q.put('%d> Detected tmp flag file for %s, ' + 're-downloading...' % (thread_num, output_filename)) + skip = False + if skip: + continue + file_url = '%s/%s' % (base_url, input_sha1_sum) - (code, _, err) = gsutil.check_call('ls', file_url) + + try: + if delete: + os.remove(output_filename) # Delete the file if it exists already. + except OSError: + if os.path.exists(output_filename): + out_q.put('%d> Warning: deleting %s failed.' % ( + thread_num, output_filename)) + if verbose: + out_q.put('%d> Downloading %s@%s...' % ( + thread_num, output_filename, input_sha1_sum)) + code, _, err = gsutil.check_call('cp', file_url, output_filename) if code != 0: if code == 404: out_q.put('%d> File %s for %s does not exist, skipping.' % ( thread_num, file_url, output_filename)) ret_codes.put((1, 'File %s for %s does not exist.' % ( file_url, output_filename))) + elif code == 401: + out_q.put( + """%d> Failed to fetch file %s for %s due to unauthorized access, + skipping. Try running `gsutil.py config` and pass 0 if you don't + know your project id.""" % (thread_num, file_url, output_filename)) + ret_codes.put( + (1, 'Failed to fetch file %s for %s due to unauthorized access.' % + (file_url, output_filename))) else: # Other error, probably auth related (bad ~/.boto, etc). out_q.put('%d> Failed to fetch file %s for %s, skipping. [Err: %s]' % (thread_num, file_url, output_filename, err)) - ret_codes.put((1, 'Failed to fetch file %s for %s. [Err: %s]' % + ret_codes.put((code, 'Failed to fetch file %s for %s. [Err: %s]' % (file_url, output_filename, err))) continue - # Fetch the file. - if verbose: - out_q.put('%d> Downloading %s...' % (thread_num, output_filename)) - try: - if delete: - os.remove(output_filename) # Delete the file if it exists already. - except OSError: - if os.path.exists(output_filename): - out_q.put('%d> Warning: deleting %s failed.' % ( - thread_num, output_filename)) - code, _, err = gsutil.check_call('cp', file_url, output_filename) - if code != 0: - out_q.put('%d> %s' % (thread_num, err)) - ret_codes.put((code, err)) - continue remote_sha1 = get_sha1(output_filename) if remote_sha1 != input_sha1_sum: @@ -327,7 +345,9 @@ def _downloader_worker_thread(thread_num, q, force, base_url, out_q.put('%d> Extracting %d entries from %s to %s' % (thread_num, len(tar.getmembers()),output_filename, extract_dir)) - tar.extractall(path=dirname) + with open(extract_dir + '.tmp', 'a'): + tar.extractall(path=dirname) + os.remove(extract_dir + '.tmp') # Set executable bit. if sys.platform == 'cygwin': # Under cygwin, mark all files as executable. The executable flag in @@ -373,7 +393,7 @@ def _data_exists(input_sha1_sum, output_filename, extract): input_sha1_sum: Expected sha1 stored on disk. output_filename: The file to potentially download later. Its sha1 will be compared to input_sha1_sum. - extract: Wheather or not a downloaded file should be extracted. If the file + extract: Whether or not a downloaded file should be extracted. If the file is not extracted, this just compares the sha1 of the file. If the file is to be extracted, this only compares the sha1 of the target archive if the target directory already exists. The content of the target directory diff --git a/tools/buildtools/gsutil.py b/tools/buildtools/gsutil.py index 63847d21..cff91fa7 100644 --- a/tools/buildtools/gsutil.py +++ b/tools/buildtools/gsutil.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2014 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -31,11 +31,11 @@ THIS_DIR = os.path.dirname(os.path.abspath(__file__)) DEFAULT_BIN_DIR = os.path.join(THIS_DIR, 'external_bin', 'gsutil') -DEFAULT_FALLBACK_GSUTIL = os.path.join( - THIS_DIR, 'third_party', 'gsutil', 'gsutil') IS_WINDOWS = os.name == 'nt' +VERSION = '4.68' + class InvalidGsutilError(Exception): pass @@ -79,7 +79,7 @@ def download_gsutil(version, target_dir): @contextlib.contextmanager def temporary_directory(base): - tmpdir = tempfile.mkdtemp(prefix='gsutil_py', dir=base) + tmpdir = tempfile.mkdtemp(prefix='t', dir=base) try: yield tmpdir finally: @@ -98,7 +98,20 @@ def ensure_gsutil(version, target, clean): return gsutil_bin if not os.path.exists(target): - os.makedirs(target) + try: + os.makedirs(target) + except FileExistsError: + # Another process is prepping workspace, so let's check if gsutil_bin is + # present. If after several checks it's still not, continue with + # downloading gsutil. + delay = 2 # base delay, in seconds + for _ in range(3): # make N attempts + # sleep first as it's not expected to have file ready just yet. + time.sleep(delay) + delay *= 1.5 # next delay increased by that factor + if os.path.isfile(gsutil_bin): + return gsutil_bin + with temporary_directory(target) as instance_dir: # Clean up if we're redownloading a corrupted gsutil. cleanup_path = os.path.join(instance_dir, 'clean') @@ -109,16 +122,12 @@ def ensure_gsutil(version, target, clean): if cleanup_path: shutil.rmtree(cleanup_path) - download_dir = os.path.join(instance_dir, 'download') + download_dir = os.path.join(instance_dir, 'd') target_zip_filename = download_gsutil(version, instance_dir) with zipfile.ZipFile(target_zip_filename, 'r') as target_zip: target_zip.extractall(download_dir) - try: - os.rename(download_dir, bin_dir) - except (OSError, IOError): - # Something else did this in parallel. - pass + shutil.move(download_dir, bin_dir) # Final check that the gsutil bin exists. This should never fail. if not os.path.isfile(gsutil_bin): raise InvalidGsutilError() @@ -129,29 +138,45 @@ def ensure_gsutil(version, target, clean): return gsutil_bin -def run_gsutil(force_version, fallback, target, args, clean=False): - if force_version: - gsutil_bin = ensure_gsutil(force_version, target, clean) - else: - gsutil_bin = fallback - disable_update = ['-o', 'GSUtil:software_update_check_period=0'] - cmd = [sys.executable, gsutil_bin] + disable_update + args - return subprocess.call(cmd) +def run_gsutil(target, args, clean=False): + gsutil_bin = ensure_gsutil(VERSION, target, clean) + args_opt = ['-o', 'GSUtil:software_update_check_period=0'] + if sys.platform == 'darwin': + # We are experiencing problems with multiprocessing on MacOS where gsutil.py + # may hang. + # This behavior is documented in gsutil codebase, and recommendation is to + # set GSUtil:parallel_process_count=1. + # https://github.com/GoogleCloudPlatform/gsutil/blob/06efc9dc23719fab4fd5fadb506d252bbd3fe0dd/gslib/command.py#L1331 + # https://github.com/GoogleCloudPlatform/gsutil/issues/1100 + args_opt.extend(['-o', 'GSUtil:parallel_process_count=1']) + assert sys.platform != 'cygwin' + cmd = [ + sys.executable, + gsutil_bin + ] + args_opt + args + return subprocess.call(cmd, shell=IS_WINDOWS) def parse_args(): bin_dir = os.environ.get('DEPOT_TOOLS_GSUTIL_BIN_DIR', DEFAULT_BIN_DIR) - parser = argparse.ArgumentParser() - parser.add_argument('--force-version', default='4.30') + # Help is disabled as it conflicts with gsutil -h, which controls headers. + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('--clean', action='store_true', help='Clear any existing gsutil package, forcing a new download.') - parser.add_argument('--fallback', default=DEFAULT_FALLBACK_GSUTIL) parser.add_argument('--target', default=bin_dir, help='The target directory to download/store a gsutil version in. ' '(default is %(default)s).') + + # These two args exist for backwards-compatibility but are no-ops. + parser.add_argument('--force-version', default=VERSION, + help='(deprecated, this flag has no effect)') + parser.add_argument('--fallback', + help='(deprecated, this flag has no effect)') + parser.add_argument('args', nargs=argparse.REMAINDER) args, extras = parser.parse_known_args() @@ -164,8 +189,7 @@ def parse_args(): def main(): args = parse_args() - return run_gsutil(args.force_version, args.fallback, args.target, args.args, - clean=args.clean) + return run_gsutil(args.target, args.args, clean=args.clean) if __name__ == '__main__': diff --git a/tools/buildtools/linux64/clang-format.sha1 b/tools/buildtools/linux64/clang-format.sha1 index e2b3199a..6f3349c5 100644 --- a/tools/buildtools/linux64/clang-format.sha1 +++ b/tools/buildtools/linux64/clang-format.sha1 @@ -1 +1 @@ -942fc8b1789144b8071d3fc03ff0fcbe1cf81ac8 \ No newline at end of file +dd736afb28430c9782750fc0fd5f0ed497399263 \ No newline at end of file diff --git a/tools/buildtools/mac/clang-format.arm64.sha1 b/tools/buildtools/mac/clang-format.arm64.sha1 new file mode 100644 index 00000000..46f9b3c1 --- /dev/null +++ b/tools/buildtools/mac/clang-format.arm64.sha1 @@ -0,0 +1 @@ +f1424c44ee758922823d6b37de43705955c99d7e \ No newline at end of file diff --git a/tools/buildtools/mac/clang-format.sha1 b/tools/buildtools/mac/clang-format.sha1 deleted file mode 100644 index d32c6265..00000000 --- a/tools/buildtools/mac/clang-format.sha1 +++ /dev/null @@ -1 +0,0 @@ -025ca7c75f37ef4a40f3a67d81ddd11d7d0cdb9b \ No newline at end of file diff --git a/tools/buildtools/mac/clang-format.x64.sha1 b/tools/buildtools/mac/clang-format.x64.sha1 new file mode 100644 index 00000000..3a23ea22 --- /dev/null +++ b/tools/buildtools/mac/clang-format.x64.sha1 @@ -0,0 +1 @@ +a1b33be85faf2578f3101d7806e443e1c0949498 \ No newline at end of file diff --git a/tools/buildtools/subprocess2.py b/tools/buildtools/subprocess2.py index dea1a2d6..7df49da1 100644 --- a/tools/buildtools/subprocess2.py +++ b/tools/buildtools/subprocess2.py @@ -21,18 +21,18 @@ if sys.version_info.major == 2: import Queue codecs.lookup('string-escape') + # Sends stdout or stderr to os.devnull. + DEVNULL = open(os.devnull, 'r+') else: import queue as Queue # pylint: disable=redefined-builtin basestring = (str, bytes) + DEVNULL = subprocess.DEVNULL # Constants forwarded from subprocess. PIPE = subprocess.PIPE STDOUT = subprocess.STDOUT -# Sends stdout or stderr to os.devnull. -VOID = open(os.devnull, 'w') -VOID_INPUT = open(os.devnull, 'r') class CalledProcessError(subprocess.CalledProcessError): @@ -48,7 +48,11 @@ def __str__(self): ' '.join(self.cmd), self.returncode) if self.cwd: out += ' in ' + self.cwd - return '\n'.join(filter(None, (out, self.stdout, self.stderr))) + if self.stdout: + out += '\n' + self.stdout.decode('utf-8', 'ignore') + if self.stderr: + out += '\n' + self.stderr.decode('utf-8', 'ignore') + return out class CygwinRebaseError(CalledProcessError): @@ -103,7 +107,7 @@ class Popen(subprocess.Popen): in English. - Sets shell=True on windows by default. You can override this by forcing shell parameter to a value. - - Adds support for VOID to not buffer when not needed. + - Adds support for DEVNULL to not buffer when not needed. - Adds self.start property. Note: Popen() can throw OSError when cwd or args[0] doesn't exist. Translate @@ -121,6 +125,17 @@ def __init__(self, args, **kwargs): env = get_english_env(kwargs.get('env')) if env: kwargs['env'] = env + if kwargs.get('env') is not None and sys.version_info.major != 2: + # Subprocess expects environment variables to be strings in Python 3. + def ensure_str(value): + if isinstance(value, bytes): + return value.decode() + return value + + kwargs['env'] = { + ensure_str(k): ensure_str(v) + for k, v in kwargs['env'].items() + } if kwargs.get('shell') is None: # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for # the executable, but shell=True makes subprocess on Linux fail when it's @@ -182,14 +197,16 @@ def communicate(args, **kwargs): def call(args, **kwargs): """Emulates subprocess.call(). - Automatically convert stdout=PIPE or stderr=PIPE to VOID. + Automatically convert stdout=PIPE or stderr=PIPE to DEVNULL. In no case they can be returned since no code path raises subprocess2.CalledProcessError. + + Returns exit code. """ if kwargs.get('stdout') == PIPE: - kwargs['stdout'] = VOID + kwargs['stdout'] = DEVNULL if kwargs.get('stderr') == PIPE: - kwargs['stderr'] = VOID + kwargs['stderr'] = DEVNULL return communicate(args, **kwargs)[1] @@ -219,7 +236,7 @@ def capture(args, **kwargs): - Discards returncode. - Blocks stdin by default if not specified since no output will be visible. """ - kwargs.setdefault('stdin', VOID_INPUT) + kwargs.setdefault('stdin', DEVNULL) # Like check_output, deny the caller from using stdout arg. return communicate(args, stdout=PIPE, **kwargs)[0][0] @@ -235,7 +252,7 @@ def check_output(args, **kwargs): - Blocks stdin by default if not specified since no output will be visible. - As per doc, "The stdout argument is not allowed as it is used internally." """ - kwargs.setdefault('stdin', VOID_INPUT) + kwargs.setdefault('stdin', DEVNULL) if 'stdout' in kwargs: raise ValueError('stdout argument not allowed, it would be overridden.') return check_call_out(args, stdout=PIPE, **kwargs)[0] diff --git a/tools/buildtools/win/clang-format.exe.sha1 b/tools/buildtools/win/clang-format.exe.sha1 index d31c76fe..c7efe6fb 100644 --- a/tools/buildtools/win/clang-format.exe.sha1 +++ b/tools/buildtools/win/clang-format.exe.sha1 @@ -1 +1 @@ -b5f5d8d5f8a8fcd2edb5b6cae37c0dc3e129c945 \ No newline at end of file +66882fadbf9e99cc00b8677d8c1e7e8b3cfdf4fe \ No newline at end of file diff --git a/tools/distrib/linux32/run.sh b/tools/distrib/linux32/run.sh index 93f7482d..a085a0ca 100755 --- a/tools/distrib/linux32/run.sh +++ b/tools/distrib/linux32/run.sh @@ -13,6 +13,16 @@ else EXAMPLE="$1" fi +# Necessary for libjcef.so to find libjawt.so. +JAVA_PATH="$(readlink -f $(which java))" +JAVA_LIB_PATH="$(dirname ${JAVA_PATH})/../lib" +if [ ! -d "$JAVA_LIB_PATH" ]; then + echo "ERROR: Java lib path does not exist" + exit 1 +fi + +LIB_PATH="${LIB_PATH}:${JAVA_LIB_PATH}" + # Necessary for jcef_helper to find libcef.so. if [ -n "$LD_LIBRARY_PATH" ]; then LD_LIBRARY_PATH="$LIB_PATH:${LD_LIBRARY_PATH}" diff --git a/tools/distrib/linux64/run.sh b/tools/distrib/linux64/run.sh index cbb4fd4c..b3fccc28 100755 --- a/tools/distrib/linux64/run.sh +++ b/tools/distrib/linux64/run.sh @@ -13,6 +13,16 @@ else EXAMPLE="$1" fi +# Necessary for libjcef.so to find libjawt.so. +JAVA_PATH="$(readlink -f $(which java))" +JAVA_LIB_PATH="$(dirname ${JAVA_PATH})/../lib" +if [ ! -d "$JAVA_LIB_PATH" ]; then + echo "ERROR: Java lib path does not exist" + exit 1 +fi + +LIB_PATH="${LIB_PATH}:${JAVA_LIB_PATH}" + # Necessary for jcef_helper to find libcef.so. if [ -n "$LD_LIBRARY_PATH" ]; then LD_LIBRARY_PATH="$LIB_PATH:${LD_LIBRARY_PATH}" diff --git a/tools/fix_style.sh b/tools/fix_style.sh index c466ab06..042c01f2 100755 --- a/tools/fix_style.sh +++ b/tools/fix_style.sh @@ -1,2 +1,2 @@ #!/bin/sh -python tools/fix_style.py $@ +python3 tools/fix_style.py $@ 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 diff --git a/tools/make_distrib.bat b/tools/make_distrib.bat index 5deb8c9b..f4863b12 100644 --- a/tools/make_distrib.bat +++ b/tools/make_distrib.bat @@ -75,8 +75,10 @@ copy %OUT_BINARY_PATH%\libGLESv2.dll %DISTRIB_LIB_PATH% copy %OUT_BINARY_PATH%\natives_blob.bin %DISTRIB_LIB_PATH% copy %OUT_BINARY_PATH%\snapshot_blob.bin %DISTRIB_LIB_PATH% copy %OUT_BINARY_PATH%\v8_context_snapshot.bin %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\vk_swiftshader.dll %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\vk_swiftshader_icd.json %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\vulkan-1.dll %DISTRIB_LIB_PATH% xcopy /sfy %OUT_BINARY_PATH%\*.pak %DISTRIB_LIB_PATH% -xcopy /sfy %OUT_BINARY_PATH%\swiftshader\* %DISTRIB_LIB_PATH%\swiftshader\ :: Copy documentation to the docs directory. xcopy /sfy %OUT_DOCS_PATH%\* %DISTRIB_DOCS_PATH%\ diff --git a/tools/make_distrib.sh b/tools/make_distrib.sh index cd2fd54b..5a9721d4 100755 --- a/tools/make_distrib.sh +++ b/tools/make_distrib.sh @@ -98,7 +98,9 @@ else cp -f "$OUT_BINARY_PATH"/v8_context_snapshot.bin "$DISTRIB_LIB_PATH" cp -f "$OUT_BINARY_PATH"/*.pak "$DISTRIB_LIB_PATH" cp -rf "$OUT_BINARY_PATH"/locales/ "$DISTRIB_LIB_PATH" - cp -rf "$OUT_BINARY_PATH"/swiftshader/ "$DISTRIB_LIB_PATH" + cp -f "$OUT_BINARY_PATH"/libvk_swiftshader.so "$DISTRIB_LIB_PATH" + cp -f "$OUT_BINARY_PATH"/vk_swiftshader_icd.json "$DISTRIB_LIB_PATH" + cp -f "$OUT_BINARY_PATH"/libvulkan.so.1 "$DISTRIB_LIB_PATH" fi fi diff --git a/tools/make_docs.sh b/tools/make_docs.sh index 01e4d522..fb026f12 100755 --- a/tools/make_docs.sh +++ b/tools/make_docs.sh @@ -6,5 +6,5 @@ DIR="$( cd "$( dirname "$0" )" && cd .. && pwd )" OUT_PATH="${DIR}/out/docs" -javadoc -Xdoclint:none -windowtitle "CEF3 Java API Docs" -footer "
Chromium Embedded Framework (CEF) Copyright © 2013 Marshall A. Greenblatt
" -nodeprecated -d "$OUT_PATH" -sourcepath "${DIR}/java" -link http://docs.oracle.com/javase/7/docs/api/ -subpackages org.cef +javadoc --ignore-source-errors -Xdoclint:none -windowtitle "CEF3 Java API Docs" -footer "
Chromium Embedded Framework (CEF) Copyright © 2013 Marshall A. Greenblatt
" -nodeprecated -d "$OUT_PATH" -sourcepath "${DIR}/java" -link http://docs.oracle.com/javase/7/docs/api/ -subpackages org.cef diff --git a/tools/run.sh b/tools/run.sh index 2267bbc7..9d0408ec 100755 --- a/tools/run.sh +++ b/tools/run.sh @@ -20,6 +20,16 @@ else exit 1 fi + # Necessary for libjcef.so to find libjawt.so. + JAVA_PATH="$(readlink -f $(which java))" + JAVA_LIB_PATH="$(dirname ${JAVA_PATH})/../lib" + if [ ! -d "$JAVA_LIB_PATH" ]; then + echo "ERROR: Java lib path does not exist" + exit 1 + fi + + LIB_PATH="${LIB_PATH}:${JAVA_LIB_PATH}" + CLS_PATH="${DIR}/third_party/jogamp/jar/*:$OUT_PATH" RUN_TYPE="$3"