diff --git a/data/health.db b/data/health.db index 212f01e..851cb6f 100644 Binary files a/data/health.db and b/data/health.db differ diff --git a/lib/chromiumembedded-java-cef-cffac273e4f9.zip b/lib/chromiumembedded-java-cef-cffac273e4f9.zip new file mode 100644 index 0000000..08e278f Binary files /dev/null and b/lib/chromiumembedded-java-cef-cffac273e4f9.zip differ diff --git a/lib/jcef/.clang-format b/lib/jcef/.clang-format new file mode 100644 index 0000000..6fdf1dc --- /dev/null +++ b/lib/jcef/.clang-format @@ -0,0 +1,8 @@ +# Defines the Chromium style for automatic reformatting. +# http://clang.llvm.org/docs/ClangFormatStyleOptions.html +BasedOnStyle: Chromium +# This defaults to 'Auto'. Explicitly set it for a while, so that +# 'vector >' in existing files gets formatted to +# 'vector>'. ('Auto' means that clang-format will only use +# 'int>>' if the file already contains at least one such instance.) +Standard: Cpp11 diff --git a/lib/jcef/.github/ISSUE_TEMPLATE/bug_report.md b/lib/jcef/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..33f56a0 --- /dev/null +++ b/lib/jcef/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,39 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen and what happened instead. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Versions (please complete the following information):** + - OS: [e.g. Windows 10, MacOS 13.2, Ubuntu 22.10] + - Java Version: [e.g. OpenJDK 14] + - JCEF Version: [e.g. 87476e9] + - CEF Version: [e.g. 110.0.25] + +**Additional context** +Does the problem reproduce with the JCEF simple or detailed sample application at the same version? + +Does the problem reproduce with the CEF cefclient or cefsimple sample application at the same version? + +Does the problem reproduce with Google Chrome at the same version? + +Add any other context about the problem here. diff --git a/lib/jcef/.github/ISSUE_TEMPLATE/feature_request.md b/lib/jcef/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..11fc491 --- /dev/null +++ b/lib/jcef/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/lib/jcef/.gitignore b/lib/jcef/.gitignore new file mode 100644 index 0000000..e7bc7d0 --- /dev/null +++ b/lib/jcef/.gitignore @@ -0,0 +1,57 @@ +*.gypcmd +*.mk +*.ncb +*.opensdf +*.props +*.pyc +*.rules +*.sdf +*.sln +*.sublime-project +*.sublime-workspace +*.suo +*.targets +*.user +*.vcproj +*.vcxproj +*.vcxproj.filters +*.vpj +*.vpw +*.vpwhistu +*.vtg +*.xcodeproj +*.xcworkspace +*_proto.xml +*_proto_cpp.xml +*~ +!Android.mk +.*.sw? +.DS_Store +.classpath +.cproject +.gdb_history +.gdbinit +.landmines +.metadata +.project +.pydevproject +# Settings directory for eclipse +/.settings +.checkstyle +cscope.* +Session.vim +tags +Thumbs.db +# JCEF generated directories +/binary_distrib +/jcef_build +/out +# JCEF generated files +/native/jcef_version.h +# CEF downloads +/third_party/cef/cef_binary_* +# clang-format downloads +/tools/buildtools/external_bin +/tools/buildtools/linux64/clang-format +/tools/buildtools/mac/clang-format +/tools/buildtools/win/clang-format.exe diff --git a/lib/jcef/.style.cfg b/lib/jcef/.style.cfg new file mode 100644 index 0000000..c2a98ee --- /dev/null +++ b/lib/jcef/.style.cfg @@ -0,0 +1,9 @@ +# Copyright (c) 2017 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 + +# Configuration settings for tools/fix_style.py +{ + # Directories containing these path components will be ignored. + 'ignore_directories': ['binary_distrib', 'buildtools', 'jcef_build', 'out', 'third_party', 'yapf'], +} diff --git a/lib/jcef/.style.yapf b/lib/jcef/.style.yapf new file mode 100644 index 0000000..de0c6a7 --- /dev/null +++ b/lib/jcef/.style.yapf @@ -0,0 +1,2 @@ +[style] +based_on_style = chromium diff --git a/lib/jcef/AUTHORS.txt b/lib/jcef/AUTHORS.txt new file mode 100644 index 0000000..3d45c0a --- /dev/null +++ b/lib/jcef/AUTHORS.txt @@ -0,0 +1,8 @@ +# This file is an addendum to the Chromium Embedded Framework AUTHORS file. It +# lists authors through March 18, 2015 when Git was introduced for source code +# management. A list of additional authors added after that date can be found +# by executing this command on a local Git checkout: +# git log --all --format="%aN <%aE>" | sort -u + +Marshall Greenblatt +Kai Klimke, censhare AG diff --git a/lib/jcef/CMakeLists.txt b/lib/jcef/CMakeLists.txt new file mode 100644 index 0000000..c7be0cb --- /dev/null +++ b/lib/jcef/CMakeLists.txt @@ -0,0 +1,317 @@ +# Copyright (c) 2016 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. + +# OVERVIEW +# +# CMake is a cross-platform open-source build system that can generate project +# files in many different formats. It can be downloaded from +# http://www.cmake.org or installed via a platform package manager. +# +# CMake-generated project formats that have been tested with JCEF include: +# +# Linux: Ninja, GCC 7.5.0+, Unix Makefiles +# MacOS: Ninja, Xcode 13.3 to 16.4 +# Windows: Ninja, Visual Studio 2022 +# +# Ninja is a cross-platform open-source tool for running fast builds using +# pre-installed platform toolchains (GNU, clang, Xcode or MSVC). It can be +# downloaded from http://martine.github.io/ninja/ or installed via a platform +# package manager. +# +# BUILD REQUIREMENTS +# +# The below requirements must be met to build JCEF. +# +# - CMake version 3.21 or newer. +# +# - Linux requirements: +# Currently supported distributions include Debian 10 (Buster), Ubuntu 18 +# (Bionic Beaver), and related. Ubuntu 18.04 64-bit with GCC 7.5.0+ is +# recommended. Newer versions will likely also work but may not have been +# tested. +# Required packages include: +# build-essential +# libgtk3.0-dev (required by the cefclient target only) +# +# - MacOS requirements: +# Xcode 13.5 to 16.4 building on MacOS 12.0 (Monterey) or newer. The Xcode +# command-line tools must also be installed. Newer Xcode versions may not have +# been been tested and are not recommended. +# +# - Windows requirements: +# Visual Studio 2022 building on Windows 10 or newer. Windows 10/11 64-bit is +# recommended. Newer versions will likely also work but may not have been +# tested. +# +# BUILD EXAMPLES +# +# The below commands will generate project files and create a Debug build of all +# JCEF native targets using CMake and the platform toolchain. +# +# Start by creating and entering the CMake build output directory. The +#`jcef_build` directory name is required by other JCEF tooling (specifically the +# tools/make_distrib.[bat|sh] and tools/run.[bat|sh] scripts) and should not be +# changed. +# > cd path/to/java-cef/src +# > mkdir jcef_build && cd jcef_build +# +# To perform a Linux build using a 32-bit CEF binary distribution on a 32-bit +# Linux platform or a 64-bit CEF binary distribution on a 64-bit Linux platform: +# Using Unix Makefiles: +# > cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug .. +# > make -j4 +# +# Using Ninja: +# > cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug .. +# > ninja +# +# To perform a MacOS build using a 64-bit CEF binary distribution: +# Using the Xcode IDE: +# > cmake -G "Xcode" -DPROJECT_ARCH="x86_64" .. +# Open jcef.xcodeproj in Xcode and select Product > Build. +# +# Using Ninja: +# > cmake -G "Ninja" -DPROJECT_ARCH="x86_64" -DCMAKE_BUILD_TYPE=Debug .. +# > ninja +# +# To perform a MacOS build using an ARM64 CEF binary distribution: +# Using the Xcode IDE: +# > cmake -G "Xcode" -DPROJECT_ARCH="arm64" .. +# Open jcef.xcodeproj in Xcode and select Product > Build. +# +# Using Ninja: +# > cmake -G "Ninja" -DPROJECT_ARCH="arm64" -DCMAKE_BUILD_TYPE=Debug .. +# > ninja +# +# To perform a Windows build using a 32-bit CEF binary distribution: +# Using the Visual Studio 2022 IDE: +# > cmake -G "Visual Studio 17" -A Win32 .. +# Open jcef.sln in Visual Studio and select Build > Build Solution. +# +# Using Ninja with Visual Studio 2022 command-line tools: +# (this path may be different depending on your Visual Studio installation) +# > "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvars32.bat" +# > cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug .. +# > ninja +# +# To perform a Windows build using a 64-bit CEF binary distribution: +# Using the Visual Studio 2022 IDE: +# > cmake -G "Visual Studio 17" -A x64 .. +# Open jcef.sln in Visual Studio and select Build > Build Solution. +# +# Using Ninja with Visual Studio 2022 command-line tools: +# (this path may be different depending on your Visual Studio installation) +# > "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvars64.bat" +# > cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug .. +# > ninja + +# +# Shared configuration. +# + +# For VS2022 and Xcode 12+ support. +cmake_minimum_required(VERSION 3.21) + +# Only generate Debug and Release configuration types. +set(CMAKE_CONFIGURATION_TYPES Debug Release) + +# Project name. +project(jcef) + +# Use folders in the resulting project files. +set_property(GLOBAL PROPERTY OS_FOLDERS ON) + + +# +# CEF configuration. +# + +# Specify the CEF distribution version. +if(NOT DEFINED CEF_VERSION) + set(CEF_VERSION "143.0.14+gdd46a37+chromium-143.0.7499.193") +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") + if(CMAKE_SIZEOF_VOID_P MATCHES 8) + set(CEF_PLATFORM "linux64") + else() + set(CEF_PLATFORM "linux32") + endif() +elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + if(CMAKE_SIZEOF_VOID_P MATCHES 8) + set(CEF_PLATFORM "windows64") + else() + set(CEF_PLATFORM "windows32") + endif() +endif() + +# Add this project's cmake/ directory to the module path. +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +# Download and extract the CEF binary distribution (executes DownloadCEF.cmake). +include(DownloadCEF) +DownloadCEF("${CEF_PLATFORM}" "${CEF_VERSION}" "${CMAKE_SOURCE_DIR}/third_party/cef") + +# Add the CEF binary distribution's cmake/ directory to the module path. +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CEF_ROOT}/cmake") + +# Load the CEF configuration (executes FindCEF.cmake). +find_package(CEF REQUIRED) + + +# +# Python configuration. +# + +# Support specification of the Python executable path via the command-line. +if(DEFINED ENV{PYTHON_EXECUTABLE}) + file(TO_CMAKE_PATH "$ENV{PYTHON_EXECUTABLE}" PYTHON_EXECUTABLE) +endif() + +if(NOT PYTHON_EXECUTABLE) + unset(PYTHON_EXECUTABLE) + + # Find the python interpreter. + find_package(PythonInterp) + + if(NOT ${PYTHONINTERP_FOUND}) + message(FATAL_ERROR "A Python installation is required. Set the " + "PYTHON_EXECUTABLE environment variable to explicitly " + "specify the Python executable path.") + endif() +endif() + +message(STATUS "Using Python: ${PYTHON_EXECUTABLE}") + + +# +# Java configuration. +# + +# Minimum required Java version. +set(JDK_MIN_VERSION 1.7) + +set(JAVA_FATAL_ERROR "A Java installation is required. Set the JAVA_HOME " + "environment variable to explicitly specify the Java " + "installation directory.") + +# Find the Java Native Interface (JNI) installation. +find_package(JNI ${JDK_MIN_VERSION}) +if(NOT ${JNI_FOUND}) + message(FATAL_ERROR ${JAVA_FATAL_ERROR}) +endif() + +if(OS_MACOSX) + # OS X stores the Java binaries separately from the JNI includes/libraries. + # Find the Java development installation. + find_package(Java ${JDK_MIN_VERSION} COMPONENTS Development) + + if(NOT ${Java_FOUND}) + message(FATAL_ERROR ${JAVA_FATAL_ERROR}) + endif() + + # Determine the root path for the Java installation. + # Remove "bin/javac" from the path. + get_filename_component(JAVA_DIR ${Java_JAVAC_EXECUTABLE} DIRECTORY) + get_filename_component(JAVA_DIR ${JAVA_DIR} DIRECTORY) +else() + # Determine the root path for the Java installation. + # Remove "include" from the path. + get_filename_component(JAVA_DIR ${JAVA_INCLUDE_PATH} DIRECTORY) +endif() + + +# +# Post-configuration actions. +# + +# Generate the JCEF version header. +message(STATUS "Generating native/jcef_version.h file...") +execute_process( + COMMAND "${PYTHON_EXECUTABLE}" + "tools/make_version_header.py" + "--header" + "native/jcef_version.h" + "--cef-path" + "${CEF_ROOT}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE EXECUTE_RV + ) +if(NOT EXECUTE_RV STREQUAL "0") + message(FATAL_ERROR "Execution failed with unexpected result: ${EXECUTE_RV}") +endif() + +# Copy the CEF README.txt file to the cmake build directory for use by the +# make_readme.py script. +file(COPY "${CEF_ROOT}/README.txt" DESTINATION "${CMAKE_BINARY_DIR}") + +# Download clang-format from Google Storage. +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") + 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...") +execute_process( + COMMAND "${PYTHON_EXECUTABLE}" + "tools/buildtools/download_from_google_storage.py" + "--no_resume" + "--platform=${GS_PLATFORM}" + "--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 + ) +if(NOT EXECUTE_RV STREQUAL "0") + message(FATAL_ERROR "Execution failed with unexpected result: ${EXECUTE_RV}") +endif() + + +# +# Include target subdirectories. +# + +add_subdirectory(${CEF_LIBCEF_DLL_WRAPPER_PATH} libcef_dll_wrapper) +add_subdirectory(native) + + +# +# Display configuration settings. +# + +PRINT_CEF_CONFIG() + +message(STATUS "*** JCEF CONFIGURATION SETTINGS ***") +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}") diff --git a/lib/jcef/LICENSE.txt b/lib/jcef/LICENSE.txt new file mode 100644 index 0000000..a5d84ad --- /dev/null +++ b/lib/jcef/LICENSE.txt @@ -0,0 +1,29 @@ +// Copyright (c) 2008-2013 Marshall A. Greenblatt. Portions Copyright (c) +// 2006-2009 Google Inc. 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. diff --git a/lib/jcef/README.md b/lib/jcef/README.md new file mode 100644 index 0000000..c35d593 --- /dev/null +++ b/lib/jcef/README.md @@ -0,0 +1,55 @@ +The Java Chromium Embedded Framework (JCEF) is a simple framework for embedding Chromium-based browsers in other applications using the Java programming language. + +# Quick Links + +* Building JCEF - https://chromiumembedded.github.io/java-cef/branches_and_building +* 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 + +# Introduction + +CEF is a BSD-licensed open source project founded by Marshall Greenblatt in 2008 and based on the [Google Chromium](http://www.chromium.org/Home) project. Unlike the Chromium project itself, which focuses mainly on Google Chrome application development, CEF focuses on facilitating embedded browser use cases in third-party applications. CEF insulates the user from the underlying Chromium and Blink code complexity by offering production-quality stable APIs, release branches tracking specific Chromium releases, and binary distributions. Most features in CEF have default implementations that provide rich functionality while requiring little or no integration work from the user. There are currently over 100 million installed instances of CEF around the world embedded in products from a wide range of companies and industries. A partial list of companies and products using CEF is available on the [CEF Wikipedia page](http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF). Some use cases for CEF include: + +* Embedding an HTML5-compliant Web browser control in an existing native application. +* Creating a light-weight native “shell” application that hosts a user interface developed primarily using Web technologies. +* Rendering Web content “off-screen” in applications that have their own custom drawing frameworks. +* Acting as a host for automated testing of existing Web properties and applications. + +CEF supports a wide range of programming languages and operating systems and can be easily integrated into both new and existing applications. It was designed from the ground up with both performance and ease of use in mind. The base framework includes C and C++ programming interfaces exposed via native libraries that insulate the host application from Chromium and Blink implementation details. It provides close integration between the browser and the host application including support for custom plugins, protocols, JavaScript objects and JavaScript extensions. The host application can optionally control resource loading, navigation, context menus, printing and more, while taking advantage of the same performance and HTML5 technologies available in the Google Chrome Web browser. + +This project provides a Java Wrapper for CEF (JCEF). + +# Building JCEF + +The JCEF project is an extension of the Chromium Embedded Framework (CEF) project hosted at https://github.com/chromiumembedded/cef. JCEF maintains a development branch that tracks the most recent CEF3 release branch. JCEF source code can be downloaded, built and packaged into a binary distribution. Once you have created the binary distribution for your platform you can distribute it as a stand-alone package without further dependencies on the JCEF, CEF or Chromium source code. Visit the [Branches and Building](https://chromiumembedded.github.io/java-cef/branches_and_building) page for detailed instructions. + +# Helping Out + +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://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: + +* Include the JCEF revision, CEF revision or binary distribution version. +* Include information about your OS and compiler version. +* If the issue is a bug please provide detailed reproduction information. +* If the issue is a feature please describe why the feature is beneficial. + +\- Write unit tests for new or existing functionality. + +\- 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: + +\- Create or find an appropriate issue for each distinct bug, feature or change. + +\- Submit a [pull request](https://chromiumembedded.github.io/java-cef/contributing_with_git) or create a patch with your changes and attach it to the JCEF issue. Changes should: + +* Be submitted against the current [JCEF master branch](https://github.com/chromiumembedded/java-cef/tree/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 diff --git a/lib/jcef/appveyor.yml b/lib/jcef/appveyor.yml new file mode 100644 index 0000000..1be24c4 --- /dev/null +++ b/lib/jcef/appveyor.yml @@ -0,0 +1,54 @@ +# This is a configuration file for the continuous delivery service provided +# by AppVeyor.com. Its purpose is to automatically build both the 32 +# and 64 bit versions of the Java Chromium Embedded Framework (JCEF). +# Please refer to https://github.com/chromiumembedded/java-cef +# for more information on JCEF. + +os: Visual Studio 2015 + +clone_folder: c:\projects\java-cef\src + +platform: + - win32 + - x64 + +configuration: + - Release + +environment: + matrix: + - buildType: win32 + generatorName: Visual Studio 14 + JAVA_HOME: C:\Program Files (x86)\Java\jdk1.8.0 + - buildType: win64 + generatorName: Visual Studio 14 Win64 + JAVA_HOME: C:\Program Files\Java\jdk1.8.0 + +matrix: + exclude: + - platform: x64 + buildType: win32 + - platform: win32 + buildType: win64 + +before_build: + - SET PATH=%JAVA_HOME%;%PATH% + - echo "Running cmake..." + - cd c:\projects\java-cef\src + - mkdir jcef_build + - cd jcef_build + - cmake -G "%generatorName%" .. + - echo "Building the JCEF Java classes..." + - cd c:\projects\java-cef\src\tools + - compile.bat %buildType% + +after_build: + - echo "Making distribution..." + - cd c:\projects\java-cef\src\tools\ + - make_distrib.bat %buildType% + - cd c:\projects\java-cef\src\binary_distrib + - 7z a jcef-%buildType%-distribution.zip %buildType% + +artifacts: + - path: binary_distrib\jcef-%buildType%-distribution.zip + name: jcef-%buildType%-distribution diff --git a/lib/jcef/build.xml b/lib/jcef/build.xml new file mode 100644 index 0000000..e7a7707 --- /dev/null +++ b/lib/jcef/build.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/jcef/cmake/DownloadCEF.cmake b/lib/jcef/cmake/DownloadCEF.cmake new file mode 100644 index 0000000..a64592b --- /dev/null +++ b/lib/jcef/cmake/DownloadCEF.cmake @@ -0,0 +1,48 @@ +# Copyright (c) 2016 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. + +# Download the CEF binary distribution for |platform| and |version| to +# |download_dir|. The |CEF_ROOT| variable will be set in global scope pointing +# to the extracted location. +# Visit https://cef-builds.spotifycdn.com/index.html for the list of +# supported platforms and versions. + +function(DownloadCEF platform version download_dir) + # Specify the binary distribution type and download directory. + set(CEF_DISTRIBUTION "cef_binary_${version}_${platform}") + set(CEF_DOWNLOAD_DIR "${download_dir}") + + # The location where we expect the extracted binary distribution. + set(CEF_ROOT "${CEF_DOWNLOAD_DIR}/${CEF_DISTRIBUTION}" CACHE INTERNAL "CEF_ROOT") + + # Download and/or extract the binary distribution if necessary. + if(NOT IS_DIRECTORY "${CEF_ROOT}") + set(CEF_DOWNLOAD_FILENAME "${CEF_DISTRIBUTION}.tar.bz2") + set(CEF_DOWNLOAD_PATH "${CEF_DOWNLOAD_DIR}/${CEF_DOWNLOAD_FILENAME}") + if(NOT EXISTS "${CEF_DOWNLOAD_PATH}") + set(CEF_DOWNLOAD_URL "https://cef-builds.spotifycdn.com/${CEF_DOWNLOAD_FILENAME}") + string(REPLACE "+" "%2B" CEF_DOWNLOAD_URL_ESCAPED ${CEF_DOWNLOAD_URL}) + + # Download the SHA1 hash for the binary distribution. + message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}.sha1 from ${CEF_DOWNLOAD_URL_ESCAPED}...") + file(DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}.sha1" "${CEF_DOWNLOAD_PATH}.sha1") + file(READ "${CEF_DOWNLOAD_PATH}.sha1" CEF_SHA1) + + # Download the binary distribution and verify the hash. + message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}...") + file( + DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}" "${CEF_DOWNLOAD_PATH}" + EXPECTED_HASH SHA1=${CEF_SHA1} + SHOW_PROGRESS + ) + endif() + + # Extract the binary distribution. + message(STATUS "Extracting ${CEF_DOWNLOAD_PATH}...") + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xzf "${CEF_DOWNLOAD_DIR}/${CEF_DOWNLOAD_FILENAME}" + WORKING_DIRECTORY ${CEF_DOWNLOAD_DIR} + ) + endif() +endfunction() diff --git a/lib/jcef/docs/README.md b/lib/jcef/docs/README.md new file mode 100644 index 0000000..1a89654 --- /dev/null +++ b/lib/jcef/docs/README.md @@ -0,0 +1,12 @@ +The Java Chromium Embedded Framework (JCEF) is a simple framework for embedding Chromium-based browsers in other applications using the Java programming language. Visit the [Project Overview page](https://github.com/chromiumembedded/java-cef) for more information. + +# Documentation + +* [Branches And Building](branches_and_building.md) - Information about JCEF branches and instructions for downloading, building and packaging source code. +* [Contributing With Git](contributing_with_git.md) - How to contribute code changes to JCEF using Git. +* [Building Open JDK](building_openjdk.md) - Instructions for building OpenJDK locally for use when debugging Java/JCEF issues. + +# External Links + +* Support Forum - +* Donations - \ No newline at end of file diff --git a/lib/jcef/docs/_config.yml b/lib/jcef/docs/_config.yml new file mode 100644 index 0000000..8f61436 --- /dev/null +++ b/lib/jcef/docs/_config.yml @@ -0,0 +1,3 @@ +title: JCEF Documentation +description: Java Chromium Embedded Framework documentation +theme: jekyll-theme-minimal diff --git a/lib/jcef/docs/assets/css/style.scss b/lib/jcef/docs/assets/css/style.scss new file mode 100644 index 0000000..2e22cfe --- /dev/null +++ b/lib/jcef/docs/assets/css/style.scss @@ -0,0 +1,221 @@ +--- +--- + +@import "{{ site.theme }}"; + +/* Reduce sidebar width */ +header, +footer { + width: 180px; + padding-right: 10px; +} + +section { + width: calc(100% - 200px); + margin-left: 200px; + max-width: 900px !important; +} + +.wrapper { + width: 900px !important; +} + +/* Smaller header text */ +header h1 { + font-size: 1.5em; +} + +/* Fix footer text wrapping */ +header p, +header small { + word-wrap: break-word; + overflow-wrap: break-word; + white-space: normal; + max-width: 100%; + font-size: 0.75em; + display: block; +} + +/* Prevent link hover from adding bold (causes layout shift) */ +a:hover { + font-weight: inherit; +} + +/* Mobile: hide sidebar, full width content */ +@media print, screen and (max-width: 720px) { + header { + width: auto; + padding-right: 0; + } + section { + width: 100%; + margin-left: 0; + max-width: 100% !important; + } + .wrapper { + width: auto !important; + max-width: 100% !important; + } +} + +/* Dark mode support */ +@media (prefers-color-scheme: dark) { + body, + .wrapper { + background-color: #1a1a1a !important; + color: #d0d0d0 !important; + } + + header, + section { + background-color: #1a1a1a !important; + } + + a { + color: #6db3f2 !important; + } + + a:hover { + color: #9dcbf5 !important; + } + + h1, h2, h3, h4, h5, h6 { + color: #f0f0f0 !important; + border-bottom-color: #444 !important; + } + + /* Inline code */ + code { + background-color: #2a2a2a !important; + color: #f0a050 !important; + border: none !important; + border-radius: 3px !important; + } + + /* Code blocks */ + pre { + background-color: #252525 !important; + border: 1px solid #3a3a3a !important; + color: #d0d0d0 !important; + } + + pre code { + background-color: transparent !important; + color: #d0d0d0 !important; + } + + blockquote { + border-left-color: #555 !important; + color: #a0a0a0 !important; + } + + hr { + border-color: #444 !important; + background-color: #444 !important; + } + + table th, + table td { + border-color: #444 !important; + } + + table th { + background-color: #333 !important; + color: #f0f0f0 !important; + font-weight: bold !important; + } + + table tr:nth-child(even) { + background-color: #222 !important; + } + + /* Lists */ + ul, ol, li { + color: #d0d0d0 !important; + } + + /* Strong/bold */ + strong, b { + color: #e8e8e8 !important; + } + + /* Syntax highlighting for code blocks (Rouge/Pygments) */ + .highlight { + background-color: #252525 !important; + } + + /* Error tokens - remove error highlighting */ + .highlight .err { + background-color: transparent !important; + color: #d4d4d4 !important; + } + + /* Comments */ + .highlight .c, .highlight .c1, .highlight .cm, .highlight .cs { + color: #6a9955 !important; + font-style: italic; + } + + /* Keywords */ + .highlight .k, .highlight .kd, .highlight .kn, .highlight .kp, + .highlight .kr, .highlight .kt, .highlight .kc { + color: #569cd6 !important; + } + + /* Strings */ + .highlight .s, .highlight .s1, .highlight .s2, .highlight .sb, + .highlight .sc, .highlight .sd, .highlight .se, .highlight .sh, + .highlight .si, .highlight .sx, .highlight .sr, .highlight .ss, + .highlight .dl { + color: #ce9178 !important; + background-color: transparent !important; + } + + /* Numbers */ + .highlight .m, .highlight .mi, .highlight .mf, .highlight .mh, + .highlight .mo, .highlight .il { + color: #b5cea8 !important; + } + + /* Operators */ + .highlight .o, .highlight .ow { + color: #d4d4d4 !important; + } + + /* Punctuation */ + .highlight .p { + color: #d4d4d4 !important; + } + + /* Names/identifiers */ + .highlight .n, .highlight .na, .highlight .nb, .highlight .nc, + .highlight .no, .highlight .nd, .highlight .ni, .highlight .ne, + .highlight .nf, .highlight .nl, .highlight .nn, .highlight .nt, + .highlight .nv, .highlight .nx { + color: #dcdcaa !important; + } + + /* Class names */ + .highlight .nc { + color: #4ec9b0 !important; + } + + /* Function names */ + .highlight .nf { + color: #dcdcaa !important; + } + + /* Preprocessor */ + .highlight .cp, .highlight .cpf { + color: #c586c0 !important; + } + + /* Generic */ + .highlight .ge { + font-style: italic; + } + + .highlight .gs { + font-weight: bold; + } +} diff --git a/lib/jcef/docs/branches_and_building.md b/lib/jcef/docs/branches_and_building.md new file mode 100644 index 0000000..4d72a6b --- /dev/null +++ b/lib/jcef/docs/branches_and_building.md @@ -0,0 +1,139 @@ +This page lists notes for JCEF releases. + +**Contents** + +- [Background](#background) +- [Development](#development) +- [Building from Source Code](#building-from-source-code) + - [Building with Docker or GitHub Actions](#building-with-docker-or-github-actions) + - [Building Manually](#building-manually) + - [Downloading Source Code](#downloading-source-code) + - [Building](#building) + - [Packaging](#packaging) + +--- + +# Background + +The JCEF project is an extension of the Chromium Embedded Framework project hosted at . JCEF maintains a development branch that tracks the most recent CEF release branch. JCEF source code (both native code and Java code) can be built manually as described below. + +# Development + +Ongoing development of JCEF occurs on the [master branch](https://github.com/chromiumembedded/java-cef/tree/master). This location tracks the current CEF3 release branch. + +# Building from Source Code + +Building JCEF from source code is currently supported on Windows, Linux and MacOS for 64-bit Oracle Java targets. 32-bit builds are also possible on Windows and Linux but they are untested. + +To build JCEF from source code you should begin by installing the build prerequisites for your operating system and development environment. For all platforms this includes: + +* [CMake](http://cmake.org/download/) version 3.21 or newer. +* [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). +* [Java](https://java.com/en/download/) version 7 to 14. +* [Python](https://www.python.org/downloads/) version 2.6+ or 3+. + +For Linux platforms: + +* Currently supported distributions include Debian 10 (Buster), Ubuntu 18 (Bionic Beaver), and related. Ubuntu 18.04 64-bit with GCC 7.5.0+ is recommended. Newer versions will likely also work but may not have been tested. Required packages include: build-essential, libgtk-3-dev. + +For MacOS platforms: + +* [Apache Ant](https://ant.apache.org/bindownload.cgi) is required to build the Java app bundle. +* Java version newer than 8u121 is required. +* Xcode 13.5 to 16.4 building on MacOS 12.0 (Monterey) or newer. The Xcode command-line tools must also be installed. + +For Windows platforms: + +* Visual Studio 2022 building on Windows 10 or newer. Windows 10/11 64-bit is recommended. + +## Building with Docker or GitHub Actions + +For a quick and easy build setup, you can run your builds on Docker (Linux/Windows) or use GitHub Actions (with Docker). The [jcefbuild repository on GitHub](https://github.com/jcefmaven/jcefbuild) can be forked and used to compile your own custom sources, providing one-line build scripts for each platform, Docker environments for Linux and Windows, as well as GitHub Actions workflows for all platforms. It also adds support for more build +architectures (arm64 + arm/v6 on Linux, arm64 on Windows). For more information, visit the repository readme file. + +## Building Manually + +Building can also be performed as a series of manual steps. + +### Downloading Source Code + +Download JCEF source code using Git. + +```sh +# The JCEF source code will exist at `/path/to/java-cef/src` +cd /path/to/java-cef +git clone https://github.com/chromiumembedded/java-cef.git src +``` + +### Building + +1\. Run CMake to generate platform-specific project files and then build the resulting native targets. See CMake output for any additional steps that may be necessary. For example, to generate a Release build of the `jcef` and `jcef_helper` targets: + +```sh +# Enter the JCEF source code directory. +cd /path/to/java-cef/src + +# Create and enter the `jcef_build` directory. +# The `jcef_build` directory name is required by other JCEF tooling +# and should not be changed. +mkdir jcef_build && cd jcef_build + +# Linux: Generate 64-bit Unix Makefiles. +cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release .. +# Build using Make. +make -j4 + +# MacOS: Generate 64-bit Xcode project files. +cmake -G "Xcode" -DPROJECT_ARCH="x86_64" .. +# Open jcef.xcodeproj in Xcode +# - Select Scheme > Edit Scheme and change the "Build Configuration" to "Release" +# - Select Product > Build. + +# MacOS: Generate ARM64 Xcode project files. +cmake -G "Xcode" -DPROJECT_ARCH="arm64" .. +# Open jcef.xcodeproj in Xcode +# - Select Scheme > Edit Scheme and change the "Build Configuration" to "Release" +# - Select Product > Build. + +# Windows: Generate 64-bit VS2022 project files. +cmake -G "Visual Studio 17" -A x64 .. +# Open jcef.sln in Visual Studio +# - Select Build > Configuration Manager and change the "Active solution configuration" to "Release" +# - Select Build > Build Solution. +``` + +JCEF supports a number of different project formats via CMake including [Ninja](http://martine.github.io/ninja/). See comments in the top-level [CMakeLists.txt](https://github.com/chromiumembedded/java-cef/blob/master/CMakeLists.txt) file for additional CMake usage instructions. + +2\. On Windows and Linux build the JCEF Java classes using the _compile.[bat\|sh]_ tool. + +```sh +cd /path/to/java-cef/src/tools +compile.bat win64 +``` + +On MacOS the JCEF Java classes are already built by the CMake project. + +3\. On Windows and Linux test that the resulting build works using the _run.[bat\|sh]_ tool. You can either run the simple example (see java/simple/MainFrame.java) or the detailed one (see java/detailed/MainFrame.java) by appending "detailed" or "simple" to the _run.[bat\|sh]_ tool. This example assumes that the "Release" configuration was built in step 1 and that you want to use the detailed example. + +```sh +cd /path/to/java-cef/src/tools +run.bat win64 Release detailed +``` + +On MacOS run jcef\_app for the detailed example. Either use the command-line or double-click on jcef\_app in Finder. + +```sh +cd /path/to/java-cef/src/jcef_build/native/Release +open jcef_app.app +``` + +### Packaging + +After building the Release configurations you can use the _make\_distrib.[bat\|sh]_ script to create a binary distribution. + +```sh +cd /path/to/java-cef/src/tools +make_distrib.bat win64 +``` + +If the process succeeds a binary distribution package will be created in the /path/to/java-cef/src/binary\_distrib directory. See the README.txt file in that directory for usage instructions. \ No newline at end of file diff --git a/lib/jcef/docs/building_openjdk.md b/lib/jcef/docs/building_openjdk.md new file mode 100644 index 0000000..721c3fb --- /dev/null +++ b/lib/jcef/docs/building_openjdk.md @@ -0,0 +1,513 @@ +This page provides information about building OpenJDK locally for use in debugging JCEF. + +**Contents** + +- [Overview](#overview) +- [OpenJDK on Windows](#openjdk-on-windows) + - [Install prerequisite software](#install-prerequisite-software) + - [Build Freetype2](#build-freetype2) + - [Setup MinGW](#setup-mingw) + - [Download OpenJDK sources](#download-openjdk-sources) + - [Patch OpenJDK sources](#patch-openjdk-sources) + - [Configure OpenJDK](#configure-openjdk) + - [Build OpenJDK](#build-openjdk) + - [Run JCEF with OpenJDK](#run-jcef-with-openjdk) +- [OpenJDK on Linux](#openjdk-on-linux) + - [Mixed mode debugging with GDB](#mixed-mode-debugging-with-gdb) + +--- + +# Overview + +[OpenJDK](http://openjdk.java.net/) is the open source project on which the Oracle JDK is based. Oracle does not provide debugging symbols for the JDK. Consequently it is necessary to build OpenJDK locally in order to debug issues that trace into JDK code. General instructions for building OpenJDK are available [here](http://hg.openjdk.java.net/build-infra/jdk8/raw-file/tip/README-builds.html), however it is recommended that you follow the below steps when building on Windows. + +# OpenJDK on Windows + +Building OpenJDK on Windows is a many-step process. Below are instructions for creating a 32-bit or 64-bit build of OpenJDK at version 8u60 on Windows 7 or newer using Visual Studio 2013. + +## Install prerequisite software + +OpenJDK requires the following software. Install all software at the default location. + +* Visual Studio 2013 Update 4 Professional. Other versions may work but are untested. +* [Java 8 Development Kit](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html). Choose the architecture version that matches the desired OpenJDK build (e.g. choose the x64 version if creating a 64-bit OpenJDK build). +* [Mercurial](https://www.mercurial-scm.org/wiki/Download). + +## Build Freetype2 + +OpenJDK requires Freetype2 which should be built locally for best results [[*]](http://stackoverflow.com/questions/6207176/compiling-freetype-to-dll-as-opposed-to-static-library) [[*]](https://technfun.wordpress.com/2015/08/03/building-openjdk-8-for-windows-using-msys/). + +1\. Download Freetype2 source code in the 2.x series. For example, [freetype-2.6.2.tar.gz](http://sourceforge.net/projects/freetype/files/freetype2/2.6.2/). + +2\. Extract the archive contents to "C:\code\freetype-2.6.2-src" + +3\. Open Visual Studio 2013 and load the "C:\code\freetype-2.6.2-src\builds\windows\vc2010\freetype.sln" solution file. + +4\. Select Build > Configuration Manager from the top menu: + +* Change configuration to "Release". +* Change platform to either "Win32" or "x64" to match the desired OpenJDK build. + +5\. Right click on the "freetype" solution, select Properties, and in the General tab: + +* Change Configuration Type to "Dynamic Library (.dll)". +* Change Target Name to "freetype" (remove the version number). + +6\. Open the ftoption.h file and add the following lines near the "DLL export compilation" remarks section: + +``` +#define FT_EXPORT(x) __declspec(dllexport) x +#define FT_BASE(x) __declspec(dllexport) x +``` + +7\. Build the project. You should now have "C:\code\freetype-2.6.2-src\objs\vc2010\[Win32\|x64]\freetype.[dll\|lib]" files. + +8\. Create a new "C:\code\freetype-2.6.2-src\lib" directory and copy the freetype.[dll\|lib] files into it. + +## Setup MinGW + +OpenJDK can be built using MinGW or Cygwin on Windows. This is how to setup the MinGW build environment. + +1\. Install MinGW using [mingw-get-setup.exe](http://sourceforge.net/projects/mingw/files/Installer/). Install to the default location (C:\MinGW). + +2\. Use the "C:\MinGW\bin\mingw-get.exe install " command to install the following packages: + +* msys-autoconf +* msys-base +* msys-bsdcpio +* msys-make +* msys-mktemp +* msys-unzip +* msys-zip + +3\. Create a "C:\MinGW\msys\1.0\etc\fstab" file with the following contents: + +``` +#Win32_Path Mount_Point +c:/mingw /mingw +c:/ /c +``` + +4\. Create a "C:\MinGW\msys\1.0\home\\[User]\\.profile" file ([User] is your Windows user name) with the following contents: + +```sh +export PATH="$PATH:/C/Program Files/Mercurial" +``` + +5\. Run "C:\MinGW\msys\1.0\msys.bat" to enter the MinGW shell. + +## Download OpenJDK sources + +Run the following commands in the MinGW shell to download the OpenJDK source code for version 8u60. + +```sh +cd /c/code +hg clone http://hg.openjdk.java.net/jdk8u/jdk8u60/ openjdk8 +cd openjdk8 +bash ./get_source.sh +``` + +## Patch OpenJDK sources + +JDK version 8 does not officially support building with VS2013. However, the build should succeed if you apply the below patches. These patches resolve the following issues: + +* The cpio utility does not exist in MinGW. Change "cpio" to "bsdcpio" in basics.m4 [[*]](https://bugs.openjdk.java.net/browse/JDK-8022177). +* MinGW installs autoconf 2.68. Change the version requirement in configure.ac [[*]](https://technfun.wordpress.com/2015/08/03/building-openjdk-8-for-windows-using-msys/). +* Configure cannot find msvcr100.dll with correct architecture. Fix the logic in toolchain_windows.m4 [[*]](http://cr.openjdk.java.net/~simonis/webrevs/8022177/). +* ad_x86_64_misc.obj : error LNK2011: precompiled object not linked in. Fix compile.make and vm.make to link against _build_pch_file.obj [[*]](https://bugs.openjdk.java.net/browse/JDK-8043492). +* LNK2038: mismatch detected for 'RuntimeLibrary'. Remove _STATIC_CPPLIB defines in toolchain.m4 [[*]](http://hg.openjdk.java.net/jdk9/client/rev/39ee0ee4f890). +* The make command hangs during the build process. Disable multiple jobs in spec.gmk.in [[*]](https://bugs.openjdk.java.net/browse/JDK-8022177). +* The value "IMVERSION" of attribute "version" in element "assemblyIdentity" is invalid (SxS manifest issue). Add a version number to java.manifest [[*]](https://bugs.openjdk.java.net/browse/JDK-8128079). + +``` +--- common/autoconf/basics.m4 Thu Jan 28 18:46:45 2016 ++++ common/autoconf/basics.m4 Thu Jan 28 16:44:34 2016 +@@ -279,7 +279,7 @@ + BASIC_REQUIRE_PROG(CMP, cmp) + BASIC_REQUIRE_PROG(COMM, comm) + BASIC_REQUIRE_PROG(CP, cp) +- BASIC_REQUIRE_PROG(CPIO, cpio) ++ BASIC_REQUIRE_PROG(CPIO, bsdcpio) + BASIC_REQUIRE_PROG(CUT, cut) + BASIC_REQUIRE_PROG(DATE, date) + BASIC_REQUIRE_PROG(DIFF, [gdiff diff]) + +--- common/autoconf/configure.ac Thu Jan 28 18:46:37 2016 ++++ common/autoconf/configure.ac Thu Jan 28 16:44:53 2016 +@@ -30,7 +30,7 @@ + ############################################################################### + + +-AC_PREREQ([2.69]) ++AC_PREREQ([2.68]) + AC_INIT(OpenJDK, jdk8, build-dev@openjdk.java.net,,http://openjdk.java.net) + + AC_CONFIG_AUX_DIR([build-aux]) + +--- common/autoconf/toolchain_windows.m4 Thu Jan 28 18:46:29 2016 ++++ common/autoconf/toolchain_windows.m4 Thu Jan 28 16:46:42 2016 +@@ -240,12 +240,22 @@ + # Need to check if the found msvcr is correct architecture + AC_MSG_CHECKING([found msvcr100.dll architecture]) + MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` ++ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then ++ # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" ++ # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. ++ if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then ++ CORRECT_MSVCR_ARCH="PE32 executable" ++ else ++ CORRECT_MSVCR_ARCH="PE32+ executable" ++ fi ++ else + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi +- if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then ++ fi ++ if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then + AC_MSG_RESULT([ok]) + MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + AC_MSG_CHECKING([for msvcr100.dll]) + +--- hotspot/make/windows/makefiles/vm.make Thu Jan 28 18:46:14 2016 ++++ hotspot/make/windows/makefiles/vm.make Thu Jan 28 17:00:04 2016 +@@ -128,8 +128,8 @@ + + !if "$(USE_PRECOMPILED_HEADER)" != "0" + CXX_USE_PCH=/Fp"vm.pch" /Yu"precompiled.hpp" +-!if "$(COMPILER_NAME)" == "VS2012" +-# VS2012 requires this object file to be listed: ++!if "$(COMPILER_NAME)" == "VS2012" || "$(COMPILER_NAME)" == "VS2013" ++# VS2012 and VS2013 require this object file to be listed: + LD_FLAGS=$(LD_FLAGS) _build_pch_file.obj + !endif + !else + +--- hotspot/make/windows/makefiles/compile.make Thu Jan 28 18:46:06 2016 ++++ hotspot/make/windows/makefiles/compile.make Thu Jan 28 17:07:44 2016 +@@ -147,6 +147,9 @@ + !if "$(MSC_VER)" == "1700" + COMPILER_NAME=VS2012 + !endif ++!if "$(MSC_VER)" == "1800" ++COMPILER_NAME=VS2013 ++!endif + !endif + + # By default, we do not want to use the debug version of the msvcrt.dll file + +--- common/autoconf/toolchain.m4 Thu Jan 28 18:45:57 2016 ++++ common/autoconf/toolchain.m4 Thu Jan 28 17:54:04 2016 +@@ -998,7 +998,7 @@ + ;; + cl ) + CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -Zi -MD -Zc:wchar_t- -W3 -wd4800 \ +- -D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB -DWIN32_LEAN_AND_MEAN \ ++ -DWIN32_LEAN_AND_MEAN \ + -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ + -DWIN32 -DIAL" + case $OPENJDK_TARGET_CPU in + +--- common/autoconf/spec.gmk.in Thu Jan 28 18:45:47 2016 ++++ common/autoconf/spec.gmk.in Thu Jan 28 17:57:06 2016 +@@ -267,7 +267,7 @@ + SJAVAC_SERVER_DIR:=@SJAVAC_SERVER_DIR@ + + # Number of parallel jobs to use for compilation +-JOBS?=@JOBS@ ++JOBS?=1 + + FREETYPE_LIBS:=@FREETYPE_LIBS@ + FREETYPE_CFLAGS:=@FREETYPE_CFLAGS@ + +--- jdk/src/windows/resource/java.manifest Thu Jan 28 18:45:19 2016 ++++ jdk/src/windows/resource/java.manifest Thu Jan 28 18:36:40 2016 +@@ -4,7 +4,7 @@ + xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" + > + and extract libcef.dll.pdb to "src\jcef_build\native\Debug". + +3\. Edit JCEF's "src\tools\run.bat" script. Replace the "java" command with "C:\code\openjdk8\build\windows-x86_64-normal-server-fastdebug\jdk\bin\java" (or the 32-bit path as appropriate). + +4\. Run the script: + +``` +run.bat win64 Debug detailed +``` + +5\. Open Visual Studio 2013 and load the "src\jcef_build\jcef.sln" solution file. + +6\. Select Debug > Attach to process.. from the top menu and choose the "java.exe" process. + +7\. Wait for the application to crash. Get a call stack with debug symbols like [this](https://github.com/chromiumembedded/java-cef/issues/157). + +8\. To delay Java startup long enough to attach the debugger add the following code at the top of the `main(String [] args)` method in "src\java\tests\detailed\MainFrame.java": + +``` +try { Thread.sleep(10000); /* delay 10 seconds */ } catch(InterruptedException e) {} +``` + +# OpenJDK on Linux + +Issues on Linux can be diagnosed using a local debug build of OpenJDK based on [these instructions](http://cr.openjdk.java.net/~ihse/demo-new-build-readme/common/doc/building.html#getting-the-source-code). You will need to build JDK8 on an Ubuntu 14.04 machine because a 3.x series kernel is required by the build configuration. + +```sh +# Install dependencies +> sudo apt-get update --fix-missing +> sudo apt-get install build-essential mercurial openjdk-7-jdk libx11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev libelf-dev libffi-dev libcups2-dev +# Download source code +> hg clone http://hg.openjdk.java.net/jdk8/jdk8 +> cd jdk8 +> bash get_source.sh +# Configure +> bash configure --enable-debug --disable-zip-debug-info --disable-ccache +# Build +> make images +# Test that it runs +> ./build/linux-x86_64-normal-server-fastdebug/jdk/bin/java -version +``` + +For GDB to successfully load OpenJDK debug symbols you need to run using the binaries in the ./build/linux-x86_64-normal-server-fastdebug/jdk/bin directory (where the *.debuginfo files exist). For example, by setting the following environment variables: + +```sh +export JAVA_HOME=/home/marshall/code/openjdk/jdk8/build/linux-x86_64-normal-server-fastdebug/jdk +export PATH=/home/marshall/code/openjdk/jdk8/build/linux-x86_64-normal-server-fastdebug/jdk/bin:$PATH +``` + +## Mixed mode debugging with GDB + +[This link](http://progdoc.de/papers/Joker2014/joker2014.html#(5)) describes how to get mixed native and Java stack traces using GDB. It's also useful to add System.out.println messages to code under the jdk/src directory and re-build. + +Here's a patch that launches the JCEF sample apps using GDB and Java debug settings: + +``` +diff --git tools/run.sh tools/run.sh +index 1a58940..466afdb 100755 +--- tools/run.sh ++++ tools/run.sh +@@ -32,7 +32,7 @@ else + shift + shift + +- LD_PRELOAD=$LIB_PATH/libcef.so java -cp "$CLS_PATH" -Djava.library.path=$LIB_PATH tests.$RUN_TYPE.MainFrame "$@" ++ LD_PRELOAD=$LIB_PATH/libcef.so gdb --args java -Dsun.awt.disablegrab=true -Xdebug -Xint -cp "$CLS_PATH" -Djava.library.path=$LIB_PATH tests.$RUN_TYPE.MainFrame "$@" + fi + fi + +``` + +Here's a patch that adds a CefApp.debugBreak() method that can be used to trigger a native breakpoint from Java code: + +```cpp +diff --git java/org/cef/CefApp.java java/org/cef/CefApp.java +index 4545c68..a7135f2 100644 +--- java/org/cef/CefApp.java ++++ java/org/cef/CefApp.java +@@ -543,6 +543,14 @@ public class CefApp extends CefAppHandlerAdapter { + return library_path; + } + ++ /** ++ * Trigger a breakpoint in the native debugger. ++ */ ++ public static final void debugBreak() { ++ N_DebugBreak(); ++ } ++ ++ private final static native void N_DebugBreak(); + private final static native boolean N_Startup(); + private final native boolean N_PreInitialize(); + private final native boolean N_Initialize( +diff --git native/CefApp.cpp native/CefApp.cpp +index 39a14d8..0f61a1c 100644 +--- native/CefApp.cpp ++++ native/CefApp.cpp +@@ -6,6 +6,7 @@ + + #include + ++#include "include/base/cef_logging.h" + #include "include/cef_app.h" + #include "include/cef_version.h" + +@@ -104,3 +105,8 @@ JNIEXPORT jboolean JNICALL Java_org_cef_CefApp_N_1Startup(JNIEnv*, jclass) { + #endif // defined(OS_MACOSX) + return JNI_TRUE; + } ++ ++JNIEXPORT void JNICALL Java_org_cef_CefApp_N_1DebugBreak(JNIEnv*, jclass) { ++ DCHECK(false) << "CefApp.DebugBreak"; ++} ++ +diff --git native/CefApp.h native/CefApp.h +index bf1c1ef..081ffd8 100644 +--- native/CefApp.h ++++ native/CefApp.h +@@ -74,6 +74,13 @@ Java_org_cef_CefApp_N_1ClearSchemeHandlerFactories(JNIEnv*, jobject); + */ + JNIEXPORT jboolean JNICALL Java_org_cef_CefApp_N_1Startup(JNIEnv*, jclass); + ++/* ++ * Class: org_cef_CefApp ++ * Method: N_DebugBreak ++ * Signature: ()V ++ */ ++JNIEXPORT void JNICALL Java_org_cef_CefApp_N_1DebugBreak(JNIEnv*, jclass); ++ + #ifdef __cplusplus + } + #endif +``` + +Example GDB usage in combination with the above patches: + +```sh +$ ./run.sh linux64 Debug detailed +(gdb) r + +0x00007ffff2736a07 in operator() () at ../../base/logging.cc:874 +874 ../../base/logging.cc: No such file or directory. +(gdb) bt +#0 0x00007ffff2736a07 in operator() () at ../../base/logging.cc:874 +#1 ~LogMessage () at ../../base/logging.cc:874 +#2 0x00007ffff2627b6b in cef_log () at ../../cef/libcef/common/base_impl.cc:333 +#3 0x00007fffc4d151e5 in cef::logging::LogMessage::~LogMessage (this=0x7fffc41b2470, __in_chrg=) + at /home/marshall/code/java-cef/src/third_party/cef/cef_binary_3.3626.1883.g00e6af4_linux64/libcef_dll/base/cef_logging.cc:187 +#4 0x00007fffc4cc62bd in Java_org_cef_CefApp_N_1DebugBreak () at /home/marshall/code/java-cef/src/native/CefApp.cpp:110 +#5 0x00007fffcd0262e7 in ?? () +#6 0x00007fffdc38d000 in ?? () +#7 0x00007fffc41b2618 in ?? () +#8 0x00007fffe0a1c298 in ?? () +#9 0x00007fffc41b2670 in ?? () +#10 0x00007fffe0a1e230 in ?? () +#11 0x0000000000000000 in ?? () + +(gdb) call help() + +"Executing help" +basic + pp(void* p) - try to make sense of p + pv(intptr_t p)- ((PrintableResourceObj*) p)->print() + ps() - print current thread stack + pss() - print all thread stacks + pm(int pc) - print Method* given compiled PC + findm(intptr_t pc) - finds Method* + find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it +misc. + flush() - flushes the log file + events() - dump events from ring buffers +compiler debugging + debug() - to set things up for compiler debugging + ndebug() - undo debug + +(gdb) call ps() + +"Executing ps" + for thread: "AWT-EventQueue-0" #9 prio=6 os_prio=0 tid=0x00007fffdc38d000 nid=0xb818 runnable [0x00007fffc41b2000] + java.lang.Thread.State: RUNNABLE + JavaThread state: _thread_in_native +Thread: 0x00007fffdc38d000 [0xb818] State: _running _has_called_back 0 _at_poll_safepoint 0 + JavaThread state: _thread_in_native + + 1 - frame( sp=0x00007fffc41b2610, unextended_sp=0x00007fffc41b2610, fp=0x00007fffc41b2658, pc=0x00007fffcd026233) +org.cef.CefApp.N_DebugBreak(Native Method) + 2 - frame( sp=0x00007fffc41b2668, unextended_sp=0x00007fffc41b2678, fp=0x00007fffc41b26b8, pc=0x00007fffcd007500) +[Thread 0x7fff527fc700 (LWP 47146) exited] +org.cef.CefApp.debugBreak(CefApp.java:550) + 3 - frame( sp=0x00007fffc41b26c8, unextended_sp=0x00007fffc41b26c8, fp=0x00007fffc41b2708, pc=0x00007fffcd007500) +tests.simple.MainFrame$6.windowDeactivated(MainFrame.java:188) + 4 - frame( sp=0x00007fffc41b2718, unextended_sp=0x00007fffc41b2718, fp=0x00007fffc41b2768, pc=0x00007fffcd007545) +java.awt.AWTEventMulticaster.windowDeactivated(AWTEventMulticaster.java:399) + 5 - frame( sp=0x00007fffc41b2778, unextended_sp=0x00007fffc41b2778, fp=0x00007fffc41b27c8, pc=0x00007fffcd007545) +java.awt.AWTEventMulticaster.windowDeactivated(AWTEventMulticaster.java:399) + 6 - frame( sp=0x00007fffc41b27d8, unextended_sp=0x00007fffc41b27d8, fp=0x00007fffc41b2828, pc=0x00007fffcd007545) +java.awt.Window.processWindowEvent(Window.java:2073) + 7 - frame( sp=0x00007fffc41b2838, unextended_sp=0x00007fffc41b2840, fp=0x00007fffc41b2890, pc=0x00007fffcd007500) +javax.swing.JFrame.processWindowEvent(JFrame.java:297) + 8 - frame( sp=0x00007fffc41b28a0, unextended_sp=0x00007fffc41b28a0, fp=0x00007fffc41b28f0, pc=0x00007fffcd007500) +java.awt.Window.processEvent(Window.java:2017) + 9 - frame( sp=0x00007fffc41b2900, unextended_sp=0x00007fffc41b2900, fp=0x00007fffc41b2950, pc=0x00007fffcd007500) +java.awt.Component.dispatchEventImpl(Component.java:4883) +10 - frame( sp=0x00007fffc41b2960, unextended_sp=0x00007fffc41b2990, fp=0x00007fffc41b29e0, pc=0x00007fffcd007500) +java.awt.Container.dispatchEventImpl(Container.java:2292) +11 - frame( sp=0x00007fffc41b29f0, unextended_sp=0x00007fffc41b2a00, fp=0x00007fffc41b2a50, pc=0x00007fffcd007500) +java.awt.Window.dispatchEventImpl(Window.java:2739) +12 - frame( sp=0x00007fffc41b2a60, unextended_sp=0x00007fffc41b2a60, fp=0x00007fffc41b2ab0, pc=0x00007fffcd007500) +java.awt.Component.dispatchEvent(Component.java:4705) +13 - frame( sp=0x00007fffc41b2ac0, unextended_sp=0x00007fffc41b2ac0, fp=0x00007fffc41b2b10, pc=0x00007fffcd007500) +java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1954) +14 - frame( sp=0x00007fffc41b2b20, unextended_sp=0x00007fffc41b2b20, fp=0x00007fffc41b2b78, pc=0x00007fffcd007500) +java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:995) +15 - frame( sp=0x00007fffc41b2b88, unextended_sp=0x00007fffc41b2bb0, fp=0x00007fffc41b2c08, pc=0x00007fffcd006e80) +java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:685) +16 - frame( sp=0x00007fffc41b2c18, unextended_sp=0x00007fffc41b2c60, fp=0x00007fffc41b2cb0, pc=0x00007fffcd006e80) +java.awt.Component.dispatchEventImpl(Component.java:4754) +17 - frame( sp=0x00007fffc41b2cc0, unextended_sp=0x00007fffc41b2cf0, fp=0x00007fffc41b2d40, pc=0x00007fffcd007500) +java.awt.Container.dispatchEventImpl(Container.java:2292) +18 - frame( sp=0x00007fffc41b2d50, unextended_sp=0x00007fffc41b2d60, fp=0x00007fffc41b2db0, pc=0x00007fffcd007500) +java.awt.Window.dispatchEventImpl(Window.java:2739) +19 - frame( sp=0x00007fffc41b2dc0, unextended_sp=0x00007fffc41b2dc0, fp=0x00007fffc41b2e10, pc=0x00007fffcd007500) +java.awt.Component.dispatchEvent(Component.java:4705) +20 - frame( sp=0x00007fffc41b2e20, unextended_sp=0x00007fffc41b2e20, fp=0x00007fffc41b2e70, pc=0x00007fffcd007500) +java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746) +21 - frame( sp=0x00007fffc41b2e80, unextended_sp=0x00007fffc41b2e80, fp=0x00007fffc41b2ed8, pc=0x00007fffcd007500) +java.awt.EventQueue.access$400(EventQueue.java:97) +22 - frame( sp=0x00007fffc41b2ee8, unextended_sp=0x00007fffc41b2ee8, fp=0x00007fffc41b2f40, pc=0x00007fffcd007500) +java.awt.EventQueue$3.run(EventQueue.java:697) +23 - frame( sp=0x00007fffc41b2f50, unextended_sp=0x00007fffc41b2f50, fp=0x00007fffc41b2f98, pc=0x00007fffcd007430) +java.awt.EventQueue$3.run(EventQueue.java:691) +C frame (sp=0x00007fffc41b2fa8 unextended sp=0x00007fffc41b2fa8, fp=0x00007fffc41b3010, real_fp=0x00007fffc41b3010, pc=0x00007fffcd000671) +(~Stub::call_stub) + BufferBlob (0x00007fffcd0003d0) used for StubRoutines (1) +``` \ No newline at end of file diff --git a/lib/jcef/docs/contributing_with_git.md b/lib/jcef/docs/contributing_with_git.md new file mode 100644 index 0000000..3de958a --- /dev/null +++ b/lib/jcef/docs/contributing_with_git.md @@ -0,0 +1,234 @@ +This page provides information about using Git to contribute code changes to JCEF. + +**Contents** + +- [Overview](#overview) +- [Initial Setup](#initial-setup) +- [Working With Private Changes](#working-with-private-changes) + - [Creating a Branch](#creating-a-branch) + - [Creating a Commit](#creating-a-commit) + - [Modifying a Commit](#modifying-a-commit) + - [Rebasing on Upstream Changes](#rebasing-on-upstream-changes) + - [Deleting a Branch](#deleting-a-branch) + - [Cleaning a Checkout](#cleaning-a-checkout) +- [Working With Pull Requests](#working-with-pull-requests) + - [Coding Style](#coding-style) + - [Creating a Pull Request](#creating-a-pull-request) + - [Reviewing a Pull Request](#reviewing-a-pull-request) + +--- + +# Overview + +The JCEF project uses the Git source code management system hosted via GitHub. The easiest way to contribute changes to JCEF is by creating your own personal fork of the JCEF Git repository and submitting pull requests with your proposed modifications. This document is intended as a quick-start guide for developers who already have some familiarity with Git. If you are completely new to Git you might want to review the series of [Git tutorials](https://docs.github.com/en/get-started/getting-started-with-git) provided by GitHub. + +# Initial Setup + +Git can maintain your changes both locally and on a remote server. To work with Git efficiently the remote server locations must be configured properly. + +1\. Log into GitHub and create a forked version of the java-cef repository using the Fork button at . + +2\. Check out JCEF source code as described on the [Branches And Building](branches_and_building.md) page. + +3\. Change the remote origin of the JCEF checkout so that it points to your personal forked repository. This is the remote server location that the `git push` and `git pull` commands will operate on by default. + +```sh +cd /path/to/java-cef + +# Replace with your GitHub user name. +git remote set-url origin https://github.com//java-cef.git +``` + +4\. Set the remote upstream of the JCEF checkout so that you can merge changes from the main JCEF repository. + +```sh +git remote add upstream https://github.com/chromiumembedded/java-cef.git +``` + +5\. Verify that the remotes are configured correctly. + +```sh +git remote -v +``` + +You should see output like the following: + +``` +origin https://github.com//java-cef.git (fetch) +origin https://github.com//java-cef.git (push) +upstream https://github.com/chromiumembedded/java-cef.git (fetch) +upstream https://github.com/chromiumembedded/java-cef.git (push) +``` + +6\. Configure your name and email address. + +```sh +git config user.name "User Name" +git config user.email user@example.com +``` + +7\. Configure the correct handling of line endings in the repository. + +```sh +# Use this value on Windows. Files will be converted to CRLF line endings +# in the working directory and LF line endings in the object database. +git config core.autocrlf true + +# Use this value on other platforms. Files will be unchanged in the working +# directory and converted to LF line endings in the object database. +git config core.autocrlf input + +# Cause Git to abort actions on files with mixed line endings if the change is +# not reversible (e.g. changes to binary files that are accidentally classified +# as text). +git config core.safecrlf true +``` + +# Working With Private Changes + +You can now commit changes to your personal repository and merge upstream changes from the main JCEF repository. To facilitate creation of a pull request or the sharing of your code changes with other developers you should make your changes in a branch. + +## Creating a Branch + +Create a new personal branch for your changes. + +```sh +# Start with the branch that your changes will be based upon. +git checkout master + +# Create a new personal branch for your changes. +# Replace with your new branch name. +git checkout -b +``` + +## Creating a Commit + +After making local modifications you can commit them to your personal branch. + +```sh +# For example, add a specified file by path. +git add path/to/file.txt + +# For example, add all existing files that have been modified or deleted. +git add -u + +# Commit the modifications locally. +git commit -m "A good description of the fix (issue #1234)" + +# Push the modifications to your personal remote repository. +git push origin +``` + +## Modifying a Commit + +You can also modify an existing commit if you need to make additional changes. + +```sh +# For example, add all existing files that have been modified or deleted. +git add -u + +# Update the current HEAD commit with the changes. +git commit --amend + +# Push the modifications to your personal remote repository. +# Using the `--force` argument is not recommended if multiple people are sharing the +# same branch. +git push origin --force +``` + +## Rebasing on Upstream Changes + +The main JCEF repository will receive additional commits over time. You will want to include these changes in your personal repository. To keep Git history correct (showing upstream JCEF commits on the JCEF branch instead of on your personal branch) you will need to rebase the local JCEF branch before rebasing your local personal branch. + +```sh +# Fetch changes from the main JCEF repository. This does not apply them to any +# particular branch. +git fetch upstream + +# Check out the local JCEF branch that tracks the upstream JCEF branch. +git checkout master + +# Rebase your local JCEF branch on top of the upstream JCEF branch. +# After this command your local JCEF branch should be identical to the upstream JCEF branch. +git rebase upstream/master + +# Check out the personal branch that you want to update with changes from the JCEF branch. +# Replace with the name of your branch. +git checkout + +# Rebase your personal branch on top of the local JCEF branch. +# After this command your local commits will come after all JCEF commits on the same branch. +git rebase master + +# Push the modifications to your personal remote repository. +git push origin +``` + +You may get merge conflicts if your personal changes conflict with changes made to the main JCEF repository. For instructions on resolving merge conflicts see [this article](https://help.github.com/articles/resolving-merge-conflicts-after-a-git-rebase/). + +For more information on using the rebase command go [here](https://www.atlassian.com/git/tutorials/merging-vs-rebasing). + +## Deleting a Branch + +Once you no longer need a branch you can delete it both locally and remotely. Do not delete branches that are associated with open pull requests. + +```sh +# Delete the branch locally. +git branch -D + +# Delete the branch remotely. +git push origin --delete +``` + +## Cleaning a Checkout + +You can remove all local changes from your checkout using the below commands. + +```sh +# Check the current state of the repository before deleting anything. +git status + +# Remove all non-committed files and directories from the local checkout. +git clean -dffx + +# Remove all local commits from the current branch and reset branch state to match +# origin/master. Replace "origin/master" with a different remote branch name as appropriate. +git reset --hard origin/master +``` + +# Working With Pull Requests + +Once your personal changes are complete you can request that they be merged into the main JCEF repository. This is done using a pull request. Before submitting a pull request you should: + +* Rebase your changes on the upstream JCEF branch (see "Rebasing on Upstream Changes"). +* Fix any coding style issues (see "Coding Style"). +* Find or create an appropriate issue in the [JCEF issue tracker](https://github.com/chromiumembedded/java-cef/issues). Make sure the issue number is referenced in your commit description. +* Include new or modified unit tests as appropriate to the functionality. +* Remove unnecessary or unrelated changes. + +## Coding Style + +JCEF uses the [Chromium coding style](https://chromium.googlesource.com/chromium/src/+/master/styleguide/styleguide.md). Changes to files should match the existing style in that file. + +## Creating a Pull Request + +Pull requests can only be created from a public repository that was [forked](https://docs.github.com/articles/fork-a-repo) using the GitHub interface. Push your branch to your fork and then create the pull request as described [here](https://docs.github.com/articles/creating-a-pull-request-from-a-fork). Pull requests will only be accepted if they meet the requirements described above. + +```sh +# Push your branch to your fork for PR submission. +git push origin +``` + +## Reviewing a Pull Request + +Your pull request will be reviewed by one or more JCEF developers. Please address any comments and update your pull request. The easiest way to update a pull request is by pushing new commits to the same branch -- those new commits will be automatically reflected in the pull request. Once your changes are deemed acceptable they will be squashed and merged into the main JCEF repository. + +The contents of a pull request can also be downloaded as a patch file and applied to your local Git checkout: + +```sh +# Download the patch file (replace {pull_no} with the PR number). +curl -L https://github.com/chromiumembedded/java-cef/pull/{pull_no}.diff -o name.patch + +# Apply the patch file to your local Git checkout. +git apply name.patch +``` diff --git a/lib/jcef/java/manifest/MANIFEST.MF b/lib/jcef/java/manifest/MANIFEST.MF new file mode 100644 index 0000000..9993ab6 --- /dev/null +++ b/lib/jcef/java/manifest/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Automatic-Module-Name: jcef diff --git a/lib/jcef/java/org/cef/CefApp.java b/lib/jcef/java/org/cef/CefApp.java new file mode 100644 index 0000000..e623b83 --- /dev/null +++ b/lib/jcef/java/org/cef/CefApp.java @@ -0,0 +1,601 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef; + +import org.cef.callback.CefSchemeHandlerFactory; +import org.cef.handler.CefAppHandler; +import org.cef.handler.CefAppHandlerAdapter; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.FilenameFilter; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashSet; + +import javax.swing.SwingUtilities; +import javax.swing.Timer; + +/** + * Exposes static methods for managing the global CEF context. + */ +public class CefApp extends CefAppHandlerAdapter { + public final class CefVersion { + public final int JCEF_COMMIT_NUMBER; + + public final int CEF_VERSION_MAJOR; + public final int CEF_VERSION_MINOR; + public final int CEF_VERSION_PATCH; + public final int CEF_COMMIT_NUMBER; + + public final int CHROME_VERSION_MAJOR; + public final int CHROME_VERSION_MINOR; + public final int CHROME_VERSION_BUILD; + public final int CHROME_VERSION_PATCH; + + private CefVersion(int jcefCommitNo, int cefMajor, int cefMinor, int cefPatch, + int cefCommitNo, int chrMajor, int chrMin, int chrBuild, int chrPatch) { + JCEF_COMMIT_NUMBER = jcefCommitNo; + + CEF_VERSION_MAJOR = cefMajor; + CEF_VERSION_MINOR = cefMinor; + CEF_VERSION_PATCH = cefPatch; + CEF_COMMIT_NUMBER = cefCommitNo; + + CHROME_VERSION_MAJOR = chrMajor; + CHROME_VERSION_MINOR = chrMin; + CHROME_VERSION_BUILD = chrBuild; + CHROME_VERSION_PATCH = chrPatch; + } + + public String getJcefVersion() { + return CEF_VERSION_MAJOR + "." + CEF_VERSION_MINOR + "." + CEF_VERSION_PATCH + "." + + JCEF_COMMIT_NUMBER; + } + + public String getCefVersion() { + return CEF_VERSION_MAJOR + "." + CEF_VERSION_MINOR + "." + CEF_VERSION_PATCH; + } + + public String getChromeVersion() { + return CHROME_VERSION_MAJOR + "." + CHROME_VERSION_MINOR + "." + CHROME_VERSION_BUILD + + "." + CHROME_VERSION_PATCH; + } + + @Override + public String toString() { + return "JCEF Version = " + getJcefVersion() + "\n" + + "CEF Version = " + getCefVersion() + "\n" + + "Chromium Version = " + getChromeVersion(); + } + } + + /** + * The CefAppState gives you a hint if the CefApp is already usable or not + * usable any more. See values for details. + */ + public enum CefAppState { + /** + * No CefApp instance was created yet. Call getInstance() to create a new + * one. + */ + NONE, + + /** + * CefApp is new created but not initialized yet. No CefClient and no + * CefBrowser was created until now. + */ + NEW, + + /** + * CefApp is in its initializing process. Please wait until initializing is + * finished. + */ + INITIALIZING, + + /** + * CefApp is up and running. At least one CefClient was created and the + * message loop is running. You can use all classes and methods of JCEF now. + */ + 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 + * be created. The message loop will be performed until all CefClients and + * all CefBrowsers are disposed completely. + */ + SHUTTING_DOWN, + + /** + * CefApp is terminated and can't be used any more. You can shutdown the + * application safely now. + */ + TERMINATED + } + + /** + * According the singleton pattern, this attribute keeps + * one single object of this class. + */ + private static CefApp self = null; + private static CefAppHandler appHandler_ = null; + private static CefAppState state_ = CefAppState.NONE; + private Timer workTimer_ = null; + private HashSet clients_ = new HashSet(); + private CefSettings settings_ = null; + + /** + * To get an instance of this class, use the method + * getInstance() instead of this CTOR. + * + * The CTOR is called by getInstance() as needed and + * loads all required JCEF libraries. + * + * @throws UnsatisfiedLinkError + */ + private CefApp(String[] args, CefSettings settings) throws UnsatisfiedLinkError { + super(args); + if (settings != null) settings_ = settings.clone(); + if (OS.isWindows()) { + SystemBootstrap.loadLibrary("jawt"); + SystemBootstrap.loadLibrary("chrome_elf"); + SystemBootstrap.loadLibrary("libcef"); + + // Other platforms load this library in CefApp.startup(). + SystemBootstrap.loadLibrary("jcef"); + } else if (OS.isLinux()) { + SystemBootstrap.loadLibrary("cef"); + } + if (appHandler_ == null) { + appHandler_ = this; + } + + // Execute on the AWT event dispatching thread. + try { + Runnable r = new Runnable() { + @Override + public void run() { + // Perform native pre-initialization. + if (!N_PreInitialize()) + throw new IllegalStateException("Failed to pre-initialize native code"); + } + }; + if (SwingUtilities.isEventDispatchThread()) + r.run(); + else + SwingUtilities.invokeAndWait(r); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Assign an AppHandler to CefApp. The AppHandler can be used to evaluate + * application arguments, to register your own schemes and to hook into the + * shutdown sequence. See CefAppHandler for more details. + * + * This method must be called before CefApp is initialized. CefApp will be + * initialized automatically if you call createClient() the first time. + * @param appHandler An instance of CefAppHandler. + * + * @throws IllegalStateException in case of CefApp is already initialized + */ + public static void addAppHandler(CefAppHandler appHandler) throws IllegalStateException { + if (getState().compareTo(CefAppState.NEW) > 0) + throw new IllegalStateException("Must be called before CefApp is initialized"); + appHandler_ = appHandler; + } + + /** + * Get an instance of this class. + * @return an instance of this class + * @throws UnsatisfiedLinkError + */ + public static synchronized CefApp getInstance() throws UnsatisfiedLinkError { + return getInstance(null, null); + } + + public static synchronized CefApp getInstance(String[] args) throws UnsatisfiedLinkError { + return getInstance(args, null); + } + + public static synchronized CefApp getInstance(CefSettings settings) + throws UnsatisfiedLinkError { + return getInstance(null, settings); + } + + public static synchronized CefApp getInstance(String[] args, CefSettings settings) + throws UnsatisfiedLinkError { + if (settings != null) { + if (getState() != CefAppState.NONE && getState() != CefAppState.NEW) + throw new IllegalStateException("Settings can only be passed to CEF" + + " before createClient is called the first time."); + } + if (self == null) { + if (getState() == CefAppState.TERMINATED) + throw new IllegalStateException("CefApp was terminated"); + self = new CefApp(args, settings); + setState(CefAppState.NEW); + } + return self; + } + + public final void setSettings(CefSettings settings) throws IllegalStateException { + if (getState() != CefAppState.NONE && getState() != CefAppState.NEW) + throw new IllegalStateException("Settings can only be passed to CEF" + + " before createClient is called the first time."); + settings_ = settings.clone(); + } + + public final CefVersion getVersion() { + try { + return N_GetVersion(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + /** + * Returns the current state of CefApp. + * @return current state. + */ + public final static CefAppState getState() { + synchronized (state_) { + return state_; + } + } + + private static final void setState(final CefAppState state) { + synchronized (state_) { + state_ = state; + } + // Execute on the AWT event dispatching thread. + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (appHandler_ != null) appHandler_.stateHasChanged(state); + } + }); + } + + /** + * To shutdown the system, it's important to call the dispose + * method. Calling this method closes all client instances with + * and all browser instances each client owns. After that the + * message loop is terminated and CEF is shutdown. + */ + public synchronized final void dispose() { + switch (getState()) { + case NEW: + // Nothing to do inspite of invalidating the state + setState(CefAppState.TERMINATED); + break; + + case INITIALIZING: + case INITIALIZED: + // (3) Shutdown sequence. Close all clients and continue. + setState(CefAppState.SHUTTING_DOWN); + if (clients_.isEmpty()) { + shutdown(); + } else { + // shutdown() will be called from clientWasDisposed() when the last + // client is gone. + // Use a copy of the HashSet to avoid iterating during modification. + HashSet clients = new HashSet(clients_); + for (CefClient c : clients) { + c.dispose(); + } + } + break; + + case NONE: + case SHUTTING_DOWN: + case TERMINATED: + // Ignore shutdown, CefApp is already terminated, in shutdown progress + // or was never created (shouldn't be possible) + break; + } + } + + /** + * Creates a new client instance and returns it to the caller. + * One client instance is responsible for one to many browser + * instances + * @return a new client instance + */ + public synchronized CefClient createClient() { + switch (getState()) { + case NEW: + setState(CefAppState.INITIALIZING); + initialize(); + // FALL THRU + + case INITIALIZING: + case INITIALIZED: + CefClient client = new CefClient(); + clients_.add(client); + return client; + + default: + throw new IllegalStateException("Can't crate client in state " + state_); + } + } + + /** + * Register a scheme handler factory for the specified |scheme_name| and + * optional |domain_name|. An empty |domain_name| value for a standard scheme + * will cause the factory to match all domain names. The |domain_name| value + * will be ignored for non-standard schemes. If |scheme_name| is a built-in + * scheme and no handler is returned by |factory| then the built-in scheme + * handler factory will be called. If |scheme_name| is a custom scheme then + * also implement the CefApp::OnRegisterCustomSchemes() method in all + * processes. This function may be called multiple times to change or remove + * the factory that matches the specified |scheme_name| and optional + * |domain_name|. Returns false if an error occurs. This function may be + * called on any thread in the browser process. + */ + public boolean registerSchemeHandlerFactory( + String schemeName, String domainName, CefSchemeHandlerFactory factory) { + try { + return N_RegisterSchemeHandlerFactory(schemeName, domainName, factory); + } catch (Exception err) { + err.printStackTrace(); + } + return false; + } + + /** + * Clear all registered scheme handler factories. Returns false on error. This + * function may be called on any thread in the browser process. + */ + public boolean clearSchemeHandlerFactories() { + try { + return N_ClearSchemeHandlerFactories(); + } catch (Exception err) { + err.printStackTrace(); + } + return false; + } + + /** + * This method is called by a CefClient if it was disposed. This causes + * CefApp to clean up its list of available client instances. If all clients + * are disposed, CefApp will be shutdown. + * @param client the disposed client. + */ + protected final synchronized void clientWasDisposed(CefClient client) { + clients_.remove(client); + if (clients_.isEmpty() && getState().compareTo(CefAppState.SHUTTING_DOWN) >= 0) { + // Shutdown native system. + shutdown(); + } + } + + /** + * Initialize the context. + * @return true on success. + */ + private final void initialize() { + // Execute on the AWT event dispatching thread. + try { + Runnable r = new Runnable() { + @Override + public void run() { + String library_path = getJcefLibPath(); + System.out.println("initialize on " + Thread.currentThread() + + " with library path " + library_path); + + CefSettings settings = settings_ != null ? settings_ : new CefSettings(); + + // Avoid to override user values by testing on NULL + if (OS.isMacintosh()) { + if (settings.browser_subprocess_path == null) { + Path path = Paths.get(library_path, + "../Frameworks/jcef Helper.app/Contents/MacOS/jcef Helper"); + settings.browser_subprocess_path = + path.normalize().toAbsolutePath().toString(); + } + } else if (OS.isWindows()) { + if (settings.browser_subprocess_path == null) { + Path path = Paths.get(library_path, "jcef_helper.exe"); + settings.browser_subprocess_path = + path.normalize().toAbsolutePath().toString(); + } + } else if (OS.isLinux()) { + if (settings.browser_subprocess_path == null) { + Path path = Paths.get(library_path, "jcef_helper"); + settings.browser_subprocess_path = + path.normalize().toAbsolutePath().toString(); + } + if (settings.resources_dir_path == null) { + Path path = Paths.get(library_path); + settings.resources_dir_path = + path.normalize().toAbsolutePath().toString(); + } + if (settings.locales_dir_path == null) { + Path path = Paths.get(library_path, "locales"); + settings.locales_dir_path = + path.normalize().toAbsolutePath().toString(); + } + } + + if (N_Initialize(appHandler_, settings)) { + setState(CefAppState.INITIALIZED); + } else { + setState(CefAppState.INITIALIZATION_FAILED); + } + } + }; + if (SwingUtilities.isEventDispatchThread()) + r.run(); + else + SwingUtilities.invokeAndWait(r); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * This method is invoked by the native code (currently on Mac only) in case + * of a termination event (e.g. someone pressed CMD+Q). + */ + protected final void handleBeforeTerminate() { + System.out.println("Cmd+Q termination request."); + // Execute on the AWT event dispatching thread. Always call asynchronously + // so the call stack has a chance to unwind. + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + CefAppHandler handler = + (CefAppHandler) ((appHandler_ == null) ? this : appHandler_); + if (!handler.onBeforeTerminate()) dispose(); + } + }); + } + + /** + * Shut down the context. + */ + private final void shutdown() { + // Execute on the AWT event dispatching thread. Always call asynchronously + // so the call stack has a chance to unwind. + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + System.out.println("shutdown on " + Thread.currentThread()); + + // Shutdown native CEF. + N_Shutdown(); + + setState(CefAppState.TERMINATED); + CefApp.self = null; + } + }); + } + + /** + * Perform a single message loop iteration. Used on all platforms except + * Windows with windowed rendering. + */ + public final void doMessageLoopWork(final long delay_ms) { + // Execute on the AWT event dispatching thread. + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (getState() == CefAppState.TERMINATED) return; + + // The maximum number of milliseconds we're willing to wait between + // calls to DoMessageLoopWork(). + final long kMaxTimerDelay = 1000 / 30; // 30fps + + if (workTimer_ != null) { + workTimer_.stop(); + workTimer_ = null; + } + + if (delay_ms <= 0) { + // Execute the work immediately. + N_DoMessageLoopWork(); + + // Schedule more work later. + doMessageLoopWork(kMaxTimerDelay); + } else { + long timer_delay_ms = delay_ms; + // Never wait longer than the maximum allowed time. + if (timer_delay_ms > kMaxTimerDelay) timer_delay_ms = kMaxTimerDelay; + + workTimer_ = new Timer((int) timer_delay_ms, new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + // Timer has timed out. + workTimer_.stop(); + workTimer_ = null; + + N_DoMessageLoopWork(); + + // Schedule more work later. + doMessageLoopWork(kMaxTimerDelay); + } + }); + workTimer_.start(); + } + } + }); + } + + /** + * This method must be called at the beginning of the main() method to perform platform- + * specific startup initialization. On Linux this initializes Xlib multithreading and on + * macOS this dynamically loads the CEF framework. + * @param args Command-line arguments massed to main(). + * @return True on successful startup. + */ + public static final boolean startup(String[] args) { + if (OS.isLinux() || OS.isMacintosh()) { + SystemBootstrap.loadLibrary("jcef"); + return N_Startup(OS.isMacintosh() ? getCefFrameworkPath(args) : null); + } + return true; + } + + /** + * Get the path which contains the jcef library + * @return The path to the jcef library + */ + private static final String getJcefLibPath() { + String library_path = System.getProperty("java.library.path"); + String[] paths = library_path.split(System.getProperty("path.separator")); + for (String path : paths) { + File dir = new File(path); + String[] found = dir.list(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return (name.equalsIgnoreCase("libjcef.dylib") + || name.equalsIgnoreCase("libjcef.so") + || name.equalsIgnoreCase("jcef.dll")); + } + }); + if (found != null && found.length != 0) return path; + } + return library_path; + } + + /** + * Get the path that contains the CEF Framework on macOS. + * @return The path to the CEF Framework. + */ + private static final String getCefFrameworkPath(String[] args) { + // Check for the path on the command-line. + String switchPrefix = "--framework-dir-path="; + for (String arg : args) { + if (arg.startsWith(switchPrefix)) { + return new File(arg.substring(switchPrefix.length())).getAbsolutePath(); + } + } + + // Determine the path relative to the JCEF lib location in the app bundle. + return new File(getJcefLibPath() + "/../Frameworks/Chromium Embedded Framework.framework") + .getAbsolutePath(); + } + + private final static native boolean N_Startup(String pathToCefFramework); + private final native boolean N_PreInitialize(); + private final native boolean N_Initialize(CefAppHandler appHandler, CefSettings settings); + private final native void N_Shutdown(); + private final native void N_DoMessageLoopWork(); + private final native CefVersion N_GetVersion(); + private final native boolean N_RegisterSchemeHandlerFactory( + String schemeName, String domainName, CefSchemeHandlerFactory factory); + private final native boolean N_ClearSchemeHandlerFactories(); +} diff --git a/lib/jcef/java/org/cef/CefBrowserSettings.java b/lib/jcef/java/org/cef/CefBrowserSettings.java new file mode 100644 index 0000000..8733a41 --- /dev/null +++ b/lib/jcef/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/lib/jcef/java/org/cef/CefClient.java b/lib/jcef/java/org/cef/CefClient.java new file mode 100644 index 0000000..687be93 --- /dev/null +++ b/lib/jcef/java/org/cef/CefClient.java @@ -0,0 +1,886 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef; + +import org.cef.browser.*; +import org.cef.callback.CefAuthCallback; +import org.cef.callback.CefBeforeDownloadCallback; +import org.cef.callback.CefCallback; +import org.cef.callback.CefContextMenuParams; +import org.cef.callback.CefDownloadItem; +import org.cef.callback.CefDownloadItemCallback; +import org.cef.callback.CefDragData; +import org.cef.callback.CefFileDialogCallback; +import org.cef.callback.CefJSDialogCallback; +import org.cef.callback.CefMenuModel; +import org.cef.callback.CefPrintDialogCallback; +import org.cef.callback.CefPrintJobCallback; +import org.cef.handler.CefClientHandler; +import org.cef.handler.CefContextMenuHandler; +import org.cef.handler.CefDialogHandler; +import org.cef.handler.CefDisplayHandler; +import org.cef.handler.CefDownloadHandler; +import org.cef.handler.CefDragHandler; +import org.cef.handler.CefFocusHandler; +import org.cef.handler.CefJSDialogHandler; +import org.cef.handler.CefKeyboardHandler; +import org.cef.handler.CefLifeSpanHandler; +import org.cef.handler.CefLoadHandler; +import org.cef.handler.CefPrintHandler; +import org.cef.handler.CefRenderHandler; +import org.cef.handler.CefRequestHandler; +import org.cef.handler.CefResourceHandler; +import org.cef.handler.CefResourceRequestHandler; +import org.cef.handler.CefScreenInfo; +import org.cef.handler.CefWindowHandler; +import org.cef.misc.BoolRef; +import org.cef.misc.CefPrintSettings; +import org.cef.misc.StringRef; +import org.cef.network.CefRequest; +import org.cef.network.CefRequest.TransitionType; +import org.cef.network.CefResponse; +import org.cef.network.CefURLRequest; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FocusTraversalPolicy; +import java.awt.KeyboardFocusManager; +import java.awt.Point; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.HashMap; +import java.util.Vector; +import java.util.function.Consumer; + +import javax.swing.SwingUtilities; + +/** + * Client that owns a browser and renderer. + */ +public class CefClient extends CefClientHandler + implements CefContextMenuHandler, CefDialogHandler, CefDisplayHandler, CefDownloadHandler, + CefDragHandler, CefFocusHandler, CefJSDialogHandler, CefKeyboardHandler, + CefLifeSpanHandler, CefLoadHandler, CefPrintHandler, CefRenderHandler, + CefRequestHandler, CefWindowHandler { + private HashMap browser_ = new HashMap(); + private CefContextMenuHandler contextMenuHandler_ = null; + private CefDialogHandler dialogHandler_ = null; + private CefDisplayHandler displayHandler_ = null; + private CefDownloadHandler downloadHandler_ = null; + private CefDragHandler dragHandler_ = null; + private CefFocusHandler focusHandler_ = null; + private CefJSDialogHandler jsDialogHandler_ = null; + private CefKeyboardHandler keyboardHandler_ = null; + private CefLifeSpanHandler lifeSpanHandler_ = null; + private CefLoadHandler loadHandler_ = null; + private CefPrintHandler printHandler_ = null; + private CefRequestHandler requestHandler_ = null; + private boolean isDisposed_ = false; + private volatile CefBrowser focusedBrowser_ = null; + private final PropertyChangeListener propertyChangeListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (focusedBrowser_ != null) { + Component browserUI = focusedBrowser_.getUIComponent(); + Object oldUI = evt.getOldValue(); + if (isPartOf(oldUI, browserUI)) { + focusedBrowser_.setFocus(false); + focusedBrowser_ = null; + } + } + } + }; + + /** + * The CTOR is only accessible within this package. + * Use CefApp.createClient() to create an instance of + * this class. + * @see org.cef.CefApp.createClient() + */ + CefClient() throws UnsatisfiedLinkError { + super(); + + KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener( + propertyChangeListener); + } + + private boolean isPartOf(Object obj, Component browserUI) { + if (obj == browserUI) return true; + if (obj instanceof Container) { + Component childs[] = ((Container) obj).getComponents(); + for (Component child : childs) { + return isPartOf(child, browserUI); + } + } + return false; + } + + @Override + public void dispose() { + isDisposed_ = true; + cleanupBrowser(-1); + } + + // CefClientHandler + + public CefBrowser createBrowser( + String url, boolean isOffscreenRendered, boolean isTransparent) { + return createBrowser(url, isOffscreenRendered, isTransparent, null); + } + + public CefBrowser createBrowser(String url, boolean isOffscreenRendered, boolean isTransparent, + CefRequestContext context) { + if (isDisposed_) + throw new IllegalStateException("Can't create browser. CefClient is disposed"); + return CefBrowserFactory.create( + this, url, isOffscreenRendered, isTransparent, context, null); + } + + public CefBrowser createBrowser(String url, boolean 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 + protected CefBrowser getBrowser(int identifier) { + synchronized (browser_) { + return browser_.get(new Integer(identifier)); + } + } + + @Override + protected Object[] getAllBrowser() { + synchronized (browser_) { + return browser_.values().toArray(); + } + } + + @Override + protected CefContextMenuHandler getContextMenuHandler() { + return this; + } + + @Override + protected CefDialogHandler getDialogHandler() { + return this; + }; + + @Override + protected CefDisplayHandler getDisplayHandler() { + return this; + } + + @Override + protected CefDownloadHandler getDownloadHandler() { + return this; + } + + @Override + protected CefDragHandler getDragHandler() { + return this; + } + + @Override + protected CefFocusHandler getFocusHandler() { + return this; + } + + @Override + protected CefJSDialogHandler getJSDialogHandler() { + return this; + } + + @Override + protected CefKeyboardHandler getKeyboardHandler() { + return this; + } + + @Override + protected CefLifeSpanHandler getLifeSpanHandler() { + return this; + } + + @Override + protected CefLoadHandler getLoadHandler() { + return this; + } + + @Override + protected CefPrintHandler getPrintHandler() { + return this; + } + + @Override + protected CefRenderHandler getRenderHandler() { + return this; + } + + @Override + protected CefRequestHandler getRequestHandler() { + return this; + } + + @Override + protected CefWindowHandler getWindowHandler() { + return this; + } + + // CefContextMenuHandler + + public CefClient addContextMenuHandler(CefContextMenuHandler handler) { + if (contextMenuHandler_ == null) contextMenuHandler_ = handler; + return this; + } + + public void removeContextMenuHandler() { + contextMenuHandler_ = null; + } + + @Override + public void onBeforeContextMenu( + CefBrowser browser, CefFrame frame, CefContextMenuParams params, CefMenuModel model) { + if (contextMenuHandler_ != null && browser != null) + contextMenuHandler_.onBeforeContextMenu(browser, frame, params, model); + } + + @Override + public boolean onContextMenuCommand(CefBrowser browser, CefFrame frame, + CefContextMenuParams params, int commandId, int eventFlags) { + if (contextMenuHandler_ != null && browser != null) + return contextMenuHandler_.onContextMenuCommand( + browser, frame, params, commandId, eventFlags); + return false; + } + + @Override + public void onContextMenuDismissed(CefBrowser browser, CefFrame frame) { + if (contextMenuHandler_ != null && browser != null) + contextMenuHandler_.onContextMenuDismissed(browser, frame); + } + + // CefDialogHandler + + public CefClient addDialogHandler(CefDialogHandler handler) { + if (dialogHandler_ == null) dialogHandler_ = handler; + return this; + } + + public void removeDialogHandler() { + dialogHandler_ = null; + } + + @Override + public boolean onFileDialog(CefBrowser browser, FileDialogMode mode, String title, + String defaultFilePath, Vector acceptFilters, Vector acceptExtensions, + Vector acceptDescriptions, CefFileDialogCallback callback) { + if (dialogHandler_ != null && browser != null) { + return dialogHandler_.onFileDialog(browser, mode, title, defaultFilePath, acceptFilters, + acceptExtensions, acceptDescriptions, callback); + } + return false; + } + + // CefDisplayHandler + + public CefClient addDisplayHandler(CefDisplayHandler handler) { + if (displayHandler_ == null) displayHandler_ = handler; + return this; + } + + public void removeDisplayHandler() { + displayHandler_ = null; + } + + @Override + public void onAddressChange(CefBrowser browser, CefFrame frame, String url) { + if (displayHandler_ != null && browser != null) + displayHandler_.onAddressChange(browser, frame, url); + } + + @Override + public void onTitleChange(CefBrowser browser, String title) { + if (displayHandler_ != null && browser != null) + 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) { + return displayHandler_.onTooltip(browser, text); + } + return false; + } + + @Override + public void onStatusMessage(CefBrowser browser, String value) { + if (displayHandler_ != null && browser != null) { + displayHandler_.onStatusMessage(browser, value); + } + } + + @Override + public boolean onConsoleMessage(CefBrowser browser, CefSettings.LogSeverity level, + String message, String source, int line) { + if (displayHandler_ != null && browser != null) { + return displayHandler_.onConsoleMessage(browser, level, message, source, line); + } + return false; + } + + @Override + public boolean onCursorChange(CefBrowser browser, int cursorType) { + if (browser == null) { + return false; + } + + if (displayHandler_ != null && displayHandler_.onCursorChange(browser, cursorType)) { + return true; + } + + CefRenderHandler realHandler = browser.getRenderHandler(); + if (realHandler != null) { + return realHandler.onCursorChange(browser, cursorType); + } + + return false; + } + + // CefDownloadHandler + + public CefClient addDownloadHandler(CefDownloadHandler handler) { + if (downloadHandler_ == null) downloadHandler_ = handler; + return this; + } + + public void removeDownloadHandler() { + downloadHandler_ = null; + } + + @Override + public boolean onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem, + String suggestedName, CefBeforeDownloadCallback callback) { + if (downloadHandler_ != null && browser != null) + return downloadHandler_.onBeforeDownload( + browser, downloadItem, suggestedName, callback); + return false; + } + + @Override + public void onDownloadUpdated( + CefBrowser browser, CefDownloadItem downloadItem, CefDownloadItemCallback callback) { + if (downloadHandler_ != null && browser != null) + downloadHandler_.onDownloadUpdated(browser, downloadItem, callback); + } + + // CefDragHandler + + public CefClient addDragHandler(CefDragHandler handler) { + if (dragHandler_ == null) dragHandler_ = handler; + return this; + } + + public void removeDragHandler() { + dragHandler_ = null; + } + + @Override + public boolean onDragEnter(CefBrowser browser, CefDragData dragData, int mask) { + if (dragHandler_ != null && browser != null) + return dragHandler_.onDragEnter(browser, dragData, mask); + return false; + } + + // CefFocusHandler + + public CefClient addFocusHandler(CefFocusHandler handler) { + if (focusHandler_ == null) focusHandler_ = handler; + return this; + } + + public void removeFocusHandler() { + focusHandler_ = null; + } + + @Override + public void onTakeFocus(CefBrowser browser, boolean next) { + if (browser == null) return; + + browser.setFocus(false); + Container parent = browser.getUIComponent().getParent(); + if (parent != null) { + FocusTraversalPolicy policy = null; + while (parent != null) { + policy = parent.getFocusTraversalPolicy(); + if (policy != null) break; + parent = parent.getParent(); + } + if (policy != null) { + Component nextComp = next + ? policy.getComponentAfter(parent, browser.getUIComponent()) + : policy.getComponentBefore(parent, browser.getUIComponent()); + if (nextComp == null) { + policy.getDefaultComponent(parent).requestFocus(); + } else { + nextComp.requestFocus(); + } + } + } + focusedBrowser_ = null; + if (focusHandler_ != null) focusHandler_.onTakeFocus(browser, next); + } + + @Override + public boolean onSetFocus(final CefBrowser browser, FocusSource source) { + if (browser == null) return false; + + boolean alreadyHandled = false; + if (focusHandler_ != null) alreadyHandled = focusHandler_.onSetFocus(browser, source); + return alreadyHandled; + } + + @Override + public void onGotFocus(CefBrowser browser) { + if (browser == null) return; + + focusedBrowser_ = browser; + browser.setFocus(true); + if (focusHandler_ != null) focusHandler_.onGotFocus(browser); + } + + // CefJSDialogHandler + + public CefClient addJSDialogHandler(CefJSDialogHandler handler) { + if (jsDialogHandler_ == null) jsDialogHandler_ = handler; + return this; + } + + public void removeJSDialogHandler() { + jsDialogHandler_ = null; + } + + @Override + public boolean onJSDialog(CefBrowser browser, String origin_url, JSDialogType dialog_type, + String message_text, String default_prompt_text, CefJSDialogCallback callback, + BoolRef suppress_message) { + if (jsDialogHandler_ != null && browser != null) + return jsDialogHandler_.onJSDialog(browser, origin_url, dialog_type, message_text, + default_prompt_text, callback, suppress_message); + return false; + } + + @Override + public boolean onBeforeUnloadDialog(CefBrowser browser, String message_text, boolean is_reload, + CefJSDialogCallback callback) { + if (jsDialogHandler_ != null && browser != null) + return jsDialogHandler_.onBeforeUnloadDialog( + browser, message_text, is_reload, callback); + return false; + } + + @Override + public void onResetDialogState(CefBrowser browser) { + if (jsDialogHandler_ != null && browser != null) + jsDialogHandler_.onResetDialogState(browser); + } + + @Override + public void onDialogClosed(CefBrowser browser) { + if (jsDialogHandler_ != null && browser != null) jsDialogHandler_.onDialogClosed(browser); + } + + // CefKeyboardHandler + + public CefClient addKeyboardHandler(CefKeyboardHandler handler) { + if (keyboardHandler_ == null) keyboardHandler_ = handler; + return this; + } + + public void removeKeyboardHandler() { + keyboardHandler_ = null; + } + + @Override + public boolean onPreKeyEvent( + CefBrowser browser, CefKeyEvent event, BoolRef is_keyboard_shortcut) { + if (keyboardHandler_ != null && browser != null) + return keyboardHandler_.onPreKeyEvent(browser, event, is_keyboard_shortcut); + return false; + } + + @Override + public boolean onKeyEvent(CefBrowser browser, CefKeyEvent event) { + if (keyboardHandler_ != null && browser != null) + return keyboardHandler_.onKeyEvent(browser, event); + return false; + } + + // CefLifeSpanHandler + + public CefClient addLifeSpanHandler(CefLifeSpanHandler handler) { + if (lifeSpanHandler_ == null) lifeSpanHandler_ = handler; + return this; + } + + public void removeLifeSpanHandler() { + lifeSpanHandler_ = null; + } + + @Override + public boolean onBeforePopup( + CefBrowser browser, CefFrame frame, String target_url, String target_frame_name) { + if (isDisposed_) return true; + if (lifeSpanHandler_ != null && browser != null) + return lifeSpanHandler_.onBeforePopup(browser, frame, target_url, target_frame_name); + return false; + } + + @Override + public void onAfterCreated(CefBrowser browser) { + if (browser == null) return; + + // keep browser reference + Integer identifier = browser.getIdentifier(); + synchronized (browser_) { + browser_.put(identifier, browser); + } + if (lifeSpanHandler_ != null) lifeSpanHandler_.onAfterCreated(browser); + } + + @Override + public void onAfterParentChanged(CefBrowser browser) { + if (browser == null) return; + if (lifeSpanHandler_ != null) lifeSpanHandler_.onAfterParentChanged(browser); + } + + @Override + public boolean doClose(CefBrowser browser) { + if (browser == null) return false; + if (lifeSpanHandler_ != null) return lifeSpanHandler_.doClose(browser); + return browser.doClose(); + } + + @Override + public void onBeforeClose(CefBrowser browser) { + if (browser == null) return; + if (lifeSpanHandler_ != null) lifeSpanHandler_.onBeforeClose(browser); + browser.onBeforeClose(); + + // remove browser reference + cleanupBrowser(browser.getIdentifier()); + } + + private void cleanupBrowser(int identifier) { + synchronized (browser_) { + if (identifier >= 0) { + // Remove the specific browser that closed. + browser_.remove(identifier); + } else if (!browser_.isEmpty()) { + // Close all browsers. + Collection browserList = browser_.values(); + for (CefBrowser browser : browserList) { + browser.close(true); + } + return; + } + + if (browser_.isEmpty() && isDisposed_) { + KeyboardFocusManager.getCurrentKeyboardFocusManager().removePropertyChangeListener( + propertyChangeListener); + removeContextMenuHandler(this); + removeDialogHandler(this); + removeDisplayHandler(this); + removeDownloadHandler(this); + removeDragHandler(this); + removeFocusHandler(this); + removeJSDialogHandler(this); + removeKeyboardHandler(this); + removeLifeSpanHandler(this); + removeLoadHandler(this); + removePrintHandler(this); + removeRenderHandler(this); + removeRequestHandler(this); + removeWindowHandler(this); + super.dispose(); + + CefApp.getInstance().clientWasDisposed(this); + } + } + } + + // CefLoadHandler + + public CefClient addLoadHandler(CefLoadHandler handler) { + if (loadHandler_ == null) loadHandler_ = handler; + return this; + } + + public void removeLoadHandler() { + loadHandler_ = null; + } + + @Override + public void onLoadingStateChange( + CefBrowser browser, boolean isLoading, boolean canGoBack, boolean canGoForward) { + if (loadHandler_ != null && browser != null) + loadHandler_.onLoadingStateChange(browser, isLoading, canGoBack, canGoForward); + } + + @Override + public void onLoadStart(CefBrowser browser, CefFrame frame, TransitionType transitionType) { + if (loadHandler_ != null && browser != null) + loadHandler_.onLoadStart(browser, frame, transitionType); + } + + @Override + public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) { + if (loadHandler_ != null && browser != null) + loadHandler_.onLoadEnd(browser, frame, httpStatusCode); + } + + @Override + public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, + String errorText, String failedUrl) { + if (loadHandler_ != null && browser != null) + loadHandler_.onLoadError(browser, frame, errorCode, errorText, failedUrl); + } + + // CefPrintHandler + + public CefClient addPrintHandler(CefPrintHandler handler) { + if (printHandler_ == null) printHandler_ = handler; + return this; + } + + public void removePrintHandler() { + printHandler_ = null; + } + + @Override + public void onPrintStart(CefBrowser browser) { + if (printHandler_ != null && browser != null) printHandler_.onPrintStart(browser); + } + + @Override + public void onPrintSettings( + CefBrowser browser, CefPrintSettings settings, boolean getDefaults) { + if (printHandler_ != null && browser != null) + printHandler_.onPrintSettings(browser, settings, getDefaults); + } + + @Override + public boolean onPrintDialog( + CefBrowser browser, boolean hasSelection, CefPrintDialogCallback callback) { + if (printHandler_ != null && browser != null) + return printHandler_.onPrintDialog(browser, hasSelection, callback); + return false; + } + + @Override + public boolean onPrintJob(CefBrowser browser, String documentName, String pdfFilePath, + CefPrintJobCallback callback) { + if (printHandler_ != null && browser != null) + return printHandler_.onPrintJob(browser, documentName, pdfFilePath, callback); + return false; + } + + @Override + public void onPrintReset(CefBrowser browser) { + if (printHandler_ != null && browser != null) printHandler_.onPrintReset(browser); + } + + @Override + public Dimension getPdfPaperSize(CefBrowser browser, int deviceUnitsPerInch) { + if (printHandler_ != null && browser != null) + return printHandler_.getPdfPaperSize(browser, deviceUnitsPerInch); + return null; + } + + // CefMessageRouter + + @Override + public synchronized void addMessageRouter(CefMessageRouter messageRouter) { + super.addMessageRouter(messageRouter); + } + + @Override + public synchronized void removeMessageRouter(CefMessageRouter messageRouter) { + super.removeMessageRouter(messageRouter); + } + + // CefRenderHandler + + @Override + public Rectangle getViewRect(CefBrowser browser) { + if (browser == null) return new Rectangle(0, 0, 0, 0); + + CefRenderHandler realHandler = browser.getRenderHandler(); + if (realHandler != null) return realHandler.getViewRect(browser); + return new Rectangle(0, 0, 0, 0); + } + + @Override + public Point getScreenPoint(CefBrowser browser, Point viewPoint) { + if (browser == null) return new Point(0, 0); + + CefRenderHandler realHandler = browser.getRenderHandler(); + if (realHandler != null) return realHandler.getScreenPoint(browser, viewPoint); + return new Point(0, 0); + } + + @Override + public void onPopupShow(CefBrowser browser, boolean show) { + if (browser == null) return; + + CefRenderHandler realHandler = browser.getRenderHandler(); + if (realHandler != null) realHandler.onPopupShow(browser, show); + } + + @Override + public void onPopupSize(CefBrowser browser, Rectangle size) { + if (browser == null) return; + + CefRenderHandler realHandler = browser.getRenderHandler(); + if (realHandler != null) realHandler.onPopupSize(browser, size); + } + + @Override + public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, + ByteBuffer buffer, int width, int height) { + if (browser == null) return; + + CefRenderHandler realHandler = browser.getRenderHandler(); + if (realHandler != null) + 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; + + CefRenderHandler realHandler = browser.getRenderHandler(); + if (realHandler != null) return realHandler.startDragging(browser, dragData, mask, x, y); + return false; + } + + @Override + public void updateDragCursor(CefBrowser browser, int operation) { + if (browser == null) return; + + CefRenderHandler realHandler = browser.getRenderHandler(); + if (realHandler != null) realHandler.updateDragCursor(browser, operation); + } + + // CefRequestHandler + + public CefClient addRequestHandler(CefRequestHandler handler) { + if (requestHandler_ == null) requestHandler_ = handler; + return this; + } + + public void removeRequestHandler() { + requestHandler_ = null; + } + + @Override + public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, + boolean user_gesture, boolean is_redirect) { + if (requestHandler_ != null && browser != null) + return requestHandler_.onBeforeBrowse( + browser, frame, request, user_gesture, is_redirect); + return false; + } + + @Override + public boolean onOpenURLFromTab( + CefBrowser browser, CefFrame frame, String target_url, boolean user_gesture) { + if (isDisposed_) return true; + if (requestHandler_ != null && browser != null) + return requestHandler_.onOpenURLFromTab(browser, frame, target_url, user_gesture); + return false; + } + + @Override + public CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame, + CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator, + BoolRef disableDefaultHandling) { + if (requestHandler_ != null && browser != null) { + return requestHandler_.getResourceRequestHandler(browser, frame, request, isNavigation, + isDownload, requestInitiator, disableDefaultHandling); + } + return null; + } + + @Override + public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy, + String host, int port, String realm, String scheme, CefAuthCallback callback) { + if (requestHandler_ != null && browser != null) + return requestHandler_.getAuthCredentials( + browser, origin_url, isProxy, host, port, realm, scheme, callback); + return false; + } + + @Override + public boolean onCertificateError( + CefBrowser browser, ErrorCode cert_error, String request_url, CefCallback callback) { + if (requestHandler_ != null) + return requestHandler_.onCertificateError(browser, cert_error, request_url, callback); + return false; + } + + @Override + 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 + + @Override + public Rectangle getRect(CefBrowser browser) { + if (browser == null) return new Rectangle(0, 0, 0, 0); + + CefWindowHandler realHandler = browser.getWindowHandler(); + if (realHandler != null) return realHandler.getRect(browser); + return new Rectangle(0, 0, 0, 0); + } + + @Override + public void onMouseEvent( + CefBrowser browser, int event, int screenX, int screenY, int modifier, int button) { + if (browser == null) return; + + CefWindowHandler realHandler = browser.getWindowHandler(); + if (realHandler != null) + realHandler.onMouseEvent(browser, event, screenX, screenY, modifier, button); + } + + @Override + public boolean getScreenInfo(CefBrowser arg0, CefScreenInfo arg1) { + return false; + } +} diff --git a/lib/jcef/java/org/cef/CefSettings.java b/lib/jcef/java/org/cef/CefSettings.java new file mode 100644 index 0000000..e956cce --- /dev/null +++ b/lib/jcef/java/org/cef/CefSettings.java @@ -0,0 +1,295 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef; + +/** + * Initialization settings. Specify NULL or 0 to get the recommended default + * values. Many of these and other settings can also configured using command- + * line switches. + */ +public class CefSettings { + /** + * Log severity levels. + */ + public enum LogSeverity { + /** + * Default logging (currently INFO logging). + */ + LOGSEVERITY_DEFAULT, + + /** + * Verbose logging. + */ + LOGSEVERITY_VERBOSE, + + /** + * INFO logging. + */ + LOGSEVERITY_INFO, + + /** + * WARNING logging. + */ + LOGSEVERITY_WARNING, + + /** + * ERROR logging. + */ + LOGSEVERITY_ERROR, + + /** + * FATAL logging. + */ + LOGSEVERITY_FATAL, + + /** + * Completely disable logging. + */ + LOGSEVERITY_DISABLE + } + + /** + * 32-bit ARGB color value, not premultiplied. The color components are always + * in a known order. Equivalent to the SkColor type. + */ + public class ColorType { + private long color_value = 0; + + private ColorType() {} + + public ColorType(int alpha, int red, int green, int blue) { + color_value = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0); + } + + public long getColor() { + return color_value; + } + + @Override + public ColorType clone() { + ColorType res = new ColorType(); + res.color_value = this.color_value; + return res; + } + } + + /** + * The path to a separate executable that will be launched for sub-processes. + * By default the browser process executable is used. See the comments on + * CefExecuteProcess() for details. Also configurable using the + * "browser-subprocess-path" command-line switch. + */ + public String browser_subprocess_path = null; + + /** + * Set to true to enable windowless (off-screen) rendering support. Do not + * enable this value if the application does not use windowless rendering as + * it may reduce rendering performance on some systems. + */ + public boolean windowless_rendering_enabled = true; + + /** + * Set to true to disable configuration of browser process features using + * standard CEF and Chromium command-line arguments. Configuration can still + * be specified using CEF data structures or via the + * CefApp::OnBeforeCommandLineProcessing() method. + */ + public boolean command_line_args_disabled = false; + + /** + * 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. 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 + * true. Session cookies are generally intended to be transient and most Web + * browsers do not persist them. A |cache_path| value must also be specified to + * enable this feature. Also configurable using the "persist-session-cookies" + * command-line switch. + */ + public boolean persist_session_cookies = false; + + /** + * Value that will be returned as the User-Agent HTTP header. If empty the + * default User-Agent string will be used. Also configurable using the + * "user-agent" command-line switch. + */ + public String user_agent = null; + + /** + * Value that will be inserted as the product portion of the default + * User-Agent string. If empty the Chromium product version will be used. If + * |userAgent| is specified this value will be ignored. Also configurable + * using the "user_agent_product" command-line switch. + */ + public String user_agent_product = null; + + /** + * The locale string that will be passed to Blink. If empty the default + * locale of "en-US" will be used. This value is ignored on Linux where locale + * is determined using environment variable parsing with the precedence order: + * LANGUAGE, LC_ALL, LC_MESSAGES and LANG. Also configurable using the "lang" + * command-line switch. + */ + public String locale = null; + + /** + * The directory and file name to use for the debug log. If empty, the + * default name of "debug.log" will be used and the file will be written + * to the application directory. Also configurable using the "log-file" + * command-line switch. + */ + public String log_file = null; + + /** + * The log severity. Only messages of this severity level or higher will be + * logged. Also configurable using the "log-severity" command-line switch with + * a value of "verbose", "info", "warning", "error", "error-report" or + * "disable". + */ + public LogSeverity log_severity = LogSeverity.LOGSEVERITY_DEFAULT; + + /** + * Custom flags that will be used when initializing the V8 JavaScript engine. + * The consequences of using custom flags may not be well tested. Also + * configurable using the "js-flags" command-line switch. + */ + public String javascript_flags = null; + + /** + * The fully qualified path for the resources directory. If this value is + * empty the cef.pak and/or devtools_resources.pak files must be located in + * the module directory on Windows/Linux or the app bundle Resources directory + * on Mac OS X. Also configurable using the "resources-dir-path" command-line + * switch. + */ + public String resources_dir_path = null; + + /** + * The fully qualified path for the locales directory. If this value is empty + * the locales directory must be located in the module directory. This value + * is ignored on Mac OS X where pack files are always loaded from the app + * bundle Resources directory. Also configurable using the "locales-dir-path" + * command-line switch. + */ + public String locales_dir_path = null; + + /** + * 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 + * will be http: *localhost:8080. CEF can be remotely debugged from any CEF or + * Chrome browser window. Also configurable using the "remote-debugging-port" + * command-line switch. + */ + 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:: + * OnUncaughtException() callback. Specify 0 (default value) and + * OnUncaughtException() will not be called. Also configurable using the + * "uncaught-exception-stack-size" command-line switch. + */ + public int uncaught_exception_stack_size = 0; + + /** + * Opaque background color used for accelerated content. By default the + * background color will be white. Only the RGB compontents of the specified + * value will be used. The alpha component must greater than 0 to enable use + * of the background color but will be otherwise ignored. + */ + public ColorType background_color = null; + + /// + // Comma delimited list of schemes supported by the associated + // CefCookieManager. If |cookieable_schemes_exclude_defaults| is false (0) the + // default schemes ("http", "https", "ws" and "wss") will also be supported. + // Specifying a |cookieable_schemes_list| value and setting + // |cookieable_schemes_exclude_defaults| to true (1) will disable all loading + // and saving of cookies for this manager. Can be overridden + // for individual CefRequestContext instances via the + // CefRequestContextSettings.cookieable_schemes_list and + // CefRequestContextSettings.cookieable_schemes_exclude_defaults values. + /// + public String cookieable_schemes_list = null; + public boolean cookieable_schemes_exclude_defaults = false; + + public CefSettings() {} + + @Override + public CefSettings clone() { + CefSettings tmp = new CefSettings(); + tmp.browser_subprocess_path = browser_subprocess_path; + 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; + tmp.locale = locale; + tmp.log_file = log_file; + tmp.log_severity = log_severity; + tmp.javascript_flags = javascript_flags; + tmp.resources_dir_path = resources_dir_path; + tmp.locales_dir_path = locales_dir_path; + tmp.remote_debugging_port = remote_debugging_port; + tmp.chrome_policy_id = chrome_policy_id; + tmp.uncaught_exception_stack_size = uncaught_exception_stack_size; + if (background_color != null) tmp.background_color = background_color.clone(); + tmp.cookieable_schemes_list = cookieable_schemes_list; + tmp.cookieable_schemes_exclude_defaults = cookieable_schemes_exclude_defaults; + return tmp; + } +} diff --git a/lib/jcef/java/org/cef/OS.java b/lib/jcef/java/org/cef/OS.java new file mode 100644 index 0000000..be464d2 --- /dev/null +++ b/lib/jcef/java/org/cef/OS.java @@ -0,0 +1,44 @@ +// 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 org.cef; + +public class OS { + private static enum OSType { + OSUndefined, + OSLinux, + OSWindows, + OSMacintosh, + OSUnknown, + } + ; + private static OSType osType = OSType.OSUndefined; + + public static final boolean isWindows() { + return getOSType() == OSType.OSWindows; + } + + public static final boolean isMacintosh() { + return getOSType() == OSType.OSMacintosh; + } + + public static final boolean isLinux() { + return getOSType() == OSType.OSLinux; + } + + private static final OSType getOSType() { + if (osType == OSType.OSUndefined) { + String os = System.getProperty("os.name").toLowerCase(); + if (os.startsWith("windows")) + osType = OSType.OSWindows; + else if (os.startsWith("linux")) + osType = OSType.OSLinux; + else if (os.startsWith("mac")) + osType = OSType.OSMacintosh; + else + osType = OSType.OSUnknown; + } + return osType; + } +} diff --git a/lib/jcef/java/org/cef/SystemBootstrap.java b/lib/jcef/java/org/cef/SystemBootstrap.java new file mode 100644 index 0000000..342aaa8 --- /dev/null +++ b/lib/jcef/java/org/cef/SystemBootstrap.java @@ -0,0 +1,40 @@ +// Copyright (c) 2020 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; + +/** + * To allow customization of System.load() calls by supplying a different + * implementation. You'll want to call setLoader with your custom + * implementation before calling into any other CEF classes which then in turn + * will start triggering libraries to be loaded at runtime. + */ +public class SystemBootstrap { + /** + * Simple interface for how a library by name should be loaded. + */ + static public interface Loader { + public void loadLibrary(String libname); + } + + /** + * Default implementation is to call System.loadLibrary + */ + static private Loader loader_ = new Loader() { + @Override + public void loadLibrary(String libname) { + System.loadLibrary(libname); + } + }; + + static public void setLoader(Loader loader) { + if (loader == null) { + throw new NullPointerException("Loader cannot be null"); + } + loader_ = loader; + } + + static public void loadLibrary(String libname) { + loader_.loadLibrary(libname); + } +} \ No newline at end of file diff --git a/lib/jcef/java/org/cef/browser/CefBrowser.java b/lib/jcef/java/org/cef/browser/CefBrowser.java new file mode 100644 index 0000000..0ba05b4 --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefBrowser.java @@ -0,0 +1,425 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.browser; + +import org.cef.CefClient; +import org.cef.callback.CefPdfPrintCallback; +import org.cef.callback.CefRunFileDialogCallback; +import org.cef.callback.CefStringVisitor; +import org.cef.handler.CefDialogHandler.FileDialogMode; +import org.cef.handler.CefRenderHandler; +import org.cef.handler.CefWindowHandler; +import org.cef.misc.CefPdfPrintSettings; +import org.cef.network.CefRequest; + +import java.awt.Component; +import java.awt.Point; +import java.awt.image.BufferedImage; +import java.util.Vector; +import java.util.concurrent.CompletableFuture; + +/** + * Interface representing a browser. + */ +public interface CefBrowser { + /** + * Call to immediately create the underlying browser object. By default the + * browser object will be created when the parent container is displayed for + * the first time. + */ + public void createImmediately(); + + /** + * Get the underlying UI component (e.g. java.awt.Canvas). + * @return The underlying UI component. + */ + public Component getUIComponent(); + + /** + * Get the client associated with this browser. + * @return The browser client. + */ + public CefClient getClient(); + + /** + * Get an implementation of CefRenderHandler if any. + * @return An instance of CefRenderHandler or null. + */ + 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. + */ + public CefWindowHandler getWindowHandler(); + + // + // The following methods are forwarded to CefBrowser. + // + + /** + * Tests if the browser can navigate backwards. + * @return true if the browser can navigate backwards. + */ + public boolean canGoBack(); + + /** + * Go back. + */ + public void goBack(); + + /** + * Tests if the browser can navigate forwards. + * @return true if the browser can navigate forwards. + */ + public boolean canGoForward(); + + /** + * Go forward. + */ + public void goForward(); + + /** + * Tests if the browser is currently loading. + * @return true if the browser is currently loading. + */ + public boolean isLoading(); + + /** + * Reload the current page. + */ + public void reload(); + + /** + * Reload the current page ignoring any cached data. + */ + public void reloadIgnoreCache(); + + /** + * Stop loading the page. + */ + public void stopLoad(); + + /** + * Returns the unique browser identifier. + * @return The browser identifier + */ + public int getIdentifier(); + + /** + * Returns the main (top-level) frame for the browser window. + * @return The main frame + */ + public CefFrame getMainFrame(); + + /** + * Returns the focused frame for the browser window. + * @return The focused frame + */ + public CefFrame getFocusedFrame(); + + /** + * Returns the frame with the specified identifier, or NULL if not found. + * @param identifier The unique frame identifier + * @return The frame or NULL if not found + */ + 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 getFrameByName(String name); + + /** + * Returns the identifiers of all existing frames. + * @return All identifiers of existing frames. + */ + public Vector getFrameIdentifiers(); + + /** + * Returns the names of all existing frames. + * @return The names of all existing frames. + */ + public Vector getFrameNames(); + + /** + * Returns the number of frames that currently exist. + * @return The number of frames + */ + public int getFrameCount(); + + /** + * Tests if the window is a popup window. + * @return true if the window is a popup window. + */ + public boolean isPopup(); + + /** + * Tests if a document has been loaded in the browser. + * @return true if a document has been loaded in the browser. + */ + public boolean hasDocument(); + + // + // The following methods are forwarded to the mainFrame. + // + + /** + * Save this frame's HTML source to a temporary file and open it in the + * default text viewing application. This method can only be called from the + * browser process. + */ + public void viewSource(); + + /** + * Retrieve this frame's HTML source as a string sent to the specified + * visitor. + * + * @param visitor + */ + public void getSource(CefStringVisitor visitor); + + /** + * Retrieve this frame's display text as a string sent to the specified + * visitor. + * + * @param visitor + */ + public void getText(CefStringVisitor visitor); + + /** + * Load the request represented by the request object. + * + * @param request The request object. + */ + public void loadRequest(CefRequest request); + + /** + * Load the specified URL in the main frame. + * @param url The URL to load. + */ + public void loadURL(String url); + + /** + * Execute a string of JavaScript code in this frame. The url + * parameter is the URL where the script in question can be found, if any. + * The renderer may request this URL to show the developer the source of the + * error. The line parameter is the base line number to use for error + * reporting. + * + * @param code The code to be executed. + * @param url The URL where the script in question can be found. + * @param line The base line number to use for error reporting. + */ + public void executeJavaScript(String code, String url, int line); + + /** + * Emits the URL currently loaded in this frame. + * @return the URL currently loaded in this frame. + */ + public String getURL(); + + // The following methods are forwarded to CefBrowserHost. + + /** + * Request that the browser close. + * @param force force the close. + */ + public void close(boolean force); + + /** + * Allow the browser to close. + */ + public void setCloseAllowed(); + + /** + * Called from CefClient.doClose. + */ + public boolean doClose(); + + /** + * Called from CefClient.onBeforeClose. + */ + public void onBeforeClose(); + + /** + * Set or remove keyboard focus to/from the browser window. + * @param enable set to true to give the focus to the browser + **/ + public void setFocus(boolean enable); + + /** + * Set whether the window containing the browser is visible + * (minimized/unminimized, app hidden/unhidden, etc). Only used on Mac OS X. + * @param visible + */ + public void setWindowVisibility(boolean visible); + + /** + * Get the current zoom level. The default zoom level is 0.0. + * @return The current zoom level. + */ + public double getZoomLevel(); + + /** + * Change the zoom level to the specified value. Specify 0.0 to reset the + * zoom level. + * + * @param zoomLevel The zoom level to be set. + */ + public void setZoomLevel(double zoomLevel); + + /** + * Call to run a file chooser dialog. Only a single file chooser dialog may be + * pending at any given time.The dialog will be initiated asynchronously on + * the UI thread. + * + * @param mode represents the type of dialog to display. + * @param title to be used for the dialog and may be empty to show the + * default title ("Open" or "Save" depending on the mode). + * @param defaultFilePath is the path with optional directory and/or file name + * component that should be initially selected in the dialog. + * @param acceptFilters are used to restrict the selectable file types and may + * any combination of (a) valid lower-cased MIME types (e.g. "text/*" or + * "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 callback will be executed after the dialog is dismissed or + * immediately if another dialog is already pending. + */ + public void runFileDialog(FileDialogMode mode, String title, String defaultFilePath, + Vector acceptFilters, int selectedAcceptFilter, + CefRunFileDialogCallback callback); + + /** + * Download the file at url using CefDownloadHandler. + * + * @param url URL to download that file. + */ + public void startDownload(String url); + + /** + * Print the current browser contents. + */ + public void print(); + + /** + * Print the current browser contents to a PDF. + * + * @param path The path of the file to write to (will be overwritten if it + * already exists). Cannot be null. + * @param settings The pdf print settings to use. If null then defaults + * will be used. + * @param callback Called when the pdf print job has completed. + */ + public void printToPDF(String path, CefPdfPrintSettings settings, CefPdfPrintCallback callback); + + /** + * Search for some kind of text on the page. + * + * @param searchText to be searched for. + * @param forward indicates whether to search forward or backward within the page. + * @param matchCase indicates whether the search should be case-sensitive. + * @param findNext indicates whether this is the first request or a follow-up. + */ + public void find(String searchText, boolean forward, boolean matchCase, boolean findNext); + + /** + * Cancel all searches that are currently going on. + * @param clearSelection Set to true to reset selection. + */ + public void stopFinding(boolean clearSelection); + + /** + * Get an instance of the DevTools to be displayed in its own window. + */ + public void openDevTools(); + + /** + * 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 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 + * this method will replace it with the specified |word|. + * + * @param word replace selected word with this word. + */ + public void replaceMisspelling(String word); + + /** + * Captures a screenshot-like image of the currently displayed content and returns it. + *

+ * 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 + * has been taken (which must happen on the event thread). + *

+ * The generated screenshot can either be returned as-is, containing all natively-rendered + * pixels, or it can be scaled to match the logical width and height of the window. + * This distinction is only relevant in case of differing logical and physical resolutions + * (for example with HiDPI/Retina displays, which have a scaling factor of for example 2 + * between the logical width of a window (ex. 400px) and the actual number of pixels in + * each row (ex. 800px with a scaling factor of 2)). + * + * @param nativeResolution whether to return an image at full native resolution (true) + * or a scaled-down version whose width and height are equal to the logical size + * of the screenshotted browser window + * @return the screenshot image + * @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/lib/jcef/java/org/cef/browser/CefBrowserFactory.java b/lib/jcef/java/org/cef/browser/CefBrowserFactory.java new file mode 100644 index 0000000..299dfcf --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefBrowserFactory.java @@ -0,0 +1,20 @@ +// 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 org.cef.browser; + +import org.cef.CefBrowserSettings; +import org.cef.CefClient; + +/** + * Creates a new instance of CefBrowser according the passed values + */ +public class CefBrowserFactory { + public static CefBrowser create(CefClient client, String url, boolean isOffscreenRendered, + 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/lib/jcef/java/org/cef/browser/CefBrowserOsr.java b/lib/jcef/java/org/cef/browser/CefBrowserOsr.java new file mode 100644 index 0000000..b999b6b --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefBrowserOsr.java @@ -0,0 +1,669 @@ +// 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 org.cef.browser; + +import com.jogamp.nativewindow.NativeSurface; +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLContext; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLProfile; +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; +import org.cef.handler.CefRenderHandler; +import org.cef.handler.CefScreenInfo; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.datatransfer.StringSelection; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureRecognizer; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DropTarget; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.lang.ClassNotFoundException; +import java.lang.IllegalAccessException; +import java.lang.IllegalArgumentException; +import java.lang.NoSuchMethodException; +import java.lang.SecurityException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.util.ArrayList; +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; + +/** + * This class represents an off-screen rendered browser. + * The visibility of this class is "package". To create a new + * CefBrowser instance, please use CefBrowserFactory. + */ +class CefBrowserOsr extends CefBrowser_N implements CefRenderHandler { + private CefRenderer renderer_; + private GLCanvas canvas_; + private long window_handle_ = 0; + private boolean justCreated_ = false; + private Rectangle browser_rect_ = new Rectangle(0, 0, 1, 1); // Work around CEF issue #1437. + private Point screenPoint_ = new Point(0, 0); + private double scaleFactor_ = 1.0; + private int depth = 32; + private int depth_per_component = 8; + private boolean isTransparent_; + + 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, + CefBrowserSettings settings) { + super(client, url, context, parent, inspectAt, settings); + isTransparent_ = transparent; + renderer_ = new CefRenderer(transparent); + createGLCanvas(); + } + + @Override + public void createImmediately() { + justCreated_ = true; + // Create the browser immediately. + createBrowserIfRequired(false); + } + + @Override + public Component getUIComponent() { + return canvas_; + } + + @Override + public CefRenderHandler getRenderHandler() { + return this; + } + + @Override + 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, null); + } + + private synchronized long getWindowHandle() { + if (window_handle_ == 0) { + NativeSurface surface = canvas_.getNativeSurface(); + if (surface != null) { + surface.lockSurface(); + window_handle_ = getWindowHandle(surface.getSurfaceHandle()); + surface.unlockSurface(); + assert (window_handle_ != 0); + } + } + return window_handle_; + } + + @SuppressWarnings("serial") + private void createGLCanvas() { + GLProfile glprofile = GLProfile.getMaxFixedFunc(true); + GLCapabilities glcapabilities = new GLCapabilities(glprofile); + canvas_ = new GLCanvas(glcapabilities) { + private Method scaleFactorAccessor = null; + private boolean removed_ = true; + + @Override + public void paint(Graphics g) { + createBrowserIfRequired(true); + if (g instanceof Graphics2D) { + GraphicsConfiguration config = ((Graphics2D) g).getDeviceConfiguration(); + depth = config.getColorModel().getPixelSize(); + depth_per_component = config.getColorModel().getComponentSize()[0]; + + if (OS.isMacintosh() + && System.getProperty("java.runtime.version").startsWith("1.8")) { + // This fixes a weird thing on MacOS: the scale factor being read from + // getTransform().getScaleX() is incorrect for Java 8 VMs; it is always + // 1, even though Retina display scaling of window sizes etc. is + // definitely ongoing somewhere in the lower levels of AWT. This isn't + // too big of a problem for us, because the transparent scaling handles + // the situation, except for one thing: the screenshot-grabbing + // code below, which reads from the OpenGL context, must know the real + // scale factor, because the image to be read is larger by that factor + // and thus a bigger buffer is required. This is why there's some + // admittedly-ugly reflection magic going on below that's able to get + // the real scale factor. + // All of this is not relevant for either Windows or MacOS JDKs > 8, + // for which the official "getScaleX()" approach works fine. + try { + if (scaleFactorAccessor == null) { + scaleFactorAccessor = getClass() + .getClassLoader() + .loadClass("sun.awt.CGraphicsDevice") + .getDeclaredMethod("getScaleFactor"); + } + Object factor = scaleFactorAccessor.invoke(config.getDevice()); + if (factor instanceof Integer) { + scaleFactor_ = ((Integer) factor).doubleValue(); + } else { + scaleFactor_ = 1.0; + } + } catch (InvocationTargetException | IllegalAccessException + | IllegalArgumentException | NoSuchMethodException + | SecurityException | ClassNotFoundException exc) { + scaleFactor_ = 1.0; + } + } else { + scaleFactor_ = ((Graphics2D) g).getTransform().getScaleX(); + } + } + super.paint(g); + } + + @Override + public void addNotify() { + super.addNotify(); + if (removed_) { + notifyAfterParentChanged(); + removed_ = false; + } + } + + @Override + public void removeNotify() { + if (!removed_) { + if (!isClosed()) { + notifyAfterParentChanged(); + } + removed_ = true; + } + super.removeNotify(); + } + }; + + // The GLContext will be re-initialized when changing displays, resulting in calls to + // dispose/init/reshape. + canvas_.addGLEventListener(new GLEventListener() { + @Override + public void reshape( + GLAutoDrawable glautodrawable, int x, int y, int width, int height) { + int newWidth = width; + int newHeight = height; + if (OS.isMacintosh()) { + // HiDPI display scale correction support code + // For some reason this does seem to be necessary on MacOS only. + // If doing this correction on Windows, the browser content would be too + // small and in the lower left corner of the canvas only. + newWidth = (int) (width / scaleFactor_); + newHeight = (int) (height / scaleFactor_); + } + browser_rect_.setBounds(x, y, newWidth, newHeight); + screenPoint_ = canvas_.getLocationOnScreen(); + wasResized(newWidth, newHeight); + } + + @Override + public void init(GLAutoDrawable glautodrawable) { + renderer_.initialize(glautodrawable.getGL().getGL2()); + } + + @Override + public void dispose(GLAutoDrawable glautodrawable) { + renderer_.cleanup(glautodrawable.getGL().getGL2()); + } + + @Override + public void display(GLAutoDrawable glautodrawable) { + renderer_.render(glautodrawable.getGL().getGL2()); + } + }); + + canvas_.addMouseListener(new MouseListener() { + @Override + public void mousePressed(MouseEvent e) { + sendMouseEvent(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + sendMouseEvent(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + sendMouseEvent(e); + } + + @Override + public void mouseExited(MouseEvent e) { + sendMouseEvent(e); + } + + @Override + public void mouseClicked(MouseEvent e) { + sendMouseEvent(e); + } + }); + + canvas_.addMouseMotionListener(new MouseMotionListener() { + @Override + public void mouseMoved(MouseEvent e) { + sendMouseEvent(e); + } + + @Override + public void mouseDragged(MouseEvent e) { + sendMouseEvent(e); + } + }); + + canvas_.addMouseWheelListener(new MouseWheelListener() { + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + sendMouseWheelEvent(e); + } + }); + + canvas_.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { + sendKeyEvent(e); + } + + @Override + public void keyPressed(KeyEvent e) { + sendKeyEvent(e); + } + + @Override + public void keyReleased(KeyEvent e) { + sendKeyEvent(e); + } + }); + + canvas_.setFocusable(true); + canvas_.addFocusListener(new FocusListener() { + @Override + public void focusLost(FocusEvent e) { + setFocus(false); + } + + @Override + public void focusGained(FocusEvent e) { + // Dismiss any Java menus that are currently displayed. + MenuSelectionManager.defaultManager().clearSelectedPath(); + setFocus(true); + } + }); + + // Connect the Canvas with a drag and drop listener. + new DropTarget(canvas_, new CefDropTargetListener(this)); + } + + @Override + public Rectangle getViewRect(CefBrowser browser) { + return browser_rect_; + } + + @Override + public Point getScreenPoint(CefBrowser browser, Point viewPoint) { + Point screenPoint = new Point(screenPoint_); + screenPoint.translate(viewPoint.x, viewPoint.y); + return screenPoint; + } + + @Override + public void onPopupShow(CefBrowser browser, boolean show) { + if (!show) { + renderer_.clearPopupRects(); + invalidate(); + } + } + + @Override + 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) { + // if window is closing, canvas_ or opengl context could be null + final GLContext context = canvas_ != null ? canvas_.getContext() : null; + + if (context == null) { + return; + } + + // This result can occur due to GLContext re-initialization when changing displays. + if (context.makeCurrent() == GLContext.CONTEXT_NOT_CURRENT) { + return; + } + + renderer_.onPaint(canvas_.getGL().getGL2(), popup, dirtyRects, buffer, width, height); + context.release(); + SwingUtilities.invokeLater(new Runnable() { + 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 + public boolean onCursorChange(CefBrowser browser, final int cursorType) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + canvas_.setCursor(new Cursor(cursorType)); + } + }); + + // OSR always handles the cursor change. + return true; + } + + private static final class SyntheticDragGestureRecognizer extends DragGestureRecognizer { + public SyntheticDragGestureRecognizer(Component c, int action, MouseEvent triggerEvent) { + super(new DragSource(), c, action); + appendEvent(triggerEvent); + } + + 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 = getDndAction(mask); + MouseEvent triggerEvent = + new MouseEvent(canvas_, MouseEvent.MOUSE_DRAGGED, 0, 0, x, y, 0, false); + DragGestureEvent ev = new DragGestureEvent( + new SyntheticDragGestureRecognizer(canvas_, action, triggerEvent), action, + new Point(x, y), new ArrayList<>(Arrays.asList(triggerEvent))); + + DragSource.getDefaultDragSource().startDrag(ev, /*dragCursor=*/null, + new StringSelection(dragData.getFragmentText()), new DragSourceAdapter() { + @Override + public void dragDropEnd(DragSourceDropEvent dsde) { + dragSourceEndedAt(dsde.getLocation(), action); + dragSourceSystemDragEnded(); + } + }); + return true; + } + + @Override + public void updateDragCursor(CefBrowser browser, int operation) { + // TODO: Consider calling onCursorChange() if we want different cursors based on + // |operation|. + } + + private void createBrowserIfRequired(boolean hasParent) { + long windowHandle = 0; + if (hasParent) { + windowHandle = getWindowHandle(); + } + + if (getNativeRef("CefBrowser") == 0) { + if (getParentBrowser() != null) { + createDevTools(getParentBrowser(), getClient(), windowHandle, true, isTransparent_, + null, getInspectAt()); + } else { + createBrowser(getClient(), windowHandle, getUrl(), true, isTransparent_, null, + getRequestContext()); + } + } else if (hasParent && justCreated_) { + notifyAfterParentChanged(); + setFocus(true); + justCreated_ = false; + } + } + + private void notifyAfterParentChanged() { + // With OSR there is no native window to reparent but we still need to send the + // notification. + getClient().onAfterParentChanged(this); + } + + @Override + public boolean getScreenInfo(CefBrowser browser, CefScreenInfo screenInfo) { + screenInfo.Set(scaleFactor_, depth, depth_per_component, false, browser_rect_.getBounds(), + browser_rect_.getBounds()); + + return true; + } + + @Override + public CompletableFuture createScreenshot(boolean nativeResolution) { + int width = (int) Math.ceil(canvas_.getWidth() * scaleFactor_); + int height = (int) Math.ceil(canvas_.getHeight() * scaleFactor_); + + // In order to grab a screenshot of the browser window, we need to get the OpenGL internals + // from the GLCanvas that displays the browser. + GL2 gl = canvas_.getGL().getGL2(); + int textureId = renderer_.getTextureID(); + + // This mirrors the two ways in which CefRenderer may render images internally - either via + // an incrementally updated texture that is the same size as the window and simply rendered + // onto a textured quad by graphics hardware, in which case we capture the data directly + // from this texture, or by directly writing pixels into the OpenGL framebuffer, in which + // case we directly read those pixels back. The latter is the way chosen if there is no + // hardware rasterizer capability detected. We can simply distinguish both approaches by + // looking whether the textureId of the renderer is a valid (non-zero) one. + boolean useReadPixels = (textureId == 0); + + // This Callable encapsulates the pixel-reading code. After running it, the screenshot + // BufferedImage contains the grabbed image. + final Callable pixelGrabberCallable = new Callable() { + @Override + public BufferedImage call() { + BufferedImage screenshot = + new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + ByteBuffer buffer = GLBuffers.newDirectByteBuffer(width * height * 4); + + gl.getContext().makeCurrent(); + try { + if (useReadPixels) { + // If pixels are copied directly to the framebuffer, we also directly read + // them back. + gl.glReadPixels( + 0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buffer); + } else { + // In this case, read the texture pixel data from the previously-retrieved + // texture ID + gl.glEnable(GL.GL_TEXTURE_2D); + gl.glBindTexture(GL.GL_TEXTURE_2D, textureId); + gl.glGetTexImage( + GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buffer); + gl.glDisable(GL.GL_TEXTURE_2D); + } + } finally { + gl.getContext().release(); + } + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + // The OpenGL functions only support RGBA, while Java BufferedImage uses + // ARGB. We must convert. + int r = (buffer.get() & 0xff); + int g = (buffer.get() & 0xff); + int b = (buffer.get() & 0xff); + int a = (buffer.get() & 0xff); + int argb = (a << 24) | (r << 16) | (g << 8) | (b << 0); + // If pixels were read from the framebuffer, we have to flip the resulting + // image on the Y axis, as the OpenGL framebuffer's y axis starts at the + // bottom of the image pointing "upwards", while BufferedImage has the + // origin in the upper left corner. This flipping is done when drawing into + // the BufferedImage. + screenshot.setRGB(x, useReadPixels ? (height - y - 1) : y, argb); + } + } + + if (!nativeResolution && scaleFactor_ != 1.0) { + // HiDPI images should be resized down to "normal" levels + BufferedImage resized = + new BufferedImage((int) (screenshot.getWidth() / scaleFactor_), + (int) (screenshot.getHeight() / scaleFactor_), + BufferedImage.TYPE_INT_ARGB); + AffineTransform tempTransform = new AffineTransform(); + tempTransform.scale(1.0 / scaleFactor_, 1.0 / scaleFactor_); + AffineTransformOp tempScaleOperation = + new AffineTransformOp(tempTransform, AffineTransformOp.TYPE_BILINEAR); + resized = tempScaleOperation.filter(screenshot, resized); + return resized; + } else { + return screenshot; + } + } + }; + + if (SwingUtilities.isEventDispatchThread()) { + // If called on the AWT event thread, just access the GL API + try { + BufferedImage screenshot = pixelGrabberCallable.call(); + return CompletableFuture.completedFuture(screenshot); + } catch (Exception e) { + CompletableFuture future = new CompletableFuture(); + future.completeExceptionally(e); + return future; + } + } else { + // If called from another thread, register a GLEventListener and trigger an async + // redraw, during which we use the GL API to grab the pixel data. An unresolved Future + // is returned, on which the caller can wait for a result (but not with the Event + // Thread, as we need that for pixel grabbing, which is why there's a safeguard in place + // to catch that situation if it accidentally happens). + CompletableFuture future = new CompletableFuture() { + private void safeguardGet() { + if (SwingUtilities.isEventDispatchThread()) { + throw new RuntimeException( + "Waiting on this Future using the AWT Event Thread is illegal, " + + "because it can potentially deadlock the thread."); + } + } + + @Override + public BufferedImage get() throws InterruptedException, ExecutionException { + safeguardGet(); + return super.get(); + } + + @Override + public BufferedImage get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + safeguardGet(); + return super.get(timeout, unit); + } + }; + canvas_.addGLEventListener(new GLEventListener() { + @Override + public void reshape( + GLAutoDrawable aDrawable, int aArg1, int aArg2, int aArg3, int aArg4) { + // ignore + } + + @Override + public void init(GLAutoDrawable aDrawable) { + // ignore + } + + @Override + public void dispose(GLAutoDrawable aDrawable) { + // ignore + } + + @Override + public void display(GLAutoDrawable aDrawable) { + canvas_.removeGLEventListener(this); + try { + future.complete(pixelGrabberCallable.call()); + } catch (Exception e) { + future.completeExceptionally(e); + } + } + }); + + // This repaint triggers an indirect call to the listeners' display method above, which + // ultimately completes the future that we return immediately. + canvas_.repaint(); + + return future; + } + } +} diff --git a/lib/jcef/java/org/cef/browser/CefBrowserWindow.java b/lib/jcef/java/org/cef/browser/CefBrowserWindow.java new file mode 100644 index 0000000..3d7f595 --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefBrowserWindow.java @@ -0,0 +1,20 @@ +// 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 org.cef.browser; + +import java.awt.Component; + +/** + * Interface representing system dependent methods for the browser. + */ +public interface CefBrowserWindow { + /** + * Get the window handle for the given UI object. + * + * @param comp a UI component + * @return a window pointer if any + */ + public long getWindowHandle(Component comp); +} diff --git a/lib/jcef/java/org/cef/browser/CefBrowserWr.java b/lib/jcef/java/org/cef/browser/CefBrowserWr.java new file mode 100644 index 0000000..677ddce --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefBrowserWr.java @@ -0,0 +1,438 @@ +// 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 org.cef.browser; + +import org.cef.CefBrowserSettings; +import org.cef.CefClient; +import org.cef.OS; +import org.cef.handler.CefWindowHandler; +import org.cef.handler.CefWindowHandlerAdapter; + +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.MouseInfo; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.HierarchyBoundsListener; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.image.BufferedImage; +import java.util.Date; +import java.util.concurrent.CompletableFuture; + +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.ToolTipManager; + +/** + * This class represents a windowed rendered browser. + * The visibility of this class is "package". To create a new + * CefBrowser instance, please use CefBrowserFactory. + */ +class CefBrowserWr extends CefBrowser_N { + private Canvas canvas_ = null; + private Component component_ = null; + private Rectangle content_rect_ = new Rectangle(0, 0, 0, 0); + private long window_handle_ = 0; + private boolean justCreated_ = false; + private double scaleFactor_ = 1.0; + private Timer delayedUpdate_ = new Timer(100, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (isClosed()) return; + + boolean hasCreatedUI = createBrowserIfRequired(true); + + if (hasCreatedUI) { + delayedUpdate_.restart(); + } else { + // If on Mac, this is needed due to the quirk described below + // (in org.cef.browser.CefBrowserWr.CefBrowserWr(...).new JPanel() + // {...}.paint(Graphics)). If on Linux, this is needed to invoke an + // XMoveResizeWindow call shortly after the UI was created. That seems to be + // necessary to actually get a windowed renderer to display something. + if (OS.isMacintosh() || OS.isLinux()) doUpdate(); + } + } + }); + } + }); + + private CefWindowHandlerAdapter win_handler_ = new CefWindowHandlerAdapter() { + private Point lastPos = new Point(-1, -1); + private long[] nextClick = new long[MouseInfo.getNumberOfButtons()]; + private int[] clickCnt = new int[MouseInfo.getNumberOfButtons()]; + + @Override + public Rectangle getRect(CefBrowser browser) { + synchronized (content_rect_) { + return content_rect_; + } + } + + @Override + public void onMouseEvent(CefBrowser browser, int event, final int screenX, + final int screenY, final int modifier, final int button) { + final Point pt = new Point(screenX, screenY); + if (event == MouseEvent.MOUSE_MOVED) { + // Remove mouse-moved events if the position of the cursor hasn't + // changed. + if (pt.equals(lastPos)) return; + lastPos = pt; + + // Change mouse-moved event to mouse-dragged event if the left mouse + // button is pressed. + if ((modifier & MouseEvent.BUTTON1_DOWN_MASK) != 0) + event = MouseEvent.MOUSE_DRAGGED; + } + + final int finalEvent = event; + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + // Send mouse event to the root UI component instead to the browser UI. + // Otherwise no mouse-entered and no mouse-exited events would be fired. + Component parent = SwingUtilities.getRoot(component_); + if (parent == null) { + return; + } + SwingUtilities.convertPointFromScreen(pt, parent); + + int clickCnt = 0; + long now = new Date().getTime(); + if (finalEvent == MouseEvent.MOUSE_WHEEL) { + int scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL; + int rotation = button > 0 ? 1 : -1; + component_.dispatchEvent(new MouseWheelEvent(parent, finalEvent, now, + modifier, pt.x, pt.y, 0, false, scrollType, 3, rotation)); + } else { + clickCnt = getClickCount(finalEvent, button); + component_.dispatchEvent(new MouseEvent(parent, finalEvent, now, modifier, + pt.x, pt.y, screenX, screenY, clickCnt, false, button)); + } + + // Always fire a mouse-clicked event after a mouse-released event. + if (finalEvent == MouseEvent.MOUSE_RELEASED) { + component_.dispatchEvent( + new MouseEvent(parent, MouseEvent.MOUSE_CLICKED, now, modifier, + pt.x, pt.y, screenX, screenY, clickCnt, false, button)); + } + } + }); + } + + public int getClickCount(int event, int button) { + // avoid exceptions by using modulo + int idx = button % nextClick.length; + + switch (event) { + case MouseEvent.MOUSE_PRESSED: + long currTime = new Date().getTime(); + if (currTime > nextClick[idx]) { + nextClick[idx] = currTime + + (Integer) Toolkit.getDefaultToolkit().getDesktopProperty( + "awt.multiClickInterval"); + clickCnt[idx] = 1; + } else { + clickCnt[idx]++; + } + // FALL THRU + case MouseEvent.MOUSE_RELEASED: + return clickCnt[idx]; + default: + return 0; + } + } + }; + + 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, CefBrowserSettings settings) { + super(client, url, context, parent, inspectAt, settings); + delayedUpdate_.setRepeats(false); + + // Disabling lightweight of popup menu is required because + // otherwise it will be displayed behind the content of component_ + JPopupMenu.setDefaultLightWeightPopupEnabled(false); + ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false); + + // We're using a JComponent instead of a Canvas now because the + // JComponent has clipping informations, which aren't accessible for Canvas. + component_ = new JPanel(new BorderLayout()) { + private boolean removed_ = true; + + @Override + public void setBounds(int x, int y, int width, int height) { + super.setBounds(x, y, width, height); + wasResized((int) (width * scaleFactor_), (int) (height * scaleFactor_)); + } + + @Override + public void setBounds(Rectangle r) { + setBounds(r.x, r.y, r.width, r.height); + } + + @Override + public void setSize(int width, int height) { + super.setSize(width, height); + wasResized((int) (width * scaleFactor_), (int) (height * scaleFactor_)); + } + + @Override + public void setSize(Dimension d) { + setSize(d.width, d.height); + } + + @Override + public void paint(Graphics g) { + // If the user resizes the UI component, the new size and clipping + // informations are forwarded to the native code. + // But on Mac the last resize information doesn't resize the native UI + // accurately (sometimes the native UI is too small). An easy way to + // solve this, is to send the last Update-Information again. Therefore + // we're setting up a delayedUpdate timer which is reset each time + // paint is called. This prevents the us of sending the UI update too + // often. + if (g instanceof Graphics2D) { + scaleFactor_ = ((Graphics2D) g).getTransform().getScaleX(); + } + doUpdate(); + delayedUpdate_.restart(); + } + + @Override + public void addNotify() { + super.addNotify(); + if (removed_) { + setParent(getWindowHandle(this), canvas_); + removed_ = false; + } + } + + @Override + public void removeNotify() { + if (!removed_) { + if (!isClosed()) { + setParent(0, null); + } + removed_ = true; + } + super.removeNotify(); + } + }; + + // On windows we have to use a Canvas because its a heavyweight component + // and we need its native HWND as parent for the browser UI. The same + // technique is used on Linux as well. + if (OS.isWindows() || OS.isLinux()) { + canvas_ = new Canvas(); + ((JPanel) component_).add(canvas_, BorderLayout.CENTER); + } + + // Initial minimal size of the component. Otherwise the UI won't work + // accordingly in panes like JSplitPane. + component_.setMinimumSize(new Dimension(0, 0)); + component_.setFocusable(true); + component_.addFocusListener(new FocusListener() { + @Override + public void focusLost(FocusEvent e) { + setFocus(false); + } + + @Override + public void focusGained(FocusEvent e) { + // Dismiss any Java menus that are currently displayed. + MenuSelectionManager.defaultManager().clearSelectedPath(); + setFocus(true); + } + }); + component_.addHierarchyBoundsListener(new HierarchyBoundsListener() { + @Override + public void ancestorResized(HierarchyEvent e) { + doUpdate(); + } + @Override + public void ancestorMoved(HierarchyEvent e) { + doUpdate(); + notifyMoveOrResizeStarted(); + } + }); + component_.addHierarchyListener(new HierarchyListener() { + @Override + public void hierarchyChanged(HierarchyEvent e) { + if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) { + setWindowVisibility(e.getChanged().isVisible()); + } + } + }); + } + + @Override + public void createImmediately() { + justCreated_ = true; + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + // Create the browser immediately. It will be parented to the Java + // window once it becomes available. + createBrowserIfRequired(false); + } + }); + } + + @Override + public Component getUIComponent() { + return component_; + } + + @Override + public CefWindowHandler getWindowHandler() { + return win_handler_; + } + + @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, null); + } + + private synchronized long getWindowHandle() { + if (window_handle_ == 0 && OS.isMacintosh()) { + window_handle_ = getWindowHandle(component_); + } + return window_handle_; + } + + private static long getWindowHandle(Component component) { + if (OS.isMacintosh()) { + try { + Class cls = Class.forName("org.cef.browser.mac.CefBrowserWindowMac"); + CefBrowserWindow browserWindow = (CefBrowserWindow) cls.newInstance(); + if (browserWindow != null) { + return browserWindow.getWindowHandle(component); + } + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + return 0; + } + + private void doUpdate() { + if (isClosed()) return; + + Rectangle vr = ((JPanel) component_).getVisibleRect(); + Rectangle clipping = new Rectangle((int) (vr.getX() * scaleFactor_), + (int) (vr.getY() * scaleFactor_), (int) (vr.getWidth() * scaleFactor_), + (int) (vr.getHeight() * scaleFactor_)); + + if (OS.isMacintosh()) { + Container parent = component_.getParent(); + Point contentPos = component_.getLocation(); + while (parent != null) { + Container next = parent.getParent(); + if (next != null && next instanceof Window) break; + Point parentPos = parent.getLocation(); + contentPos.translate(parentPos.x, parentPos.y); + parent = next; + } + contentPos.translate(clipping.x, clipping.y); + + Point browserPos = clipping.getLocation(); + browserPos.x *= -1; + browserPos.y *= -1; + + synchronized (content_rect_) { + content_rect_ = new Rectangle(contentPos, clipping.getSize()); + Rectangle browserRect = new Rectangle(browserPos, component_.getSize()); + updateUI(content_rect_, browserRect); + } + } else { + synchronized (content_rect_) { + Rectangle bounds = null != canvas_ ? canvas_.getBounds() : component_.getBounds(); + content_rect_ = new Rectangle((int) (bounds.getX() * scaleFactor_), + (int) (bounds.getY() * scaleFactor_), + (int) (bounds.getWidth() * scaleFactor_), + (int) (bounds.getHeight() * scaleFactor_)); + updateUI(clipping, content_rect_); + } + } + } + + private boolean createBrowserIfRequired(boolean hasParent) { + if (isClosed()) return false; + + long windowHandle = 0; + Component canvas = null; + if (hasParent) { + windowHandle = getWindowHandle(); + canvas = (OS.isWindows() || OS.isLinux()) ? canvas_ : component_; + } + + if (getNativeRef("CefBrowser") == 0) { + if (getParentBrowser() != null) { + createDevTools(getParentBrowser(), getClient(), windowHandle, false, false, canvas, + getInspectAt()); + return true; + } else { + createBrowser(getClient(), windowHandle, getUrl(), false, false, canvas, + getRequestContext()); + return true; + } + } else if (hasParent && justCreated_) { + setParent(windowHandle, canvas); + setFocus(true); + justCreated_ = false; + } + + return false; + } + + @Override + 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/lib/jcef/java/org/cef/browser/CefBrowser_N.java b/lib/jcef/java/org/cef/browser/CefBrowser_N.java new file mode 100644 index 0000000..c89e296 --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefBrowser_N.java @@ -0,0 +1,887 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.browser; + +import org.cef.CefBrowserSettings; +import org.cef.CefClient; +import org.cef.browser.CefDevToolsClient.DevToolsException; +import org.cef.callback.CefDragData; +import org.cef.callback.CefNativeAdapter; +import org.cef.callback.CefPdfPrintCallback; +import org.cef.callback.CefRunFileDialogCallback; +import org.cef.callback.CefStringVisitor; +import org.cef.handler.CefClientHandler; +import org.cef.handler.CefDialogHandler.FileDialogMode; +import org.cef.handler.CefRenderHandler; +import org.cef.handler.CefWindowHandler; +import org.cef.misc.CefPdfPrintSettings; +import org.cef.network.CefRequest; + +import java.awt.Component; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.WindowEvent; +import java.util.Vector; +import java.util.concurrent.CompletableFuture; + +import javax.swing.SwingUtilities; + +/** + * This class represents all methods which are connected to the + * native counterpart CEF. + * The visibility of this class is "package". To create a new + * CefBrowser instance, please use CefBrowserFactory. + */ +abstract class CefBrowser_N extends CefNativeAdapter implements CefBrowser { + private volatile boolean isPending_ = false; + private final CefClient client_; + private final String url_; + private final CefRequestContext request_context_; + private volatile CefBrowser_N parent_ = null; + private volatile Point inspectAt_ = 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, 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_; + } + + @Override + public CefRequestContext getRequestContext() { + return request_context_ != null ? request_context_ : CefRequestContext.getGlobalContext(); + } + + protected CefBrowser_N getParentBrowser() { + return parent_; + } + + protected Point getInspectAt() { + return inspectAt_; + } + + protected boolean isClosed() { + return isClosed_; + } + + @Override + public CefClient getClient() { + return client_; + } + + @Override + public CefRenderHandler getRenderHandler() { + return null; + } + + @Override + public CefWindowHandler getWindowHandler() { + return null; + } + + @Override + public synchronized void setCloseAllowed() { + closeAllowed_ = true; + } + + @Override + public synchronized boolean doClose() { + if (closeAllowed_) { + // Allow the close to proceed. + return false; + } + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + // Trigger close of the parent window. + Component parent = SwingUtilities.getRoot(getUIComponent()); + if (parent != null) { + parent.dispatchEvent( + new WindowEvent((Window) parent, WindowEvent.WINDOW_CLOSING)); + } + } + }); + + // Cancel the close. + return true; + } + + @Override + public synchronized void onBeforeClose() { + isClosed_ = true; + if (request_context_ != null) request_context_.dispose(); + if (parent_ != null) { + parent_.closeDevTools(); + parent_ = null; + } + if (devToolsClient_ != null) { + devToolsClient_.close(); + } + } + + @Override + public void openDevTools() { + openDevTools(null); + } + + @Override + public synchronized void openDevTools(Point inspectAt) { + createDevToolsBrowser(client_, url_, request_context_, this, inspectAt).createImmediately(); + } + + @Override + public synchronized CefDevToolsClient getDevToolsClient() { + if (!isPending_ || isClosing_ || isClosed_) { + return null; + } + if (devToolsClient_ == null || devToolsClient_.isClosed()) { + devToolsClient_ = new CefDevToolsClient(this); + } + 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, + CefRequestContext context, CefBrowser_N parent, Point inspectAt); + + /** + * Create a new browser. + */ + protected void createBrowser(CefClientHandler clientHandler, long windowHandle, String url, + boolean osr, boolean transparent, Component canvas, CefRequestContext context) { + if (getNativeRef("CefBrowser") == 0 && !isPending_) { + try { + N_CreateBrowser(clientHandler, windowHandle, url, osr, transparent, canvas, context, + settings_); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + } + + /** + * Called async from the (native) main UI thread. + */ + private void notifyBrowserCreated() { + isPending_ = true; + } + + /** + * Create a new browser as dev tools + */ + protected final void createDevTools(CefBrowser_N parent, CefClientHandler clientHandler, + long windowHandle, boolean osr, boolean transparent, Component canvas, + Point inspectAt) { + if (getNativeRef("CefBrowser") == 0 && !isPending_) { + try { + isPending_ = N_CreateDevTools( + parent, clientHandler, windowHandle, osr, transparent, canvas, inspectAt); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + } + + /** + * Returns the native window handle for the specified native surface handle. + */ + protected final long getWindowHandle(long surfaceHandle) { + try { + return N_GetWindowHandle(surfaceHandle); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + return 0; + } + + @Override + protected void finalize() throws Throwable { + close(true); + super.finalize(); + } + + @Override + public boolean canGoBack() { + try { + return N_CanGoBack(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public void goBack() { + try { + N_GoBack(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean canGoForward() { + try { + return N_CanGoForward(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public void goForward() { + try { + N_GoForward(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean isLoading() { + try { + return N_IsLoading(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public void reload() { + try { + N_Reload(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void reloadIgnoreCache() { + try { + N_ReloadIgnoreCache(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void stopLoad() { + try { + N_StopLoad(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public int getIdentifier() { + try { + return N_GetIdentifier(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return -1; + } + } + + @Override + public CefFrame getMainFrame() { + try { + return N_GetMainFrame(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public CefFrame getFocusedFrame() { + try { + return N_GetFocusedFrame(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public CefFrame getFrameByIdentifier(String identifier) { + try { + return N_GetFrameByIdentifier(identifier); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public CefFrame getFrameByName(String name) { + try { + return N_GetFrameByName(name); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public Vector getFrameIdentifiers() { + try { + return N_GetFrameIdentifiers(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public Vector getFrameNames() { + try { + return N_GetFrameNames(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public int getFrameCount() { + try { + return N_GetFrameCount(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return -1; + } + } + + @Override + public boolean isPopup() { + try { + return N_IsPopup(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean hasDocument() { + try { + return N_HasDocument(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public void viewSource() { + try { + N_ViewSource(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void getSource(CefStringVisitor visitor) { + try { + N_GetSource(visitor); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void getText(CefStringVisitor visitor) { + try { + N_GetText(visitor); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void loadRequest(CefRequest request) { + try { + N_LoadRequest(request); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void loadURL(String url) { + try { + N_LoadURL(url); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void executeJavaScript(String code, String url, int line) { + try { + N_ExecuteJavaScript(code, url, line); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public String getURL() { + try { + return N_GetURL(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return ""; + } + + @Override + public void close(boolean force) { + if (isClosing_ || isClosed_) return; + if (force) isClosing_ = true; + + try { + N_Close(force); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void setFocus(boolean enable) { + try { + N_SetFocus(enable); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void setWindowVisibility(boolean visible) { + try { + N_SetWindowVisibility(visible); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public double getZoomLevel() { + try { + return N_GetZoomLevel(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0.0; + } + + @Override + public void setZoomLevel(double zoomLevel) { + try { + N_SetZoomLevel(zoomLevel); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void runFileDialog(FileDialogMode mode, String title, String defaultFilePath, + Vector acceptFilters, int selectedAcceptFilter, + CefRunFileDialogCallback callback) { + try { + N_RunFileDialog( + mode, title, defaultFilePath, acceptFilters, selectedAcceptFilter, callback); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void startDownload(String url) { + try { + N_StartDownload(url); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void print() { + try { + N_Print(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void printToPDF( + String path, CefPdfPrintSettings settings, CefPdfPrintCallback callback) { + if (path == null || path.isEmpty()) { + throw new IllegalArgumentException("path was null or empty"); + } + try { + N_PrintToPDF(path, settings, callback); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void find(String searchText, boolean forward, boolean matchCase, boolean findNext) { + try { + N_Find(searchText, forward, matchCase, findNext); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void stopFinding(boolean clearSelection) { + try { + N_StopFinding(clearSelection); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void closeDevTools() { + try { + N_CloseDevTools(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void replaceMisspelling(String word) { + try { + N_ReplaceMisspelling(word); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Notify that the browser was resized. + * @param width The new width of the browser + * @param height The new height of the browser + */ + protected final void wasResized(int width, int height) { + try { + N_WasResized(width, height); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Invalidate the UI. + */ + protected final void invalidate() { + try { + N_Invalidate(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Send a key event. + * @param e The event to send. + */ + protected final void sendKeyEvent(KeyEvent e) { + try { + N_SendKeyEvent(e); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Send a mouse event. + * @param e The event to send. + */ + protected final void sendMouseEvent(MouseEvent e) { + try { + N_SendMouseEvent(e); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Send a mouse wheel event. + * @param e The event to send. + */ + protected final void sendMouseWheelEvent(MouseWheelEvent e) { + try { + N_SendMouseWheelEvent(e); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Call this method when the user drags the mouse into the web view (before + * calling DragTargetDragOver/DragTargetLeave/DragTargetDrop). + * |drag_data| should not contain file contents as this type of data is not + * allowed to be dragged into the web view. File contents can be removed using + * CefDragData::ResetFileContents (for example, if |drag_data| comes from + * CefRenderHandler::StartDragging). + * This method is only used when window rendering is disabled. + */ + protected final void dragTargetDragEnter( + CefDragData dragData, Point pos, int modifiers, int allowedOps) { + try { + N_DragTargetDragEnter(dragData, pos, modifiers, allowedOps); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Call this method each time the mouse is moved across the web view during + * a drag operation (after calling DragTargetDragEnter and before calling + * DragTargetDragLeave/DragTargetDrop). + * This method is only used when window rendering is disabled. + */ + protected final void dragTargetDragOver(Point pos, int modifiers, int allowedOps) { + try { + N_DragTargetDragOver(pos, modifiers, allowedOps); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Call this method when the user drags the mouse out of the web view (after + * calling DragTargetDragEnter). + * This method is only used when window rendering is disabled. + */ + protected final void dragTargetDragLeave() { + try { + N_DragTargetDragLeave(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Call this method when the user completes the drag operation by dropping + * the object onto the web view (after calling DragTargetDragEnter). + * The object being dropped is |drag_data|, given as an argument to + * the previous DragTargetDragEnter call. + * This method is only used when window rendering is disabled. + */ + protected final void dragTargetDrop(Point pos, int modifiers) { + try { + N_DragTargetDrop(pos, modifiers); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Call this method when the drag operation started by a + * CefRenderHandler.startDragging call has ended either in a drop or + * by being cancelled. |x| and |y| are mouse coordinates relative to the + * upper-left corner of the view. If the web view is both the drag source + * and the drag target then all DragTarget* methods should be called before + * DragSource* methods. + * This method is only used when window rendering is disabled. + */ + protected final void dragSourceEndedAt(Point pos, int operation) { + try { + N_DragSourceEndedAt(pos, operation); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Call this method when the drag operation started by a + * CefRenderHandler.startDragging call has completed. This method may be + * called immediately without first calling DragSourceEndedAt to cancel a + * drag operation. If the web view is both the drag source and the drag + * target then all DragTarget* methods should be called before DragSource* + * methods. + * This method is only used when window rendering is disabled. + */ + protected final void dragSourceSystemDragEnded() { + try { + N_DragSourceSystemDragEnded(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + protected final void updateUI(Rectangle contentRect, Rectangle browserRect) { + try { + N_UpdateUI(contentRect, browserRect); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + protected final void setParent(long windowHandle, Component canvas) { + if (isClosing_ || isClosed_) return; + + try { + N_SetParent(windowHandle, canvas); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + /** + * Call this method if the browser frame was moved. + * This fixes positioning of select popups and dismissal on window move/resize. + */ + protected final void notifyMoveOrResizeStarted() { + try { + N_NotifyMoveOrResizeStarted(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + 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, 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(); + private final native boolean N_CanGoForward(); + private final native void N_GoForward(); + private final native boolean N_IsLoading(); + private final native void N_Reload(); + private final native void N_ReloadIgnoreCache(); + private final native void N_StopLoad(); + private final native int N_GetIdentifier(); + private final native CefFrame N_GetMainFrame(); + private final native CefFrame N_GetFocusedFrame(); + 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(); + private final native boolean N_HasDocument(); + private final native void N_ViewSource(); + private final native void N_GetSource(CefStringVisitor visitor); + private final native void N_GetText(CefStringVisitor visitor); + private final native void N_LoadRequest(CefRequest request); + private final native void N_LoadURL(String url); + private final native void N_ExecuteJavaScript(String code, String url, int line); + private final native String N_GetURL(); + private final native void N_Close(boolean force); + private final native void N_SetFocus(boolean enable); + private final native void N_SetWindowVisibility(boolean visible); + private final native double N_GetZoomLevel(); + private final native void N_SetZoomLevel(double zoomLevel); + private final native void N_RunFileDialog(FileDialogMode mode, String title, + String defaultFilePath, Vector acceptFilters, int selectedAcceptFilter, + CefRunFileDialogCallback callback); + private final native void N_StartDownload(String url); + private final native void N_Print(); + private final native void N_PrintToPDF( + String path, CefPdfPrintSettings settings, CefPdfPrintCallback callback); + private final native void N_Find( + String searchText, boolean forward, boolean matchCase, boolean findNext); + private final native void N_StopFinding(boolean clearSelection); + private final native void N_CloseDevTools(); + private final native void N_ReplaceMisspelling(String word); + private final native void N_WasResized(int width, int height); + private final native void N_Invalidate(); + private final native void N_SendKeyEvent(KeyEvent e); + private final native void N_SendMouseEvent(MouseEvent e); + private final native void N_SendMouseWheelEvent(MouseWheelEvent e); + private final native void N_DragTargetDragEnter( + CefDragData dragData, Point pos, int modifiers, int allowed_ops); + private final native void N_DragTargetDragOver(Point pos, int modifiers, int allowed_ops); + private final native void N_DragTargetDragLeave(); + private final native void N_DragTargetDrop(Point pos, int modifiers); + private final native void N_DragSourceEndedAt(Point pos, int operation); + private final native void N_DragSourceSystemDragEnded(); + private final native void N_UpdateUI(Rectangle contentRect, Rectangle browserRect); + private final native void N_SetParent(long windowHandle, Component canvas); + private final native void N_NotifyMoveOrResizeStarted(); + private final native void N_SetWindowlessFrameRate(int frameRate); + private final native void N_GetWindowlessFrameRate(IntCallback frameRateCallback); +} diff --git a/lib/jcef/java/org/cef/browser/CefDevToolsClient.java b/lib/jcef/java/org/cef/browser/CefDevToolsClient.java new file mode 100644 index 0000000..3fed09f --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefDevToolsClient.java @@ -0,0 +1,170 @@ +// 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)); + } + removeQueuedCommand(messageId); + } + + @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<>()); + } + + private void removeQueuedCommand(Integer messageId) { + queuedCommands_.remove(messageId); + } + + /** + * 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/lib/jcef/java/org/cef/browser/CefDevToolsMessageObserver.java b/lib/jcef/java/org/cef/browser/CefDevToolsMessageObserver.java new file mode 100644 index 0000000..3a85135 --- /dev/null +++ b/lib/jcef/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/lib/jcef/java/org/cef/browser/CefDropTargetListener.java b/lib/jcef/java/org/cef/browser/CefDropTargetListener.java new file mode 100644 index 0000000..e5e0be0 --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefDropTargetListener.java @@ -0,0 +1,127 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.browser; + +import org.cef.callback.CefDragData; +import org.cef.misc.EventFlags; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.io.File; +import java.util.List; + +class CefDropTargetListener implements DropTargetListener { + private CefBrowser_N browser_; + private CefDragData dragData_ = null; + private int dragOperations_ = CefDragData.DragOperations.DRAG_OPERATION_COPY; + private int dragModifiers_ = EventFlags.EVENTFLAG_NONE; + private int acceptOperations_ = DnDConstants.ACTION_COPY; + + CefDropTargetListener(CefBrowser_N browser) { + browser_ = browser; + } + + @Override + public void dragEnter(DropTargetDragEvent event) { + CreateDragData(event); + browser_.dragTargetDragEnter( + dragData_, event.getLocation(), dragModifiers_, dragOperations_); + } + + @Override + public void dragExit(DropTargetEvent event) { + AssertDragData(); + browser_.dragTargetDragLeave(); + ClearDragData(); + } + + @Override + public void dragOver(DropTargetDragEvent event) { + AssertDragData(); + browser_.dragTargetDragOver(event.getLocation(), dragModifiers_, dragOperations_); + } + + @Override + public void dropActionChanged(DropTargetDragEvent event) { + AssertDragData(); + acceptOperations_ = event.getDropAction(); + switch (acceptOperations_) { + case DnDConstants.ACTION_LINK: + dragOperations_ = CefDragData.DragOperations.DRAG_OPERATION_LINK; + dragModifiers_ = + EventFlags.EVENTFLAG_CONTROL_DOWN | EventFlags.EVENTFLAG_SHIFT_DOWN; + break; + case DnDConstants.ACTION_COPY: + dragOperations_ = CefDragData.DragOperations.DRAG_OPERATION_COPY; + dragModifiers_ = EventFlags.EVENTFLAG_CONTROL_DOWN; + break; + case DnDConstants.ACTION_MOVE: + dragOperations_ = CefDragData.DragOperations.DRAG_OPERATION_MOVE; + dragModifiers_ = EventFlags.EVENTFLAG_SHIFT_DOWN; + break; + case DnDConstants.ACTION_NONE: + // The user did not select an action, so use COPY as the default. + dragOperations_ = CefDragData.DragOperations.DRAG_OPERATION_COPY; + dragModifiers_ = EventFlags.EVENTFLAG_NONE; + acceptOperations_ = DnDConstants.ACTION_COPY; + break; + } + } + + @Override + public void drop(DropTargetDropEvent event) { + AssertDragData(); + browser_.dragTargetDrop(event.getLocation(), dragModifiers_); + event.acceptDrop(acceptOperations_); + event.dropComplete(true); + ClearDragData(); + } + + private void CreateDragData(DropTargetDragEvent event) { + assert dragData_ == null; + dragData_ = createDragData(event); + dropActionChanged(event); + } + + private void AssertDragData() { + assert dragData_ != null; + } + + private void ClearDragData() { + dragData_ = null; + } + + private static CefDragData createDragData(DropTargetDragEvent event) { + CefDragData dragData = CefDragData.create(); + + Transferable transferable = event.getTransferable(); + DataFlavor[] flavors = transferable.getTransferDataFlavors(); + for (DataFlavor flavor : flavors) { + try { + if (flavor.isFlavorTextType()) { + Object ob = transferable.getTransferData(flavor); + if (!(ob instanceof String)) continue; + dragData.setFragmentText((String) ob); + } else if (flavor.isFlavorJavaFileListType()) { + List files = (List) transferable.getTransferData(flavor); + for (File file : files) { + dragData.addFile(file.getPath(), file.getName()); + } + } + } catch (Exception e) { + // Data is no longer available or of unsupported flavor. + e.printStackTrace(); + } + } + + return dragData; + } +} diff --git a/lib/jcef/java/org/cef/browser/CefFrame.java b/lib/jcef/java/org/cef/browser/CefFrame.java new file mode 100644 index 0000000..a64b4ed --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefFrame.java @@ -0,0 +1,106 @@ +// Copyright (c) 2017 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; + +/** + * Interface representing a frame. + */ +public interface CefFrame { + /** + * Removes the native reference from an unused object. + */ + void dispose(); + + /** + * Returns the globally unique identifier for this frame or an empty string if the + * underlying frame does not yet exist. + * @return The frame identifier + */ + String getIdentifier(); + + /** + * Emits the URL currently loaded in this frame. + * @return the URL currently loaded in this frame. + */ + String getURL(); + + /** + * Returns the name for this frame. If the frame has an assigned name (for + * example, set via the iframe "name" attribute) then that value will be + * returned. Otherwise a unique name will be constructed based on the frame + * parent hierarchy. The main (top-level) frame will always have an empty name + * value. + * @return The frame name + */ + String getName(); + + /** + * Returns true if this is the main (top-level) frame. + * @return True if this frame is top-level otherwise false. + */ + boolean isMain(); + + /** + * True if this object is currently attached to a valid frame. + * @return True if valid otherwise false. + */ + boolean isValid(); + + /** + * Returns true if this is the focused frame. + * @return True if valid otherwise false. + */ + boolean isFocused(); + + /** + * Returns the parent of this frame or NULL if this is the main (top-level) + * frame. + * @return The parent frame or NULL if this is the main frame + */ + CefFrame getParent(); + + /** + * Execute a string of JavaScript code in this frame. The url + * parameter is the URL where the script in question can be found, if any. + * The renderer may request this URL to show the developer the source of the + * error. The line parameter is the base line number to use for error + * reporting. + * + * @param code The code to be executed. + * @param url The URL where the script in question can be found. + * @param line The base line number to use for error reporting. + */ + public void executeJavaScript(String code, String url, int line); + + /** + * Execute undo in this frame. + */ + public void undo(); + + /** + * Execute redo in this frame. + */ + public void redo(); + + /** + * Execute cut in this frame. + */ + public void cut(); + + /** + * Execute copy in this frame. + */ + public void copy(); + + /** + * Execute paste in this frame. + */ + public void paste(); + + /** + * Execute selectAll in this frame. + */ + public void selectAll(); +} diff --git a/lib/jcef/java/org/cef/browser/CefFrame_N.java b/lib/jcef/java/org/cef/browser/CefFrame_N.java new file mode 100644 index 0000000..0bd1c6a --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefFrame_N.java @@ -0,0 +1,174 @@ +// Copyright (c) 2017 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.CefNativeAdapter; + +/** + * This class represents all methods which are connected to the + * native counterpart CEF. + * The visibility of this class is "package". + */ +class CefFrame_N extends CefNativeAdapter implements CefFrame { + CefFrame_N() {} + + @Override + protected void finalize() throws Throwable { + dispose(); + super.finalize(); + } + + @Override + public void dispose() { + try { + N_Dispose(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public String getIdentifier() { + try { + return N_GetIdentifier(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public String getURL() { + try { + return N_GetURL(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public String getName() { + try { + return N_GetName(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public boolean isMain() { + try { + return N_IsMain(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return false; + } + } + + @Override + public boolean isValid() { + try { + return N_IsValid(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return false; + } + } + + @Override + public boolean isFocused() { + try { + return N_IsFocused(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return false; + } + } + + @Override + public CefFrame getParent() { + try { + return N_GetParent(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public void executeJavaScript(String code, String url, int line) { + try { + N_ExecuteJavaScript(getNativeRef(null), code, url, line); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void undo() { + try { + N_Undo(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void redo() { + try { + N_Redo(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void cut() { + try { + N_Cut(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void copy() { + try { + N_Copy(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void paste() { + try { + N_Paste(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void selectAll() { + try { + N_SelectAll(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Dispose(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); + private final native boolean N_IsValid(long self); + private final native boolean N_IsFocused(long self); + private final native CefFrame N_GetParent(long self); + private final native void N_ExecuteJavaScript(long self, String code, String url, int line); + private final native void N_Undo(long self); + private final native void N_Redo(long self); + 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/lib/jcef/java/org/cef/browser/CefMessageRouter.java b/lib/jcef/java/org/cef/browser/CefMessageRouter.java new file mode 100644 index 0000000..1fdfd69 --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefMessageRouter.java @@ -0,0 +1,261 @@ +// 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 org.cef.browser; + +import org.cef.handler.CefMessageRouterHandler; + +/** + * The below classes implement support for routing aynchronous messages between + * JavaScript running in the renderer process and C++ running in the browser + * process. An application interacts with the router by passing it data from + * standard CEF C++ callbacks (OnBeforeBrowse, OnProcessMessageRecieved, + * OnContextCreated, etc). The renderer-side router supports generic JavaScript + * callback registration and execution while the browser-side router supports + * application-specific logic via one or more application-provided Handler + * instances. + * + * The renderer-side router implementation exposes a query function and a cancel + * function via the JavaScript 'window' object: + * + * // Create and send a new query. + * var request_id = window.cefQuery({ + * request: 'my_request', + * persistent: false, + * onSuccess: function(response) {}, + * onFailure: function(error_code, error_message) {} + * }); + * + * // Optionally cancel the query. + * window.cefQueryCancel(request_id); + * + * When |window.cefQuery| is executed the request is sent asynchronously to one + * or more C++ Handler objects registered in the browser process. Each C++ + * Handler can choose to either handle or ignore the query in the + * Handler::OnQuery callback. If a Handler chooses to handle the query then it + * should execute Callback::Success when a response is available or + * Callback::Failure if an error occurs. This will result in asynchronous + * execution of the associated JavaScript callback in the renderer process. Any + * queries unhandled by C++ code in the browser process will be automatically + * canceled and the associated JavaScript onFailure callback will be executed + * with an error code of -1. + * + * Queries can be either persistent or non-persistent. If the query is + * persistent than the callbacks will remain registered until one of the + * following conditions are met: + * + * A. The query is canceled in JavaScript using the |window.cefQueryCancel| + * function. + * B. The query is canceled in C++ code using the Callback::Failure function. + * C. The context associated with the query is released due to browser + * destruction, navigation or renderer process termination. + * + * If the query is non-persistent then the registration will be removed after + * the JavaScript callback is executed a single time. If a query is canceled for + * a reason other than Callback::Failure being executed then the associated + * Handler's OnQueryCanceled method will be called. + * + * Some possible usage patterns include: + * + * One-time Request. Use a non-persistent query to send a JavaScript request. + * The Handler evaluates the request and returns the response. The query is + * then discarded. + * + * Broadcast. Use a persistent query to register as a JavaScript broadcast + * receiver. The Handler keeps track of all registered Callbacks and executes + * them sequentially to deliver the broadcast message. + * + * Subscription. Use a persistent query to register as a JavaScript subscription + * receiver. The Handler initiates the subscription feed on the first request + * and delivers responses to all registered subscribers as they become + * available. The Handler cancels the subscription feed when there are no + * longer any registered JavaScript receivers. + * + * Message routing occurs on a per-browser and per-context basis. Consequently, + * additional application logic can be applied by restricting which browser or + * context instances are passed into the router. If you choose to use this + * approach do so cautiously. In order for the router to function correctly any + * browser or context instance passed into a single router callback must then + * be passed into all router callbacks. + * + * There is generally no need to have multiple renderer-side routers unless you + * wish to have multiple bindings with different JavaScript function names. It + * can be useful to have multiple browser-side routers with different client- + * provided Handler instances when implementing different behaviors on a per- + * browser basis. + * + * This implementation places no formatting restrictions on payload content. + * An application may choose to exchange anything from simple formatted + * strings to serialized XML or JSON data. + * + * + * EXAMPLE USAGE + * + * 1. Define the router configuration. You can optionally specify settings + * like the JavaScript function names. The configuration must be the same in + * both the browser and renderer processes. If using multiple routers in the + * same application make sure to specify unique function names for each + * router configuration. + * + * // Example config object showing the default values. + * CefMessageRouterConfig config = new CefMessageRouterConfig(); + * config.jsQueryFunction = "cefQuery"; + * config.jsCancelFunction = "cefQueryCancel"; + * + * 2. Create an instance of CefMessageRouter in the browser process. + * + * messageRouter_ = CefMessageRouter.create(config); + * + * 3. Register one or more Handlers. The Handler instances must either outlive + * the router or be removed from the router before they're deleted. + * + * messageRouter_.addHandler(myHandler); + * + * 4. Add your message router to all CefClient instances you want to get your + * JavaScript code be handled. + * + * myClient.addMessageRouter(messageRouter_); + * + * 4. Execute the query function from JavaScript code. + * + * window.cefQuery({request: 'my_request', + * persistent: false, + * onSuccess: function(response) { print(response); }, + * onFailure: function(error_code, error_message) {} }); + * + * 5. Handle the query in your CefMessageRouterHandler.onQuery implementation + * and execute the appropriate callback either immediately or asynchronously. + * + * public boolean onQuery(CefBrowser browser, + * long query_id, + * String request, + * boolean persistent, + * CefQueryCallback callback) { + * if (request.indexOf("my_request") == 0) { + * callback.success("my_response"); + * return true; + * } + * return false; // Not handled. + * } + * + * 6. Notice that the success callback is executed in JavaScript. + */ +public abstract class CefMessageRouter { + private CefMessageRouterConfig routerConfig_ = null; + + /** + * Used to configure the query router. If using multiple router pairs make + * sure to choose values that do not conflict. + */ + public static class CefMessageRouterConfig { + /** + * Name of the JavaScript function that will be added to the 'window' object + * for sending a query. The default value is "cefQuery". + */ + public String jsQueryFunction; + + /** + * Name of the JavaScript function that will be added to the 'window' object + * for canceling a pending query. The default value is "cefQueryCancel". + */ + public String jsCancelFunction; + + public CefMessageRouterConfig() { + this("cefQuery", "cefQueryCancel"); + } + + public CefMessageRouterConfig(String queryFunction, String cancelFunction) { + jsQueryFunction = queryFunction; + jsCancelFunction = cancelFunction; + } + } + + // This CTOR can't be called directly. Call method create() instead. + CefMessageRouter() {} + + @Override + protected void finalize() throws Throwable { + dispose(); + super.finalize(); + } + + /** + * Create a new router with the default configuration. The addHandler() method should be called + * to add a handler. + */ + public static final CefMessageRouter create() { + return CefMessageRouter.create(null, null); + } + + /** + * Create a new router with the specified configuration. The addHandler() method should be + * called to add a handler. + */ + public static final CefMessageRouter create(CefMessageRouterConfig config) { + return CefMessageRouter.create(config, null); + } + + /** + * Create a new router with the specified handler and default configuration. + */ + public static final CefMessageRouter create(CefMessageRouterHandler handler) { + return CefMessageRouter.create(null, handler); + } + + /** + * Create a new router with the specified handler and configuration. + */ + public static final CefMessageRouter create( + CefMessageRouterConfig config, CefMessageRouterHandler handler) { + CefMessageRouter router = CefMessageRouter_N.createNative(config); + if (router != null && handler != null) router.addHandler(handler, true); + return router; + } + + /** + * Must be called if the CefMessageRouter instance isn't used any more. + */ + public abstract void dispose(); + + // Called from native code during handling of createNative(). + void setMessageRouterConfig(CefMessageRouterConfig config) { + routerConfig_ = config; + } + + // Called from native code during handling of CefClientHandler.[add|remove]MessageRouter(). + public final CefMessageRouterConfig getMessageRouterConfig() { + return routerConfig_; + } + + /** + * Add a new query handler. + * + * @param handler The handler to be added. + * @param first If true the handler will be added as the first handler, otherwise it will be + * added as the last handler. + * @return True if the handler is added successfully. + */ + public abstract boolean addHandler(CefMessageRouterHandler handler, boolean first); + + /** + * Remove an existing query handler. Any pending queries associated with the handler will be + * canceled. onQueryCanceled will be called and the associated JavaScript onFailure callback + * will be executed with an error code of -1. + * + * @param handler The handler to be removed. + * @return True if the handler is removed successfully. + */ + public abstract boolean removeHandler(CefMessageRouterHandler handler); + + /** + * Cancel all pending queries associated with either |browser| or |handler|. If both |browser| + * and |handler| are NULL all pending queries will be canceled. onQueryCanceled will be called + * and the associated JavaScript onFailure callback will be executed in all cases with an error + * code of -1. + * + * @param browser The associated browser, or null. + * @param handler The associated handler, or null. + */ + public abstract void cancelPending(CefBrowser browser, CefMessageRouterHandler handler); +} diff --git a/lib/jcef/java/org/cef/browser/CefMessageRouter_N.java b/lib/jcef/java/org/cef/browser/CefMessageRouter_N.java new file mode 100644 index 0000000..5f8fefd --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefMessageRouter_N.java @@ -0,0 +1,82 @@ +// 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 org.cef.browser; + +import org.cef.callback.CefNative; +import org.cef.handler.CefMessageRouterHandler; + +class CefMessageRouter_N extends CefMessageRouter implements CefNative { + // Used internally to store a pointer to the CEF object. + private long N_CefHandle = 0; + + @Override + public void setNativeRef(String identifer, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return N_CefHandle; + } + + private CefMessageRouter_N() { + super(); + } + + public static final CefMessageRouter createNative(CefMessageRouterConfig config) { + try { + return CefMessageRouter_N.N_Create(config); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public void dispose() { + try { + N_Dispose(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean addHandler(CefMessageRouterHandler handler, boolean first) { + try { + return N_AddHandler(N_CefHandle, handler, first); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return false; + } + } + + @Override + public boolean removeHandler(CefMessageRouterHandler handler) { + try { + return N_RemoveHandler(N_CefHandle, handler); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return false; + } + } + + @Override + public void cancelPending(CefBrowser browser, CefMessageRouterHandler handler) { + try { + N_CancelPending(N_CefHandle, browser, handler); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native static CefMessageRouter_N N_Create(CefMessageRouterConfig config); + private final native void N_Dispose(long self); + private final native boolean N_AddHandler( + long self, CefMessageRouterHandler handler, boolean first); + private final native boolean N_RemoveHandler(long self, CefMessageRouterHandler handler); + private final native void N_CancelPending( + long self, CefBrowser browser, CefMessageRouterHandler handler); +} diff --git a/lib/jcef/java/org/cef/browser/CefPaintEvent.java b/lib/jcef/java/org/cef/browser/CefPaintEvent.java new file mode 100644 index 0000000..aed9af3 --- /dev/null +++ b/lib/jcef/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/lib/jcef/java/org/cef/browser/CefRegistration.java b/lib/jcef/java/org/cef/browser/CefRegistration.java new file mode 100644 index 0000000..1105140 --- /dev/null +++ b/lib/jcef/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/lib/jcef/java/org/cef/browser/CefRegistration_N.java b/lib/jcef/java/org/cef/browser/CefRegistration_N.java new file mode 100644 index 0000000..a7defd1 --- /dev/null +++ b/lib/jcef/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/lib/jcef/java/org/cef/browser/CefRenderer.java b/lib/jcef/java/org/cef/browser/CefRenderer.java new file mode 100644 index 0000000..2a29546 --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefRenderer.java @@ -0,0 +1,258 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.browser; + +import com.jogamp.opengl.GL2; + +import java.awt.Rectangle; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; + +class CefRenderer { + private boolean transparent_; + private GL2 initialized_context_ = null; + private int[] texture_id_ = new int[1]; + private int view_width_ = 0; + private int view_height_ = 0; + private float spin_x_ = 0f; + private float spin_y_ = 0f; + private Rectangle popup_rect_ = new Rectangle(0, 0, 0, 0); + private Rectangle original_popup_rect_ = new Rectangle(0, 0, 0, 0); + private boolean use_draw_pixels_ = false; + + protected CefRenderer(boolean transparent) { + transparent_ = transparent; + } + + protected boolean isTransparent() { + return transparent_; + } + + protected int getTextureID() { + return texture_id_[0]; + } + + @SuppressWarnings("static-access") + protected void initialize(GL2 gl2) { + if (initialized_context_ == gl2) return; + + initialized_context_ = gl2; + + if (!gl2.getContext().isHardwareRasterizer()) { + // Workaround for Windows Remote Desktop which requires pot textures. + System.out.println( + "opengl rendering may be slow as hardware rendering isn't available"); + use_draw_pixels_ = true; + return; + } + + gl2.glHint(gl2.GL_POLYGON_SMOOTH_HINT, gl2.GL_NICEST); + + gl2.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + + // Necessary for non-power-of-2 textures to render correctly. + gl2.glPixelStorei(gl2.GL_UNPACK_ALIGNMENT, 1); + + // Create the texture. + gl2.glGenTextures(1, texture_id_, 0); + assert (texture_id_[0] != 0); + + gl2.glBindTexture(gl2.GL_TEXTURE_2D, texture_id_[0]); + gl2.glTexParameteri(gl2.GL_TEXTURE_2D, gl2.GL_TEXTURE_MIN_FILTER, gl2.GL_NEAREST); + gl2.glTexParameteri(gl2.GL_TEXTURE_2D, gl2.GL_TEXTURE_MAG_FILTER, gl2.GL_NEAREST); + gl2.glTexEnvf(gl2.GL_TEXTURE_ENV, gl2.GL_TEXTURE_ENV_MODE, gl2.GL_MODULATE); + } + + protected void cleanup(GL2 gl2) { + if (texture_id_[0] != 0) gl2.glDeleteTextures(1, texture_id_, 0); + view_width_ = view_height_ = 0; + } + + @SuppressWarnings("static-access") + protected void render(GL2 gl2) { + if (use_draw_pixels_ || view_width_ == 0 || view_height_ == 0) return; + + assert (initialized_context_ != null); + + final float[] vertex_data = {// tu, tv, x, y, z + 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f}; + FloatBuffer vertices = FloatBuffer.wrap(vertex_data); + + gl2.glClear(gl2.GL_COLOR_BUFFER_BIT | gl2.GL_DEPTH_BUFFER_BIT); + + gl2.glMatrixMode(gl2.GL_MODELVIEW); + gl2.glLoadIdentity(); + + // Match GL units to screen coordinates. + gl2.glViewport(0, 0, view_width_, view_height_); + gl2.glMatrixMode(gl2.GL_PROJECTION); + gl2.glLoadIdentity(); + + // Draw the background gradient. + gl2.glPushAttrib(gl2.GL_ALL_ATTRIB_BITS); + gl2.glBegin(gl2.GL_QUADS); + gl2.glColor4f(1.0f, 0.0f, 0.0f, 1.0f); // red + gl2.glVertex2f(-1.0f, -1.0f); + gl2.glVertex2f(1.0f, -1.0f); + gl2.glColor4f(0.0f, 0.0f, 1.0f, 1.0f); // blue + gl2.glVertex2f(1.0f, 1.0f); + gl2.glVertex2f(-1.0f, 1.0f); + gl2.glEnd(); + gl2.glPopAttrib(); + + // Rotate the view based on the mouse spin. + if (spin_x_ != 0) gl2.glRotatef(-spin_x_, 1.0f, 0.0f, 0.0f); + if (spin_y_ != 0) gl2.glRotatef(-spin_y_, 0.0f, 1.0f, 0.0f); + + if (transparent_) { + // Alpha blending style. Texture values have premultiplied alpha. + gl2.glBlendFunc(gl2.GL_ONE, gl2.GL_ONE_MINUS_SRC_ALPHA); + + // Enable alpha blending. + gl2.glEnable(gl2.GL_BLEND); + } + + // Enable 2D textures. + gl2.glEnable(gl2.GL_TEXTURE_2D); + + // Draw the facets with the texture. + assert (texture_id_[0] != 0); + gl2.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + gl2.glBindTexture(gl2.GL_TEXTURE_2D, texture_id_[0]); + gl2.glInterleavedArrays(gl2.GL_T2F_V3F, 0, vertices); + gl2.glDrawArrays(gl2.GL_QUADS, 0, 4); + + // Disable 2D textures. + gl2.glDisable(gl2.GL_TEXTURE_2D); + + if (transparent_) { + // Disable alpha blending. + gl2.glDisable(gl2.GL_BLEND); + } + } + + protected void onPopupSize(Rectangle rect) { + if (rect.width <= 0 || rect.height <= 0) return; + original_popup_rect_ = rect; + popup_rect_ = getPopupRectInWebView(original_popup_rect_); + } + + protected Rectangle getPopupRect() { + return (Rectangle) popup_rect_.clone(); + } + + protected Rectangle getPopupRectInWebView(Rectangle original_rect) { + Rectangle rc = original_rect; + // if x or y are negative, move them to 0. + if (rc.x < 0) rc.x = 0; + if (rc.y < 0) rc.y = 0; + // if popup goes outside the view, try to reposition origin + if (rc.x + rc.width > view_width_) rc.x = view_width_ - rc.width; + if (rc.y + rc.height > view_height_) rc.y = view_height_ - rc.height; + // if x or y became negative, move them to 0 again. + if (rc.x < 0) rc.x = 0; + if (rc.y < 0) rc.y = 0; + return rc; + } + + protected void clearPopupRects() { + popup_rect_.setBounds(0, 0, 0, 0); + original_popup_rect_.setBounds(0, 0, 0, 0); + } + + @SuppressWarnings("static-access") + protected void onPaint(GL2 gl2, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, + int width, int height) { + initialize(gl2); + + if (use_draw_pixels_) { + gl2.glRasterPos2f(-1, 1); + gl2.glPixelZoom(1, -1); + gl2.glDrawPixels(width, height, GL2.GL_BGRA, GL2.GL_UNSIGNED_BYTE, buffer); + return; + } + + if (transparent_) { + // Enable alpha blending. + gl2.glEnable(gl2.GL_BLEND); + } + + // Enable 2D textures. + gl2.glEnable(gl2.GL_TEXTURE_2D); + + assert (texture_id_[0] != 0); + gl2.glBindTexture(gl2.GL_TEXTURE_2D, texture_id_[0]); + + if (!popup) { + int old_width = view_width_; + int old_height = view_height_; + + view_width_ = width; + view_height_ = height; + + gl2.glPixelStorei(gl2.GL_UNPACK_ROW_LENGTH, view_width_); + + if (old_width != view_width_ || old_height != view_height_) { + // Update/resize the whole texture. + gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_PIXELS, 0); + gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_ROWS, 0); + gl2.glTexImage2D(gl2.GL_TEXTURE_2D, 0, gl2.GL_RGBA, view_width_, view_height_, 0, + gl2.GL_BGRA, gl2.GL_UNSIGNED_INT_8_8_8_8_REV, buffer); + } else { + // Update just the dirty rectangles. + for (int i = 0; i < dirtyRects.length; ++i) { + Rectangle rect = dirtyRects[i]; + gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_PIXELS, rect.x); + gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_ROWS, rect.y); + gl2.glTexSubImage2D(gl2.GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width, + rect.height, gl2.GL_BGRA, gl2.GL_UNSIGNED_INT_8_8_8_8_REV, buffer); + } + } + } else if (popup && popup_rect_.width > 0 && popup_rect_.height > 0) { + int skip_pixels = 0, x = popup_rect_.x; + int skip_rows = 0, y = popup_rect_.y; + int w = width; + int h = height; + + // Adjust the popup to fit inside the view. + if (x < 0) { + skip_pixels = -x; + x = 0; + } + if (y < 0) { + skip_rows = -y; + y = 0; + } + if (x + w > view_width_) w -= x + w - view_width_; + if (y + h > view_height_) h -= y + h - view_height_; + + // Update the popup rectangle. + gl2.glPixelStorei(gl2.GL_UNPACK_ROW_LENGTH, width); + gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_PIXELS, skip_pixels); + gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_ROWS, skip_rows); + gl2.glTexSubImage2D(gl2.GL_TEXTURE_2D, 0, x, y, w, h, gl2.GL_BGRA, + gl2.GL_UNSIGNED_INT_8_8_8_8_REV, buffer); + } + + // Disable 2D textures. + gl2.glDisable(gl2.GL_TEXTURE_2D); + + if (transparent_) { + // Disable alpha blending. + gl2.glDisable(gl2.GL_BLEND); + } + } + + protected void setSpin(float spinX, float spinY) { + spin_x_ = spinX; + spin_y_ = spinY; + } + + protected void incrementSpin(float spinDX, float spinDY) { + spin_x_ -= spinDX; + spin_y_ -= spinDY; + } +} diff --git a/lib/jcef/java/org/cef/browser/CefRequestContext.java b/lib/jcef/java/org/cef/browser/CefRequestContext.java new file mode 100644 index 0000000..38ccef0 --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefRequestContext.java @@ -0,0 +1,100 @@ +// 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 org.cef.browser; + +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 + * via the CefClient.createBrowser method. Browser objects with different + * request contexts will never be hosted in the same render process. Browser + * objects with the same request context may or may not be hosted in the same + * render process depending on the process model. Browser objects created + * indirectly via the JavaScript window.open function or targeted links will + * share the same render process and the same request context as the source + * browser. When running in single-process mode there is only a single render + * process (the main process) and so all browsers created in single-process mode + * will share the same request context. This will be the first request context + * passed into the CefClient.createBrowser method and all other request + * context objects will be ignored. + */ +public abstract class CefRequestContext { + // This CTOR can't be called directly. Call method create() instead. + CefRequestContext() {} + + /** + * Returns the global context object. + */ + public static final CefRequestContext getGlobalContext() { + return CefRequestContext_N.getGlobalContextNative(); + } + + /** + * Creates a new context object with the specified handler. + */ + public static final CefRequestContext createContext(CefRequestContextHandler handler) { + return CefRequestContext_N.createNative(handler); + } + + public abstract void dispose(); + + /** + * Returns true if this object is the global context. + */ + public abstract boolean isGlobal(); + + /** + * 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/lib/jcef/java/org/cef/browser/CefRequestContext_N.java b/lib/jcef/java/org/cef/browser/CefRequestContext_N.java new file mode 100644 index 0000000..6e26e7d --- /dev/null +++ b/lib/jcef/java/org/cef/browser/CefRequestContext_N.java @@ -0,0 +1,145 @@ +// 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 org.cef.browser; + +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. + private long N_CefHandle = 0; + private static CefRequestContext_N globalInstance = null; + private CefRequestContextHandler handler = null; + + @Override + public void setNativeRef(String identifer, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return N_CefHandle; + } + + CefRequestContext_N() { + super(); + } + + static final CefRequestContext_N getGlobalContextNative() { + CefRequestContext_N result = null; + try { + result = CefRequestContext_N.N_GetGlobalContext(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + + if (globalInstance == null) { + globalInstance = result; + } else if (globalInstance.N_CefHandle == result.N_CefHandle) { + result.N_CefRequestContext_DTOR(); + } + return globalInstance; + } + + static final CefRequestContext_N createNative(CefRequestContextHandler handler) { + CefRequestContext_N result = null; + try { + result = CefRequestContext_N.N_CreateContext(handler); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + if (result != null) result.handler = handler; + return result; + } + + @Override + public void dispose() { + try { + N_CefRequestContext_DTOR(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean isGlobal() { + try { + return N_IsGlobal(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + 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; + } + + private final static native CefRequestContext_N N_GetGlobalContext(); + private final static native CefRequestContext_N N_CreateContext( + CefRequestContextHandler handler); + private final native boolean N_IsGlobal(); + 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); + private final native void N_CefRequestContext_DTOR(); +} diff --git a/lib/jcef/java/org/cef/browser/mac/CefBrowserWindowMac.java b/lib/jcef/java/org/cef/browser/mac/CefBrowserWindowMac.java new file mode 100644 index 0000000..3239edc --- /dev/null +++ b/lib/jcef/java/org/cef/browser/mac/CefBrowserWindowMac.java @@ -0,0 +1,45 @@ +// 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 org.cef.browser.mac; + +import org.cef.browser.CefBrowserWindow; + +import java.awt.Component; +import java.awt.peer.ComponentPeer; + +import sun.awt.AWTAccessor; +import sun.lwawt.LWComponentPeer; +import sun.lwawt.PlatformWindow; +import sun.lwawt.macosx.CFRetainedResource; +import sun.lwawt.macosx.CPlatformWindow; + +public class CefBrowserWindowMac implements CefBrowserWindow { + @Override + public long getWindowHandle(Component comp) { + final long[] result = new long[1]; + while (comp != null) { + if (comp.isLightweight()) { + comp = comp.getParent(); + continue; + } + ComponentPeer peer = AWTAccessor.getComponentAccessor().getPeer(comp); + if (peer instanceof LWComponentPeer) { + @SuppressWarnings("rawtypes") + PlatformWindow pWindow = ((LWComponentPeer) peer).getPlatformWindow(); + if (pWindow instanceof CPlatformWindow) { + ((CPlatformWindow) pWindow).execute(new CFRetainedResource.CFNativeAction() { + @Override + public void run(long l) { + result[0] = l; + } + }); + break; + } + } + comp = comp.getParent(); + } + return result[0]; + } +} diff --git a/lib/jcef/java/org/cef/callback/CefAuthCallback.java b/lib/jcef/java/org/cef/callback/CefAuthCallback.java new file mode 100644 index 0000000..9cef71b --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefAuthCallback.java @@ -0,0 +1,21 @@ +// 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 org.cef.callback; + +/** + * Callback interface used for asynchronous continuation of authentication + * requests. + */ +public interface CefAuthCallback { + /** + * Continue the authentication request. + */ + public void Continue(String username, String password); + + /** + * Cancel the authentication request. + */ + public void cancel(); +} diff --git a/lib/jcef/java/org/cef/callback/CefAuthCallback_N.java b/lib/jcef/java/org/cef/callback/CefAuthCallback_N.java new file mode 100644 index 0000000..7957557 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefAuthCallback_N.java @@ -0,0 +1,36 @@ +// 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 org.cef.callback; + +class CefAuthCallback_N extends CefNativeAdapter implements CefAuthCallback { + CefAuthCallback_N() {} + + @Override + protected void finalize() throws Throwable { + cancel(); + super.finalize(); + } + + @Override + public void Continue(String username, String password) { + try { + N_Continue(getNativeRef(null), username, password); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void cancel() { + try { + N_Cancel(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Continue(long self, String username, String password); + private final native void N_Cancel(long self); +} diff --git a/lib/jcef/java/org/cef/callback/CefBeforeDownloadCallback.java b/lib/jcef/java/org/cef/callback/CefBeforeDownloadCallback.java new file mode 100644 index 0000000..442eb49 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefBeforeDownloadCallback.java @@ -0,0 +1,20 @@ +// 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 org.cef.callback; + +/** + * Callback interface used to asynchronously continue a download. + */ +public interface CefBeforeDownloadCallback { + /** + * Call to continue the download. + * @param downloadPath Set it to the full file path for the download + * including the file name or leave blank to use the suggested name and + * the default temp directory. + * @param showDialog Set it to true if you do wish to show the default + * "Save As" dialog. + */ + public void Continue(String downloadPath, boolean showDialog); +} diff --git a/lib/jcef/java/org/cef/callback/CefBeforeDownloadCallback_N.java b/lib/jcef/java/org/cef/callback/CefBeforeDownloadCallback_N.java new file mode 100644 index 0000000..93a14f2 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefBeforeDownloadCallback_N.java @@ -0,0 +1,26 @@ +// 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 org.cef.callback; + +class CefBeforeDownloadCallback_N extends CefNativeAdapter implements CefBeforeDownloadCallback { + CefBeforeDownloadCallback_N() {} + + @Override + protected void finalize() throws Throwable { + Continue("", false); + super.finalize(); + } + + @Override + public void Continue(String downloadPath, boolean showDialog) { + try { + N_Continue(getNativeRef(null), downloadPath, showDialog); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Continue(long self, String downloadPath, boolean showDialog); +} diff --git a/lib/jcef/java/org/cef/callback/CefCallback.java b/lib/jcef/java/org/cef/callback/CefCallback.java new file mode 100644 index 0000000..9d4f405 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefCallback.java @@ -0,0 +1,20 @@ +// 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 org.cef.callback; + +/** + * Generic callback interface used for asynchronous continuation. + */ +public interface CefCallback { + /** + * Continue processing. + */ + void Continue(); + + /** + * Cancel processing. + */ + void cancel(); +} diff --git a/lib/jcef/java/org/cef/callback/CefCallback_N.java b/lib/jcef/java/org/cef/callback/CefCallback_N.java new file mode 100644 index 0000000..fb4321a --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefCallback_N.java @@ -0,0 +1,36 @@ +// 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 org.cef.callback; + +class CefCallback_N extends CefNativeAdapter implements CefCallback { + CefCallback_N() {} + + @Override + protected void finalize() throws Throwable { + cancel(); + super.finalize(); + } + + @Override + public void Continue() { + try { + N_Continue(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void cancel() { + try { + N_Cancel(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Continue(long self); + private final native void N_Cancel(long self); +} diff --git a/lib/jcef/java/org/cef/callback/CefCommandLine.java b/lib/jcef/java/org/cef/callback/CefCommandLine.java new file mode 100644 index 0000000..1daeba4 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefCommandLine.java @@ -0,0 +1,95 @@ +// 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 org.cef.callback; + +import java.util.Map; +import java.util.Vector; + +/** + * Class used to create and/or parse command line arguments. Arguments with + * '--', '-' and, on Windows, '/' prefixes are considered switches. Switches + * will always precede any arguments without switch prefixes. Switches can + * optionally have a value specified using the '=' delimiter (e.g. + * "-switch=value"). An argument of "--" will terminate switch parsing with all + * subsequent tokens, regardless of prefix, being interpreted as non-switch + * arguments. Switch names are considered case-insensitive. + */ +public interface CefCommandLine { + /** + * Reset the command-line switches and arguments but leave the program + * component unchanged. + */ + public void reset(); + + /** + * Get the program part of the command line string (the first item). + */ + public String getProgram(); + + /** + * Set the program part of the command line string (the first item). + * @param program Name of the program. + */ + public void setProgram(String program); + + /** + * Checks if the command line has switches. + * @return true if the command line has switches. + */ + public boolean hasSwitches(); + + /** + * Checks if the command line has a specific switches. + * @param name A switch name to test for. + * @return true if the command line contains the given switch. + */ + public boolean hasSwitch(String name); + + /** + * Returns the value associated with the given switch. If the switch has no + * value or isn't present this method returns the empty string. + * @param name the name of the switch. + * @return the value of the switch. + */ + public String getSwitchValue(String name); + + /** + * Returns the map of switch names and values. If a switch has no value an + * empty string is returned. + * @return Map of switches and each value. + */ + public Map getSwitches(); + + /** + * Add a switch with an empty value to the end of the command line. + * @param name name of the switch. + */ + public void appendSwitch(String name); + + /** + * Add a switch with the specified value to the end of the command line. + * @param name name of the switch. + * @param value value for the switch. + */ + public void appendSwitchWithValue(String name, String value); + + /** + * Tests if there are remaining command line arguments. + * @return True if there are remaining command line arguments. + */ + public boolean hasArguments(); + + /** + * Get the remaining command line arguments. + * @return Vector of command line arguments. + */ + public Vector getArguments(); + + /** + * Add an argument to the end of the command line. + * @param argument name of the argument. + */ + public void appendArgument(String argument); +} diff --git a/lib/jcef/java/org/cef/callback/CefCommandLine_N.java b/lib/jcef/java/org/cef/callback/CefCommandLine_N.java new file mode 100644 index 0000000..27881fc --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefCommandLine_N.java @@ -0,0 +1,154 @@ +// 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 org.cef.callback; + +import java.util.Map; +import java.util.Vector; + +class CefCommandLine_N extends CefNativeAdapter implements CefCommandLine { + CefCommandLine_N() {} + + @Override + public void reset() { + try { + N_Reset(getNativeRef(null)); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + @Override + public String getProgram() { + try { + return N_GetProgram(getNativeRef(null)); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + return null; + } + + @Override + public void setProgram(String program) { + try { + N_SetProgram(getNativeRef(null), program); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + @Override + public boolean hasSwitches() { + try { + return N_HasSwitches(getNativeRef(null)); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + return false; + } + + @Override + public boolean hasSwitch(String name) { + try { + return N_HasSwitch(getNativeRef(null), name); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + return false; + } + + @Override + public String getSwitchValue(String name) { + try { + return N_GetSwitchValue(getNativeRef(null), name); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + return null; + } + + @Override + public Map getSwitches() { + try { + return N_GetSwitches(getNativeRef(null)); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + return null; + } + + @Override + public void appendSwitch(String name) { + try { + N_AppendSwitch(getNativeRef(null), name); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + @Override + public void appendSwitchWithValue(String name, String value) { + try { + N_AppendSwitchWithValue(getNativeRef(null), name, value); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + @Override + public boolean hasArguments() { + try { + return N_HasArguments(getNativeRef(null)); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + return false; + } + + @Override + public Vector getArguments() { + try { + return N_GetArguments(getNativeRef(null)); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + return null; + } + + @Override + public void appendArgument(String argument) { + try { + N_AppendArgument(getNativeRef(null), argument); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + @Override + public String toString() { + String result = "CefCommandLine [program=\'" + getProgram() + "\'"; + if (hasSwitches()) { + Map switches = getSwitches(); + result += ", switches=" + switches; + } + if (hasArguments()) { + Vector arguments = getArguments(); + result += ", arguments=" + arguments; + } + return result + "]"; + } + + private final native void N_Reset(long self); + private final native String N_GetProgram(long self); + private final native void N_SetProgram(long self, String program); + private final native boolean N_HasSwitches(long self); + private final native boolean N_HasSwitch(long self, String name); + private final native String N_GetSwitchValue(long self, String name); + private final native Map N_GetSwitches(long self); + private final native void N_AppendSwitch(long self, String name); + private final native void N_AppendSwitchWithValue(long self, String name, String value); + private final native boolean N_HasArguments(long self); + private final native Vector N_GetArguments(long self); + private final native void N_AppendArgument(long self, String argument); +} diff --git a/lib/jcef/java/org/cef/callback/CefCompletionCallback.java b/lib/jcef/java/org/cef/callback/CefCompletionCallback.java new file mode 100644 index 0000000..7349390 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefCompletionCallback.java @@ -0,0 +1,15 @@ +// 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 org.cef.callback; + +/** + * Generic callback interface used for asynchronous completion. + */ +public interface CefCompletionCallback { + /** + * Method that will be called once the task is complete. + */ + public abstract void onComplete(); +} diff --git a/lib/jcef/java/org/cef/callback/CefContextMenuParams.java b/lib/jcef/java/org/cef/callback/CefContextMenuParams.java new file mode 100644 index 0000000..e2c4d58 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefContextMenuParams.java @@ -0,0 +1,180 @@ +// 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 org.cef.callback; + +import java.util.Vector; + +/** + * Provides information about the context menu state. The methods of this class + * can only be accessed on browser process the UI thread. + */ +public interface CefContextMenuParams { + /** + * Supported context menu type flags. + */ + public static final class TypeFlags { + public final static int CM_TYPEFLAG_NONE = 0; //!< No node is selected. + public final static int CM_TYPEFLAG_PAGE = 1 << 0; //!< The top page is selected. + public final static int CM_TYPEFLAG_FRAME = 1 << 1; //!< A subframe page is selected. + public final static int CM_TYPEFLAG_LINK = 1 << 2; //!< A link is selected. + public final static int CM_TYPEFLAG_MEDIA = 1 << 3; //!< A media node is selected. + public final static int CM_TYPEFLAG_SELECTION = 1 + << 4; //!< There is a textual or mixed selection that is selected. + public final static int CM_TYPEFLAG_EDITABLE = 1 << 5; //!< An editable element is selected. + } + + /** + * Supported context menu media types. + */ + public enum MediaType { + CM_MEDIATYPE_NONE, //!< No special node is in context. + CM_MEDIATYPE_IMAGE, //!< An image node is selected. + CM_MEDIATYPE_VIDEO, //!< A video node is selected. + CM_MEDIATYPE_AUDIO, //!< An audio node is selected. + CM_MEDIATYPE_FILE, //!< A file node is selected. + CM_MEDIATYPE_PLUGIN, //!< A plugin node is selected. + } + + /** + * Supported context menu media state bit flags. + */ + public static final class MediaStateFlags { + public final static int CM_MEDIAFLAG_NONE = 0; + public final static int CM_MEDIAFLAG_ERROR = 1 << 0; + public final static int CM_MEDIAFLAG_PAUSED = 1 << 1; + public final static int CM_MEDIAFLAG_MUTED = 1 << 2; + public final static int CM_MEDIAFLAG_LOOP = 1 << 3; + public final static int CM_MEDIAFLAG_CAN_SAVE = 1 << 4; + public final static int CM_MEDIAFLAG_HAS_AUDIO = 1 << 5; + public final static int CM_MEDIAFLAG_HAS_VIDEO = 1 << 6; + public final static int CM_MEDIAFLAG_CONTROL_ROOT_ELEMENT = 1 << 7; + public final static int CM_MEDIAFLAG_CAN_PRINT = 1 << 8; + public final static int CM_MEDIAFLAG_CAN_ROTATE = 1 << 9; + } + + /** + * Supported context menu edit state bit flags. + */ + public static final class EditStateFlags { + public final static int CM_EDITFLAG_NONE = 0; + public final static int CM_EDITFLAG_CAN_UNDO = 1 << 0; + public final static int CM_EDITFLAG_CAN_REDO = 1 << 1; + public final static int CM_EDITFLAG_CAN_CUT = 1 << 2; + public final static int CM_EDITFLAG_CAN_COPY = 1 << 3; + public final static int CM_EDITFLAG_CAN_PASTE = 1 << 4; + public final static int CM_EDITFLAG_CAN_DELETE = 1 << 5; + public final static int CM_EDITFLAG_CAN_SELECT_ALL = 1 << 6; + public final static int CM_EDITFLAG_CAN_TRANSLATE = 1 << 7; + } + + /** + * Returns the X coordinate of the mouse where the context menu was invoked. + * Coords are relative to the associated RenderView's origin. + */ + int getXCoord(); + + /** + * Returns the Y coordinate of the mouse where the context menu was invoked. + * Coords are relative to the associated RenderView's origin. + */ + int getYCoord(); + + /** + * Returns flags representing the type of node that the context menu was + * invoked on. See TypeFlags for supported values + */ + int getTypeFlags(); + + /** + * Returns the URL of the link, if any, that encloses the node that the + * context menu was invoked on. + */ + String getLinkUrl(); + + /** + * Returns the link URL, if any, to be used ONLY for "copy link address". We + * don't validate this field in the frontend process. + */ + String getUnfilteredLinkUrl(); + + /** + * Returns the source URL, if any, for the element that the context menu was + * invoked on. Example of elements with source URLs are img, audio, and video. + */ + String getSourceUrl(); + + /** + * Returns true if the context menu was invoked on an image which has + * non-empty contents. + */ + boolean hasImageContents(); + + /** + * Returns the URL of the top level page that the context menu was invoked on. + */ + String getPageUrl(); + + /** + * Returns the URL of the subframe that the context menu was invoked on. + */ + String getFrameUrl(); + + /** + * Returns the character encoding of the subframe that the context menu was + * invoked on. + */ + String getFrameCharset(); + + /** + * Returns the type of context node that the context menu was invoked on. + */ + MediaType getMediaType(); + + /** + * Returns flags representing the actions supported by the media element, if + * any, that the context menu was invoked on. See MediaStateFlags for possible + * values. + */ + int getMediaStateFlags(); + + /** + * Returns the text of the selection, if any, that the context menu was + * invoked on. + */ + + String getSelectionText(); + + /** + * Returns the text of the misspelled word, if any, that the context menu was + * invoked on. + */ + String getMisspelledWord(); + + /** + * Returns true if suggestions exist, false otherwise. Fills in |suggestions| + * from the spell check service for the misspelled word if there is one. + */ + boolean getDictionarySuggestions(Vector suggestions); + + /** + * Returns true if the context menu was invoked on an editable node. + */ + + boolean isEditable(); + + /** + * Returns true if the context menu was invoked on an editable node where + * spell-check is enabled. + */ + + boolean isSpellCheckEnabled(); + + /** + * Returns flags representing the actions supported by the editable node, if + * any, that the context menu was invoked on. See EditStateFlags for possible + * values. + */ + int getEditStateFlags(); +} diff --git a/lib/jcef/java/org/cef/callback/CefContextMenuParams_N.java b/lib/jcef/java/org/cef/callback/CefContextMenuParams_N.java new file mode 100644 index 0000000..a7bd7ad --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefContextMenuParams_N.java @@ -0,0 +1,210 @@ +// 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 org.cef.callback; + +import java.util.Vector; + +class CefContextMenuParams_N extends CefNativeAdapter implements CefContextMenuParams { + CefContextMenuParams_N() {} + + @Override + public int getXCoord() { + try { + return N_GetXCoord(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public int getYCoord() { + try { + return N_GetYCoord(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public int getTypeFlags() { + try { + return N_GetTypeFlags(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public String getLinkUrl() { + try { + return N_GetLinkUrl(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getUnfilteredLinkUrl() { + try { + return N_GetUnfilteredLinkUrl(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getSourceUrl() { + try { + return N_GetSourceUrl(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public boolean hasImageContents() { + try { + return N_HasImageContents(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public String getPageUrl() { + try { + return N_GetPageUrl(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getFrameUrl() { + try { + return N_GetFrameUrl(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getFrameCharset() { + try { + return N_GetFrameCharset(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public MediaType getMediaType() { + try { + return N_GetMediaType(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public int getMediaStateFlags() { + try { + return N_GetMediaStateFlags(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public String getSelectionText() { + try { + return N_GetSelectionText(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getMisspelledWord() { + try { + return N_GetMisspelledWord(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public boolean getDictionarySuggestions(Vector suggestions) { + try { + return N_GetDictionarySuggestions(getNativeRef(null), suggestions); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isEditable() { + try { + return N_IsEditable(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isSpellCheckEnabled() { + try { + return N_IsSpellCheckEnabled(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public int getEditStateFlags() { + try { + return N_GetEditStateFlags(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + private final native int N_GetXCoord(long self); + private final native int N_GetYCoord(long self); + private final native int N_GetTypeFlags(long self); + private final native String N_GetLinkUrl(long self); + private final native String N_GetUnfilteredLinkUrl(long self); + private final native String N_GetSourceUrl(long self); + private final native boolean N_HasImageContents(long self); + private final native String N_GetPageUrl(long self); + private final native String N_GetFrameUrl(long self); + private final native String N_GetFrameCharset(long self); + private final native MediaType N_GetMediaType(long self); + private final native int N_GetMediaStateFlags(long self); + private final native String N_GetSelectionText(long self); + private final native String N_GetMisspelledWord(long self); + private final native boolean N_GetDictionarySuggestions(long self, Vector suggestions); + private final native boolean N_IsEditable(long self); + private final native boolean N_IsSpellCheckEnabled(long self); + private final native int N_GetEditStateFlags(long self); +} diff --git a/lib/jcef/java/org/cef/callback/CefCookieVisitor.java b/lib/jcef/java/org/cef/callback/CefCookieVisitor.java new file mode 100644 index 0000000..1d55764 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefCookieVisitor.java @@ -0,0 +1,23 @@ +// 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 org.cef.callback; + +import org.cef.misc.BoolRef; +import org.cef.network.CefCookie; + +/** + * Interface to implement for visiting cookie values. The methods of this class + * will always be called on the IO thread. + */ +public interface CefCookieVisitor { + /** + * Method that will be called once for each cookie. |count| is the 0-based + * index for the current cookie. |total| is the total number of cookies. + * Set |deleteCookie| to true to delete the cookie currently being visited. + * Return false to stop visiting cookies. This method may never be called if + * no cookies are found. + */ + public abstract boolean visit(CefCookie cookie, int count, int total, BoolRef delete); +} diff --git a/lib/jcef/java/org/cef/callback/CefDownloadItem.java b/lib/jcef/java/org/cef/callback/CefDownloadItem.java new file mode 100644 index 0000000..b9302dd --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefDownloadItem.java @@ -0,0 +1,94 @@ +// 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 org.cef.callback; + +import java.util.Date; + +/** + * Class used to represent a download item. + */ +public interface CefDownloadItem { + /** + * Returns true if this object is valid. Do not call any other methods if this + * function returns false. + */ + boolean isValid(); + + /** + * Returns true if the download is in progress. + */ + boolean isInProgress(); + + /** + * Returns true if the download is complete. + */ + boolean isComplete(); + + /** + * Returns true if the download has been canceled or interrupted. + */ + boolean isCanceled(); + + /** + * Returns a simple speed estimate in bytes/s. + */ + long getCurrentSpeed(); + + /** + * Returns the rough percent complete or -1 if the receive total size is + * unknown. + */ + int getPercentComplete(); + + /** + * Returns the total number of bytes. + */ + long getTotalBytes(); + + /** + * Returns the number of received bytes. + */ + long getReceivedBytes(); + + /** + * Returns the time that the download started. + */ + Date getStartTime(); + + /** + * Returns the time that the download ended. + */ + Date getEndTime(); + + /** + * Returns the full path to the downloaded or downloading file. + */ + String getFullPath(); + + /** + * Returns the unique identifier for this download. + */ + int getId(); + + /** + * Returns the URL. + */ + String getURL(); + + /** + * Returns the suggested file name. + */ + String getSuggestedFileName(); + + /** + * Returns the content disposition. + */ + String getContentDisposition(); + + /** + * Returns the mime type. + */ + String getMimeType(); +} diff --git a/lib/jcef/java/org/cef/callback/CefDownloadItemCallback.java b/lib/jcef/java/org/cef/callback/CefDownloadItemCallback.java new file mode 100644 index 0000000..1e2fc34 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefDownloadItemCallback.java @@ -0,0 +1,25 @@ +// 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 org.cef.callback; + +/** + * Callback interface used to asynchronously modify download status. + */ +public interface CefDownloadItemCallback { + /** + * Call to cancel the download. + */ + public void cancel(); + + /** + * Call to pause the download. + */ + public void pause(); + + /** + * Call to resume the download. + */ + public void resume(); +} diff --git a/lib/jcef/java/org/cef/callback/CefDownloadItemCallback_N.java b/lib/jcef/java/org/cef/callback/CefDownloadItemCallback_N.java new file mode 100644 index 0000000..46aace1 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefDownloadItemCallback_N.java @@ -0,0 +1,51 @@ +// 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 org.cef.callback; + +class CefDownloadItemCallback_N extends CefNativeAdapter implements CefDownloadItemCallback { + CefDownloadItemCallback_N() {} + + @Override + protected void finalize() throws Throwable { + try { + N_Dispose(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + super.finalize(); + } + + @Override + public void cancel() { + try { + N_Cancel(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void pause() { + try { + N_Pause(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void resume() { + try { + N_Resume(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Dispose(long self); + private final native void N_Cancel(long self); + private final native void N_Pause(long self); + private final native void N_Resume(long self); +} diff --git a/lib/jcef/java/org/cef/callback/CefDownloadItem_N.java b/lib/jcef/java/org/cef/callback/CefDownloadItem_N.java new file mode 100644 index 0000000..114c4af --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefDownloadItem_N.java @@ -0,0 +1,188 @@ +// 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 org.cef.callback; + +import java.util.Date; + +class CefDownloadItem_N extends CefNativeAdapter implements CefDownloadItem { + CefDownloadItem_N() {} + + @Override + public boolean isValid() { + try { + return N_IsValid(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isInProgress() { + try { + return N_IsInProgress(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isComplete() { + try { + return N_IsComplete(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isCanceled() { + try { + return N_IsCanceled(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public long getCurrentSpeed() { + try { + return N_GetCurrentSpeed(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public int getPercentComplete() { + try { + return N_GetPercentComplete(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public long getTotalBytes() { + try { + return N_GetTotalBytes(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public long getReceivedBytes() { + try { + return N_GetReceivedBytes(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public Date getStartTime() { + try { + return N_GetStartTime(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public Date getEndTime() { + try { + return N_GetEndTime(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getFullPath() { + try { + return N_GetFullPath(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public int getId() { + try { + return N_GetId(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public String getURL() { + try { + return N_GetURL(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getSuggestedFileName() { + try { + return N_GetSuggestedFileName(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getContentDisposition() { + try { + return N_GetContentDisposition(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getMimeType() { + try { + return N_GetMimeType(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + private final native boolean N_IsValid(long self); + private final native boolean N_IsInProgress(long self); + private final native boolean N_IsComplete(long self); + private final native boolean N_IsCanceled(long self); + private final native long N_GetCurrentSpeed(long self); + private final native int N_GetPercentComplete(long self); + private final native long N_GetTotalBytes(long self); + private final native long N_GetReceivedBytes(long self); + private final native Date N_GetStartTime(long self); + private final native Date N_GetEndTime(long self); + private final native String N_GetFullPath(long self); + private final native int N_GetId(long self); + private final native String N_GetURL(long self); + private final native String N_GetSuggestedFileName(long self); + private final native String N_GetContentDisposition(long self); + private final native String N_GetMimeType(long self); +} diff --git a/lib/jcef/java/org/cef/callback/CefDragData.java b/lib/jcef/java/org/cef/callback/CefDragData.java new file mode 100644 index 0000000..25a5547 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefDragData.java @@ -0,0 +1,195 @@ +// 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 org.cef.callback; + +import java.io.OutputStream; +import java.util.Vector; + +/** + * Class used to represent drag data. The methods of this class may be called + * on any thread. + */ +public abstract class CefDragData { + /** + * Supported drag operation bit flags. + */ + public static final class DragOperations { + public final static int DRAG_OPERATION_NONE = 0; + public final static int DRAG_OPERATION_COPY = 1; + public final static int DRAG_OPERATION_LINK = 2; + public final static int DRAG_OPERATION_GENERIC = 4; + public final static int DRAG_OPERATION_PRIVATE = 8; + public final static int DRAG_OPERATION_MOVE = 16; + public final static int DRAG_OPERATION_DELETE = 32; + public final static int DRAG_OPERATION_EVERY = Integer.MAX_VALUE; + } + + // This CTOR can't be called directly. Call method create() instead. + CefDragData() {} + + @Override + protected void finalize() throws Throwable { + dispose(); + super.finalize(); + } + + /** + * Create a new CefDragData object. + */ + public static final CefDragData create() { + return CefDragData_N.createNative(); + } + + /** + * Returns a copy of the current object + */ + public abstract CefDragData clone(); + + /** + * Removes the native reference from an unused object. + */ + public abstract void dispose(); + + /** + * Test if the object is set to read-only. + * @return true if this object is read-only. + */ + public abstract boolean isReadOnly(); + + /** + * Returns true if the drag data is a link. + */ + public abstract boolean isLink(); + + /** + * Returns true if the drag data is a text or html fragment. + */ + public abstract boolean isFragment(); + + /** + * Returns true if the drag data is a file. + */ + public abstract boolean isFile(); + + /** + * Return the link URL that is being dragged. + */ + public abstract String getLinkURL(); + + /** + * Return the title associated with the link being dragged. + */ + public abstract String getLinkTitle(); + + /** + * Return the metadata, if any, associated with the link being dragged. + */ + public abstract String getLinkMetadata(); + + /** + * Return the plain text fragment that is being dragged. + */ + public abstract String getFragmentText(); + + /** + * Return the text/html fragment that is being dragged. + */ + public abstract String getFragmentHtml(); + + /** + * Return the base URL that the fragment came from. This value is used for + * resolving relative URLs and may be empty. + */ + public abstract String getFragmentBaseURL(); + + /** + * Write the contents of the file being dragged out of the web view into + * |writer|. Returns the number of bytes sent to |writer|. If |writer| is + * NULL this method will return the size of the file contents in bytes. + * Call getFileName() to get a suggested name for the file. + * + * @param writer Writes the contents into this object. + * @return The number of bytes sent to writer. If writer is NULL the size of + * the file contents in bytes is returned. + */ + public abstract int getFileContents(OutputStream writer); + + /** + * Return the name of the file being dragged out of the browser window. + */ + public abstract String getFileName(); + + /** + * Retrieve the list of file names that are being dragged into the browser + * window. + */ + 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. + */ + public abstract void setLinkURL(String url); + + /** + * Set the title associated with the link being dragged. + * @param title The tile associated with the link. + */ + public abstract void setLinkTitle(String title); + + /** + * Set the metadata associated with the link being dragged. + * @param data The metadata associated with the link. + */ + public abstract void setLinkMetadata(String data); + + /** + * Set the plain text fragment that is being dragged. + * @param text The plain text fragment to be set. + */ + public abstract void setFragmentText(String text); + + /** + * Set the text/html fragment that is being dragged. + * @param html The html fragment to be set. + */ + public abstract void setFragmentHtml(String html); + + /** + * Set the base URL that the fragment came from. + * @param baseUrl The base URL to be set. + */ + public abstract void setFragmentBaseURL(String baseUrl); + + /** + * Reset the file contents. You should do this before calling + * CefBrowser.dragTargetDragEnter as the web view does not allow us to + * drag in this kind of data. + */ + public abstract void resetFileContents(); + + /** + * Add a file that is being dragged into the webview. + * @param path The file and path to be set. + * @param displayName The name to be displayed. + */ + public abstract void addFile(String path, String displayName); + + @Override + public String toString() { + return "CefDragData [isReadOnly()=" + isReadOnly() + ", isLink()=" + isLink() + + ", isFragment()=" + isFragment() + ", isFile()=" + isFile() + ", getLinkURL()=" + + getLinkURL() + ", getLinkTitle()=" + getLinkTitle() + ", getLinkMetadata()=" + + getLinkMetadata() + ", getFragmentText()=" + getFragmentText() + + ", getFragmentHtml()=" + getFragmentHtml() + ", getFragmentBaseURL()=" + + getFragmentBaseURL() + ", getFileName()=" + getFileName() + "]"; + } +} diff --git a/lib/jcef/java/org/cef/callback/CefDragData_N.java b/lib/jcef/java/org/cef/callback/CefDragData_N.java new file mode 100644 index 0000000..e56867d --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefDragData_N.java @@ -0,0 +1,298 @@ +package org.cef.callback; + +import java.io.OutputStream; +import java.util.Vector; + +class CefDragData_N extends CefDragData implements CefNative { + // Used internally to store a pointer to the CEF object. + private long N_CefHandle = 0; + + @Override + public void setNativeRef(String identifer, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return N_CefHandle; + } + + CefDragData_N() { + super(); + } + + public static CefDragData createNative() { + try { + return CefDragData_N.N_Create(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public CefDragData clone() { + try { + return N_Clone(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public void dispose() { + try { + N_Dispose(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean isReadOnly() { + try { + return N_IsReadOnly(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return true; + } + } + + @Override + public boolean isLink() { + try { + return N_IsLink(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isFragment() { + try { + return N_IsFragment(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isFile() { + try { + return N_IsFile(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public String getLinkURL() { + try { + return N_GetLinkURL(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getLinkTitle() { + try { + return N_GetLinkTitle(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getLinkMetadata() { + try { + return N_GetLinkMetadata(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getFragmentText() { + try { + return N_GetFragmentText(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getFragmentHtml() { + try { + return N_GetFragmentHtml(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getFragmentBaseURL() { + try { + return N_GetFragmentBaseURL(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public int getFileContents(OutputStream writer) { + try { + return N_GetFileContents(N_CefHandle, writer); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public String getFileName() { + try { + return N_GetFileName(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public boolean getFileNames(Vector names) { + try { + return N_GetFileNames(N_CefHandle, names); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + 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); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void setLinkTitle(String title) { + try { + N_SetLinkTitle(N_CefHandle, title); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void setLinkMetadata(String data) { + try { + N_SetLinkMetadata(N_CefHandle, data); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void setFragmentText(String text) { + try { + N_SetFragmentText(N_CefHandle, text); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void setFragmentHtml(String html) { + try { + N_SetFragmentHtml(N_CefHandle, html); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void setFragmentBaseURL(String baseUrl) { + try { + N_SetFragmentBaseURL(N_CefHandle, baseUrl); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void resetFileContents() { + try { + N_ResetFileContents(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public void addFile(String path, String displayName) { + try { + N_AddFile(N_CefHandle, path, displayName); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native static CefDragData_N N_Create(); + private final native CefDragData_N N_Clone(long self); + private final native void N_Dispose(long self); + private final native boolean N_IsReadOnly(long self); + private final native boolean N_IsLink(long self); + private final native boolean N_IsFragment(long self); + private final native boolean N_IsFile(long self); + private final native String N_GetLinkURL(long self); + private final native String N_GetLinkTitle(long self); + private final native String N_GetLinkMetadata(long self); + private final native String N_GetFragmentText(long self); + private final native String N_GetFragmentHtml(long self); + private final native String N_GetFragmentBaseURL(long self); + 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); + private final native void N_SetFragmentText(long self, String text); + private final native void N_SetFragmentHtml(long self, String html); + private final native void N_SetFragmentBaseURL(long self, String baseUrl); + private final native void N_ResetFileContents(long self); + private final native void N_AddFile(long self, String path, String displayName); + + @Override + public String toString() { + Vector names = new Vector<>(); + getFileNames(names); + String fileNamesStr = "{"; + for (String s : names) fileNamesStr += s + ","; + fileNamesStr += "}"; + + return "CefDragData_N [isLink()=" + isLink() + ", isFragment()=" + isFragment() + + ", isFile()=" + isFile() + ", getLinkURL()=" + getLinkURL() + + ", getLinkTitle()=" + getLinkTitle() + ", getLinkMetadata()=" + getLinkMetadata() + + ", getFragmentText()=" + getFragmentText() + ", getFragmentHtml()=" + + getFragmentHtml() + ", getFragmentBaseURL()=" + getFragmentBaseURL() + + ", getFileName()=" + getFileName() + ", getFileNames(vector)=" + fileNamesStr + + "]"; + } +} diff --git a/lib/jcef/java/org/cef/callback/CefFileDialogCallback.java b/lib/jcef/java/org/cef/callback/CefFileDialogCallback.java new file mode 100644 index 0000000..edc06c3 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefFileDialogCallback.java @@ -0,0 +1,26 @@ +// 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 org.cef.callback; + +import java.util.Vector; + +/** + * Callback interface for asynchronous continuation of file dialog requests. + */ +public interface CefFileDialogCallback { + /** + * Continue the file selection with the specified file_paths. This may be + * a single value or a list of values depending on the dialog mode. An empty + * value is treated the same as calling Cancel(). + * + * @param filePaths list of selected file paths or an empty list. + */ + public void Continue(Vector filePaths); + + /** + * Cancel the file selection. + */ + public void Cancel(); +} diff --git a/lib/jcef/java/org/cef/callback/CefFileDialogCallback_N.java b/lib/jcef/java/org/cef/callback/CefFileDialogCallback_N.java new file mode 100644 index 0000000..770ed97 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefFileDialogCallback_N.java @@ -0,0 +1,38 @@ +// 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 org.cef.callback; + +import java.util.Vector; + +class CefFileDialogCallback_N extends CefNativeAdapter implements CefFileDialogCallback { + CefFileDialogCallback_N() {} + + @Override + protected void finalize() throws Throwable { + Cancel(); + super.finalize(); + } + + @Override + public void Continue(Vector filePaths) { + try { + N_Continue(getNativeRef(null), filePaths); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void Cancel() { + try { + N_Cancel(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Continue(long self, Vector filePaths); + private final native void N_Cancel(long self); +} diff --git a/lib/jcef/java/org/cef/callback/CefJSDialogCallback.java b/lib/jcef/java/org/cef/callback/CefJSDialogCallback.java new file mode 100644 index 0000000..bb30a6a --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefJSDialogCallback.java @@ -0,0 +1,19 @@ +// 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 org.cef.callback; + +/** + * Callback interface used for asynchronous continuation of JavaScript dialog + * requests. + */ +public interface CefJSDialogCallback { + /** + * Continue the JS dialog request. + * + * @param success Set to true if the OK button was pressed. + * @param user_input The value should be specified for prompt dialogs. + */ + public void Continue(boolean success, String user_input); +} diff --git a/lib/jcef/java/org/cef/callback/CefJSDialogCallback_N.java b/lib/jcef/java/org/cef/callback/CefJSDialogCallback_N.java new file mode 100644 index 0000000..6256d3d --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefJSDialogCallback_N.java @@ -0,0 +1,26 @@ +// 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 org.cef.callback; + +class CefJSDialogCallback_N extends CefNativeAdapter implements CefJSDialogCallback { + CefJSDialogCallback_N() {} + + @Override + protected void finalize() throws Throwable { + Continue(false, ""); + super.finalize(); + } + + @Override + public void Continue(boolean success, String user_input) { + try { + N_Continue(getNativeRef(null), success, user_input); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Continue(long self, boolean success, String user_input); +} diff --git a/lib/jcef/java/org/cef/callback/CefMenuModel.java b/lib/jcef/java/org/cef/callback/CefMenuModel.java new file mode 100644 index 0000000..e783709 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefMenuModel.java @@ -0,0 +1,338 @@ +// 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 org.cef.callback; + +import org.cef.misc.BoolRef; +import org.cef.misc.IntRef; + +/** + * Supports creation and modification of menus. See cef_menu_id_t for the + * command ids that have default implementations. All user-defined command ids + * should be between MENU_ID_USER_FIRST and MENU_ID_USER_LAST. The methods of + * this class can only be accessed on the browser process the UI thread. + */ +public interface CefMenuModel { + public static final class MenuId { + public static final int MENU_ID_BACK = 100; + public static final int MENU_ID_FORWARD = 101; + public static final int MENU_ID_RELOAD = 102; + public static final int MENU_ID_RELOAD_NOCACHE = 103; + public static final int MENU_ID_STOPLOAD = 104; + + // Editing. + public static final int MENU_ID_UNDO = 110; + public static final int MENU_ID_REDO = 111; + public static final int MENU_ID_CUT = 112; + public static final int MENU_ID_COPY = 113; + public static final int MENU_ID_PASTE = 114; + public static final int MENU_ID_DELETE = 115; + public static final int MENU_ID_SELECT_ALL = 116; + + // Miscellaneous. + public static final int MENU_ID_FIND = 130; + public static final int MENU_ID_PRINT = 131; + public static final int MENU_ID_VIEW_SOURCE = 132; + + // Spell checking word correction suggestions. + public static final int MENU_ID_SPELLCHECK_SUGGESTION_0 = 200; + public static final int MENU_ID_SPELLCHECK_SUGGESTION_1 = 201; + public static final int MENU_ID_SPELLCHECK_SUGGESTION_2 = 202; + public static final int MENU_ID_SPELLCHECK_SUGGESTION_3 = 203; + public static final int MENU_ID_SPELLCHECK_SUGGESTION_4 = 204; + public static final int MENU_ID_SPELLCHECK_SUGGESTION_LAST = 204; + public static final int MENU_ID_NO_SPELLING_SUGGESTIONS = 205; + + // All user-defined menu IDs should come between MENU_ID_USER_FIRST and + // MENU_ID_USER_LAST to avoid overlapping the Chromium and CEF ID ranges + // defined in the tools/gritsettings/resource_ids file. + public static final int MENU_ID_USER_FIRST = 26500; + public static final int MENU_ID_USER_LAST = 28500; + } + + /** + * Supported menu item types. + */ + public enum MenuItemType { + MENUITEMTYPE_NONE, + MENUITEMTYPE_COMMAND, + MENUITEMTYPE_CHECK, + MENUITEMTYPE_RADIO, + MENUITEMTYPE_SEPARATOR, + MENUITEMTYPE_SUBMENU, + } + + /** + * Clears the menu. Returns true on success. + */ + boolean clear(); + + /** + * Returns the number of items in this menu. + */ + int getCount(); + + /** + * Add a separator to the menu. Returns true on success. + */ + boolean addSeparator(); + + /** + * Add an item to the menu. Returns true on success. + */ + boolean addItem(int command_id, String label); + + /** + * Add a check item to the menu. Returns true on success. + */ + boolean addCheckItem(int command_id, String label); + + /** + * Add a radio item to the menu. Only a single item with the specified + * |group_id| can be checked at a time. Returns true on success. + */ + boolean addRadioItem(int command_id, String label, int group_id); + + /** + * Add a sub-menu to the menu. The new sub-menu is returned. + */ + CefMenuModel addSubMenu(int command_id, String label); + + /** + * Insert a separator in the menu at the specified |index|. Returns true on + * success. + */ + boolean insertSeparatorAt(int index); + + /** + * Insert an item in the menu at the specified |index|. Returns true on + * success. + */ + boolean insertItemAt(int index, int command_id, String label); + + /** + * Insert a check item in the menu at the specified |index|. Returns true on + * success. + */ + boolean insertCheckItemAt(int index, int command_id, String label); + + /** + * Insert a radio item in the menu at the specified |index|. Only a single + * item with the specified |group_id| can be checked at a time. Returns true + * on success. + */ + boolean insertRadioItemAt(int index, int command_id, String label, int group_id); + + /** + * Insert a sub-menu in the menu at the specified |index|. The new sub-menu + * is returned. + */ + CefMenuModel insertSubMenuAt(int index, int command_id, String label); + + /** + * Removes the item with the specified |command_id|. Returns true on success. + */ + boolean remove(int command_id); + + /** + * Removes the item at the specified |index|. Returns true on success. + */ + boolean removeAt(int index); + + /** + * Returns the index associated with the specified |command_id| or -1 if not + * found due to the command id not existing in the menu. + */ + int getIndexOf(int command_id); + + /** + * Returns the command id at the specified |index| or -1 if not found due to + * invalid range or the index being a separator. + */ + int getCommandIdAt(int index); + + /** + * Sets the command id at the specified |index|. Returns true on success. + */ + boolean setCommandIdAt(int index, int command_id); + + /** + * Returns the label for the specified |command_id| or empty if not found. + */ + String getLabel(int command_id); + + /** + * Returns the label at the specified |index| or empty if not found due to + * invalid range or the index being a separator. + */ + String getLabelAt(int index); + + /** + * Sets the label for the specified |command_id|. Returns true on success. + */ + boolean setLabel(int command_id, String label); + + /** + * Set the label at the specified |index|. Returns true on success. + */ + boolean setLabelAt(int index, String label); + + /** + * Returns the item type for the specified |command_id|. + */ + MenuItemType getType(int command_id); + + /** + * Returns the item type at the specified |index|. + */ + MenuItemType getTypeAt(int index); + + /** + * Returns the group id for the specified |command_id| or -1 if invalid. + */ + int getGroupId(int command_id); + + /** + * Returns the group id at the specified |index| or -1 if invalid. + */ + int getGroupIdAt(int index); + + /** + * Sets the group id for the specified |command_id|. Returns true on success. + */ + boolean setGroupId(int command_id, int group_id); + + /** + * Sets the group id at the specified |index|. Returns true on success. + */ + boolean setGroupIdAt(int index, int group_id); + + /** + * Returns the submenu for the specified |command_id| or empty if invalid. + */ + CefMenuModel getSubMenu(int command_id); + + /** + * Returns the submenu at the specified |index| or empty if invalid. + */ + CefMenuModel getSubMenuAt(int index); + + /** + * Returns true if the specified |command_id| is visible. + */ + boolean isVisible(int command_id); + + /** + * Returns true if the specified |index| is visible. + */ + boolean isVisibleAt(int index); + + /** + * Change the visibility of the specified |command_id|. Returns true on + * success. + */ + boolean setVisible(int command_id, boolean visible); + + /** + * Change the visibility at the specified |index|. Returns true on success. + */ + boolean setVisibleAt(int index, boolean visible); + + /** + * Returns true if the specified |command_id| is enabled. + */ + boolean isEnabled(int command_id); + + /** + * Returns true if the specified |index| is enabled. + */ + boolean isEnabledAt(int index); + + /** + * Change the enabled status of the specified |command_id|. Returns true on + * success. + */ + boolean setEnabled(int command_id, boolean enabled); + + /** + * Change the enabled status at the specified |index|. Returns true on + * success. + */ + boolean setEnabledAt(int index, boolean enabled); + + /** + * Returns true if the specified |command_id| is checked. Only applies to + * check and radio items. + */ + boolean isChecked(int command_id); + + /** + * Returns true if the specified |index| is checked. Only applies to check + * and radio items. + */ + boolean isCheckedAt(int index); + + /** + * Check the specified |command_id|. Only applies to check and radio items. + * Returns true on success. + */ + boolean setChecked(int command_id, boolean checked); + + /** + * Check the specified |index|. Only applies to check and radio items. Returns + * true on success. + */ + boolean setCheckedAt(int index, boolean checked); + + /** + * Returns true if the specified |command_id| has a keyboard accelerator + * assigned. + */ + boolean hasAccelerator(int command_id); + + /** + * Returns true if the specified |index| has a keyboard accelerator assigned. + */ + boolean hasAcceleratorAt(int index); + + /** + * Set the keyboard accelerator for the specified |command_id|. |key_code| can + * be any key or character value. Returns true on success. + */ + boolean setAccelerator(int command_id, int key_code, boolean shift_pressed, + boolean ctrl_pressed, boolean alt_pressed); + + /** + * Set the keyboard accelerator at the specified |index|. |key_code| can be + * any key or character value. Returns true on success. + */ + boolean setAcceleratorAt(int index, int key_code, boolean shift_pressed, boolean ctrl_pressed, + boolean alt_pressed); + + /** + * Remove the keyboard accelerator for the specified |command_id|. Returns + * true on success. + */ + boolean removeAccelerator(int command_id); + + /** + * Remove the keyboard accelerator at the specified |index|. Returns true on + * success. + */ + boolean removeAcceleratorAt(int index); + + /** + * Retrieves the keyboard accelerator for the specified |command_id|. Returns + * true on success. + */ + boolean getAccelerator(int command_id, IntRef key_code, BoolRef shift_pressed, + BoolRef ctrl_pressed, BoolRef alt_pressed); + + /** + * Retrieves the keyboard accelerator for the specified |index|. Returns true + * on success. + */ + boolean getAcceleratorAt(int index, IntRef key_code, BoolRef shift_pressed, + BoolRef ctrl_pressed, BoolRef alt_pressed); +} diff --git a/lib/jcef/java/org/cef/callback/CefMenuModel_N.java b/lib/jcef/java/org/cef/callback/CefMenuModel_N.java new file mode 100644 index 0000000..89db5c3 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefMenuModel_N.java @@ -0,0 +1,568 @@ +// 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 org.cef.callback; + +import org.cef.misc.BoolRef; +import org.cef.misc.IntRef; + +class CefMenuModel_N extends CefNativeAdapter implements CefMenuModel { + public CefMenuModel_N() {} + + @Override + public boolean clear() { + try { + return N_Clear(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public int getCount() { + try { + return N_GetCount(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public boolean addSeparator() { + try { + return N_AddSeparator(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean addItem(int command_id, String label) { + try { + return N_AddItem(getNativeRef(null), command_id, label); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean addCheckItem(int command_id, String label) { + try { + return N_AddCheckItem(getNativeRef(null), command_id, label); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean addRadioItem(int command_id, String label, int group_id) { + try { + return N_AddRadioItem(getNativeRef(null), command_id, label, group_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public CefMenuModel addSubMenu(int command_id, String label) { + try { + return N_AddSubMenu(getNativeRef(null), command_id, label); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public boolean insertSeparatorAt(int index) { + try { + return N_InsertSeparatorAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean insertItemAt(int index, int command_id, String label) { + try { + return N_InsertItemAt(getNativeRef(null), index, command_id, label); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean insertCheckItemAt(int index, int command_id, String label) { + try { + return N_InsertCheckItemAt(getNativeRef(null), index, command_id, label); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean insertRadioItemAt(int index, int command_id, String label, int group_id) { + try { + return N_InsertRadioItemAt(getNativeRef(null), index, command_id, label, group_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public CefMenuModel insertSubMenuAt(int index, int command_id, String label) { + try { + return N_InsertSubMenuAt(getNativeRef(null), index, command_id, label); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public boolean remove(int command_id) { + try { + return N_Remove(getNativeRef(null), command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean removeAt(int index) { + try { + return N_RemoveAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public int getIndexOf(int command_id) { + try { + return N_GetIndexOf(getNativeRef(null), command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public int getCommandIdAt(int index) { + try { + return N_GetCommandIdAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public boolean setCommandIdAt(int index, int command_id) { + try { + return N_SetCommandIdAt(getNativeRef(null), index, command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public String getLabel(int command_id) { + try { + return N_GetLabel(getNativeRef(null), command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getLabelAt(int index) { + try { + return N_GetLabelAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public boolean setLabel(int command_id, String label) { + try { + return N_SetLabel(getNativeRef(null), command_id, label); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean setLabelAt(int index, String label) { + try { + return N_SetLabelAt(getNativeRef(null), index, label); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public MenuItemType getType(int command_id) { + try { + return N_GetType(getNativeRef(null), command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public MenuItemType getTypeAt(int index) { + try { + return N_GetTypeAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public int getGroupId(int command_id) { + try { + return N_GetGroupId(getNativeRef(null), command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public int getGroupIdAt(int index) { + try { + return N_GetGroupIdAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public boolean setGroupId(int command_id, int group_id) { + try { + return N_SetGroupId(getNativeRef(null), command_id, group_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean setGroupIdAt(int index, int group_id) { + try { + return N_SetGroupIdAt(getNativeRef(null), index, group_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public CefMenuModel getSubMenu(int command_id) { + try { + return N_GetSubMenu(getNativeRef(null), command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public CefMenuModel getSubMenuAt(int index) { + try { + return N_GetSubMenuAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public boolean isVisible(int command_id) { + try { + return N_IsVisible(getNativeRef(null), command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isVisibleAt(int index) { + try { + return N_IsVisibleAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean setVisible(int command_id, boolean visible) { + try { + return N_SetVisible(getNativeRef(null), command_id, visible); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean setVisibleAt(int index, boolean visible) { + try { + return N_SetVisibleAt(getNativeRef(null), index, visible); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isEnabled(int command_id) { + try { + return N_IsEnabled(getNativeRef(null), command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isEnabledAt(int index) { + try { + return N_IsEnabledAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean setEnabled(int command_id, boolean enabled) { + try { + return N_SetEnabled(getNativeRef(null), command_id, enabled); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean setEnabledAt(int index, boolean enabled) { + try { + return N_SetEnabledAt(getNativeRef(null), index, enabled); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isChecked(int command_id) { + try { + return N_IsChecked(getNativeRef(null), command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isCheckedAt(int index) { + try { + return N_IsCheckedAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean setChecked(int command_id, boolean checked) { + try { + return N_SetChecked(getNativeRef(null), command_id, checked); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean setCheckedAt(int index, boolean checked) { + try { + return N_SetCheckedAt(getNativeRef(null), index, checked); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean hasAccelerator(int command_id) { + try { + return N_HasAccelerator(getNativeRef(null), command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean hasAcceleratorAt(int index) { + try { + return N_HasAcceleratorAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean setAccelerator(int command_id, int key_code, boolean shift_pressed, + boolean ctrl_pressed, boolean alt_pressed) { + try { + return N_SetAccelerator(getNativeRef(null), command_id, key_code, shift_pressed, + ctrl_pressed, alt_pressed); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean setAcceleratorAt(int index, int key_code, boolean shift_pressed, + boolean ctrl_pressed, boolean alt_pressed) { + try { + return N_SetAcceleratorAt( + getNativeRef(null), index, key_code, shift_pressed, ctrl_pressed, alt_pressed); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean removeAccelerator(int command_id) { + try { + return N_RemoveAccelerator(getNativeRef(null), command_id); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean removeAcceleratorAt(int index) { + try { + return N_RemoveAcceleratorAt(getNativeRef(null), index); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean getAccelerator(int command_id, IntRef key_code, BoolRef shift_pressed, + BoolRef ctrl_pressed, BoolRef alt_pressed) { + try { + return N_GetAccelerator(getNativeRef(null), command_id, key_code, shift_pressed, + ctrl_pressed, alt_pressed); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean getAcceleratorAt(int index, IntRef key_code, BoolRef shift_pressed, + BoolRef ctrl_pressed, BoolRef alt_pressed) { + try { + return N_GetAcceleratorAt( + getNativeRef(null), index, key_code, shift_pressed, ctrl_pressed, alt_pressed); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + private final native boolean N_Clear(long self); + private final native int N_GetCount(long self); + private final native boolean N_AddSeparator(long self); + private final native boolean N_AddItem(long self, int command_id, String label); + private final native boolean N_AddCheckItem(long self, int command_id, String label); + private final native boolean N_AddRadioItem( + long self, int command_id, String label, int group_id); + private final native CefMenuModel N_AddSubMenu(long self, int command_id, String label); + private final native boolean N_InsertSeparatorAt(long self, int index); + private final native boolean N_InsertItemAt(long self, int index, int command_id, String label); + private final native boolean N_InsertCheckItemAt( + long self, int index, int command_id, String label); + private final native boolean N_InsertRadioItemAt( + long self, int index, int command_id, String label, int group_id); + private final native CefMenuModel N_InsertSubMenuAt( + long self, int index, int command_id, String label); + private final native boolean N_Remove(long self, int command_id); + private final native boolean N_RemoveAt(long self, int index); + private final native int N_GetIndexOf(long self, int command_id); + private final native int N_GetCommandIdAt(long self, int index); + private final native boolean N_SetCommandIdAt(long self, int index, int command_id); + private final native String N_GetLabel(long self, int command_id); + private final native String N_GetLabelAt(long self, int index); + private final native boolean N_SetLabel(long self, int command_id, String label); + private final native boolean N_SetLabelAt(long self, int index, String label); + private final native MenuItemType N_GetType(long self, int command_id); + private final native MenuItemType N_GetTypeAt(long self, int index); + private final native int N_GetGroupId(long self, int command_id); + private final native int N_GetGroupIdAt(long self, int index); + private final native boolean N_SetGroupId(long self, int command_id, int group_id); + private final native boolean N_SetGroupIdAt(long self, int index, int group_id); + private final native CefMenuModel N_GetSubMenu(long self, int command_id); + private final native CefMenuModel N_GetSubMenuAt(long self, int index); + private final native boolean N_IsVisible(long self, int command_id); + private final native boolean N_IsVisibleAt(long self, int index); + private final native boolean N_SetVisible(long self, int command_id, boolean visible); + private final native boolean N_SetVisibleAt(long self, int index, boolean visible); + private final native boolean N_IsEnabled(long self, int command_id); + private final native boolean N_IsEnabledAt(long self, int index); + private final native boolean N_SetEnabled(long self, int command_id, boolean enabled); + private final native boolean N_SetEnabledAt(long self, int index, boolean enabled); + private final native boolean N_IsChecked(long self, int command_id); + private final native boolean N_IsCheckedAt(long self, int index); + private final native boolean N_SetChecked(long self, int command_id, boolean checked); + private final native boolean N_SetCheckedAt(long self, int index, boolean checked); + private final native boolean N_HasAccelerator(long self, int command_id); + private final native boolean N_HasAcceleratorAt(long self, int index); + private final native boolean N_SetAccelerator(long self, int command_id, int key_code, + boolean shift_pressed, boolean ctrl_pressed, boolean alt_pressed); + private final native boolean N_SetAcceleratorAt(long self, int index, int key_code, + boolean shift_pressed, boolean ctrl_pressed, boolean alt_pressed); + private final native boolean N_RemoveAccelerator(long self, int command_id); + private final native boolean N_RemoveAcceleratorAt(long self, int index); + private final native boolean N_GetAccelerator(long self, int command_id, IntRef key_code, + BoolRef shift_pressed, BoolRef ctrl_pressed, BoolRef alt_pressed); + private final native boolean N_GetAcceleratorAt(long self, int index, IntRef key_code, + BoolRef shift_pressed, BoolRef ctrl_pressed, BoolRef alt_pressed); +} diff --git a/lib/jcef/java/org/cef/callback/CefNative.java b/lib/jcef/java/org/cef/callback/CefNative.java new file mode 100644 index 0000000..d72d88b --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefNative.java @@ -0,0 +1,29 @@ +// 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 org.cef.callback; + +/** + * The methods of this interface are triggered by the native code + * to store and get the JNI counterparts of the JCEF implementation. + */ +public interface CefNative { + /** + * Method is called by the native code to store a reference + * to an implemented native JNI counterpart. + * + * @param identifer The name of the interface class (e.g. CefFocusHandler). + * @param nativeRef The reference to the native code. + */ + public void setNativeRef(String identifer, long nativeRef); + + /** + * Method is called by the native code to get the reference + * to an previous stored identifier. + * + * @param identifer The name of the interface class (e.g. CefFocusHandler). + * @return The stored reference value of the native code. + */ + public long getNativeRef(String identifer); +} diff --git a/lib/jcef/java/org/cef/callback/CefNativeAdapter.java b/lib/jcef/java/org/cef/callback/CefNativeAdapter.java new file mode 100644 index 0000000..aa227e2 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefNativeAdapter.java @@ -0,0 +1,16 @@ +package org.cef.callback; + +public class CefNativeAdapter implements CefNative { + // Used internally to store a pointer to the CEF object. + private long N_CefHandle = 0; + + @Override + public void setNativeRef(String identifer, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return N_CefHandle; + } +} diff --git a/lib/jcef/java/org/cef/callback/CefPdfPrintCallback.java b/lib/jcef/java/org/cef/callback/CefPdfPrintCallback.java new file mode 100644 index 0000000..cd48404 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefPdfPrintCallback.java @@ -0,0 +1,20 @@ +// Copyright (c) 2017 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 for CefBrowser.PrintToPDF(). The methods of this class + * 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 + * successfully or false otherwise. + * @param path The path of the PDF file that was written. + * @param ok True if printing completed or false otherwise. + */ + public abstract void onPdfPrintFinished(String path, boolean ok); +} diff --git a/lib/jcef/java/org/cef/callback/CefPrintDialogCallback.java b/lib/jcef/java/org/cef/callback/CefPrintDialogCallback.java new file mode 100644 index 0000000..88e5c6a --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefPrintDialogCallback.java @@ -0,0 +1,22 @@ +// 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 org.cef.callback; + +import org.cef.misc.CefPrintSettings; + +/** + * Callback interface for asynchronous continuation of print dialog requests. + */ +public interface CefPrintDialogCallback { + /** + * Continue printing with the specified |settings|. + */ + void Continue(CefPrintSettings settings); + + /** + * Cancel the printing. + */ + void cancel(); +} diff --git a/lib/jcef/java/org/cef/callback/CefPrintDialogCallback_N.java b/lib/jcef/java/org/cef/callback/CefPrintDialogCallback_N.java new file mode 100644 index 0000000..8883906 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefPrintDialogCallback_N.java @@ -0,0 +1,38 @@ +// 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 org.cef.callback; + +import org.cef.misc.CefPrintSettings; + +class CefPrintDialogCallback_N extends CefNativeAdapter implements CefPrintDialogCallback { + CefPrintDialogCallback_N() {} + + @Override + protected void finalize() throws Throwable { + cancel(); + super.finalize(); + } + + @Override + public void Continue(CefPrintSettings settings) { + try { + N_Continue(getNativeRef(null), settings); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void cancel() { + try { + N_Cancel(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Continue(long self, CefPrintSettings settings); + private final native void N_Cancel(long self); +} diff --git a/lib/jcef/java/org/cef/callback/CefPrintJobCallback.java b/lib/jcef/java/org/cef/callback/CefPrintJobCallback.java new file mode 100644 index 0000000..f042537 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefPrintJobCallback.java @@ -0,0 +1,15 @@ +// 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 org.cef.callback; + +/** + * Callback interface for asynchronous continuation of print job requests. + */ +public interface CefPrintJobCallback { + /** + * Indicate completion of the print job. + */ + void Continue(); +} diff --git a/lib/jcef/java/org/cef/callback/CefPrintJobCallback_N.java b/lib/jcef/java/org/cef/callback/CefPrintJobCallback_N.java new file mode 100644 index 0000000..18e319c --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefPrintJobCallback_N.java @@ -0,0 +1,26 @@ +// 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 org.cef.callback; + +class CefPrintJobCallback_N extends CefNativeAdapter implements CefPrintJobCallback { + CefPrintJobCallback_N() {} + + @Override + protected void finalize() throws Throwable { + Continue(); + super.finalize(); + } + + @Override + public void Continue() { + try { + N_Continue(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Continue(long self); +} diff --git a/lib/jcef/java/org/cef/callback/CefQueryCallback.java b/lib/jcef/java/org/cef/callback/CefQueryCallback.java new file mode 100644 index 0000000..0972bf2 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefQueryCallback.java @@ -0,0 +1,25 @@ +// 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 org.cef.callback; + +/** + * Interface representing a query callback. + */ +public interface CefQueryCallback { + /** + * Notify the associated JavaScript onSuccess callback that the query has + * completed successfully. + * @param response Response passed to JavaScript. + */ + public void success(String response); + + /** + * Notify the associated JavaScript onFailure callback that the query has + * failed. + * @param error_code Error code passed to JavaScript. + * @param error_message Error message passed to JavaScript. + */ + public void failure(int error_code, String error_message); +} diff --git a/lib/jcef/java/org/cef/callback/CefQueryCallback_N.java b/lib/jcef/java/org/cef/callback/CefQueryCallback_N.java new file mode 100644 index 0000000..14b32e3 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefQueryCallback_N.java @@ -0,0 +1,36 @@ +// 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 org.cef.callback; + +class CefQueryCallback_N extends CefNativeAdapter implements CefQueryCallback { + CefQueryCallback_N() {} + + @Override + protected void finalize() throws Throwable { + failure(-1, "Unexpected call to CefQueryCallback_N::finalize()"); + super.finalize(); + } + + @Override + public void success(String response) { + try { + N_Success(getNativeRef(null), response); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void failure(int error_code, String error_message) { + try { + N_Failure(getNativeRef(null), error_code, error_message); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Success(long self, String response); + private final native void N_Failure(long self, int error_code, String error_message); +} diff --git a/lib/jcef/java/org/cef/callback/CefResourceReadCallback.java b/lib/jcef/java/org/cef/callback/CefResourceReadCallback.java new file mode 100644 index 0000000..01e2343 --- /dev/null +++ b/lib/jcef/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(); +} diff --git a/lib/jcef/java/org/cef/callback/CefResourceReadCallback_N.java b/lib/jcef/java/org/cef/callback/CefResourceReadCallback_N.java new file mode 100644 index 0000000..f00c69d --- /dev/null +++ b/lib/jcef/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); +} diff --git a/lib/jcef/java/org/cef/callback/CefResourceSkipCallback.java b/lib/jcef/java/org/cef/callback/CefResourceSkipCallback.java new file mode 100644 index 0000000..75022ce --- /dev/null +++ b/lib/jcef/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); +} diff --git a/lib/jcef/java/org/cef/callback/CefResourceSkipCallback_N.java b/lib/jcef/java/org/cef/callback/CefResourceSkipCallback_N.java new file mode 100644 index 0000000..eae840e --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefResourceSkipCallback_N.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; + +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); +} diff --git a/lib/jcef/java/org/cef/callback/CefRunFileDialogCallback.java b/lib/jcef/java/org/cef/callback/CefRunFileDialogCallback.java new file mode 100644 index 0000000..9d7381a --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefRunFileDialogCallback.java @@ -0,0 +1,25 @@ +// 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 org.cef.callback; + +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. + */ +public interface CefRunFileDialogCallback { + /** + * Called asynchronously after the file dialog is dismissed. If the selection + * was successful filePaths will be a single value or a list of values + * depending on the dialog mode. If the selection was cancelled filePaths + * will be empty. + * + * @param filePaths list of file paths or empty list. + */ + void onFileDialogDismissed(Vector filePaths); +} diff --git a/lib/jcef/java/org/cef/callback/CefSchemeHandlerFactory.java b/lib/jcef/java/org/cef/callback/CefSchemeHandlerFactory.java new file mode 100644 index 0000000..bb2546a --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefSchemeHandlerFactory.java @@ -0,0 +1,32 @@ +// 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 org.cef.callback; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.handler.CefResourceHandler; +import org.cef.network.CefRequest; + +/** + * Class that creates CefResourceHandler instances for handling scheme requests. + * The methods of this class will always be called on the IO thread. + */ +public interface CefSchemeHandlerFactory { + /** + * Return a new resource handler instance to handle the request or NULL to allow default + * handling of the request. + * + * @param browser The corresponding browser, or NULL if the request did not originate from a + * browser window (for example, if the request came from CefURLRequest). + * @param frame The frame generating the event, or NULL if the request did not originate from a + * browser window (for example, if the request came from CefURLRequest). Instance only + * valid within the scope of this method. + * @param schemeName Name of the scheme being created. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + */ + public CefResourceHandler create( + CefBrowser browser, CefFrame frame, String schemeName, CefRequest request); +} diff --git a/lib/jcef/java/org/cef/callback/CefSchemeRegistrar.java b/lib/jcef/java/org/cef/callback/CefSchemeRegistrar.java new file mode 100644 index 0000000..f59263c --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefSchemeRegistrar.java @@ -0,0 +1,75 @@ +// 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 org.cef.callback; + +/** + * Class that manages custom scheme registrations. + */ +public interface CefSchemeRegistrar { + /** + * Register a custom scheme. This method should not be called for the built-in + * HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes. + * + * If |isStandard| is true the scheme will be treated as a standard scheme. + * Standard schemes are subject to URL canonicalization and parsing rules as + * defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1 available + * at http://www.ietf.org/rfc/rfc1738.txt + * + * In particular, the syntax for standard scheme URLs must be of the form: + *

+     *  [scheme]://[username]:[password]@[host]:[port]/[url-path]
+     * 
+ * Standard scheme URLs must have a host component that is a fully qualified + * domain name as defined in Section 3.5 of RFC 1034 [13] and Section 2.1 of + * RFC 1123. These URLs will be canonicalized to "scheme://host/path" in the + * simplest case and "scheme://username:password@host:port/path" in the most + * explicit case. For example, "scheme:host/path" and "scheme:///host/path" + * will both be canonicalized to "scheme://host/path". The origin of a + * standard scheme URL is the combination of scheme, host and port (i.e., + * "scheme://host:port" in the most explicit case). + * + * For non-standard scheme URLs only the "scheme:" component is parsed and + * canonicalized. The remainder of the URL will be passed to the handler + * as-is. For example, "scheme:///some%20text" will remain the same. + * Non-standard scheme URLs cannot be used as a target for form submission. + * + * If |isLocal| is true the scheme will be treated with the same security + * rules as those applied to "file" URLs. Normal pages cannot link to or + * access local URLs. Also, by default, local URLs can only perform + * XMLHttpRequest calls to the same URL (origin + path) that originated the + * request. To allow XMLHttpRequest calls from a local URL to other URLs with + * the same origin set the CefSettings.file_access_from_file_urls_allowed + * value to true. To allow XMLHttpRequest calls from a local URL to all + * origins set the CefSettings.universal_access_from_file_urls_allowed value + * to true. + * + * If |isDisplayIsolated| is true the scheme can only be displayed from + * other content hosted with the same scheme. For example, pages in other + * origins cannot create iframes or hyperlinks to URLs with the scheme. For + * schemes that must be accessible from other schemes set this value to false, + * set |is_cors_enabled| to true, and use CORS "Access-Control-Allow-Origin" + * headers to further restrict access. + * + * If |isSecure| is true the scheme will be treated with the same security + * rules as those applied to "https" URLs. For example, loading this scheme + * from other secure schemes will not trigger mixed content warnings. + * + * If |isCorsEnabled| is true the scheme that can be sent CORS requests. + * This value should be true in most cases where |isStandard| is true. + * + * 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 + * per unique |schemeName| value. If |schemeName| is already registered or + * if an error occurs this method will return false. + */ + public boolean addCustomScheme(String schemeName, boolean isStandard, boolean isLocal, + boolean isDisplayIsolated, boolean isSecure, boolean isCorsEnabled, + boolean isCspBypassing, boolean isFetchEnabled); +} diff --git a/lib/jcef/java/org/cef/callback/CefSchemeRegistrar_N.java b/lib/jcef/java/org/cef/callback/CefSchemeRegistrar_N.java new file mode 100644 index 0000000..a6f47b7 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefSchemeRegistrar_N.java @@ -0,0 +1,24 @@ +// 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 org.cef.callback; + +class CefSchemeRegistrar_N extends CefNativeAdapter implements CefSchemeRegistrar { + @Override + public boolean addCustomScheme(String schemeName, boolean isStandard, boolean isLocal, + boolean isDisplayIsolated, boolean isSecure, boolean isCorsEnabled, + boolean isCspBypassing, boolean isFetchEnabled) { + try { + return N_AddCustomScheme(schemeName, isStandard, isLocal, isDisplayIsolated, isSecure, + isCorsEnabled, isCspBypassing, isFetchEnabled); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + return false; + } + + private final native boolean N_AddCustomScheme(String schemeName, boolean isStandard, + boolean isLocal, boolean isDisplayIsolated, boolean isSecure, boolean isCorsEnabled, + boolean isCspBypassing, boolean isFetchEnabled); +} diff --git a/lib/jcef/java/org/cef/callback/CefStringVisitor.java b/lib/jcef/java/org/cef/callback/CefStringVisitor.java new file mode 100644 index 0000000..19ee8d7 --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefStringVisitor.java @@ -0,0 +1,16 @@ +// 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 org.cef.callback; + +/** + * Public interface to receive string values asynchronously. + */ +public interface CefStringVisitor { + /** + * Called when the string is available. + * @param string Requested string. + */ + void visit(String string); +} diff --git a/lib/jcef/java/org/cef/callback/CefURLRequestClient.java b/lib/jcef/java/org/cef/callback/CefURLRequestClient.java new file mode 100644 index 0000000..5417e8b --- /dev/null +++ b/lib/jcef/java/org/cef/callback/CefURLRequestClient.java @@ -0,0 +1,54 @@ +// 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 org.cef.callback; + +import org.cef.network.CefURLRequest; + +/** + * Interface that should be implemented by the CefURLRequest client. The + * methods of this class will be called on the same thread that created the + * request unless otherwise documented. + */ +public interface CefURLRequestClient extends CefNative { + /** + * Notifies the client that the request has completed. Use the + * CefURLRequest::GetRequestStatus method to determine if the request was + * successful or not. + */ + void onRequestComplete(CefURLRequest request); + + /** + * Notifies the client of upload progress. |current| denotes the number of + * bytes sent so far and |total| is the total size of uploading data (or -1 if + * chunked upload is enabled). This method will only be called if the + * UR_FLAG_REPORT_UPLOAD_PROGRESS flag is set on the request. + */ + void onUploadProgress(CefURLRequest request, int current, int total); + + /** + * Notifies the client of download progress. |current| denotes the number of + * bytes received up to the call and |total| is the expected total size of the + * response (or -1 if not determined). + */ + void onDownloadProgress(CefURLRequest request, int current, int total); + + /** + * Called when some part of the response is read. |data| contains the current + * bytes received since the last call. This method will not be called if the + * UR_FLAG_NO_DOWNLOAD_DATA flag is set on the request. + */ + void onDownloadData(CefURLRequest request, byte[] data, int data_length); + + /** + * Called on the IO thread when the browser needs credentials from the user. + * |isProxy| indicates whether the host is a proxy server. |host| contains the + * hostname and |port| contains the port number. Return true to continue the + * request and call CefAuthCallback::Continue() when the authentication + * information is available. Return false to cancel the request. This method + * will only be called for requests initiated from the browser process. + */ + boolean getAuthCredentials(boolean isProxy, String host, int port, String realm, String scheme, + CefAuthCallback callback); +} diff --git a/lib/jcef/java/org/cef/handler/CefAppHandler.java b/lib/jcef/java/org/cef/handler/CefAppHandler.java new file mode 100644 index 0000000..b6ede71 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefAppHandler.java @@ -0,0 +1,94 @@ +// 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 org.cef.handler; + +import org.cef.CefApp.CefAppState; +import org.cef.callback.CefCommandLine; +import org.cef.callback.CefSchemeRegistrar; + +/** + * Implement this interface to provide handler implementations. Methods will be + * called by the process and/or thread indicated. + */ +public interface CefAppHandler { + /** + * Provides an opportunity to view and/or modify command-line arguments before + * processing by CEF and Chromium. The |process_type| value will be empty for + * the browser process. Be cautious when using this method to modify + * command-line arguments for non-browser processes as this may result in + * undefined behavior including crashes. + * @param process_type type of process (empty for browser process). + * @param command_line values of the command line. + */ + public void onBeforeCommandLineProcessing(String process_type, CefCommandLine command_line); + + /** + * Provides an opportunity to hook into the native shutdown process. This + * method is invoked if the user tries to terminate the app by sending the + * corresponding key code (e.g. on Mac: CMD+Q) or something similar. If you + * want to proceed with the default behavior of the native system, return + * false. If you want to abort the terminate or if you want to implement your + * own shutdown sequence return true and do the cleanup on your own. + * @return false to proceed with the default behavior, true to abort + * terminate. + */ + public boolean onBeforeTerminate(); + + /** + * Implement this method to get state changes of the CefApp. + * See {@link CefAppState} for a complete list of possible states. + * + * For example, this method can be used e.g. to get informed if CefApp has + * completed its initialization or its shutdown process. + * + * @param state The current state of CefApp. + */ + public void stateHasChanged(CefAppState state); + + /** + * Provides an opportunity to register custom schemes. Do not keep a reference + * to the |registrar| object. This method is called on the main thread for + * each process and the registered schemes should be the same across all + * processes. + */ + public void onRegisterCustomSchemes(CefSchemeRegistrar registrar); + + // Inherited of CefBrowserProcessHandler + /** + * Called on the browser process UI thread immediately after the CEF context + * has been initialized. + */ + public void onContextInitialized(); + + /** + * Called from any thread when work has been scheduled for the browser process + * main (UI) thread. This callback should schedule a + * CefApp.DoMessageLoopWork() call to happen on the main (UI) thread. + * |delay_ms| is the requested delay in milliseconds. If |delay_ms| is <= 0 + * then the call should happen reasonably soon. If |delay_ms| is > 0 then the + * call should be scheduled to happen after the specified delay and any + * 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/lib/jcef/java/org/cef/handler/CefAppHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefAppHandlerAdapter.java new file mode 100644 index 0000000..9947b74 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefAppHandlerAdapter.java @@ -0,0 +1,101 @@ +// 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 org.cef.handler; + +import org.cef.CefApp; +import org.cef.CefApp.CefAppState; +import org.cef.callback.CefCommandLine; +import org.cef.callback.CefSchemeRegistrar; + +/** + * An abstract adapter class for managing app handler events. + * The methods in this class are using a default implementation. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefAppHandlerAdapter implements CefAppHandler { + private String[] args_; + + public CefAppHandlerAdapter(String[] args) { + args_ = args; + } + + @Override + public void onBeforeCommandLineProcessing(String process_type, CefCommandLine command_line) { + if (process_type.isEmpty() && args_ != null) { + // Forward switches and arguments from Java to Cef + boolean parseSwitchesDone = false; + for (String arg : args_) { + if (parseSwitchesDone || arg.length() < 2) { + command_line.appendArgument(arg); + continue; + } + // Arguments with '--', '-' and, on Windows, '/' prefixes are considered switches. + 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 + // tokens + if (arg.length() == 2) { + parseSwitchesDone = true; + continue; + } + // FALL THRU + case 1: { + // Switches can optionally have a value specified using the '=' delimiter + // (e.g. "-switch=value"). + 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(switchStr); + } + break; + } + case 0: + command_line.appendArgument(arg); + break; + } + } + } + } + + @Override + public boolean onBeforeTerminate() { + // The default implementation does nothing + return false; + } + + @Override + public void stateHasChanged(CefAppState state) { + // The default implementation does nothing + } + + @Override + public void onRegisterCustomSchemes(CefSchemeRegistrar registrar) { + // The default implementation does nothing + } + + @Override + public void onContextInitialized() { + // The default implementation does nothing + } + + @Override + 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/lib/jcef/java/org/cef/handler/CefClientHandler.java b/lib/jcef/java/org/cef/handler/CefClientHandler.java new file mode 100644 index 0000000..6a263a8 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefClientHandler.java @@ -0,0 +1,317 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefMessageRouter; +import org.cef.callback.CefNative; + +import java.util.HashMap; +import java.util.Vector; + +/** + * Implement this interface to provide handler implementations. + */ +public abstract class CefClientHandler implements CefNative { + // Used internally to store a pointer to the CEF object. + private HashMap N_CefHandle = new HashMap(); + private Vector msgRouters = new Vector<>(); + + @Override + public void setNativeRef(String identifer, long nativeRef) { + synchronized (N_CefHandle) { + N_CefHandle.put(identifer, nativeRef); + } + } + + @Override + public long getNativeRef(String identifer) { + synchronized (N_CefHandle) { + if (N_CefHandle.containsKey(identifer)) return N_CefHandle.get(identifer); + } + return 0; + } + + public CefClientHandler() { + try { + N_CefClientHandler_CTOR(); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void dispose() { + try { + // Call native DTOR if handler will be destroyed + for (int i = 0; i < msgRouters.size(); i++) { + msgRouters.get(i).dispose(); + } + msgRouters.clear(); + + N_CefClientHandler_DTOR(); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + /** + * Returns the java part of the browser implementation. + * @param identifer the unique identifier of the browser. + * @return The found browser or null if none is found. + */ + abstract protected CefBrowser getBrowser(int identifier); + + /** + * Returns a list of all browser instances. + * @return an array of browser Instances. + */ + abstract protected Object[] getAllBrowser(); + + /** + * Return the handler for context menus. If no handler is provided the + * default implementation will be used. + */ + abstract protected CefContextMenuHandler getContextMenuHandler(); + + /** + * Return the handler for dialogs. If no handler is provided the + * default implementation will be used. + */ + abstract protected CefDialogHandler getDialogHandler(); + + /** + * Return the handler for browser display state events. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefDisplayHandler getDisplayHandler(); + + /** + * Return the handler for download events. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefDownloadHandler getDownloadHandler(); + + /** + * Return the handler for drag events. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefDragHandler getDragHandler(); + + /** + * Return the handler for focus events. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefFocusHandler getFocusHandler(); + + /** + * Return the handler for javascript dialog requests. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefJSDialogHandler getJSDialogHandler(); + + /** + * Return the handler for keyboard events. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefKeyboardHandler getKeyboardHandler(); + + /** + * Return the handler for browser life span events. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefLifeSpanHandler getLifeSpanHandler(); + + /** + * Return the handler for browser load status events. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefLoadHandler getLoadHandler(); + + /** + * Return the handler for printing on Linux. If a print handler is not + * provided then printing will not be supported on the Linux platform. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefPrintHandler getPrintHandler(); + + /** + * Return the handler for off-screen rendering events. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefRenderHandler getRenderHandler(); + + /** + * Return the handler for browser request events. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefRequestHandler getRequestHandler(); + + /** + * Return the handler for windowed rendering events. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefWindowHandler getWindowHandler(); + + protected synchronized void addMessageRouter(CefMessageRouter h) { + try { + msgRouters.add(h); + N_addMessageRouter(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeContextMenuHandler(CefContextMenuHandler h) { + try { + N_removeContextMenuHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeDialogHandler(CefDialogHandler h) { + try { + N_removeDialogHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeDisplayHandler(CefDisplayHandler h) { + try { + N_removeDisplayHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeDownloadHandler(CefDisplayHandler h) { + try { + N_removeDownloadHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeDragHandler(CefDragHandler h) { + try { + N_removeDragHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeFocusHandler(CefFocusHandler h) { + try { + N_removeFocusHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeJSDialogHandler(CefJSDialogHandler h) { + try { + N_removeJSDialogHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeKeyboardHandler(CefKeyboardHandler h) { + try { + N_removeKeyboardHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeLifeSpanHandler(CefLifeSpanHandler h) { + try { + N_removeLifeSpanHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeLoadHandler(CefLoadHandler h) { + try { + N_removeLoadHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removePrintHandler(CefPrintHandler h) { + try { + N_removePrintHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected synchronized void removeMessageRouter(CefMessageRouter h) { + try { + msgRouters.remove(h); + N_removeMessageRouter(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeRenderHandler(CefRenderHandler h) { + try { + N_removeRenderHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeRequestHandler(CefRequestHandler h) { + try { + N_removeRequestHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + protected void removeWindowHandler(CefWindowHandler h) { + try { + N_removeWindowHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } + + private final native void N_CefClientHandler_CTOR(); + private final native void N_addMessageRouter(CefMessageRouter h); + private final native void N_removeContextMenuHandler(CefContextMenuHandler h); + private final native void N_removeDialogHandler(CefDialogHandler h); + private final native void N_removeDisplayHandler(CefDisplayHandler h); + private final native void N_removeDownloadHandler(CefDisplayHandler h); + private final native void N_removeDragHandler(CefDragHandler h); + private final native void N_removeFocusHandler(CefFocusHandler h); + private final native void N_removeJSDialogHandler(CefJSDialogHandler h); + private final native void N_removeKeyboardHandler(CefKeyboardHandler h); + private final native void N_removeLifeSpanHandler(CefLifeSpanHandler h); + private final native void N_removeLoadHandler(CefLoadHandler h); + private final native void N_removePrintHandler(CefPrintHandler h); + private final native void N_removeMessageRouter(CefMessageRouter h); + private final native void N_removeRenderHandler(CefRenderHandler h); + private final native void N_removeRequestHandler(CefRequestHandler h); + private final native void N_removeWindowHandler(CefWindowHandler h); + private final native void N_CefClientHandler_DTOR(); +} diff --git a/lib/jcef/java/org/cef/handler/CefContextMenuHandler.java b/lib/jcef/java/org/cef/handler/CefContextMenuHandler.java new file mode 100644 index 0000000..4860568 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefContextMenuHandler.java @@ -0,0 +1,59 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefContextMenuParams; +import org.cef.callback.CefMenuModel; + +/** + * Implement this interface to handle context menu events. The methods of this + * class will be called on the UI thread. + */ +public interface CefContextMenuHandler { + /** + * Called before a context menu is displayed. + * + * @param browser The browser generating the event. + * @param frame The frame generating the event. Instance only valid within the scope + * of this method. + * @param params Provides information about the context menu state. Instance + * only valid within the scope of this method. + * @param model Can be cleared to show no context menu or modified + * to show a custom menu. Instance only valid within the scope of this + * method. + */ + public void onBeforeContextMenu( + CefBrowser browser, CefFrame frame, CefContextMenuParams params, CefMenuModel model); + + /** + * Called to execute a command selected from the context menu. Return true if + * the command was handled or false for the default implementation. See + * cef_menu_id_t for the command ids that have default implementations. All + * user-defined command ids should be between MENU_ID_USER_FIRST and + * + * @param browser The browser generating the event. + * @param frame The frame generating the event. Instance only valid within the scope + * of this method. + * @param params Will have the same values that were passed to onBeforeContextMenu(). + * Instance only valid within the scope of this method. + * @param commandId The id of the command. + * @param eventFlags A combination of event flags defined in EventFlags + * @return true if the command was handled or false for the default implementation. + */ + public boolean onContextMenuCommand(CefBrowser browser, CefFrame frame, + CefContextMenuParams params, int commandId, int eventFlags); + + /** + * Called when the context menu is dismissed irregardless of whether the menu + * was empty or a command was selected. + * + * @param browser The browser generating the event. + * @param frame The corresponding frame. Instance only valid within the scope + * of this method. + */ + public void onContextMenuDismissed(CefBrowser browser, CefFrame frame); +} diff --git a/lib/jcef/java/org/cef/handler/CefContextMenuHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefContextMenuHandlerAdapter.java new file mode 100644 index 0000000..1b4557c --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefContextMenuHandlerAdapter.java @@ -0,0 +1,30 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefContextMenuParams; +import org.cef.callback.CefMenuModel; + +/** + * An abstract adapter class for receiving context menu events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefContextMenuHandlerAdapter implements CefContextMenuHandler { + @Override + public void onBeforeContextMenu( + CefBrowser browser, CefFrame frame, CefContextMenuParams params, CefMenuModel model) {} + + @Override + public boolean onContextMenuCommand(CefBrowser browser, CefFrame frame, + CefContextMenuParams params, int commandId, int eventFlags) { + return false; + } + + @Override + public void onContextMenuDismissed(CefBrowser browser, CefFrame frame) {} +} diff --git a/lib/jcef/java/org/cef/handler/CefCookieAccessFilter.java b/lib/jcef/java/org/cef/handler/CefCookieAccessFilter.java new file mode 100644 index 0000000..ecdba42 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefCookieAccessFilter.java @@ -0,0 +1,52 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.network.CefCookie; +import org.cef.network.CefRequest; +import org.cef.network.CefResponse; + +/** + * Implement this interface to filter cookies that may be sent or received from resource requests. + * The methods of this class will be called on the IO thread. + */ +public interface CefCookieAccessFilter { + /** + * Called on the IO thread before a resource request is sent. The |browser| and |frame| values + * represent the source of the request, and may be null for requests originating from service + * workers or CefURLRequest. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @param cookie The cookie that will be sent with the request. Cannot be modified in this + * callback. Instance only valid within the scope of this method. + * @return True if the cookie can be sent or false otherwise. + */ + boolean canSendCookie(CefBrowser browser, CefFrame frame, CefRequest request, CefCookie cookie); + + /** + * Called on the IO thread after a resource response is received. The |browser| and |frame| + * values represent the source of the request, and may be null for requests originating from + * service workers or CefURLRequest. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @param response The request response. Cannot be modified in this callback. Instance only + * valid within the scope of this method. + * @param cookie The cookie that will be sent with the request. Cannot be modified in this + * callback. Instance only valid within the scope of this method. + * @return True if the cookie can be saved or false otherwise. + */ + boolean canSaveCookie(CefBrowser browser, CefFrame frame, CefRequest request, + CefResponse response, CefCookie cookie); +} diff --git a/lib/jcef/java/org/cef/handler/CefCookieAccessFilterAdapter.java b/lib/jcef/java/org/cef/handler/CefCookieAccessFilterAdapter.java new file mode 100644 index 0000000..94f788e --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefCookieAccessFilterAdapter.java @@ -0,0 +1,30 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.network.CefCookie; +import org.cef.network.CefRequest; +import org.cef.network.CefResponse; + +/** + * An abstract adapter class for cookie access filter events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefCookieAccessFilterAdapter implements CefCookieAccessFilter { + @Override + public boolean canSendCookie( + CefBrowser browser, CefFrame frame, CefRequest request, CefCookie cookie) { + return true; + } + + @Override + public boolean canSaveCookie(CefBrowser browser, CefFrame frame, CefRequest request, + CefResponse response, CefCookie cookie) { + return true; + } +} diff --git a/lib/jcef/java/org/cef/handler/CefDialogHandler.java b/lib/jcef/java/org/cef/handler/CefDialogHandler.java new file mode 100644 index 0000000..13f6218 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefDialogHandler.java @@ -0,0 +1,55 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefFileDialogCallback; + +import java.util.Vector; + +/** + * Implement this interface to handle dialog events. The methods of this class + * will be called on the browser process UI thread. + */ +public interface CefDialogHandler { + /** + * Supported file dialog modes. + */ + 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, //!< Like Open, but selects a folder to open. + FILE_DIALOG_SAVE //!< Allows picking a nonexistent file, and prompts to overwrite if the + //! file already exists. + } + + /** + * Called to run a file chooser dialog. + * + * @param browser + * @param mode represents the type of dialog to display. + * @param title to be used for the dialog and may be empty to show the default + * title ("Open" or "Save" depending on the mode). + * @param defaultFilePath is the path with optional directory and/or file name + * component that should be initially selected in the dialog. + * @param acceptFilters are used to restrict the selectable file types and may + * any combination of (a) valid lower-cased MIME types (e.g. "text/*" or + * "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 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, Vector acceptExtensions, + Vector acceptDescriptions, CefFileDialogCallback callback); +} diff --git a/lib/jcef/java/org/cef/handler/CefDisplayHandler.java b/lib/jcef/java/org/cef/handler/CefDisplayHandler.java new file mode 100644 index 0000000..f2a828e --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefDisplayHandler.java @@ -0,0 +1,72 @@ +// 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 org.cef.handler; + +import org.cef.CefSettings; +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; + +/** + * Implement this interface to handle events related to browser display state. + * The methods of this class will be called on the UI thread. + */ +public interface CefDisplayHandler { + /** + * Browser address changed. + * @param browser The browser generating the event. + * @param frame The frame generating the event. + * @param url The new address. + */ + public void onAddressChange(CefBrowser browser, CefFrame frame, String url); + + /** + * Browser title changed. + * @param browser The browser generating the event. + * @param title The new title. + */ + 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. + * @param text Contains the text that will be displayed in the tooltip. + * @return true to handle the tooltip display yourself. + */ + public boolean onTooltip(CefBrowser browser, String text); + + /** + * Received a status message. + * @param browser The browser generating the event. + * @param value Contains the text that will be displayed in the status message. + */ + public void onStatusMessage(CefBrowser browser, String value); + + /** + * Display a console message. + * @param browser The browser generating the event. + * @param level + * @param message + * @param source + * @param line + * @return true to stop the message from being output to the console. + */ + public boolean onConsoleMessage(CefBrowser browser, CefSettings.LogSeverity level, + String message, String source, int line); + + /** + * Handle cursor changes. + * @param browser The browser generating the event. + * @param cursorType The new cursor type. + * @return true if the cursor change was handled. + */ + public boolean onCursorChange(CefBrowser browser, int cursorType); +} diff --git a/lib/jcef/java/org/cef/handler/CefDisplayHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefDisplayHandlerAdapter.java new file mode 100644 index 0000000..90d22d5 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefDisplayHandlerAdapter.java @@ -0,0 +1,52 @@ +// 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 org.cef.handler; + +import org.cef.CefSettings; +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; + +/** + * An abstract adapter class for receiving display events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefDisplayHandlerAdapter implements CefDisplayHandler { + @Override + public void onAddressChange(CefBrowser browser, CefFrame frame, String url) { + return; + } + + @Override + 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; + } + + @Override + public void onStatusMessage(CefBrowser browser, String value) { + return; + } + + @Override + public boolean onConsoleMessage(CefBrowser browser, CefSettings.LogSeverity level, + String message, String source, int line) { + return false; + } + + @Override + public boolean onCursorChange(CefBrowser browser, int cursorType) { + return false; + } +} diff --git a/lib/jcef/java/org/cef/handler/CefDownloadHandler.java b/lib/jcef/java/org/cef/handler/CefDownloadHandler.java new file mode 100644 index 0000000..3f0ee6f --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefDownloadHandler.java @@ -0,0 +1,41 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefBeforeDownloadCallback; +import org.cef.callback.CefDownloadItem; +import org.cef.callback.CefDownloadItemCallback; + +/** + * Implement this interface to handle file downloads. The methods of this class + * will called on the browser process UI thread. + */ +public interface CefDownloadHandler { + /** + * 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 + * method. + * @param suggestedName is the suggested name for the download file. + * @param callback start the download by calling the Continue method + */ + public boolean onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem, + String suggestedName, CefBeforeDownloadCallback callback); + + /** + * Called when a download's status or progress information has been updated. + * @param browser The desired browser. + * @param downloadItem The downloading item. + * @param callback Execute callback to cancel the download + */ + public void onDownloadUpdated( + CefBrowser browser, CefDownloadItem downloadItem, CefDownloadItemCallback callback); +} diff --git a/lib/jcef/java/org/cef/handler/CefDownloadHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefDownloadHandlerAdapter.java new file mode 100644 index 0000000..f031163 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefDownloadHandlerAdapter.java @@ -0,0 +1,27 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefBeforeDownloadCallback; +import org.cef.callback.CefDownloadItem; +import org.cef.callback.CefDownloadItemCallback; + +/** + * An abstract adapter class for receiving download events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefDownloadHandlerAdapter implements CefDownloadHandler { + @Override + public boolean onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem, + String suggestedName, CefBeforeDownloadCallback callback) { + return false; + } + + @Override + public void onDownloadUpdated( + CefBrowser browser, CefDownloadItem downloadItem, CefDownloadItemCallback callback) {} +} diff --git a/lib/jcef/java/org/cef/handler/CefDragHandler.java b/lib/jcef/java/org/cef/handler/CefDragHandler.java new file mode 100644 index 0000000..d783af1 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefDragHandler.java @@ -0,0 +1,39 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefDragData; + +/** + * Implement this interface to handle events related to dragging. The methods of + * this class will be called on the UI thread. + */ +public interface CefDragHandler { + /** + * + */ + public static final class DragOperationMask { + public static final int DRAG_OPERATION_NONE = 0; + public static final int DRAG_OPERATION_COPY = 1; + public static final int DRAG_OPERATION_LINK = 2; + public static final int DRAG_OPERATION_GENERIC = 4; + public static final int DRAG_OPERATION_PRIVATE = 8; + public static final int DRAG_OPERATION_MOVE = 16; + public static final int DRAG_OPERATION_DELETE = 32; + public static final int DRAG_OPERATION_EVERY = Integer.MAX_VALUE; + } + + /** + * Called when an external drag event enters the browser window. + * + * @param browser The browser generating the event. + * @param dragData Contains the drag event data. Instance only valid within the scope + * of this method. + * @param mask Represents the type of drag operation. See DragOperationMask for possible values. + * @return False for default drag handling behavior or true to cancel the drag event. + */ + public boolean onDragEnter(CefBrowser browser, CefDragData dragData, int mask); +} diff --git a/lib/jcef/java/org/cef/handler/CefFocusHandler.java b/lib/jcef/java/org/cef/handler/CefFocusHandler.java new file mode 100644 index 0000000..57a9327 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefFocusHandler.java @@ -0,0 +1,48 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; + +/** + * Implement this interface to handle events related to focus. The methods of + * this class will be called on the UI thread. + */ +public interface CefFocusHandler { + /** + * Focus sources. + */ + enum FocusSource { + FOCUS_SOURCE_NAVIGATION, //!< The source is explicit navigation via the API (LoadURL(), + //! etc). + FOCUS_SOURCE_SYSTEM //!< The source is a system-generated focus event. + } + + /** + * Called when the browser component is about to loose focus. + * For instance, if focus was on the last HTML element and the + * user pressed the TAB key. + * @param browser The browser generating the event. + * @param next will be true if the browser is giving focus to the + * next component and false if the browser is giving focus + * to the previous component. + */ + public void onTakeFocus(CefBrowser browser, boolean next); + + /** + * Called when the browser component is requesting focus. + * @param browser The browser generating the event. + * @param source indicates/ where the focus request is originating from. + * + * @return false to allow the focus to be set or true to cancel setting the focus. + */ + public boolean onSetFocus(CefBrowser browser, FocusSource source); + + /** + * Called when the browser component has received focus. + * @param browser The browser generating the event. + */ + public void onGotFocus(CefBrowser browser); +} diff --git a/lib/jcef/java/org/cef/handler/CefFocusHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefFocusHandlerAdapter.java new file mode 100644 index 0000000..9936b19 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefFocusHandlerAdapter.java @@ -0,0 +1,27 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; + +/** + * An abstract adapter class for receiving focus events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefFocusHandlerAdapter implements CefFocusHandler { + @Override + public void onTakeFocus(CefBrowser browser, boolean next) { + return; + } + + @Override + public boolean onSetFocus(CefBrowser browser, FocusSource source) { + return false; + } + + @Override + public void onGotFocus(CefBrowser browser) {} +} diff --git a/lib/jcef/java/org/cef/handler/CefJSDialogHandler.java b/lib/jcef/java/org/cef/handler/CefJSDialogHandler.java new file mode 100644 index 0000000..d522c9b --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefJSDialogHandler.java @@ -0,0 +1,81 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefJSDialogCallback; +import org.cef.misc.BoolRef; + +/** + * Implement this interface to handle events related to JavaScript dialogs. The + * methods of this class will be called on the UI thread. + */ +public interface CefJSDialogHandler { + /** + * Supported JavaScript dialog types. + */ + public static enum JSDialogType { + JSDIALOGTYPE_ALERT, + JSDIALOGTYPE_CONFIRM, + JSDIALOGTYPE_PROMPT, + } + + /** + * Called to run a JavaScript dialog. Set suppress_message to true and + * return false to suppress the message (suppressing messages is preferable + * to immediately executing the callback as this is used to detect presumably + * malicious behavior like spamming alert messages in onbeforeunload). Set + * suppress_message to false and return false to use the default + * implementation (the default implementation will show one modal dialog at a + * time and suppress any additional dialog requests until the displayed dialog + * is dismissed). Return true if the application will use a custom dialog or + * if the callback has been executed immediately. Custom dialogs may be either + * modal or modeless. If a custom dialog is used the application must execute + * callback once the custom dialog is dismissed. + * + * @param browser The corresponding browser. + * @param origin_url The originating url. + * @param dialog_type the dialog type. + * @param message_text the text to be displayed. + * @param default_prompt_text value will be specified for prompt dialogs only. + * @param callback execute callback once the custom dialog is dismissed. + * @param suppress_message set to true to suppress displaying the message. + * @return false to use the default dialog implementation. Return true if the + * application will use a custom dialog. + */ + public boolean onJSDialog(CefBrowser browser, String origin_url, JSDialogType dialog_type, + String message_text, String default_prompt_text, CefJSDialogCallback callback, + BoolRef suppress_message); + + /** + * Called to run a dialog asking the user if they want to leave a page. Return + * false to use the default dialog implementation. Return true if the + * application will use a custom dialog or if the callback has been executed + * immediately. Custom dialogs may be either modal or modeless. If a custom + * dialog is used the application must execute callback once the custom + * dialog is dismissed. + * + * @param browser The corresponding browser. + * @param message_text The text to be displayed. + * @param is_reload true if the page is reloaded. + * @param callback execute callback once the custom dialog is dismissed. + * @return false to use the default dialog implementation. Return true if the + * application will use a custom dialog. + */ + public boolean onBeforeUnloadDialog(CefBrowser browser, String message_text, boolean is_reload, + CefJSDialogCallback callback); + + /** + * Called to cancel any pending dialogs and reset any saved dialog state. Will + * be called due to events like page navigation irregardless of whether any + * dialogs are currently pending. + */ + public void onResetDialogState(CefBrowser browser); + + /** + * Called when the default implementation dialog is closed. + */ + public void onDialogClosed(CefBrowser browser); +} diff --git a/lib/jcef/java/org/cef/handler/CefJSDialogHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefJSDialogHandlerAdapter.java new file mode 100644 index 0000000..4bbad36 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefJSDialogHandlerAdapter.java @@ -0,0 +1,35 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefJSDialogCallback; +import org.cef.misc.BoolRef; + +/** + * An abstract adapter class for receiving javascript dialog requests. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefJSDialogHandlerAdapter implements CefJSDialogHandler { + @Override + public boolean onJSDialog(CefBrowser browser, String origin_url, JSDialogType dialog_type, + String message_text, String default_prompt_text, CefJSDialogCallback callback, + BoolRef suppress_message) { + return false; + } + + @Override + public boolean onBeforeUnloadDialog(CefBrowser browser, String message_text, boolean is_reload, + CefJSDialogCallback callback) { + return false; + } + + @Override + public void onResetDialogState(CefBrowser browser) {} + + @Override + public void onDialogClosed(CefBrowser browser) {} +} diff --git a/lib/jcef/java/org/cef/handler/CefKeyboardHandler.java b/lib/jcef/java/org/cef/handler/CefKeyboardHandler.java new file mode 100644 index 0000000..72027b8 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefKeyboardHandler.java @@ -0,0 +1,140 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.misc.BoolRef; + +/** + * Implement this interface to handle events related to keyboard input. The + * methods of this class will be called on the UI thread. + */ +public interface CefKeyboardHandler { + /** + * Structure representing keyboard event information. + */ + public static final class CefKeyEvent { + /** + * Key event types. + */ + public static enum EventType { + /** + * Notification that a key transitioned from "up" to "down" + */ + KEYEVENT_RAWKEYDOWN, + + /** + * Notification that a key was pressed. This does not necessarily + * correspond to a character depending on the key and language. Use + * KEYEVENT_CHAR for character input. + */ + KEYEVENT_KEYDOWN, + + /** + * Notification that a key was released + */ + KEYEVENT_KEYUP, + + /** + * Notification that a character was typed. Use this for text input. Key + * down events may generate 0, 1, or more than one character event + * depending on the key, locale, and operating system. + */ + KEYEVENT_CHAR + } + + CefKeyEvent(EventType typeAttr, int modifiersAttr, int windows_key_codeAttr, + int native_key_codeAttr, boolean is_system_keyAttr, char characterAttr, + char unmodified_characterAttr, boolean focus_on_editable_fieldAttr) { + type = typeAttr; + modifiers = modifiersAttr; + windows_key_code = windows_key_codeAttr; + native_key_code = native_key_codeAttr; + is_system_key = is_system_keyAttr; + character = characterAttr; + unmodified_character = unmodified_characterAttr; + focus_on_editable_field = focus_on_editable_fieldAttr; + } + + /** + * The type of keyboard event. + */ + public final EventType type; + + /** + * Bit flags describing any pressed modifier keys. + * @see org.cef.handler.CefContextMenuHandler.EventFlags for values. + */ + public final int modifiers; + + /** + * The Windows key code for the key event. This value is used by the DOM + * specification. Sometimes it comes directly from the event (i.e. on + * Windows) and sometimes it's determined using a mapping function. See + * WebCore/platform/chromium/KeyboardCodes.h for the list of values. + */ + public final int windows_key_code; + + /** + * The actual key code genenerated by the platform. + */ + public final int native_key_code; + + /** + * Indicates whether the event is considered a "system key" event (see + * http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx for details). + * This value will always be false on non-Windows platforms. + */ + public final boolean is_system_key; + + /** + * The character generated by the keystroke. + */ + public final char character; + + /** + * Same as character but unmodified by any concurrently-held modifiers + * (except shift). This is useful for working out shortcut keys. + **/ + public final char unmodified_character; + + /** + * True if the focus is currently on an editable field on the page. This is + * useful for determining if standard key events should be intercepted. + */ + public final boolean focus_on_editable_field; + + @Override + public String toString() { + return "CefKeyEvent [type=" + type + ", modifiers=" + modifiers + + ", windows_key_code=" + windows_key_code + + ", native_key_code=" + native_key_code + ", is_system_key=" + is_system_key + + ", character=" + character + ", unmodified_character=" + unmodified_character + + ", focus_on_editable_field=" + focus_on_editable_field + "]"; + } + } + + /** + * Called before a keyboard event is sent to the renderer. + * + * @param browser the corresponding browser. + * @param event contains information about the keyboard event. + * @param is_keyboard_shortcut set to true and return false, if + * the event will be handled in OnKeyEvent() as a keyboard shortcut. + * @return true if the event was handled or false otherwise. + */ + public boolean onPreKeyEvent( + CefBrowser browser, CefKeyEvent event, BoolRef is_keyboard_shortcut); + + /** + * Called after the renderer and JavaScript in the page has had a chance to + * handle the event. + * + * @param browser the corresponding browser. + * @param event contains information about the keyboard event. + * @return true if the keyboard event was handled or false otherwise. + */ + public boolean onKeyEvent(CefBrowser browser, CefKeyEvent event); +} diff --git a/lib/jcef/java/org/cef/handler/CefKeyboardHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefKeyboardHandlerAdapter.java new file mode 100644 index 0000000..af37023 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefKeyboardHandlerAdapter.java @@ -0,0 +1,26 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.misc.BoolRef; + +/** + * An abstract adapter class for receiving keyboard events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefKeyboardHandlerAdapter implements CefKeyboardHandler { + @Override + public boolean onPreKeyEvent( + CefBrowser browser, CefKeyEvent event, BoolRef is_keyboard_shortcut) { + return false; + } + + @Override + public boolean onKeyEvent(CefBrowser browser, CefKeyEvent event) { + return false; + } +} diff --git a/lib/jcef/java/org/cef/handler/CefLifeSpanHandler.java b/lib/jcef/java/org/cef/handler/CefLifeSpanHandler.java new file mode 100644 index 0000000..cc132f3 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefLifeSpanHandler.java @@ -0,0 +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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; + +/** + * Implement this interface to handle events related to browser life span. The methods of this class + * will be called on the UI thread unless otherwise indicated. + */ +public interface CefLifeSpanHandler { + /** + * Called on the IO thread before a new popup window is created. + * @param browser The source of the popup request. + * @param frame The source of the popup request. Instance only valid within the scope of this + * method. + * @param target_url May be empty if none is specified with the request. + * @param target_frame_name May be empty if none is specified with the request. + * @return True to cancel creation of the popup window or false to proceed. + */ + boolean onBeforePopup( + CefBrowser browser, CefFrame frame, String target_url, String target_frame_name); + + /** + * Handle creation of a new browser window. + * @param browser The browser generating the event. + */ + void onAfterCreated(CefBrowser browser); + + /** + * Called after a browser's native parent window has changed. + * @param browser The browser generating the event. + */ + void onAfterParentChanged(CefBrowser browser); + + /** + * Called when a browser has received a request to close. + * + * If CEF created an OS window for the browser returning false will send an OS close + * notification to the browser window's top-level owner (e.g. WM_CLOSE on Windows, performClose: + * on OS-X and "delete_event" on Linux). If no OS window exists (window rendering disabled) + * returning false will cause the browser object to be destroyed immediately. Return true if the + * browser is parented to another window and that other window needs to receive close + * notification via some non-standard technique. + * + * @param browser The browser generating the event. + * @return False to send an OS close notification to the browser window's top-level owner. + */ + boolean doClose(CefBrowser browser); + + /** + * Called just before a browser is destroyed. + * + * Release all references to the browser object and do not attempt to execute any methods on the + * browser object after this callback returns. If this is a modal window and a custom modal loop + * implementation was provided in runModal() this callback should be used to exit the custom + * modal loop. See doClose() documentation for additional usage information. + * + * @param browser The browser generating the event. + */ + void onBeforeClose(CefBrowser browser); +} diff --git a/lib/jcef/java/org/cef/handler/CefLifeSpanHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefLifeSpanHandlerAdapter.java new file mode 100644 index 0000000..4cf96ef --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefLifeSpanHandlerAdapter.java @@ -0,0 +1,35 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; + +/** + * An abstract adapter class for receiving life span events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefLifeSpanHandlerAdapter implements CefLifeSpanHandler { + @Override + public boolean onBeforePopup( + CefBrowser browser, CefFrame frame, String target_url, String target_frame_name) { + return false; + } + + @Override + public void onAfterCreated(CefBrowser browser) {} + + @Override + public void onAfterParentChanged(CefBrowser browser) {} + + @Override + public boolean doClose(CefBrowser browser) { + return false; + } + + @Override + public void onBeforeClose(CefBrowser browser) {} +} diff --git a/lib/jcef/java/org/cef/handler/CefLoadHandler.java b/lib/jcef/java/org/cef/handler/CefLoadHandler.java new file mode 100644 index 0000000..4f0bb83 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefLoadHandler.java @@ -0,0 +1,329 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.network.CefRequest.TransitionType; + +import java.util.HashMap; +import java.util.Map; + +/** + * Implement this interface to handle events related to browser load status. + */ +public interface CefLoadHandler { + enum ErrorCode { + ERR_NONE(0), + ERR_IO_PENDING(-1), + ERR_FAILED(-2), + ERR_ABORTED(-3), + ERR_INVALID_ARGUMENT(-4), + ERR_INVALID_HANDLE(-5), + ERR_FILE_NOT_FOUND(-6), + ERR_TIMED_OUT(-7), + ERR_FILE_TOO_BIG(-8), + ERR_UNEXPECTED(-9), + ERR_ACCESS_DENIED(-10), + ERR_NOT_IMPLEMENTED(-11), + ERR_INSUFFICIENT_RESOURCES(-12), + ERR_OUT_OF_MEMORY(-13), + ERR_UPLOAD_FILE_CHANGED(-14), + ERR_SOCKET_NOT_CONNECTED(-15), + ERR_FILE_EXISTS(-16), + ERR_FILE_PATH_TOO_LONG(-17), + ERR_FILE_NO_SPACE(-18), + ERR_FILE_VIRUS_INFECTED(-19), + ERR_BLOCKED_BY_CLIENT(-20), + ERR_NETWORK_CHANGED(-21), + ERR_BLOCKED_BY_ADMINISTRATOR(-22), + ERR_SOCKET_IS_CONNECTED(-23), + ERR_UPLOAD_STREAM_REWIND_NOT_SUPPORTED(-25), + ERR_CONTEXT_SHUT_DOWN(-26), + ERR_BLOCKED_BY_RESPONSE(-27), + ERR_CLEARTEXT_NOT_PERMITTED(-29), + ERR_CONNECTION_CLOSED(-100), + ERR_CONNECTION_RESET(-101), + ERR_CONNECTION_REFUSED(-102), + ERR_CONNECTION_ABORTED(-103), + ERR_CONNECTION_FAILED(-104), + ERR_NAME_NOT_RESOLVED(-105), + ERR_INTERNET_DISCONNECTED(-106), + ERR_SSL_PROTOCOL_ERROR(-107), + ERR_ADDRESS_INVALID(-108), + ERR_ADDRESS_UNREACHABLE(-109), + ERR_SSL_CLIENT_AUTH_CERT_NEEDED(-110), + ERR_TUNNEL_CONNECTION_FAILED(-111), + ERR_NO_SSL_VERSIONS_ENABLED(-112), + ERR_SSL_VERSION_OR_CIPHER_MISMATCH(-113), + ERR_SSL_RENEGOTIATION_REQUESTED(-114), + ERR_PROXY_AUTH_UNSUPPORTED(-115), + ERR_BAD_SSL_CLIENT_AUTH_CERT(-117), + ERR_CONNECTION_TIMED_OUT(-118), + ERR_HOST_RESOLVER_QUEUE_TOO_LARGE(-119), + ERR_SOCKS_CONNECTION_FAILED(-120), + ERR_SOCKS_CONNECTION_HOST_UNREACHABLE(-121), + ERR_ALPN_NEGOTIATION_FAILED(-122), + ERR_SSL_NO_RENEGOTIATION(-123), + ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES(-124), + ERR_SSL_DECOMPRESSION_FAILURE_ALERT(-125), + ERR_SSL_BAD_RECORD_MAC_ALERT(-126), + ERR_PROXY_AUTH_REQUESTED(-127), + ERR_PROXY_CONNECTION_FAILED(-130), + ERR_MANDATORY_PROXY_CONFIGURATION_FAILED(-131), + ERR_PRECONNECT_MAX_SOCKET_LIMIT(-133), + ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED(-134), + ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY(-135), + ERR_PROXY_CERTIFICATE_INVALID(-136), + ERR_NAME_RESOLUTION_FAILED(-137), + ERR_NETWORK_ACCESS_DENIED(-138), + ERR_TEMPORARILY_THROTTLED(-139), + ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT(-140), + ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED(-141), + ERR_MSG_TOO_BIG(-142), + ERR_WS_PROTOCOL_ERROR(-145), + ERR_ADDRESS_IN_USE(-147), + ERR_SSL_HANDSHAKE_NOT_COMPLETED(-148), + ERR_SSL_BAD_PEER_PUBLIC_KEY(-149), + ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN(-150), + ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED(-151), + ERR_SSL_DECRYPT_ERROR_ALERT(-153), + ERR_WS_THROTTLE_QUEUE_TOO_LARGE(-154), + ERR_SSL_SERVER_CERT_CHANGED(-156), + ERR_SSL_UNRECOGNIZED_NAME_ALERT(-159), + ERR_SOCKET_SET_RECEIVE_BUFFER_SIZE_ERROR(-160), + ERR_SOCKET_SET_SEND_BUFFER_SIZE_ERROR(-161), + ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE(-162), + ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE(-163), + ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT(-164), + ERR_ICANN_NAME_COLLISION(-166), + ERR_SSL_SERVER_CERT_BAD_FORMAT(-167), + ERR_CT_STH_PARSING_FAILED(-168), + ERR_CT_STH_INCOMPLETE(-169), + ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH(-170), + ERR_CT_CONSISTENCY_PROOF_PARSING_FAILED(-171), + ERR_SSL_OBSOLETE_CIPHER(-172), + ERR_WS_UPGRADE(-173), + ERR_READ_IF_READY_NOT_IMPLEMENTED(-174), + ERR_NO_BUFFER_SPACE(-176), + ERR_SSL_CLIENT_AUTH_NO_COMMON_ALGORITHMS(-177), + ERR_EARLY_DATA_REJECTED(-178), + ERR_WRONG_VERSION_ON_EARLY_DATA(-179), + ERR_TLS13_DOWNGRADE_DETECTED(-180), + ERR_SSL_KEY_USAGE_INCOMPATIBLE(-181), + ERR_INVALID_ECH_CONFIG_LIST(-182), + ERR_ECH_NOT_NEGOTIATED(-183), + ERR_ECH_FALLBACK_CERTIFICATE_INVALID(-184), + ERR_CERT_COMMON_NAME_INVALID(-200), + ERR_CERT_DATE_INVALID(-201), + ERR_CERT_AUTHORITY_INVALID(-202), + ERR_CERT_CONTAINS_ERRORS(-203), + ERR_CERT_NO_REVOCATION_MECHANISM(-204), + ERR_CERT_UNABLE_TO_CHECK_REVOCATION(-205), + ERR_CERT_REVOKED(-206), + ERR_CERT_INVALID(-207), + ERR_CERT_WEAK_SIGNATURE_ALGORITHM(-208), + ERR_CERT_NON_UNIQUE_NAME(-210), + ERR_CERT_WEAK_KEY(-211), + ERR_CERT_NAME_CONSTRAINT_VIOLATION(-212), + ERR_CERT_VALIDITY_TOO_LONG(-213), + ERR_CERTIFICATE_TRANSPARENCY_REQUIRED(-214), + ERR_CERT_SYMANTEC_LEGACY(-215), + ERR_CERT_KNOWN_INTERCEPTION_BLOCKED(-217), + ERR_CERT_END(-219), + ERR_INVALID_URL(-300), + ERR_DISALLOWED_URL_SCHEME(-301), + ERR_UNKNOWN_URL_SCHEME(-302), + ERR_INVALID_REDIRECT(-303), + ERR_TOO_MANY_REDIRECTS(-310), + ERR_UNSAFE_REDIRECT(-311), + ERR_UNSAFE_PORT(-312), + ERR_INVALID_RESPONSE(-320), + ERR_INVALID_CHUNKED_ENCODING(-321), + ERR_METHOD_NOT_SUPPORTED(-322), + ERR_UNEXPECTED_PROXY_AUTH(-323), + ERR_EMPTY_RESPONSE(-324), + ERR_RESPONSE_HEADERS_TOO_BIG(-325), + ERR_PAC_SCRIPT_FAILED(-327), + ERR_REQUEST_RANGE_NOT_SATISFIABLE(-328), + ERR_MALFORMED_IDENTITY(-329), + ERR_CONTENT_DECODING_FAILED(-330), + ERR_NETWORK_IO_SUSPENDED(-331), + ERR_SYN_REPLY_NOT_RECEIVED(-332), + ERR_ENCODING_CONVERSION_FAILED(-333), + ERR_UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT(-334), + ERR_NO_SUPPORTED_PROXIES(-336), + ERR_HTTP2_PROTOCOL_ERROR(-337), + ERR_INVALID_AUTH_CREDENTIALS(-338), + ERR_UNSUPPORTED_AUTH_SCHEME(-339), + ERR_ENCODING_DETECTION_FAILED(-340), + ERR_MISSING_AUTH_CREDENTIALS(-341), + ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS(-342), + ERR_MISCONFIGURED_AUTH_ENVIRONMENT(-343), + ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS(-344), + ERR_RESPONSE_BODY_TOO_BIG_TO_DRAIN(-345), + ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH(-346), + ERR_INCOMPLETE_HTTP2_HEADERS(-347), + ERR_PAC_NOT_IN_DHCP(-348), + ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION(-349), + ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION(-350), + ERR_HTTP2_SERVER_REFUSED_STREAM(-351), + ERR_HTTP2_PING_FAILED(-352), + ERR_CONTENT_LENGTH_MISMATCH(-354), + ERR_INCOMPLETE_CHUNKED_ENCODING(-355), + ERR_QUIC_PROTOCOL_ERROR(-356), + ERR_RESPONSE_HEADERS_TRUNCATED(-357), + ERR_QUIC_HANDSHAKE_FAILED(-358), + ERR_HTTP2_INADEQUATE_TRANSPORT_SECURITY(-360), + ERR_HTTP2_FLOW_CONTROL_ERROR(-361), + ERR_HTTP2_FRAME_SIZE_ERROR(-362), + ERR_HTTP2_COMPRESSION_ERROR(-363), + ERR_PROXY_AUTH_REQUESTED_WITH_NO_CONNECTION(-364), + ERR_HTTP_1_1_REQUIRED(-365), + ERR_PROXY_HTTP_1_1_REQUIRED(-366), + ERR_PAC_SCRIPT_TERMINATED(-367), + ERR_INVALID_HTTP_RESPONSE(-370), + ERR_CONTENT_DECODING_INIT_FAILED(-371), + ERR_HTTP2_RST_STREAM_NO_ERROR_RECEIVED(-372), + ERR_TOO_MANY_RETRIES(-375), + ERR_HTTP2_STREAM_CLOSED(-376), + ERR_HTTP_RESPONSE_CODE_FAILURE(-379), + ERR_QUIC_CERT_ROOT_NOT_KNOWN(-380), + ERR_QUIC_GOAWAY_REQUEST_CAN_BE_RETRIED(-381), + ERR_CACHE_MISS(-400), + ERR_CACHE_READ_FAILURE(-401), + ERR_CACHE_WRITE_FAILURE(-402), + ERR_CACHE_OPERATION_NOT_SUPPORTED(-403), + ERR_CACHE_OPEN_FAILURE(-404), + ERR_CACHE_CREATE_FAILURE(-405), + ERR_CACHE_RACE(-406), + ERR_CACHE_CHECKSUM_READ_FAILURE(-407), + ERR_CACHE_CHECKSUM_MISMATCH(-408), + ERR_CACHE_LOCK_TIMEOUT(-409), + ERR_CACHE_AUTH_FAILURE_AFTER_READ(-410), + ERR_CACHE_ENTRY_NOT_SUITABLE(-411), + ERR_CACHE_DOOM_FAILURE(-412), + ERR_CACHE_OPEN_OR_CREATE_FAILURE(-413), + ERR_INSECURE_RESPONSE(-501), + ERR_NO_PRIVATE_KEY_FOR_CERT(-502), + ERR_ADD_USER_CERT_FAILED(-503), + ERR_INVALID_SIGNED_EXCHANGE(-504), + ERR_INVALID_WEB_BUNDLE(-505), + ERR_TRUST_TOKEN_OPERATION_FAILED(-506), + ERR_TRUST_TOKEN_OPERATION_SUCCESS_WITHOUT_SENDING_REQUEST(-507), + ERR_PKCS12_IMPORT_BAD_PASSWORD(-701), + ERR_PKCS12_IMPORT_FAILED(-702), + ERR_IMPORT_CA_CERT_NOT_CA(-703), + ERR_IMPORT_CERT_ALREADY_EXISTS(-704), + ERR_IMPORT_CA_CERT_FAILED(-705), + ERR_IMPORT_SERVER_CERT_FAILED(-706), + ERR_PKCS12_IMPORT_INVALID_MAC(-707), + ERR_PKCS12_IMPORT_INVALID_FILE(-708), + ERR_PKCS12_IMPORT_UNSUPPORTED(-709), + ERR_KEY_GENERATION_FAILED(-710), + ERR_PRIVATE_KEY_EXPORT_FAILED(-712), + ERR_SELF_SIGNED_CERT_GENERATION_FAILED(-713), + ERR_CERT_DATABASE_CHANGED(-714), + ERR_DNS_MALFORMED_RESPONSE(-800), + ERR_DNS_SERVER_REQUIRES_TCP(-801), + ERR_DNS_SERVER_FAILED(-802), + ERR_DNS_TIMED_OUT(-803), + ERR_DNS_CACHE_MISS(-804), + ERR_DNS_SEARCH_EMPTY(-805), + ERR_DNS_SORT_ERROR(-806), + ERR_DNS_SECURE_RESOLVER_HOSTNAME_RESOLUTION_FAILED(-808), + ERR_DNS_NAME_HTTPS_ONLY(-809), + ERR_DNS_REQUEST_CANCELLED(-810); + + static private final Map CODES = new HashMap<>(); + static { + for (ErrorCode ec : ErrorCode.values()) { + // only put first value into map (so enums listed first have + // priority over others for duplicate error code values) + if (!CODES.containsKey(ec.code)) { + CODES.put(ec.code, ec); + } + } + } + + private final int code; + + ErrorCode(int code) { + this.code = code; + } + + /** + * Gets the underlying native chrome embedded framework error code value + * as an integer. + * @return The error code as an integer. + */ + public int getCode() { + return code; + } + + /** + * Finds the ErrorCode by the native chrome embedded framework integer-based + * error code value. + * @param code The integer-based raw error code. + * @return The Java enum mapped to that error code or null if none was found. + */ + static public ErrorCode findByCode(int code) { + return CODES.get(code); + } + } + + /** + * Called when the loading state has changed. This callback will be executed twice -- once when + * loading is initiated either programmatically or by user action, and once when loading is + * terminated due to completion, cancellation of failure. + * + * @param browser The corresponding browser. + * @param isLoading true if it is loading. + * @param canGoBack true if you can navigate back. + * @param canGoForward true if you can navigate forward. + */ + public void onLoadingStateChange( + CefBrowser browser, boolean isLoading, boolean canGoBack, boolean canGoForward); + + /** + * Called when the browser begins loading a frame. The frameIdentifer value will never be empty. + * Multiple frames may be loading at the same time. Sub-frames may start or continue loading + * after the main frame load has ended. This method may not be called for a particular frame if + * the load request for that frame fails. For notification of overall browser load status use + * onLoadingStateChange instead. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param transitionType The transition type. + */ + public void onLoadStart(CefBrowser browser, CefFrame frame, TransitionType transitionType); + + /** + * Called when the browser is done loading a frame. The frameIdentifer value will never be + * empty. Multiple frames may be loading at the same time. Sub-frames may start or continue + * loading after the main frame load has ended. This method will always be called for all frames + * irrespective of whether the request completes successfully. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param httpStatusCode The status code of the load. + */ + public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode); + + /** + * Called when the resource load for a navigation fails or is canceled. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param errorCode The error code number. + * @param errorText The error text. + * @param failedUrl The URL that failed to load. + */ + public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, + String errorText, String failedUrl); +} diff --git a/lib/jcef/java/org/cef/handler/CefLoadHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefLoadHandlerAdapter.java new file mode 100644 index 0000000..edbbae1 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefLoadHandlerAdapter.java @@ -0,0 +1,30 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.network.CefRequest.TransitionType; + +/** + * An abstract adapter class for receiving load events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefLoadHandlerAdapter implements CefLoadHandler { + @Override + public void onLoadingStateChange( + CefBrowser browser, boolean isLoading, boolean canGoBack, boolean canGoForward) {} + + @Override + public void onLoadStart(CefBrowser browser, CefFrame frame, TransitionType transitionType) {} + + @Override + public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) {} + + @Override + public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, + String errorText, String failedUrl) {} +} diff --git a/lib/jcef/java/org/cef/handler/CefMessageRouterHandler.java b/lib/jcef/java/org/cef/handler/CefMessageRouterHandler.java new file mode 100644 index 0000000..4827a47 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefMessageRouterHandler.java @@ -0,0 +1,43 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefNative; +import org.cef.callback.CefQueryCallback; + +/** + * Implement this interface to handle queries. All methods will be executed on the browser process + * UI thread. + */ +public interface CefMessageRouterHandler extends CefNative { + /** + * Called when the browser receives a JavaScript query. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param queryId The unique ID for the query. + * @param persistent True if the query is persistent. + * @param callback Object used to continue or cancel the query asynchronously. + * @return True to handle the query or false to propagate the query to other registered + * handlers, if any. If no handlers return true from this method then the query will be + * automatically canceled with an error code of -1 delivered to the JavaScript onFailure + * callback. + */ + public boolean onQuery(CefBrowser browser, CefFrame frame, long queryId, String request, + boolean persistent, CefQueryCallback callback); + + /** + * Called when a pending JavaScript query is canceled. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param queryId The unique ID for the query. + */ + public void onQueryCanceled(CefBrowser browser, CefFrame frame, long queryId); +} diff --git a/lib/jcef/java/org/cef/handler/CefMessageRouterHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefMessageRouterHandlerAdapter.java new file mode 100644 index 0000000..c924dbf --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefMessageRouterHandlerAdapter.java @@ -0,0 +1,29 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefNativeAdapter; +import org.cef.callback.CefQueryCallback; + +/** + * An abstract adapter class for receiving message router events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefMessageRouterHandlerAdapter + extends CefNativeAdapter implements CefMessageRouterHandler { + @Override + public boolean onQuery(CefBrowser browser, CefFrame frame, long queryId, String request, + boolean persistent, CefQueryCallback callback) { + return false; + } + + @Override + public void onQueryCanceled(CefBrowser browser, CefFrame frame, long queryId) { + return; + } +} diff --git a/lib/jcef/java/org/cef/handler/CefPrintHandler.java b/lib/jcef/java/org/cef/handler/CefPrintHandler.java new file mode 100644 index 0000000..ec9cec3 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefPrintHandler.java @@ -0,0 +1,77 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefNative; +import org.cef.callback.CefPrintDialogCallback; +import org.cef.callback.CefPrintJobCallback; +import org.cef.misc.CefPrintSettings; + +import java.awt.Dimension; + +/** + * Implement this interface to handle printing on Linux. The methods of this class will be called on + * the browser process UI thread. + */ +public interface CefPrintHandler extends CefNative { + /** + * Called when printing has started. This method will be called before the other onPrint*() + * methods and irrespective of how printing was initiated (e.g. CefBrowser::print(), JavaScript + * window.print() or PDF extension print button). + * + * @param browser The corresponding browser. + */ + void onPrintStart(CefBrowser browser); + + /** + * Called to get print settings. + * + * @param browser The corresponding browser. + * @param settings Populate with the desired print settings. Do not keep a reference to this + * object outside of this callback. + * @param getDefaults If true |settings| should be populated with the default print settings. + */ + void onPrintSettings(CefBrowser browser, CefPrintSettings settings, boolean getDefaults); + + /** + * Called to show the print dialog. + * + * @param browser The corresponding browser. + * @param hasSelection True if the user has selected a region of the page to print. + * @param callback Callback to execute after the dialog is dismissed. + * @return True if the dialog will be displayed or false to cancel the printing immediately. + */ + boolean onPrintDialog( + CefBrowser browser, boolean hasSelection, CefPrintDialogCallback callback); + + /** + * Called to send the print job to the printer. + * + * @param browser The corresponding browser. + * @param documentName Name of the document that is printing. + * @param pdfFilePath Path to the PDF file that contains the document contents. + * @param callback Callback to execute after the print job has completed. + * @return True if the job will proceed or false to cancel the printing immediately. + */ + boolean onPrintJob(CefBrowser browser, String documentName, String pdfFilePath, + CefPrintJobCallback callback); + + /** + * Called to reset client state related to printing. + * + * @param browser The corresponding browser. + */ + void onPrintReset(CefBrowser browser); + + /** + * Called to retrieve the page size when printToPDF is requested for a browser. + * + * @param browser The corresponding browser. + * @param deviceUnitsPerInch The DPI of the print. Use this to calculate the page size to use. + * @return The page size in microns. + */ + Dimension getPdfPaperSize(CefBrowser browser, int deviceUnitsPerInch); +} diff --git a/lib/jcef/java/org/cef/handler/CefPrintHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefPrintHandlerAdapter.java new file mode 100644 index 0000000..65a63f5 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefPrintHandlerAdapter.java @@ -0,0 +1,60 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefNativeAdapter; +import org.cef.callback.CefPrintDialogCallback; +import org.cef.callback.CefPrintJobCallback; +import org.cef.misc.CefPrintSettings; + +import java.awt.Dimension; + +/** + * An abstract adapter class for receiving print events on Linux. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefPrintHandlerAdapter extends CefNativeAdapter implements CefPrintHandler { + @Override + public void onPrintStart(CefBrowser browser) { + // The default implementation does nothing + } + + @Override + public void onPrintSettings( + CefBrowser browser, CefPrintSettings settings, boolean getDefaults) { + // The default implementation does nothing + } + + @Override + public boolean onPrintDialog( + CefBrowser browser, boolean hasSelection, CefPrintDialogCallback callback) { + // The default implementation does nothing + return false; + } + + @Override + public boolean onPrintJob(CefBrowser browser, String documentName, String pdfFilePath, + CefPrintJobCallback callback) { + // The default implementation does nothing + return false; + } + + @Override + public void onPrintReset(CefBrowser browser) { + // The default implementation does nothing + } + + @Override + public Dimension getPdfPaperSize(CefBrowser browser, int deviceUnitsPerInch) { + // default implementation is A4 letter size + // @ 300 DPI, A4 is 2480 x 3508 + // @ 150 DPI, A4 is 1240 x 1754 + int adjustedWidth = (int) (((double) deviceUnitsPerInch / 300d) * 2480d); + int adjustedHeight = (int) (((double) deviceUnitsPerInch / 300d) * 3508d); + return new Dimension(adjustedWidth, adjustedHeight); + } +} diff --git a/lib/jcef/java/org/cef/handler/CefRenderHandler.java b/lib/jcef/java/org/cef/handler/CefRenderHandler.java new file mode 100644 index 0000000..258df88 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefRenderHandler.java @@ -0,0 +1,126 @@ +// 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 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. + * The methods of this class will be called on the UI thread. + */ +public interface CefRenderHandler { + /** + * Retrieve the view rectangle. + * @param browser The browser generating the event. + * @return The view rectangle. + */ + public Rectangle getViewRect(CefBrowser browser); + + /** + * Retrieve the screen info. + * @param browser The browser generating the event. + * @param screenInfo The screenInfo + * @return True if this callback was handled. False to fallback to defaults. + */ + public boolean getScreenInfo(CefBrowser browser, CefScreenInfo screenInfo); + + /** + * Retrieve the screen point for the specified view point. + * @param browser The browser generating the event. + * @param viewPoint The point in the view. + * @return The screen point. + */ + public Point getScreenPoint(CefBrowser browser, Point viewPoint); + + /** + * Show or hide the popup window. + * @param browser The browser generating the event. + * @param show True if the popup window is being shown. + */ + public void onPopupShow(CefBrowser browser, boolean show); + + /** + * Size the popup window. + * @param browser The browser generating the event. + * @param size Size of the popup window. + */ + public void onPopupSize(CefBrowser browser, Rectangle size); + + /** + * Handle painting. + * @param browser The browser generating the event. + * @param popup True if painting a popup window. + * @param dirtyRects Array of dirty regions. + * @param buffer Pixel buffer for the whole window. + * @param width Width of the buffer. + * @param height Height of the buffer. + */ + 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. + * @param cursorType The new cursor type. + * @return true if the cursor change was handled. + */ + public boolean onCursorChange(CefBrowser browser, int cursorType); + + /** + * Called when the user starts dragging content in the web view. Contextual + * information about the dragged content is supplied by dragData. + * OS APIs that run a system message loop may be used within the + * StartDragging call. + * + * Return false to abort the drag operation. Don't call any of + * CefBrowser-dragSource*Ended* methods after returning false. + * + * Return true to handle the drag operation. Call + * CefBrowser.dragSourceEndedAt and CefBrowser.ragSourceSystemDragEnded either + * synchronously or asynchronously to inform the web view that the drag + * operation has ended. + * @param browser The browser generating the event. + * @param dragData Contextual information about the dragged content + * @param mask Describes the allowed operation (none, move, copy, link). + * @param x Coordinate within CefBrowser + * @param y Coordinate within CefBrowser + * @return false to abort the drag operation or true to handle the drag operation. + */ + public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y); + + /** + * Called when the web view wants to update the mouse cursor during a + * drag & drop operation. + * + * @param browser The browser generating the event. + * @param operation Describes the allowed operation (none, move, copy, link). + */ + public void updateDragCursor(CefBrowser browser, int operation); +} diff --git a/lib/jcef/java/org/cef/handler/CefRenderHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefRenderHandlerAdapter.java new file mode 100644 index 0000000..ea78283 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefRenderHandlerAdapter.java @@ -0,0 +1,57 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefDragData; + +import java.awt.Point; +import java.awt.Rectangle; +import java.nio.ByteBuffer; + +/** + * An abstract adapter class for receiving render events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefRenderHandlerAdapter implements CefRenderHandler { + @Override + public Rectangle getViewRect(CefBrowser browser) { + return new Rectangle(0, 0, 0, 0); + } + + @Override + public boolean getScreenInfo(CefBrowser browser, CefScreenInfo screenInfo) { + return false; + } + + @Override + public Point getScreenPoint(CefBrowser browser, Point viewPoint) { + return new Point(0, 0); + } + + @Override + public void onPopupShow(CefBrowser browser, boolean show) {} + + @Override + public void onPopupSize(CefBrowser browser, Rectangle size) {} + + @Override + public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, + ByteBuffer buffer, int width, int height) {} + + @Override + public boolean onCursorChange(CefBrowser browser, int cursorType) { + return false; + } + + @Override + public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y) { + return false; + } + + @Override + public void updateDragCursor(CefBrowser browser, int operation) {} +} diff --git a/lib/jcef/java/org/cef/handler/CefRequestContextHandler.java b/lib/jcef/java/org/cef/handler/CefRequestContextHandler.java new file mode 100644 index 0000000..627f77e --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefRequestContextHandler.java @@ -0,0 +1,40 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.handler.CefResourceRequestHandler; +import org.cef.misc.BoolRef; +import org.cef.network.CefRequest; + +/** + * Implement this interface to provide handler implementations. + */ +public interface CefRequestContextHandler { + /** + * Called on the IO thread before a resource request is initiated. The |browser| and |frame| + * values represent the source of the request. This method will not be called if the client + * associated with |browser| returns a non-null value from + * CefRequestHandler.getResourceRequestHandler for the same request (identified by + * CefRequest.getIdentifier). + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @param isNavigation True if the resource request is a navigation. + * @param isDownload True if the resource request is a download. + * @param requestInitiator The origin (scheme + domain) of the page that initiated the request. + * @param disableDefaultHandling Set to true to disable default handling of the request, in + * which case it will need to be handled via + * CefResourceRequestHandler.getResourceHandler or it will be canceled. + * @return A CefResourceRequestHandler instance or null. + */ + CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame, + CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator, + BoolRef disableDefaultHandling); +} diff --git a/lib/jcef/java/org/cef/handler/CefRequestContextHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefRequestContextHandlerAdapter.java new file mode 100644 index 0000000..7fab771 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefRequestContextHandlerAdapter.java @@ -0,0 +1,24 @@ +// 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 org.cef.browser.CefFrame; +import org.cef.misc.BoolRef; +import org.cef.network.CefRequest; + +/** + * An abstract adapter class for receiving browser request context events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefRequestContextHandlerAdapter implements CefRequestContextHandler { + @Override + public CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame, + CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator, + BoolRef disableDefaultHandling) { + return null; + } +} diff --git a/lib/jcef/java/org/cef/handler/CefRequestHandler.java b/lib/jcef/java/org/cef/handler/CefRequestHandler.java new file mode 100644 index 0000000..22ba60d --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefRequestHandler.java @@ -0,0 +1,134 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefAuthCallback; +import org.cef.callback.CefCallback; +import org.cef.misc.BoolRef; +import org.cef.network.CefRequest; +import org.cef.network.CefURLRequest; + +/** + * Implement this interface to handle events related to browser requests. The methods of this class + * will be called on the thread indicated. + */ +public interface CefRequestHandler { + /** + * Process termination status values. + */ + 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_LAUNCH_FAILED, //!< Failed to launch. + TS_INTEGRITY_FAILURE, //!< Integrity check failed. + TS_NUM_VALUES + } + + /** + * Called on the UI thread before browser navigation. + * + * CefLoadHandler.onLoadingStateChange() will be called twice in all cases. If the navigation is + * allowed CefLoadHandler.onLoadStart() and CefLoadHandler.onLoadEnd() will be called. If the + * navigation is canceled CefLoadHandler.onLoadError() will be called with an errorCode value of + * ERR_ABORTED. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @param user_gesture True if the request was initiated by a user gesture. + * @param is_redirect True if the request was redirected. + * @return True to cancel the navigation or false to continue. + */ + boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, + boolean user_gesture, boolean is_redirect); + + /** + * Called on the UI thread before OnBeforeBrowse in certain limited cases + * where navigating a new or different browser might be desirable. This + * includes user-initiated navigation that might open in a special way (e.g. + * links clicked via middle-click or ctrl + left-click) and certain types of + * cross-origin navigation initiated from the renderer process (e.g. + * navigating the top-level frame to/from a file URL). + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method + * @param user_gesture True if the request was initiated by a user gesture. + * @return True to cancel navigation or false to continue + */ + boolean onOpenURLFromTab( + CefBrowser browser, CefFrame frame, String target_url, boolean user_gesture); + + /** + * Called on the IO thread before a resource request is initiated. The |browser| and |frame| + * values represent the source of the request. If this callback returns null the same method + * will be called on the associated CefRequestContextHandler, if any. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @param isNavigation True if the resource request is a navigation. + * @param isDownload True if the resource request is a download. + * @param requestInitiator The origin (scheme + domain) of the page that initiated the request. + * @param disableDefaultHandling Set to true to disable default handling of the request, in + * which case it will need to be handled via + * CefResourceRequestHandler.getResourceHandler or it will be canceled. + * @return A CefResourceRequestHandler instance or null. + */ + CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame, + CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator, + BoolRef disableDefaultHandling); + + /** + * Called on the IO thread when the browser needs credentials from the user. + * + * @param browser The corresponding browser. + * @param origin_url The origin making this authentication request. + * @param isProxy True if the host is a proxy server. + * @param host Hostname. + * @param port Port number. + * @param realm Realm of the request. + * @param scheme Scheme of the request. + * @param callback Call CefAuthCallback.Continue() when the authentication information is + * available. + * @return True to continue the request (callback must be executed) or false to cancel. + */ + boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy, String host, + int port, String realm, String scheme, CefAuthCallback 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 + * accepted without calling this method. + * + * @param browser The corresponding browser. + * @param cert_error Error code describing the error. + * @param request_url The requesting URL. + * @param callback Call CefCallback.Continue() either in this method or at a later time + * to continue or cancel the request. If null the error cannot be recovered from and the + * request will be canceled automatically. + * @return True to handle the request (callback must be executed) or false to reject it. + */ + boolean onCertificateError(CefBrowser browser, CefLoadHandler.ErrorCode cert_error, + String request_url, CefCallback callback); + + /** + * 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, int error_code, String error_string); +} diff --git a/lib/jcef/java/org/cef/handler/CefRequestHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefRequestHandlerAdapter.java new file mode 100644 index 0000000..a6c04ef --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefRequestHandlerAdapter.java @@ -0,0 +1,56 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefAuthCallback; +import org.cef.callback.CefCallback; +import org.cef.handler.CefLoadHandler.ErrorCode; +import org.cef.misc.BoolRef; +import org.cef.network.CefRequest; +import org.cef.network.CefURLRequest; + +/** + * An abstract adapter class for receiving browser request events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefRequestHandlerAdapter implements CefRequestHandler { + @Override + public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, + boolean user_gesture, boolean is_redirect) { + return false; + } + + @Override + public boolean onOpenURLFromTab( + CefBrowser browser, CefFrame frame, String target_url, boolean user_gesture) { + return false; + } + + @Override + public CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame, + CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator, + BoolRef disableDefaultHandling) { + return null; + } + + @Override + public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy, + String host, int port, String realm, String scheme, CefAuthCallback callback) { + return false; + } + + @Override + public boolean onCertificateError( + CefBrowser browser, ErrorCode cert_error, String request_url, CefCallback callback) { + return false; + } + + @Override + public void onRenderProcessTerminated( + CefBrowser browser, TerminationStatus status, int error_code, String error_string) {} +} diff --git a/lib/jcef/java/org/cef/handler/CefResourceHandler.java b/lib/jcef/java/org/cef/handler/CefResourceHandler.java new file mode 100644 index 0000000..24908f6 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefResourceHandler.java @@ -0,0 +1,110 @@ +// 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 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. 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 { + /** + * Begin processing the request. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @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 + * response length is known set |responseLength| to a positive value and readResponse() will be + * called until it returns false or the specified number of bytes have been read. Use the + * |response| object to set the mime type, http status code and other optional header values. + * @param response The request response that should be returned. Instance only valid within the + * scope of this method. + * @param responseLength Optionally set the response length if known. + * @param redirectUrl Optionally redirect the request to a new URL. + */ + void getResponseHeaders(CefResponse response, IntRef responseLength, StringRef redirectUrl); + + /** + * 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 set |bytesRead| to 0, return true and call CefCallback.Continue() when the + * data is available. To indicate response completion return false. + * @param dataOut Write data to this buffer. + * @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. + * @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. + */ + void cancel(); +} diff --git a/lib/jcef/java/org/cef/handler/CefResourceHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefResourceHandlerAdapter.java new file mode 100644 index 0000000..5360597 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefResourceHandlerAdapter.java @@ -0,0 +1,62 @@ +// 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 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; + +/** + * An abstract adapter class for receiving resource requests. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefResourceHandlerAdapter implements CefResourceHandler { + @Override + 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) {} + + @Override + public boolean readResponse( + byte[] dataOut, int bytesToRead, IntRef bytesRead, CefCallback callback) { + 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/lib/jcef/java/org/cef/handler/CefResourceRequestHandler.java b/lib/jcef/java/org/cef/handler/CefResourceRequestHandler.java new file mode 100644 index 0000000..7556681 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefResourceRequestHandler.java @@ -0,0 +1,144 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefCallback; +import org.cef.misc.BoolRef; +import org.cef.misc.StringRef; +import org.cef.network.CefRequest; +import org.cef.network.CefResponse; +import org.cef.network.CefURLRequest; + +/** + * Implement this interface to handle events related to browser requests. The methods of this class + * will be called on the IO thread unless otherwise indicated. + */ +public interface CefResourceRequestHandler { + /** + * Called on the IO thread before a resource is loaded. The |browser| and |frame| values + * represent the source of the request, and may be null for requests originating from service + * workers or CefURLRequest. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @return A CefCookieAccessFilter instance or null. + */ + CefCookieAccessFilter getCookieAccessFilter( + CefBrowser browser, CefFrame frame, CefRequest request); + + /** + * Called on the IO thread before a resource request is loaded. The |browser| and |frame| values + * represent the source of the request, and may be null for requests originating from service + * workers or CefURLRequest. To redirect or change the resource load optionally modify + * |request|. Modification of the request URL will be treated as a redirect. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. May be modified in this callback. Instance only valid + * within the scope of this method. + * @return To cancel the request return true otherwise return false. + */ + boolean onBeforeResourceLoad(CefBrowser browser, CefFrame frame, CefRequest request); + + /** + * Called on the IO thread before a resource is loaded. The |browser| and |frame| values + * represent the source of the request, and may be null for requests originating from service + * workers or CefURLRequest. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @return A CefResourceHandler instance or null. + */ + CefResourceHandler getResourceHandler(CefBrowser browser, CefFrame frame, CefRequest request); + + /** + * Called on the IO thread when a resource load is redirected. The |browser| and |frame| values + * represent the source of the request, and may be null for requests originating from service + * workers or CefURLRequest. The |request| parameter will contain the old URL and other + * request-related information. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @param response The response that resulted in the redirect. Cannot be modified in this + * callback. Instance only valid within the scope of this method. + * @param new_url Contains the new URL and can be changed if desired. + */ + void onResourceRedirect(CefBrowser browser, CefFrame frame, CefRequest request, + CefResponse response, StringRef new_url); + + /** + * Called on the IO thread when a resource response is received. The |browser| and |frame| + * values represent the source of the request, and may be null for requests originating from + * service workers or CefURLRequest. To allow the resource load to proceed without modification + * return false. To redirect or retry the resource load optionally modify |request| and return + * true. Modification of the request URL will be treated as a redirect. Requests handled using + * the default network loader cannot be redirected in this callback. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. May be modified in this callback. Instance only valid + * within the scope of this method. + * @param response The request response. Cannot be modified in this callback. Instance only + * valid within the scope of this method. + * @return True if |request| was modified or false otherwise + */ + boolean onResourceResponse( + CefBrowser browser, CefFrame frame, CefRequest request, CefResponse response); + + /** + * Called on the IO thread when a resource load has completed. The |browser| and |frame| values + * represent the source of the request, and may be null for requests originating from service + * workers or CefURLRequest. This method will be called for all requests, including requests + * that are aborted due to CEF shutdown or destruction of the associated browser. In cases where + * the associated browser is destroyed this callback may arrive after the + * CefLifeSpanHandler.onBeforeClose callback for that browser. The CefFrame.isValid method can + * be used to test for this situation, and care should be taken not to call |browser| or |frame| + * methods that modify state (like loadURL, sendProcessMessage, etc.) if the frame is invalid. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @param response The request response. Cannot be modified in this callback. Instance only + * valid within the scope of this method. + * @param status The load completion status. + * @param receivedContentLength The number of bytes read. + */ + void onResourceLoadComplete(CefBrowser browser, CefFrame frame, CefRequest request, + CefResponse response, CefURLRequest.Status status, long receivedContentLength); + + /** + * Called on the IO thread to handle requests for URLs with an unknown protocol component. The + * |browser| and |frame| values represent the source of the request, and may be null for + * requests originating from service workers or CefURLRequest. + * + * SECURITY WARNING: YOU SHOULD USE THIS METHOD TO ENFORCE RESTRICTIONS BASED ON SCHEME, HOST + * OR OTHER URL ANALYSIS BEFORE ALLOWING OS EXECUTION. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param request The request itself. Cannot be modified in this callback. Instance only valid + * within the scope of this method. + * @param allowOsExecution Set to true to attempt execution via the registered + * OS protocol handler, if any. + */ + void onProtocolExecution( + CefBrowser browser, CefFrame frame, CefRequest request, BoolRef allowOsExecution); +} diff --git a/lib/jcef/java/org/cef/handler/CefResourceRequestHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefResourceRequestHandlerAdapter.java new file mode 100644 index 0000000..51e4e4b --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefResourceRequestHandlerAdapter.java @@ -0,0 +1,56 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefCallback; +import org.cef.misc.BoolRef; +import org.cef.misc.StringRef; +import org.cef.network.CefRequest; +import org.cef.network.CefResponse; +import org.cef.network.CefURLRequest; + +/** + * An abstract adapter class for receiving browser request events. + * The methods in this class are empty. + * This class exists as convenience for creating handler objects. + */ +public abstract class CefResourceRequestHandlerAdapter implements CefResourceRequestHandler { + @Override + public CefCookieAccessFilter getCookieAccessFilter( + CefBrowser browser, CefFrame frame, CefRequest request) { + return null; + } + + @Override + public boolean onBeforeResourceLoad(CefBrowser browser, CefFrame frame, CefRequest request) { + return false; + } + + @Override + public CefResourceHandler getResourceHandler( + CefBrowser browser, CefFrame frame, CefRequest request) { + return null; + } + + @Override + public void onResourceRedirect(CefBrowser browser, CefFrame frame, CefRequest request, + CefResponse response, StringRef new_url) {} + + @Override + public boolean onResourceResponse( + CefBrowser browser, CefFrame frame, CefRequest request, CefResponse response) { + return false; + } + + @Override + public void onResourceLoadComplete(CefBrowser browser, CefFrame frame, CefRequest request, + CefResponse response, CefURLRequest.Status status, long receivedContentLength) {} + + @Override + public void onProtocolExecution( + CefBrowser browser, CefFrame frame, CefRequest request, BoolRef allowOsExecution) {} +} diff --git a/lib/jcef/java/org/cef/handler/CefScreenInfo.java b/lib/jcef/java/org/cef/handler/CefScreenInfo.java new file mode 100644 index 0000000..8a8cd4a --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefScreenInfo.java @@ -0,0 +1,36 @@ +// 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 org.cef.handler; + +import java.awt.Rectangle; + +/** + * + * @author shannah + */ +public class CefScreenInfo { + public double device_scale_factor; + public int depth; + public int depth_per_component; + public boolean is_monochrome; + public int x, y, width, height; + public int available_x, available_y, available_width, available_height; + + public void Set(double device_scale_factor, int depth, int depth_per_component, + boolean is_monochrome, Rectangle rect, Rectangle availableRect) { + this.device_scale_factor = device_scale_factor; + this.depth = depth; + this.depth_per_component = depth_per_component; + this.is_monochrome = is_monochrome; + this.x = rect.x; + this.y = rect.y; + this.width = rect.width; + this.height = rect.height; + this.available_x = availableRect.x; + this.available_y = availableRect.y; + this.available_width = availableRect.width; + this.available_height = availableRect.height; + } +} diff --git a/lib/jcef/java/org/cef/handler/CefWindowHandler.java b/lib/jcef/java/org/cef/handler/CefWindowHandler.java new file mode 100644 index 0000000..c0bc0f1 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefWindowHandler.java @@ -0,0 +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 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/lib/jcef/java/org/cef/handler/CefWindowHandlerAdapter.java b/lib/jcef/java/org/cef/handler/CefWindowHandlerAdapter.java new file mode 100644 index 0000000..839c0c7 --- /dev/null +++ b/lib/jcef/java/org/cef/handler/CefWindowHandlerAdapter.java @@ -0,0 +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 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/lib/jcef/java/org/cef/misc/BoolRef.java b/lib/jcef/java/org/cef/misc/BoolRef.java new file mode 100644 index 0000000..69a37e9 --- /dev/null +++ b/lib/jcef/java/org/cef/misc/BoolRef.java @@ -0,0 +1,26 @@ +// 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 org.cef.misc; + +/** + * Helper class for passing boolean values by reference. + */ +public class BoolRef { + private boolean value_; + + public BoolRef() {} + + public BoolRef(boolean value) { + value_ = value; + } + + public void set(boolean value) { + value_ = value; + } + + public boolean get() { + return value_; + } +} diff --git a/lib/jcef/java/org/cef/misc/CefPageRange.java b/lib/jcef/java/org/cef/misc/CefPageRange.java new file mode 100644 index 0000000..dee4fdf --- /dev/null +++ b/lib/jcef/java/org/cef/misc/CefPageRange.java @@ -0,0 +1,20 @@ +// 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 org.cef.misc; + +/** + * Class representing a print job page range. + */ +public class CefPageRange { + public int from; + public int to; + + public CefPageRange() {} + + public CefPageRange(int from, int to) { + this.from = from; + this.to = to; + } +} \ No newline at end of file diff --git a/lib/jcef/java/org/cef/misc/CefPdfPrintSettings.java b/lib/jcef/java/org/cef/misc/CefPdfPrintSettings.java new file mode 100644 index 0000000..a014d81 --- /dev/null +++ b/lib/jcef/java/org/cef/misc/CefPdfPrintSettings.java @@ -0,0 +1,142 @@ +// Copyright (c) 2017 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; + +/** + * PDF print settings for browser.printToPDF() + */ +public class CefPdfPrintSettings { + public enum MarginType { + // Default margins. + DEFAULT, + + // No margins + NONE, + + // Custom margins using the values from CefPdfPrintSettings + CUSTOM + } + + /** + * Set to true for landscape mode or false for portrait mode. + */ + public boolean landscape; + + /** + * Set to true to print background graphics or false to not print + * background graphics. + */ + public boolean print_background; + + /** + * 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 double scale; + + /** + * 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 double paper_width; + public double paper_height; + + /** + * 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 prefer_css_page_size; + + /** + * Margin type. + */ + public MarginType margin_type; + + /** + * Margins in inches. Only used if margin_type is set to CUSTOM. + */ + public double margin_top; + public double margin_right; + public double margin_bottom; + public double margin_left; + + /** + * 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 boolean display_header_footer; + + /** + * 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 String header_template; + + /** + * HTML template for the print footer. Only displayed if + * |display_header_footer| is true (1). Uses the same format as + * |header_template|. + */ + 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.landscape = this.landscape; + 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_bottom = this.margin_bottom; + tmp.margin_right = this.margin_right; + tmp.margin_left = this.margin_left; + 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/lib/jcef/java/org/cef/misc/CefPrintSettings.java b/lib/jcef/java/org/cef/misc/CefPrintSettings.java new file mode 100644 index 0000000..6dc56fe --- /dev/null +++ b/lib/jcef/java/org/cef/misc/CefPrintSettings.java @@ -0,0 +1,188 @@ +// 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 org.cef.misc; + +import java.awt.Dimension; +import java.awt.Rectangle; +import java.util.Vector; + +/** + * Class representing print settings. + */ +public abstract class CefPrintSettings { + /** + * Print job color mode values. + */ + public enum ColorModel { + COLOR_MODEL_UNKNOWN, + COLOR_MODEL_GRAY, + COLOR_MODEL_COLOR, + COLOR_MODEL_CMYK, + COLOR_MODEL_CMY, + COLOR_MODEL_KCMY, + COLOR_MODEL_CMY_K, //!< CMY_K represents CMY+K. + COLOR_MODEL_BLACK, + COLOR_MODEL_GRAYSCALE, + COLOR_MODEL_RGB, + COLOR_MODEL_RGB16, + COLOR_MODEL_RGBA, + COLOR_MODEL_COLORMODE_COLOR, //!< Used in samsung printer ppds. + COLOR_MODEL_COLORMODE_MONOCHROME, //!< Used in samsung printer ppds. + COLOR_MODEL_HP_COLOR_COLOR, //!< Used in HP color printer ppds. + COLOR_MODEL_HP_COLOR_BLACK, //!< Used in HP color printer ppds. + COLOR_MODEL_PRINTOUTMODE_NORMAL, //!< Used in foomatic ppds. + COLOR_MODEL_PRINTOUTMODE_NORMAL_GRAY, //!< Used in foomatic ppds. + COLOR_MODEL_PROCESSCOLORMODEL_CMYK, //!< Used in canon printer ppds. + COLOR_MODEL_PROCESSCOLORMODEL_GREYSCALE, //!< Used in canon printer ppds. + COLOR_MODEL_PROCESSCOLORMODEL_RGB, //!< Used in canon printer ppds + } + + /** + * Print job duplex mode values. + */ + public enum DuplexMode { + DUPLEX_MODE_UNKNOWN, + DUPLEX_MODE_SIMPLEX, + DUPLEX_MODE_LONG_EDGE, + DUPLEX_MODE_SHORT_EDGE, + } + + // This CTOR can't be called directly. Call method create() instead. + CefPrintSettings() {} + + @Override + protected void finalize() throws Throwable { + dispose(); + super.finalize(); + } + + /** + * Create a new CefPrintSettings object. + */ + public static final CefPrintSettings create() { + return CefPrintSettings_N.createNative(); + } + + /** + * Removes the native reference from an unused object. + */ + public abstract void dispose(); + + /** + * Returns true if this object is valid. Do not call any other methods if this + * function returns false. + */ + public abstract boolean isValid(); + + /** + * Returns true if the values of this object are read-only. Some APIs may + * expose read-only objects. + */ + public abstract boolean isReadOnly(); + + /** + * Set the page orientation. + */ + public abstract void setOrientation(boolean landscape); + + /** + * Returns true if the orientation is landscape. + * + */ + public abstract boolean isLandscape(); + + /** + * Set the printer printable area in device units. + * Some platforms already provide flipped area. Set |landscape_needs_flip| + * to false on those platforms to avoid double flipping. + */ + public abstract void setPrinterPrintableArea(Dimension physical_size_device_units, + Rectangle printable_area_device_units, boolean landscape_needs_flip); + + /** + * Set the device name. + */ + public abstract void setDeviceName(String name); + + /** + * Get the device name. + */ + public abstract String getDeviceName(); + + /** + * Set the DPI (dots per inch). + */ + public abstract void setDPI(int dpi); + + /** + * Get the DPI (dots per inch). + */ + public abstract int getDPI(); + + /** + * Set the page ranges. + */ + public abstract void setPageRanges(Vector ranges); + + /** + * Returns the number of page ranges that currently exist. + */ + public abstract int getPageRangesCount(); + + /** + * Retrieve the page ranges. + */ + public abstract void getPageRanges(Vector ranges); + + /** + * Set whether only the selection will be printed. + */ + public abstract void setSelectionOnly(boolean selection_only); + + /** + * Returns true if only the selection will be printed. + */ + public abstract boolean isSelectionOnly(); + + /** + * Set whether pages will be collated. + */ + public abstract void setCollate(boolean collate); + + /** + * Returns true if pages will be collated. + */ + public abstract boolean willCollate(); + + /** + * Set the color model. + */ + public abstract void setColorModel(ColorModel model); + + /** + * Get the color model. + */ + public abstract ColorModel getColorModel(); + + /** + * Set the number of copies. + */ + public abstract void setCopies(int copies); + + /** + * Get the number of copies. + */ + public abstract int getCopies(); + + /** + * Set the duplex mode. + */ + public abstract void setDuplexMode(DuplexMode mode); + + /** + * Get the duplex mode. + */ + public abstract DuplexMode getDuplexMode(); +} diff --git a/lib/jcef/java/org/cef/misc/CefPrintSettings_N.java b/lib/jcef/java/org/cef/misc/CefPrintSettings_N.java new file mode 100644 index 0000000..bc0f83a --- /dev/null +++ b/lib/jcef/java/org/cef/misc/CefPrintSettings_N.java @@ -0,0 +1,286 @@ +// 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 org.cef.misc; + +import org.cef.callback.CefNative; + +import java.awt.Dimension; +import java.awt.Rectangle; +import java.util.Vector; + +class CefPrintSettings_N extends CefPrintSettings implements CefNative { + // Used internally to store a pointer to the CEF object. + private long N_CefHandle = 0; + + @Override + public void setNativeRef(String identifer, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return N_CefHandle; + } + + CefPrintSettings_N() { + super(); + } + + public static CefPrintSettings createNative() { + try { + return CefPrintSettings_N.N_Create(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public void dispose() { + try { + N_Dispose(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean isValid() { + try { + return N_IsValid(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean isReadOnly() { + try { + return N_IsReadOnly(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public void setOrientation(boolean landscape) { + try { + N_SetOrientation(N_CefHandle, landscape); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean isLandscape() { + try { + return N_IsLandscape(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public void setPrinterPrintableArea(Dimension physical_size_device_units, + Rectangle printable_area_device_units, boolean landscape_needs_flip) { + try { + N_SetPrinterPrintableArea(N_CefHandle, physical_size_device_units, + printable_area_device_units, landscape_needs_flip); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void setDeviceName(String name) { + try { + N_SetDeviceName(N_CefHandle, name); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public String getDeviceName() { + try { + return N_GetDeviceName(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void setDPI(int dpi) { + try { + N_SetDPI(N_CefHandle, dpi); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public int getDPI() { + try { + return N_GetDPI(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public void setPageRanges(Vector ranges) { + try { + N_SetPageRanges(N_CefHandle, ranges); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public int getPageRangesCount() { + try { + return N_GetPageRangesCount(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public void getPageRanges(Vector ranges) { + try { + N_GetPageRanges(N_CefHandle, ranges); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void setSelectionOnly(boolean selection_only) { + try { + N_SetSelectionOnly(N_CefHandle, selection_only); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean isSelectionOnly() { + try { + return N_IsSelectionOnly(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public void setCollate(boolean collate) { + try { + N_SetCollate(N_CefHandle, collate); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean willCollate() { + try { + return N_WillCollate(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public void setColorModel(ColorModel model) { + try { + N_SetColorModel(N_CefHandle, model); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public ColorModel getColorModel() { + try { + return N_GetColorModel(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void setCopies(int copies) { + try { + N_SetCopies(N_CefHandle, copies); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public int getCopies() { + try { + return N_GetCopies(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public void setDuplexMode(DuplexMode mode) { + try { + N_SetDuplexMode(N_CefHandle, mode); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public DuplexMode getDuplexMode() { + try { + return N_GetDuplexMode(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + private final native static CefPrintSettings_N N_Create(); + private final native void N_Dispose(long self); + private final native boolean N_IsValid(long self); + private final native boolean N_IsReadOnly(long self); + private final native void N_SetOrientation(long self, boolean landscape); + private final native boolean N_IsLandscape(long self); + private final native void N_SetPrinterPrintableArea(long self, + Dimension physical_size_device_units, Rectangle printable_area_device_units, + boolean landscape_needs_flip); + private final native void N_SetDeviceName(long self, String name); + private final native String N_GetDeviceName(long self); + private final native void N_SetDPI(long self, int dpi); + private final native int N_GetDPI(long self); + private final native void N_SetPageRanges(long self, Vector ranges); + private final native int N_GetPageRangesCount(long self); + private final native void N_GetPageRanges(long self, Vector ranges); + private final native void N_SetSelectionOnly(long self, boolean selection_only); + private final native boolean N_IsSelectionOnly(long self); + private final native void N_SetCollate(long self, boolean collate); + private final native boolean N_WillCollate(long self); + private final native void N_SetColorModel(long self, ColorModel model); + private final native ColorModel N_GetColorModel(long self); + private final native void N_SetCopies(long self, int copies); + private final native int N_GetCopies(long self); + private final native void N_SetDuplexMode(long self, DuplexMode mode); + private final native DuplexMode N_GetDuplexMode(long self); +} diff --git a/lib/jcef/java/org/cef/misc/EventFlags.java b/lib/jcef/java/org/cef/misc/EventFlags.java new file mode 100644 index 0000000..efcc370 --- /dev/null +++ b/lib/jcef/java/org/cef/misc/EventFlags.java @@ -0,0 +1,21 @@ +package org.cef.misc; + +/** + * Supported event bit flags. + */ +public final class EventFlags { + public final static int EVENTFLAG_NONE = 0; + public final static int EVENTFLAG_CAPS_LOCK_ON = 1 << 0; + public final static int EVENTFLAG_SHIFT_DOWN = 1 << 1; + public final static int EVENTFLAG_CONTROL_DOWN = 1 << 2; + public final static int EVENTFLAG_ALT_DOWN = 1 << 3; + public final static int EVENTFLAG_LEFT_MOUSE_BUTTON = 1 << 4; + public final static int EVENTFLAG_MIDDLE_MOUSE_BUTTON = 1 << 5; + public final static int EVENTFLAG_RIGHT_MOUSE_BUTTON = 1 << 6; + // Mac OS-X command key. + public final static int EVENTFLAG_COMMAND_DOWN = 1 << 7; + public final static int EVENTFLAG_NUM_LOCK_ON = 1 << 8; + public final static int EVENTFLAG_IS_KEY_PAD = 1 << 9; + public final static int EVENTFLAG_IS_LEFT = 1 << 10; + public final static int EVENTFLAG_IS_RIGHT = 1 << 11; +} diff --git a/lib/jcef/java/org/cef/misc/IntRef.java b/lib/jcef/java/org/cef/misc/IntRef.java new file mode 100644 index 0000000..30be742 --- /dev/null +++ b/lib/jcef/java/org/cef/misc/IntRef.java @@ -0,0 +1,26 @@ +// 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 org.cef.misc; + +/** + * Helper class for passing int values by reference. + */ +public class IntRef { + private int value_; + + public IntRef() {} + + public IntRef(int value) { + value_ = value; + } + + public void set(int value) { + value_ = value; + } + + public int get() { + return value_; + } +} diff --git a/lib/jcef/java/org/cef/misc/LongRef.java b/lib/jcef/java/org/cef/misc/LongRef.java new file mode 100644 index 0000000..5a7b663 --- /dev/null +++ b/lib/jcef/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_; + } +} diff --git a/lib/jcef/java/org/cef/misc/StringRef.java b/lib/jcef/java/org/cef/misc/StringRef.java new file mode 100644 index 0000000..d84ac10 --- /dev/null +++ b/lib/jcef/java/org/cef/misc/StringRef.java @@ -0,0 +1,26 @@ +// 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 org.cef.misc; + +/** + * Helper class for passing String values by reference. + */ +public class StringRef { + private String value_; + + public StringRef() {} + + public StringRef(String value) { + value_ = value; + } + + public void set(String value) { + value_ = value; + } + + public String get() { + return value_; + } +} diff --git a/lib/jcef/java/org/cef/network/CefCookie.java b/lib/jcef/java/org/cef/network/CefCookie.java new file mode 100644 index 0000000..5020ba1 --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefCookie.java @@ -0,0 +1,77 @@ +// 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 org.cef.network; + +import java.util.Date; + +/** + * Cookie information. + */ +public final class CefCookie { + public CefCookie(String name, String value, String domain, String path, boolean secure, + boolean httponly, Date creation, Date lastAccess, boolean hasExpires, Date expires) { + this.name = name; + this.value = value; + this.domain = domain; + this.path = path; + this.secure = secure; + this.httponly = httponly; + this.creation = creation; + this.lastAccess = lastAccess; + this.hasExpires = hasExpires; + this.expires = expires; + } + + /** + * The cookie name. + */ + public final String name; + + /** + * The cookie value. + */ + public final String value; + + /** + * If domain is empty a host cookie will be created instead of a domain + * cookie. Domain cookies are stored with a leading "." and are visible to + * sub-domains whereas host cookies are not. + */ + public final String domain; + + /** + * If path is non-empty only URLs at or below the path will get the cookie + * value. + */ + public final String path; + + /** + * If secure is true the cookie will only be sent for HTTPS requests. + */ + public final boolean secure; + + /** + * If httponly is true the cookie will only be sent for HTTP requests. + */ + public final boolean httponly; + + /** + * The cookie creation date. This is automatically populated by the system on + * cookie creation. + */ + public final Date creation; + + /** + * The cookie last access date. This is automatically populated by the system + * on access. + */ + public final Date lastAccess; + + /** + * The cookie expiration date is only valid if |has_expires| is true. + */ + public final boolean hasExpires; + public final Date expires; +} diff --git a/lib/jcef/java/org/cef/network/CefCookieManager.java b/lib/jcef/java/org/cef/network/CefCookieManager.java new file mode 100644 index 0000000..83ee66d --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefCookieManager.java @@ -0,0 +1,88 @@ +// 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 org.cef.network; + +import org.cef.callback.CefCompletionCallback; +import org.cef.callback.CefCookieVisitor; + +import java.util.Vector; + +/** + * Class used for managing cookies. The methods of this class may be called on any thread unless + * otherwise indicated. + */ +public abstract class CefCookieManager { + // This CTOR can't be called directly. Call method create() instead. + CefCookieManager() {} + + @Override + protected void finalize() throws Throwable { + dispose(); + super.finalize(); + } + + /** + * Returns the global cookie manager. By default data will be stored at CefSettings.cache_path + * if specified or in memory otherwise. + * @return The global cookie manager. + */ + public static final CefCookieManager getGlobalManager() { + return CefCookieManager_N.getGlobalManagerNative(); + } + + /** + * Removes the native reference from an unused object. + */ + public abstract void dispose(); + + /** + * Visit all cookies. The returned cookies are ordered by longest path, then by earliest + * creation date. + * @param visitor Callback that will receive cookies on the UI thread. + * @return False if cookies cannot be accessed. + */ + public abstract boolean visitAllCookies(CefCookieVisitor visitor); + + /** + * Visit a subset of cookies. The returned cookies are ordered by longest path, then by earliest + * creation date. + * @param url Results are filtered by the given url scheme, host, domain and path. + * @param includeHttpOnly If true HTTP-only cookies will also be included in the results. + * @param visitor Callback that will receive cookies on the UI thread. + * @return False if cookies cannot be accessed. + */ + public abstract boolean visitUrlCookies( + String url, boolean includeHttpOnly, CefCookieVisitor visitor); + + /** + * Sets a cookie given a valid URL and explicit user-provided cookie attributes. This function + * expects each attribute to be well-formed. It will check for disallowed characters (e.g. the + * ';' character is disallowed within the cookie value attribute) and fail without setting the + * cookie if such characters are found. + * @param url The cookie URL. + * @param cookie The cookie attributes. + * @return False if an invalid URL is specified or if cookies cannot be accessed. + */ + public abstract boolean setCookie(String url, CefCookie cookie); + + /** + * Delete all cookies that match the specified parameters. If both |url| and |cookieName| values + * are specified all host and domain cookies matching both will be deleted. If only |url| is + * specified all host cookies (but not domain cookies) irrespective of path will be deleted. If + * |url| is empty all cookies for all hosts and domains will be deleted. Cookies can alternately + * be deleted using the visit*Cookies() methods. + * @param url The cookie URL to delete or null. + * @param cookieName The cookie name to delete or null. + * @return False if a non-empty invalid URL is secified or if cookies cannot be accessed. + */ + public abstract boolean deleteCookies(String url, String cookieName); + + /** + * Flush the backing store (if any) to disk. + * @param handler Callback that will be executed on the UI thread upon completion. + * @return False if cookies cannot be accessed. + */ + public abstract boolean flushStore(CefCompletionCallback handler); +} diff --git a/lib/jcef/java/org/cef/network/CefCookieManager_N.java b/lib/jcef/java/org/cef/network/CefCookieManager_N.java new file mode 100644 index 0000000..846240b --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefCookieManager_N.java @@ -0,0 +1,116 @@ +// 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 org.cef.network; + +import org.cef.callback.CefCompletionCallback; +import org.cef.callback.CefCookieVisitor; +import org.cef.callback.CefNative; + +import java.util.Vector; + +class CefCookieManager_N extends CefCookieManager implements CefNative { + // Used internally to store a pointer to the CEF object. + private long N_CefHandle = 0; + private static CefCookieManager_N globalInstance = null; + + @Override + public void setNativeRef(String identifer, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return N_CefHandle; + } + + CefCookieManager_N() { + super(); + } + + static synchronized final CefCookieManager_N getGlobalManagerNative() { + if (globalInstance != null && globalInstance.N_CefHandle != 0) { + // The global instance is still valid. + return globalInstance; + } + + CefCookieManager_N result = null; + try { + result = CefCookieManager_N.N_GetGlobalManager(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + + globalInstance = result; + return globalInstance; + } + + @Override + public void dispose() { + try { + N_Dispose(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean visitAllCookies(CefCookieVisitor visitor) { + try { + return N_VisitAllCookies(N_CefHandle, visitor); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean visitUrlCookies(String url, boolean includeHttpOnly, CefCookieVisitor visitor) { + try { + return N_VisitUrlCookies(N_CefHandle, url, includeHttpOnly, visitor); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean setCookie(String url, CefCookie cookie) { + try { + return N_SetCookie(N_CefHandle, url, cookie); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean deleteCookies(String url, String cookieName) { + try { + return N_DeleteCookies(N_CefHandle, url, cookieName); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean flushStore(CefCompletionCallback handler) { + try { + return N_FlushStore(N_CefHandle, handler); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + private final static native CefCookieManager_N N_GetGlobalManager(); + private final native void N_Dispose(long self); + private final native boolean N_VisitAllCookies(long self, CefCookieVisitor visitor); + private final native boolean N_VisitUrlCookies( + long self, String url, boolean includeHttpOnly, CefCookieVisitor visitor); + private final native boolean N_SetCookie(long self, String url, CefCookie cookie); + private final native boolean N_DeleteCookies(long self, String url, String cookieName); + private final native boolean N_FlushStore(long self, CefCompletionCallback handler); +} diff --git a/lib/jcef/java/org/cef/network/CefPostData.java b/lib/jcef/java/org/cef/network/CefPostData.java new file mode 100644 index 0000000..85ba6f9 --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefPostData.java @@ -0,0 +1,81 @@ +// 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 org.cef.network; + +import java.util.Vector; + +/** + * Class used to represent post data for a web request. The methods of this + * class may be called on any thread. + */ +public abstract class CefPostData { + // This CTOR can't be called directly. Call method create() instead. + CefPostData() {} + + @Override + protected void finalize() throws Throwable { + dispose(); + super.finalize(); + } + + /** + * Create a new CefPostData object. + */ + public static final CefPostData create() { + return CefPostData_N.createNative(); + } + + /** + * Removes the native reference from an unused object. + */ + public abstract void dispose(); + + /** + * Returns true if this object is read-only. + */ + public abstract boolean isReadOnly(); + + /** + * Returns the number of existing post data elements. + */ + public abstract int getElementCount(); + + /** + * Retrieve the post data elements. + */ + public abstract void getElements(Vector elements); + + /** + * Remove the specified post data element. Returns true if the removal + * succeeds. + */ + public abstract boolean removeElement(CefPostDataElement element); + + /** + * Add the specified post data element. Returns true if the add succeeds. + */ + public abstract boolean addElement(CefPostDataElement element); + + /** + * Remove all existing post data elements. + */ + public abstract void removeElements(); + + @Override + public String toString() { + return toString(null); + } + + public String toString(String mimeType) { + Vector elements = new Vector(); + getElements(elements); + + String returnValue = ""; + for (CefPostDataElement el : elements) { + returnValue += el.toString(mimeType) + "\n"; + } + return returnValue; + } +} diff --git a/lib/jcef/java/org/cef/network/CefPostDataElement.java b/lib/jcef/java/org/cef/network/CefPostDataElement.java new file mode 100644 index 0000000..576e940 --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefPostDataElement.java @@ -0,0 +1,128 @@ +// 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 org.cef.network; + +/** + * Class used to represent a single element in the request post data. The + * methods of this class may be called on any thread. + */ +public abstract class CefPostDataElement { + /** + * Post data elements may represent either bytes or files. + */ + 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. + CefPostDataElement() {} + + @Override + protected void finalize() throws Throwable { + dispose(); + super.finalize(); + } + + /** + * Create a new CefPostDataElement object. + */ + public static final CefPostDataElement create() { + return CefPostDataElement_N.createNative(); + } + + /** + * Removes the native reference from an unused object. + */ + public abstract void dispose(); + + /** + * Returns true if this object is read-only. + */ + public abstract boolean isReadOnly(); + + /** + * Remove all contents from the post data element. + */ + public abstract void setToEmpty(); + + /** + * The post data element will represent a file. + */ + public abstract void setToFile(String fileName); + + /** + * The post data element will represent bytes. The bytes passed + * in will be copied. + */ + public abstract void setToBytes(int size, byte[] bytes); + + /** + * Return the type of this post data element. + */ + public abstract Type getType(); + + /** + * Return the file name. + */ + public abstract String getFile(); + + /** + * Return the number of bytes. + */ + public abstract int getBytesCount(); + + /** + * Read up to size bytes into bytes and return the number of bytes + * actually read. + */ + public abstract int getBytes(int size, byte[] bytes); + + @Override + public String toString() { + return toString(null); + } + + public String toString(String mimeType) { + int bytesCnt = getBytesCount(); + byte[] bytes = null; + if (bytesCnt > 0) { + bytes = new byte[bytesCnt]; + } + + boolean asText = false; + if (mimeType != null) { + if (mimeType.startsWith("text/")) + asText = true; + else if (mimeType.startsWith("application/xml")) + asText = true; + else if (mimeType.startsWith("application/xhtml")) + asText = true; + else if (mimeType.startsWith("application/x-www-form-urlencoded")) + asText = true; + } + + String returnValue = ""; + + if (getType() == Type.PDE_TYPE_BYTES) { + int setBytes = getBytes(bytes.length, bytes); + returnValue += " Content-Length: " + bytesCnt + "\n"; + if (asText) { + returnValue += "\n " + new String(bytes); + } else { + for (int i = 0; i < setBytes; i++) { + if (i % 40 == 0) returnValue += "\n "; + returnValue += String.format("%02X", bytes[i]) + " "; + } + } + returnValue += "\n"; + } else if (getType() == Type.PDE_TYPE_FILE) { + returnValue += "\n Bytes of file: " + getFile() + "\n"; + } + return returnValue; + } +} diff --git a/lib/jcef/java/org/cef/network/CefPostDataElement_N.java b/lib/jcef/java/org/cef/network/CefPostDataElement_N.java new file mode 100644 index 0000000..6d3fddd --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefPostDataElement_N.java @@ -0,0 +1,132 @@ +// 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 org.cef.network; + +import org.cef.callback.CefNative; + +class CefPostDataElement_N extends CefPostDataElement implements CefNative { + // Used internally to store a pointer to the CEF object. + private long N_CefHandle = 0; + + @Override + public void setNativeRef(String identifer, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return N_CefHandle; + } + + CefPostDataElement_N() { + super(); + } + + public static CefPostDataElement createNative() { + try { + return CefPostDataElement_N.N_Create(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public void dispose() { + try { + N_Dispose(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean isReadOnly() { + try { + return N_IsReadOnly(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public void setToEmpty() { + try { + N_SetToEmpty(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void setToFile(String fileName) { + try { + N_SetToFile(N_CefHandle, fileName); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void setToBytes(int size, byte[] bytes) { + try { + N_SetToBytes(N_CefHandle, size, bytes); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public Type getType() { + try { + return N_GetType(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public String getFile() { + try { + return N_GetFile(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public int getBytesCount() { + try { + return N_GetBytesCount(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public int getBytes(int size, byte[] bytes) { + try { + return N_GetBytes(N_CefHandle, size, bytes); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + private final native static CefPostDataElement_N N_Create(); + private final native void N_Dispose(long self); + private final native boolean N_IsReadOnly(long self); + private final native void N_SetToEmpty(long self); + private final native void N_SetToFile(long self, String fileName); + private final native void N_SetToBytes(long self, int size, byte[] bytes); + private final native Type N_GetType(long self); + private final native String N_GetFile(long self); + private final native int N_GetBytesCount(long self); + private final native int N_GetBytes(long self, int size, byte[] bytes); +} diff --git a/lib/jcef/java/org/cef/network/CefPostData_N.java b/lib/jcef/java/org/cef/network/CefPostData_N.java new file mode 100644 index 0000000..3b79cf5 --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefPostData_N.java @@ -0,0 +1,116 @@ +// 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 org.cef.network; + +import org.cef.callback.CefNative; + +import java.util.Vector; + +/** + * + */ +class CefPostData_N extends CefPostData implements CefNative { + // Used internally to store a pointer to the CEF object. + private long N_CefHandle = 0; + + @Override + public void setNativeRef(String identifer, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return N_CefHandle; + } + + CefPostData_N() { + super(); + } + + public static CefPostData createNative() { + try { + return CefPostData_N.N_Create(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public void dispose() { + try { + N_Dispose(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean isReadOnly() { + try { + return N_IsReadOnly(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public int getElementCount() { + try { + return N_GetElementCount(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public void getElements(Vector elements) { + try { + N_GetElements(N_CefHandle, elements); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean removeElement(CefPostDataElement element) { + try { + return N_RemoveElement(N_CefHandle, element); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public boolean addElement(CefPostDataElement element) { + try { + return N_AddElement(N_CefHandle, element); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public void removeElements() { + try { + N_RemoveElements(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native static CefPostData_N N_Create(); + private final native void N_Dispose(long self); + private final native boolean N_IsReadOnly(long self); + private final native int N_GetElementCount(long self); + private final native void N_GetElements(long self, Vector elements); + private final native boolean N_RemoveElement(long self, CefPostDataElement element); + private final native boolean N_AddElement(long self, CefPostDataElement element); + private final native void N_RemoveElements(long self); +} diff --git a/lib/jcef/java/org/cef/network/CefRequest.java b/lib/jcef/java/org/cef/network/CefRequest.java new file mode 100644 index 0000000..5ce6445 --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefRequest.java @@ -0,0 +1,506 @@ +// 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 org.cef.network; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +/** + * Class used to represent a web request. The methods of this class may be + * called on any thread. + */ +public abstract class CefRequest { + /** + * Resource type for a request. + */ + public enum ResourceType { + RT_MAIN_FRAME, //!< Top level page. + RT_SUB_FRAME, //!< Frame or iframe. + RT_STYLESHEET, //!< CSS stylesheet. + RT_SCRIPT, //!< External script. + RT_IMAGE, //!< Image (jpg/gif/png/etc). + RT_FONT_RESOURCE, //!< Font. + RT_SUB_RESOURCE, //!< Some other subresource. This is the default type if + // the actual type is unknown. + RT_OBJECT, //!< Object (or embed) tag for a plugin, or a resource + // that a plugin requested. + RT_MEDIA, //!< Media resource. + RT_WORKER, //!< Main resource of a dedicated worker. + RT_SHARED_WORKER, //!< Main resource of a shared worker. + RT_PREFETCH, //!< Explicitly requested prefetch. + RT_FAVICON, //!< Favicon. + RT_XHR, //!< XMLHttpRequest. + RT_PING, //!< A request for a + RT_SERVICE_WORKER, //!< Main resource of a service worker. + RT_CSP_REPORT, //!< A report of Content Security Policy violations. + RT_PLUGIN_RESOURCE, //!< A resource that a plugin requested. + 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, + } + + /** + * Transition type for a request. Made up of one source value and 0 or more + * qualifiers. + */ + public enum TransitionType { + /** + * Source is a link click or the JavaScript window.open function. This is + * also the default value for requests like sub-resource loads that are not + * navigations. + */ + TT_LINK(0), + + /** + * Source is some other "explicit" navigation action such as creating a new + * browser or using the LoadURL function. This is also the default value + * for navigations where the actual type is unknown. + */ + TT_EXPLICIT(1), + + /** + * Source is a subframe navigation. This is any content that is automatically + * loaded in a non-toplevel frame. For example, if a page consists of several + * frames containing ads, those ad URLs will have this transition type. + * The user may not even realize the content in these pages is a separate + * frame, so may not care about the URL. + */ + TT_AUTO_SUBFRAME(3), + + /** + * Source is a subframe navigation explicitly requested by the user that will + * generate new navigation entries in the back/forward list. These are + * probably more important than frames that were automatically loaded in + * the background because the user probably cares about the fact that this + * link was loaded. + */ + TT_MANUAL_SUBFRAME(4), + + /** + * Source is a form submission by the user. NOTE: In some situations + * submitting a form does not result in this transition type. This can happen + * if the form uses a script to submit the contents. + */ + TT_FORM_SUBMIT(7), + + /** + * Source is a "reload" of the page via the Reload function or by re-visiting + * the same URL. NOTE: This is distinct from the concept of whether a + * particular load uses "reload semantics" (i.e. bypasses cached data). + */ + TT_RELOAD(8); + + private int value; + private TransitionType(int source) { + value = source; + } + + /** + * Returns the integer representation of this enum, containing the source + * and the qualifier as one value. + * @return The integer value of the enum with all its qualifiers. + */ + public int getValue() { + return value; + } + + /** + * Returns the source part of the enum as integer. + * @return Integer representation of the set source. + */ + public int getSource() { + return (value & 0xFF); + } + + /** + * Any of the core values above can be augmented by one or more qualifiers + * defined as TransitionFlags. + * These qualifiers further define the transition. + */ + public void addQualifier(TransitionFlags flag) { + value |= flag.getValue(); + } + + /** + * Add qualifiers as integer value + */ + public void addQualifiers(int flags) { + value |= (flags & 0xFFFFFF00); + } + + /** + * Returns the qualifier part of the enum as integer. + * @return Integer representation of the set qualifiers. + */ + public int getQualifiers() { + return (value & 0xFFFFFF00); + } + + /** + * Removes a qualifier from the enum. + * @param The qualifier to be removed. + */ + public void removeQualifier(TransitionFlags flag) { + value &= ~flag.getValue(); + } + + /** + * Tests if a qualifier is set. + */ + public boolean isSet(TransitionFlags flag) { + return (value & flag.getValue()) != 0; + } + + /** + * Tests if one of the redirect qualifiers is set. + */ + public boolean isRedirect() { + return (value & 0xC0000000) != 0; + } + } + + public static final class CefUrlRequestFlags { + /** + * Default behavior. + */ + public static final int UR_FLAG_NONE = 0; + + /** + * If set the cache will be skipped when handling the request. + */ + public static final int UR_FLAG_SKIP_CACHE = 1 << 0; + + /** + * If set user name, password, and cookies may be sent with the request, and + * cookies may be saved from the response. + */ + public static final int UR_FLAG_ALLOW_CACHED_CREDENTIALS = 1 << 1; + + /** + * If set upload progress events will be generated when a request has a body. + */ + public static final int UR_FLAG_REPORT_UPLOAD_PROGRESS = 1 << 3; + + /** + * If set the headers sent and received for the request will be recorded. + */ + public static final int UR_FLAG_REPORT_RAW_HEADERS = 1 << 5; + + /** + * If set the CefURLRequestClient.onDownloadData method will not be called. + */ + public static final int UR_FLAG_NO_DOWNLOAD_DATA = 1 << 6; + + /** + * If set 5XX redirect errors will be propagated to the observer instead of + * automatically re-tried. This currently only applies for requests + * originated in the browser process. + */ + public static final int UR_FLAG_NO_RETRY_ON_5XX = 1 << 7; + } + + /** + * Transition qualifiers. + * Any of the core values above can be augmented by one or more qualifiers. + * These qualifiers further define the transition. + */ + public enum TransitionFlags { + /** + * Attempted to visit a URL but was blocked. + */ + TT_BLOCKED_FLAG(0x00800000), + + /** + * Used the Forward or Back function to navigate among browsing history. + */ + TT_FORWARD_BACK_FLAG(0x01000000), + + /** + * The beginning of a navigation chain. + */ + TT_CHAIN_START_FLAG(0x10000000), + + /** + * The last transition in a redirect chain. + */ + TT_CHAIN_END_FLAG(0x20000000), + + /** + * Redirects caused by JavaScript or a meta refresh tag on the page. + */ + TT_CLIENT_REDIRECT_FLAG(0x40000000), + + /** + * Redirects sent from the server by HTTP headers. + */ + TT_SERVER_REDIRECT_FLAG(0x80000000); + + private final int flag; + private TransitionFlags(int flag) { + this.flag = flag; + } + + /** + * Returns the integer representation of the enum. + * @return Integer representation of the enum. + */ + public int getValue() { + return flag; + } + } + + /** + * Policy for how the Referrer HTTP header value will be sent during navigation. + * If the `--no-referrers` command-line flag is specified then the policy value + * will be ignored and the Referrer value will never be sent. + */ + public enum ReferrerPolicy { + + /** + * This is the same as REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE + * but here to match CEF native. + */ + REFERRER_POLICY_DEFAULT, + + /** + * Clear the referrer header if the header value is HTTPS but the request + * destination is HTTP. This is the default behavior. + */ + REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, + + /** + * A slight variant on CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE: + * If the request destination is HTTP, an HTTPS referrer will be cleared. If + * the request's destination is cross-origin with the referrer (but does not + * downgrade), the referrer's granularity will be stripped down to an origin + * rather than a full URL. Same-origin requests will send the full referrer. + */ + REFERRER_POLICY_REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, + + /** + * Strip the referrer down to an origin when the origin of the referrer is + * different from the destination's origin. + */ + REFERRER_POLICY_ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, + + /** + * Never change the referrer. + */ + REFERRER_POLICY_NEVER_CLEAR_REFERRER, + + /** + * Strip the referrer down to the origin regardless of the redirect location. + */ + REFERRER_POLICY_ORIGIN, + + /** + * Clear the referrer when the request's referrer is cross-origin with the + * request destination. + */ + REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN, + + /** + * Strip the referrer down to the origin, but clear it entirely if the + * referrer value is HTTPS and the destination is HTTP. + */ + REFERRER_POLICY_ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, + + /** + * Always clear the referrer regardless of the request destination. + */ + REFERRER_POLICY_NO_REFERRER, + + /** + * Always the last value in this enumeration. + */ + REFERRER_POLICY_NUM_VALUES + } + + // This CTOR can't be called directly. Call method create() instead. + CefRequest() {} + + @Override + protected void finalize() throws Throwable { + dispose(); + super.finalize(); + } + + /** + * Create a new CefRequest object. + */ + public static final CefRequest create() { + return CefRequest_N.createNative(); + } + + /** + * Removes the native reference from an unused object. + */ + public abstract void dispose(); + + /** + * Returns the globally unique identifier for this request or 0 if not + * specified. Can be used by CefRequestHandler implementations in the browser + * process to track a single request across multiple callbacks. + */ + public abstract long getIdentifier(); + + /** + * Returns true if this object is read-only. + */ + public abstract boolean isReadOnly(); + + /** + * Get the fully qualified URL. + */ + public abstract String getURL(); + + /** + * Set the fully qualified URL. + */ + public abstract void setURL(String url); + + /** + * Get the request method type. The value will default to POST if post data + * is provided and GET otherwise. + */ + public abstract String getMethod(); + + /** + * Set the request method type. + */ + public abstract void setMethod(String method); + + /** + * Set the referrer URL and policy. If non-empty the referrer URL must be + * fully qualified with an HTTP or HTTPS scheme component. Any username, + * password or ref component will be removed. + */ + public abstract void setReferrer(String url, ReferrerPolicy policy); + + /** + * Get the referrer URL. + */ + public abstract String getReferrerURL(); + + /** + * Get the referrer policy. + */ + public abstract ReferrerPolicy getReferrerPolicy(); + + /** + * Get the post data. + */ + public abstract CefPostData getPostData(); + + /** + * Set the post data. + */ + public abstract void setPostData(CefPostData postData); + + /** + * Get the value for the specified response header field. The Referer value cannot be retrieved + * using this method. Use getHeaderMap instead if there might be multiple values. + * @param name The header name. + * @return The header value. + */ + public abstract String getHeaderByName(String name); + + /** + * Set the value for the specified response header field. The Referer value cannot be set using + * this method. + * @param name The header name. + * @param value The header value. + * @param overwrite If true any existing values will be replaced with the new value. If false + * any existing values will not be overwritten. + */ + public abstract void setHeaderByName(String name, String value, boolean overwrite); + + /** + * Get the header values. + */ + public abstract void getHeaderMap(Map headerMap); + + /** + * Set the header values. + */ + public abstract void setHeaderMap(Map headerMap); + + /** + * Set all values at one time. + */ + public abstract void set( + String url, String method, CefPostData postData, Map headerMap); + + /** + * Get the flags used in combination with CefURLRequest. See + * CefUrlRequestFlags for supported values. + */ + public abstract int getFlags(); + + /** + * Set the flags used in combination with CefURLRequest. See + * CefUrlRequestFlags for supported values. + */ + public abstract void setFlags(int flags); + + /** + * Get the URL to the first party for cookies used in combination with + * CefURLRequest. + */ + public abstract String getFirstPartyForCookies(); + + /** + * Set the URL to the first party for cookies used in combination with + * CefURLRequest. + */ + public abstract void setFirstPartyForCookies(String url); + + /** + * Get the resource type for this request. Accurate resource type information + * may only be available in the browser process. + */ + public abstract ResourceType getResourceType(); + + /** + * Get the transition type for this request. Only available in the browser + * process and only applies to requests that represent a main frame or + * sub-frame navigation. + */ + public abstract TransitionType getTransitionType(); + + @Override + public String toString() { + String returnValue = "\nHTTP-Request"; + returnValue += "\n flags: " + getFlags(); + returnValue += "\n resourceType: " + getResourceType(); + returnValue += "\n transitionType: " + getTransitionType(); + returnValue += "\n firstPartyForCookies: " + getFirstPartyForCookies(); + returnValue += "\n referrerURL: " + getReferrerURL(); + returnValue += "\n referrerPolicy: " + getReferrerPolicy(); + returnValue += "\n " + getMethod() + " " + getURL() + " HTTP/1.1\n"; + + Map headerMap = new HashMap<>(); + getHeaderMap(headerMap); + Set> entrySet = headerMap.entrySet(); + String mimeType = null; + for (Entry entry : entrySet) { + String key = entry.getKey(); + returnValue += " " + key + "=" + entry.getValue() + "\n"; + if (key.equals("Content-Type")) { + mimeType = entry.getValue(); + } + } + + CefPostData pd = getPostData(); + if (pd != null) { + returnValue += pd.toString(mimeType); + } + + return returnValue; + } +} diff --git a/lib/jcef/java/org/cef/network/CefRequest_N.java b/lib/jcef/java/org/cef/network/CefRequest_N.java new file mode 100644 index 0000000..71bdf00 --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefRequest_N.java @@ -0,0 +1,284 @@ +// 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 org.cef.network; + +import org.cef.callback.CefNative; + +import java.util.Map; + +class CefRequest_N extends CefRequest implements CefNative { + // Used internally to store a pointer to the CEF object. + private long N_CefHandle = 0; + + @Override + public void setNativeRef(String identifer, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return N_CefHandle; + } + + CefRequest_N() { + super(); + } + + public static CefRequest createNative() { + try { + return CefRequest_N.N_Create(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public void dispose() { + try { + N_Dispose(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public long getIdentifier() { + try { + return N_GetIdentifier(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public boolean isReadOnly() { + try { + return N_IsReadOnly(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public String getURL() { + try { + return N_GetURL(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void setURL(String url) { + try { + N_SetURL(N_CefHandle, url); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public String getMethod() { + try { + return N_GetMethod(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void setMethod(String string) { + try { + N_SetMethod(N_CefHandle, string); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void setReferrer(String url, ReferrerPolicy policy) { + try { + N_SetReferrer(N_CefHandle, url, policy); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public String getReferrerURL() { + try { + return N_GetReferrerURL(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public ReferrerPolicy getReferrerPolicy() { + try { + return N_GetReferrerPolicy(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public CefPostData getPostData() { + try { + return N_GetPostData(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void setPostData(CefPostData postData) { + try { + N_SetPostData(N_CefHandle, postData); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public String getHeaderByName(String name) { + try { + return N_GetHeaderByName(N_CefHandle, name); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void setHeaderByName(String name, String value, boolean overwrite) { + try { + N_SetHeaderByName(N_CefHandle, name, value, overwrite); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void getHeaderMap(Map headerMap) { + try { + N_GetHeaderMap(N_CefHandle, headerMap); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void setHeaderMap(Map headerMap) { + try { + N_SetHeaderMap(N_CefHandle, headerMap); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void set( + String url, String method, CefPostData postData, Map headerMap) { + try { + N_Set(N_CefHandle, url, method, postData, headerMap); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public int getFlags() { + try { + return N_GetFlags(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public void setFlags(int flags) { + try { + N_SetFlags(N_CefHandle, flags); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public String getFirstPartyForCookies() { + try { + return N_GetFirstPartyForCookies(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void setFirstPartyForCookies(String url) { + try { + N_SetFirstPartyForCookies(N_CefHandle, url); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public ResourceType getResourceType() { + try { + return N_GetResourceType(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return ResourceType.RT_MAIN_FRAME; + } + + @Override + public TransitionType getTransitionType() { + try { + return N_GetTransitionType(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return TransitionType.TT_AUTO_SUBFRAME; + } + + private final native static CefRequest_N N_Create(); + private final native void N_Dispose(long self); + private final native long N_GetIdentifier(long self); + private final native boolean N_IsReadOnly(long self); + private final native String N_GetURL(long self); + private final native void N_SetURL(long self, String url); + private final native String N_GetMethod(long self); + private final native void N_SetMethod(long self, String method); + private final native void N_SetReferrer(long self, String url, ReferrerPolicy policy); + private final native String N_GetReferrerURL(long self); + private final native ReferrerPolicy N_GetReferrerPolicy(long self); + private final native CefPostData N_GetPostData(long self); + private final native void N_SetPostData(long self, CefPostData postData); + private final native String N_GetHeaderByName(long self, String name); + private final native void N_SetHeaderByName( + long self, String name, String value, boolean overwrite); + private final native void N_GetHeaderMap(long self, Map headerMap); + private final native void N_SetHeaderMap(long self, Map headerMap); + private final native void N_Set(long self, String url, String method, CefPostData postData, + Map headerMap); + private final native int N_GetFlags(long self); + private final native void N_SetFlags(long self, int flags); + private final native String N_GetFirstPartyForCookies(long self); + private final native void N_SetFirstPartyForCookies(long self, String url); + private final native ResourceType N_GetResourceType(long self); + private final native TransitionType N_GetTransitionType(long self); +} diff --git a/lib/jcef/java/org/cef/network/CefResponse.java b/lib/jcef/java/org/cef/network/CefResponse.java new file mode 100644 index 0000000..fe705ba --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefResponse.java @@ -0,0 +1,130 @@ +// 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 org.cef.network; + +import org.cef.handler.CefLoadHandler.ErrorCode; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +/** + * Class used to represent a web response. The methods of this class may be + * called on any thread. + */ +public abstract class CefResponse { + // This CTOR can't be called directly. Call method create() instead. + CefResponse() {} + + @Override + protected void finalize() throws Throwable { + dispose(); + super.finalize(); + } + + /** + * Create a new CefRequest object. + */ + public static final CefResponse create() { + return CefResponse_N.createNative(); + } + + /** + * Removes the native reference from an unused object. + */ + public abstract void dispose(); + + /** + * Returns true if this object is read-only. + */ + public abstract boolean isReadOnly(); + + /** + * Get the response error code. Returns ERR_NONE if there was no error. + */ + public abstract ErrorCode getError(); + + /** + * Get the response error code. Returns ERR_NONE if there was no error. + */ + public abstract void setError(ErrorCode errorCode); + + /** + * Get the response status code. + */ + public abstract int getStatus(); + + /** + * Set the response status code. + */ + public abstract void setStatus(int status); + + /** + * Get the response status text. + */ + public abstract String getStatusText(); + + /** + * Set the response status text. + */ + public abstract void setStatusText(String statusText); + + /** + * Get the response mime type. + */ + public abstract String getMimeType(); + + /** + * Set the response mime type. + */ + public abstract void setMimeType(String mimeType); + + /** + * Get the value for the specified response header field. Use getHeaderMap instead if there + * might be multiple values. + * @param name The header name. + * @return The header value. + */ + public abstract String getHeaderByName(String name); + + /** + * Set the value for the specified response header field. + * @param name The header name. + * @param value The header value. + * @param overwrite If true any existing values will be replaced with the new value. If false + * any existing values will not be overwritten. + */ + public abstract void setHeaderByName(String name, String value, boolean overwrite); + + /** + * Get all response header fields. + */ + public abstract void getHeaderMap(Map headerMap); + + /** + * Set all response header fields. + */ + public abstract void setHeaderMap(Map headerMap); + + @Override + public String toString() { + String returnValue = "\nHTTP-Response:"; + + returnValue += "\n error: " + getError(); + returnValue += "\n readOnly: " + isReadOnly(); + returnValue += "\n HTTP/1.1 " + getStatus() + " " + getStatusText(); + returnValue += "\n Content-Type: " + getMimeType(); + + Map headerMap = new HashMap<>(); + getHeaderMap(headerMap); + Set> entrySet = headerMap.entrySet(); + for (Entry entry : entrySet) { + returnValue += " " + entry.getKey() + "=" + entry.getValue() + "\n"; + } + + return returnValue; + } +} diff --git a/lib/jcef/java/org/cef/network/CefResponse_N.java b/lib/jcef/java/org/cef/network/CefResponse_N.java new file mode 100644 index 0000000..60e2525 --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefResponse_N.java @@ -0,0 +1,187 @@ +// 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 org.cef.network; + +import org.cef.callback.CefNative; +import org.cef.handler.CefLoadHandler.ErrorCode; + +import java.util.Map; + +class CefResponse_N extends CefResponse implements CefNative { + // Used internally to store a pointer to the CEF object. + private long N_CefHandle = 0; + + @Override + public void setNativeRef(String identifer, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return N_CefHandle; + } + + CefResponse_N() { + super(); + } + + public static CefResponse createNative() { + try { + return CefResponse_N.N_Create(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + return null; + } + } + + @Override + public void dispose() { + try { + N_Dispose(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public boolean isReadOnly() { + try { + return N_IsReadOnly(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return false; + } + + @Override + public ErrorCode getError() { + try { + return N_GetError(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void setError(ErrorCode errorCode) { + try { + N_SetError(N_CefHandle, errorCode); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public int getStatus() { + try { + return N_GetStatus(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return 0; + } + + @Override + public void setStatus(int status) { + try { + N_SetStatus(N_CefHandle, status); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public String getStatusText() { + try { + return N_GetStatusText(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void setStatusText(String statusText) { + try { + N_SetStatusText(N_CefHandle, statusText); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public String getMimeType() { + try { + return N_GetMimeType(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void setMimeType(String mimeType) { + try { + N_SetMimeType(N_CefHandle, mimeType); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public String getHeaderByName(String name) { + try { + return N_GetHeaderByName(N_CefHandle, name); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void setHeaderByName(String name, String value, boolean overwrite) { + try { + N_SetHeaderByName(N_CefHandle, name, value, overwrite); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void getHeaderMap(Map headerMap) { + try { + N_GetHeaderMap(N_CefHandle, headerMap); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void setHeaderMap(Map headerMap) { + try { + N_SetHeaderMap(N_CefHandle, headerMap); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native static CefResponse_N N_Create(); + private final native void N_Dispose(long self); + private final native boolean N_IsReadOnly(long self); + private final native ErrorCode N_GetError(long self); + private final native void N_SetError(long self, ErrorCode errorCode); + private final native int N_GetStatus(long self); + private final native void N_SetStatus(long self, int status); + private final native String N_GetStatusText(long self); + private final native void N_SetStatusText(long self, String statusText); + private final native String N_GetMimeType(long self); + private final native void N_SetMimeType(long self, String mimeType); + private final native String N_GetHeaderByName(long self, String name); + private final native void N_SetHeaderByName( + long self, String name, String value, boolean overwrite); + private final native void N_GetHeaderMap(long self, Map headerMap); + private final native void N_SetHeaderMap(long self, Map headerMap); +} diff --git a/lib/jcef/java/org/cef/network/CefURLRequest.java b/lib/jcef/java/org/cef/network/CefURLRequest.java new file mode 100644 index 0000000..2327cd4 --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefURLRequest.java @@ -0,0 +1,89 @@ +// 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 org.cef.network; + +import org.cef.callback.CefURLRequestClient; +import org.cef.handler.CefLoadHandler.ErrorCode; + +/** + * Class used to make a URL request. URL requests are not associated with a + * browser instance so no CefClient callbacks will be executed. URL requests + * can be created on any valid CEF thread in either the browser or render + * process. Once created the methods of the URL request object must be accessed + * on the same thread that created it. + */ +public abstract class CefURLRequest { + public static enum Status { + UR_UNKNOWN, + UR_SUCCESS, + UR_IO_PENDING, + UR_CANCELED, + UR_FAILED, + } + + // This CTOR can't be called directly. Call method create() instead. + CefURLRequest() {} + + @Override + protected void finalize() throws Throwable { + dispose(); + super.finalize(); + } + + /** + * Create a new URL request. Only GET, POST, HEAD, DELETE and PUT request + * methods are supported. Multiple post data elements are not supported and + * elements of type PDE_TYPE_FILE are only supported for requests originating + * from the browser process. Requests originating from the render process will + * receive the same handling as requests originating from Web content -- if + * the response contains Content-Disposition or Mime-Type header values that + * would not normally be rendered then the response may receive special + * handling inside the browser (for example, via the file download code path + * instead of the URL request code path). The |request| object will be marked + * as read-only after calling this method. + */ + public static final CefURLRequest create(CefRequest request, CefURLRequestClient client) { + return CefURLRequest_N.createNative(request, client); + } + + /** + * Removes the native reference from an unused object. + */ + public abstract void dispose(); + + /** + * Returns the request object used to create this URL request. The returned + * object is read-only and should not be modified. + */ + public abstract CefRequest getRequest(); + + /** + * Returns the client. + */ + public abstract CefURLRequestClient getClient(); + + /** + * Returns the request status. + */ + public abstract Status getRequestStatus(); + + /** + * Returns the request error if status is UR_CANCELED or UR_FAILED, or 0 + * otherwise. + */ + public abstract ErrorCode getRequestError(); + + /** + * Returns the response, or NULL if no response information is available. + * Response information will only be available after the upload has completed. + * The returned object is read-only and should not be modified. + */ + public abstract CefResponse getResponse(); + + /** + * Cancel the request. + */ + public abstract void cancel(); +} diff --git a/lib/jcef/java/org/cef/network/CefURLRequest_N.java b/lib/jcef/java/org/cef/network/CefURLRequest_N.java new file mode 100644 index 0000000..e5a73ab --- /dev/null +++ b/lib/jcef/java/org/cef/network/CefURLRequest_N.java @@ -0,0 +1,109 @@ +// 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 org.cef.network; + +import org.cef.callback.CefNative; +import org.cef.callback.CefURLRequestClient; +import org.cef.handler.CefLoadHandler.ErrorCode; + +class CefURLRequest_N extends CefURLRequest implements CefNative { + // Used internally to store a pointer to the CEF object. + private long N_CefHandle = 0; + private final CefRequest request_; + private final CefURLRequestClient client_; + + @Override + public void setNativeRef(String identifer, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return N_CefHandle; + } + + CefURLRequest_N(CefRequest request, CefURLRequestClient client) { + super(); + request_ = request; + client_ = client; + } + + public static final CefURLRequest createNative(CefRequest request, CefURLRequestClient client) { + // keep a reference to the request and client objects. + CefURLRequest_N result = new CefURLRequest_N(request, client); + try { + result.N_Create(request, client); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + if (result.N_CefHandle == 0) return null; + return result; + } + + @Override + public void dispose() { + try { + N_Dispose(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public CefRequest getRequest() { + return request_; + } + + @Override + public CefURLRequestClient getClient() { + return client_; + } + + @Override + public Status getRequestStatus() { + try { + return N_GetRequestStatus(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public ErrorCode getRequestError() { + try { + return N_GetRequestError(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public CefResponse getResponse() { + try { + return N_GetResponse(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + return null; + } + + @Override + public void cancel() { + try { + N_Cancel(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Create(CefRequest request, CefURLRequestClient client); + private final native void N_Dispose(long self); + private final native Status N_GetRequestStatus(long self); + private final native ErrorCode N_GetRequestError(long self); + private final native CefResponse N_GetResponse(long self); + private final native void N_Cancel(long self); +} diff --git a/lib/jcef/java/tests/detailed/BrowserFrame.java b/lib/jcef/java/tests/detailed/BrowserFrame.java new file mode 100644 index 0000000..dedcd1f --- /dev/null +++ b/lib/jcef/java/tests/detailed/BrowserFrame.java @@ -0,0 +1,138 @@ +// Copyright (c) 2018 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed; + +import org.cef.CefApp; +import org.cef.browser.CefBrowser; +import org.cef.handler.CefLifeSpanHandlerAdapter; + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class BrowserFrame extends JFrame { + private volatile boolean isClosed_ = false; + private CefBrowser browser_ = null; + private static int browserCount_ = 0; + private Runnable afterParentChangedAction_ = null; + + public BrowserFrame() { + this(null); + } + + public BrowserFrame(String title) { + super(title); + + // Browser window closing works as follows: + // 1. Clicking the window X button calls WindowAdapter.windowClosing. + // 2. WindowAdapter.windowClosing calls CefBrowser.close(false). + // 3. CEF calls CefLifeSpanHandler.doClose() which calls CefBrowser.doClose() + // which returns true (canceling the close). + // 4. CefBrowser.doClose() triggers another call to WindowAdapter.windowClosing. + // 5. WindowAdapter.windowClosing calls CefBrowser.close(true). + // 6. For windowed browsers CEF destroys the native window handle. For OSR + // browsers CEF calls CefLifeSpanHandler.doClose() which calls + // CefBrowser.doClose() again which returns false (allowing the close). + // 7. CEF calls CefLifeSpanHandler.onBeforeClose and the browser is destroyed. + // + // On macOS pressing Cmd+Q results in a call to CefApp.handleBeforeTerminate + // which calls CefBrowser.close(true) for each existing browser. CEF then calls + // CefLifeSpanHandler.onBeforeClose and the browser is destroyed. + // + // Application shutdown works as follows: + // 1. CefLifeSpanHandler.onBeforeClose calls CefApp.getInstance().dispose() + // when the last browser window is destroyed. + // 2. CefAppHandler.stateHasChanged terminates the application by calling + // System.exit(0) when the state changes to CefAppState.TERMINATED. + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + if (browser_ == null) { + // If there's no browser we can dispose immediately. + isClosed_ = true; + System.out.println("BrowserFrame.windowClosing Frame.dispose"); + dispose(); + return; + } + + boolean isClosed = isClosed_; + + if (isClosed) { + // Cause browser.doClose() to return false so that OSR browsers + // can close. + browser_.setCloseAllowed(); + } + + // Results in another call to this method. + System.out.println("BrowserFrame.windowClosing CefBrowser.close(" + isClosed + ")"); + browser_.close(isClosed); + if (!isClosed_) { + isClosed_ = true; + } + if (isClosed) { + // Dispose after the 2nd call to this method. + System.out.println("BrowserFrame.windowClosing Frame.dispose"); + dispose(); + } + } + }); + } + + public void setBrowser(CefBrowser browser) { + if (browser_ == null) browser_ = browser; + + browser_.getClient().removeLifeSpanHandler(); + browser_.getClient().addLifeSpanHandler(new CefLifeSpanHandlerAdapter() { + @Override + public void onAfterCreated(CefBrowser browser) { + System.out.println("BrowserFrame.onAfterCreated id=" + browser.getIdentifier()); + browserCount_++; + } + + @Override + public void onAfterParentChanged(CefBrowser browser) { + System.out.println( + "BrowserFrame.onAfterParentChanged id=" + browser.getIdentifier()); + if (afterParentChangedAction_ != null) { + SwingUtilities.invokeLater(afterParentChangedAction_); + afterParentChangedAction_ = null; + } + } + + @Override + public boolean doClose(CefBrowser browser) { + boolean result = browser.doClose(); + System.out.println("BrowserFrame.doClose id=" + browser.getIdentifier() + + " CefBrowser.doClose=" + result); + return result; + } + + @Override + public void onBeforeClose(CefBrowser browser) { + System.out.println("BrowserFrame.onBeforeClose id=" + browser.getIdentifier()); + if (--browserCount_ == 0) { + System.out.println("BrowserFrame.onBeforeClose CefApp.dispose"); + CefApp.getInstance().dispose(); + } + } + }); + } + + public void removeBrowser(Runnable r) { + System.out.println("BrowserFrame.removeBrowser"); + afterParentChangedAction_ = r; + remove(browser_.getUIComponent()); + // The removeNotify() notification should be sent as a result of calling remove(). + // However, it isn't in all cases so we do it manually here. + browser_.getUIComponent().removeNotify(); + browser_ = null; + } + + public CefBrowser getBrowser() { + return browser_; + } +} diff --git a/lib/jcef/java/tests/detailed/MainFrame.java b/lib/jcef/java/tests/detailed/MainFrame.java new file mode 100644 index 0000000..77d76ab --- /dev/null +++ b/lib/jcef/java/tests/detailed/MainFrame.java @@ -0,0 +1,349 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed; + +import org.cef.CefApp; +import org.cef.CefApp.CefVersion; +import org.cef.CefBrowserSettings; +import org.cef.CefClient; +import org.cef.CefSettings; +import org.cef.CefSettings.ColorType; +import org.cef.OS; +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.browser.CefMessageRouter; +import org.cef.browser.CefRequestContext; +import org.cef.handler.CefDisplayHandlerAdapter; +import org.cef.handler.CefFocusHandlerAdapter; +import org.cef.handler.CefLoadHandlerAdapter; +import org.cef.handler.CefRequestContextHandlerAdapter; +import org.cef.network.CefCookieManager; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.GraphicsConfiguration; +import java.awt.KeyboardFocusManager; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.io.File; +import java.lang.Thread.UncaughtExceptionHandler; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import tests.detailed.dialog.DownloadDialog; +import tests.detailed.handler.AppHandler; +import tests.detailed.handler.ContextMenuHandler; +import tests.detailed.handler.DragHandler; +import tests.detailed.handler.JSDialogHandler; +import tests.detailed.handler.KeyboardHandler; +import tests.detailed.handler.MessageRouterHandler; +import tests.detailed.handler.MessageRouterHandlerEx; +import tests.detailed.handler.RequestHandler; +import tests.detailed.ui.ControlPanel; +import tests.detailed.ui.MenuBar; +import tests.detailed.ui.StatusPanel; +import tests.detailed.util.DataUri; + +public class MainFrame extends BrowserFrame { + private static final long serialVersionUID = -2295538706810864538L; + public static void main(String[] args) { + // Perform startup initialization on platforms that require it. + if (!CefApp.startup(args)) { + System.out.println("Startup initialization failed!"); + return; + } + + // OSR mode is enabled by default on Linux. + // and disabled by default on Windows and Mac OS X. + boolean osrEnabledArg = false; + boolean transparentPaintingEnabledArg = false; + boolean createImmediately = false; + int windowless_frame_rate = 0; + for (String arg : args) { + arg = arg.toLowerCase(); + if (arg.equals("--off-screen-rendering-enabled")) { + osrEnabledArg = true; + } else if (arg.equals("--transparent-painting-enabled")) { + transparentPaintingEnabledArg = true; + } else if (arg.equals("--create-immediately")) { + createImmediately = true; + } else if (arg.equals("--windowless-frame-rate-60")) { + windowless_frame_rate = 60; + } + } + + System.out.println("Offscreen rendering " + (osrEnabledArg ? "enabled" : "disabled")); + + // MainFrame keeps all the knowledge to display the embedded browser + // frame. + final MainFrame frame = new MainFrame(osrEnabledArg, transparentPaintingEnabledArg, + createImmediately, 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_; + private String errorMsg_ = ""; + private ControlPanel control_pane_; + private StatusPanel status_panel_; + 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, int windowless_frame_rate, String[] args) { + this.osr_enabled_ = osrEnabled; + this.transparent_painting_enabled_ = transparentPaintingEnabled; + + CefApp myApp; + if (CefApp.getState() != CefApp.CefAppState.INITIALIZED) { + // 1) CefApp is the entry point for JCEF. You can pass + // application arguments to it, if you want to handle any + // chromium or CEF related switches/attributes in + // the native world. + CefSettings settings = new CefSettings(); + settings.windowless_rendering_enabled = osrEnabled; + // try to load URL "about:blank" to see the background color + settings.background_color = settings.new ColorType(100, 255, 242, 211); + myApp = CefApp.getInstance(args, settings); + + CefVersion version = myApp.getVersion(); + System.out.println("Using:\n" + version); + + // We're registering our own AppHandler because we want to + // add an own schemes (search:// and client://) and its corresponding + // protocol handlers. So if you enter "search:something on the web", your + // search request "something on the web" is forwarded to www.google.com + CefApp.addAppHandler(new AppHandler(args)); + } else { + myApp = CefApp.getInstance(); + } + + // By calling the method createClient() the native part + // of JCEF/CEF will be initialized and an instance of + // CefClient will be created. You can create one to many + // instances of CefClient. + client_ = myApp.createClient(); + + // 2) You have the ability to pass different handlers to your + // instance of CefClient. Each handler is responsible to + // deal with different informations (e.g. keyboard input). + // + // For each handler (with more than one method) adapter + // classes exists. So you don't need to override methods + // you're not interested in. + DownloadDialog downloadDialog = new DownloadDialog(this); + client_.addContextMenuHandler(new ContextMenuHandler(this)); + client_.addDownloadHandler(downloadDialog); + client_.addDragHandler(new DragHandler()); + client_.addJSDialogHandler(new JSDialogHandler()); + client_.addKeyboardHandler(new KeyboardHandler()); + client_.addRequestHandler(new RequestHandler(this)); + + // Beside the normal handler instances, we're registering a MessageRouter + // as well. That gives us the opportunity to reply to JavaScript method + // calls (JavaScript binding). We're using the default configuration, so + // that the JavaScript binding methods "cefQuery" and "cefQueryCancel" + // are used. + CefMessageRouter msgRouter = CefMessageRouter.create(); + msgRouter.addHandler(new MessageRouterHandler(), true); + msgRouter.addHandler(new MessageRouterHandlerEx(client_), false); + client_.addMessageRouter(msgRouter); + + // 2.1) We're overriding CefDisplayHandler as nested anonymous class + // to update our address-field, the title of the panel as well + // as for updating the status-bar on the bottom of the browser + client_.addDisplayHandler(new CefDisplayHandlerAdapter() { + @Override + public void onAddressChange(CefBrowser browser, CefFrame frame, String url) { + control_pane_.setAddress(browser, url); + } + @Override + public void onTitleChange(CefBrowser browser, String title) { + setTitle(title); + } + @Override + public void onStatusMessage(CefBrowser browser, String value) { + status_panel_.setStatusText(value); + } + @Override + public void onFullscreenModeChange(CefBrowser browser, boolean fullscreen) { + setBrowserFullscreen(fullscreen); + } + }); + + // 2.2) To disable/enable navigation buttons and to display a prgress bar + // which indicates the load state of our website, we're overloading + // the CefLoadHandler as nested anonymous class. Beside this, the + // load handler is responsible to deal with (load) errors as well. + // For example if you navigate to a URL which does not exist, the + // browser will show up an error message. + client_.addLoadHandler(new CefLoadHandlerAdapter() { + @Override + public void onLoadingStateChange(CefBrowser browser, boolean isLoading, + boolean canGoBack, boolean canGoForward) { + 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 + && frame == browser.getMainFrame()) { + errorMsg_ = ""; + errorMsg_ += "Error while loading"; + errorMsg_ += ""; + errorMsg_ += "

" + errorCode + "

"; + errorMsg_ += "

Failed to load " + failedUrl + "

"; + errorMsg_ += "

" + (errorText == null ? "" : errorText) + "

"; + errorMsg_ += ""; + browser.stopLoad(); + } + } + }); + + 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, browserSettings); + setBrowser(browser); + + // Set up the UI for this example implementation. + contentPanel_ = createContentPanel(); + getContentPane().add(contentPanel_, BorderLayout.CENTER); + + // Clear focus from the browser when the address field gains focus. + control_pane_.getAddressField().addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + if (!browserFocus_) return; + browserFocus_ = false; + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + control_pane_.getAddressField().requestFocus(); + } + }); + + // Clear focus from the address field when the browser gains focus. + client_.addFocusHandler(new CefFocusHandlerAdapter() { + @Override + public void onGotFocus(CefBrowser browser) { + if (browserFocus_) return; + browserFocus_ = true; + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + browser.setFocus(true); + } + + @Override + public void onTakeFocus(CefBrowser browser, boolean next) { + browserFocus_ = false; + } + }); + + if (createImmediately) browser.createImmediately(); + + // Add the browser to the UI. + contentPanel_.add(getBrowser().getUIComponent(), BorderLayout.CENTER); + + MenuBar menuBar = new MenuBar( + this, browser, control_pane_, downloadDialog, CefCookieManager.getGlobalManager()); + + menuBar.addBookmark("Binding Test", "client://tests/binding_test.html"); + menuBar.addBookmark("Binding Test 2", "client://tests/binding_test2.html"); + menuBar.addBookmark("Download Test", "https://cef-builds.spotifycdn.com/index.html"); + menuBar.addBookmark("Login Test (username:pumpkin, password:pie)", + "http://www.colostate.edu/~ric/protect/your.html"); + menuBar.addBookmark("Certificate-error Test", "https://www.k2go.de"); + menuBar.addBookmark("Resource-Handler Test", "http://www.foo.bar/"); + menuBar.addBookmark("Resource-Handler Set Error Test", "http://seterror.test/"); + menuBar.addBookmark( + "Scheme-Handler Test 1: (scheme \"client\")", "client://tests/handler.html"); + menuBar.addBookmark( + "Scheme-Handler Test 2: (scheme \"search\")", "search://do a barrel roll/"); + menuBar.addBookmark("Spellcheck Test", "client://tests/spellcheck.html"); + menuBar.addBookmark("LocalStorage Test", "client://tests/localstorage.html"); + menuBar.addBookmark("Transparency Test", "client://tests/transparency.html"); + menuBar.addBookmark("Fullscreen Test", + "https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_fullscreen2"); + menuBar.addBookmarkSeparator(); + menuBar.addBookmark( + "javachromiumembedded", "https://github.com/chromiumembedded/java-cef"); + menuBar.addBookmark("chromiumembedded", "https://github.com/chromiumembedded/cef"); + setJMenuBar(menuBar); + } + + private JPanel createContentPanel() { + JPanel contentPanel = new JPanel(new BorderLayout()); + control_pane_ = new ControlPanel(getBrowser()); + status_panel_ = new StatusPanel(); + contentPanel.add(control_pane_, BorderLayout.NORTH); + contentPanel.add(status_panel_, BorderLayout.SOUTH); + return contentPanel; + } + + public boolean isOsrEnabled() { + return osr_enabled_; + } + + public boolean isTransparentPaintingEnabled() { + return transparent_painting_enabled_; + } + + 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/lib/jcef/java/tests/detailed/dialog/CertErrorDialog.java b/lib/jcef/java/tests/detailed/dialog/CertErrorDialog.java new file mode 100644 index 0000000..4c78ea7 --- /dev/null +++ b/lib/jcef/java/tests/detailed/dialog/CertErrorDialog.java @@ -0,0 +1,40 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.dialog; + +import org.cef.callback.CefCallback; +import org.cef.handler.CefLoadHandler.ErrorCode; + +import java.awt.Frame; + +import javax.swing.JOptionPane; + +public class CertErrorDialog implements Runnable { + private final Frame owner_; + private final ErrorCode cert_error_; + private final String request_url_; + private final CefCallback callback_; + + public CertErrorDialog( + Frame owner, ErrorCode cert_error, String request_url, CefCallback callback) { + owner_ = owner; + cert_error_ = cert_error; + request_url_ = request_url; + callback_ = callback; + } + + @Override + public void run() { + int dialogResult = JOptionPane.showConfirmDialog(owner_, + "An certificate error (" + cert_error_ + ") occurreed " + + "while requesting\n" + request_url_ + "\nDo you want to proceed anyway?", + "Certificate error", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE); + if (dialogResult == JOptionPane.YES_OPTION) { + callback_.Continue(); + } else { + callback_.cancel(); + } + } +} diff --git a/lib/jcef/java/tests/detailed/dialog/CookieManagerDialog.java b/lib/jcef/java/tests/detailed/dialog/CookieManagerDialog.java new file mode 100644 index 0000000..279ebbf --- /dev/null +++ b/lib/jcef/java/tests/detailed/dialog/CookieManagerDialog.java @@ -0,0 +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 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/lib/jcef/java/tests/detailed/dialog/DownloadDialog.java b/lib/jcef/java/tests/detailed/dialog/DownloadDialog.java new file mode 100644 index 0000000..c3ffaea --- /dev/null +++ b/lib/jcef/java/tests/detailed/dialog/DownloadDialog.java @@ -0,0 +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 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/lib/jcef/java/tests/detailed/dialog/PasswordDialog.java b/lib/jcef/java/tests/detailed/dialog/PasswordDialog.java new file mode 100644 index 0000000..61662f4 --- /dev/null +++ b/lib/jcef/java/tests/detailed/dialog/PasswordDialog.java @@ -0,0 +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 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/lib/jcef/java/tests/detailed/dialog/SearchDialog.java b/lib/jcef/java/tests/detailed/dialog/SearchDialog.java new file mode 100644 index 0000000..88838c3 --- /dev/null +++ b/lib/jcef/java/tests/detailed/dialog/SearchDialog.java @@ -0,0 +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 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/lib/jcef/java/tests/detailed/dialog/ShowTextDialog.java b/lib/jcef/java/tests/detailed/dialog/ShowTextDialog.java new file mode 100644 index 0000000..7081304 --- /dev/null +++ b/lib/jcef/java/tests/detailed/dialog/ShowTextDialog.java @@ -0,0 +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 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/lib/jcef/java/tests/detailed/dialog/UrlRequestDialog.java b/lib/jcef/java/tests/detailed/dialog/UrlRequestDialog.java new file mode 100644 index 0000000..b1cc175 --- /dev/null +++ b/lib/jcef/java/tests/detailed/dialog/UrlRequestDialog.java @@ -0,0 +1,395 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.dialog; + +import org.cef.network.CefPostData; +import org.cef.network.CefPostDataElement; +import org.cef.network.CefRequest; +import org.cef.network.CefRequest.CefUrlRequestFlags; + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Vector; + +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.table.AbstractTableModel; + +@SuppressWarnings("serial") +public class UrlRequestDialog extends JDialog { + private final Vector requestMethods = new Vector<>(); + private final Map requestFlags = new HashMap<>(); + private final TableModel headerTblModel = new TableModel(true); + private final TableModel postDataModel = new TableModel(false); + private final JTextField urlField; + private final JTextField cookieUrl; + private final Frame owner_; + + private CefRequest createRequest() { + String url = urlField.getText(); + if (url.isEmpty() || url.trim().equalsIgnoreCase("http://")) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JOptionPane.showMessageDialog(owner_, + "Please specify at least an URL. Otherwise the CefRequest is invalid"); + } + }); + return null; + } + + CefRequest request = CefRequest.create(); + if (request == null) return null; + + String firstPartyForCookie = cookieUrl.getText(); + if (firstPartyForCookie.isEmpty() || firstPartyForCookie.trim().equalsIgnoreCase("http://")) + firstPartyForCookie = url; + + String method = "GET"; + for (int i = 0; i < requestMethods.size(); i++) { + JRadioButton button = requestMethods.get(i); + if (button.isSelected()) { + method = button.getText(); + break; + } + } + + CefPostData postData = null; + int postDataRows = postDataModel.getRowCount(); + if (postDataRows > 0) { + postData = CefPostData.create(); + } else if (method.equalsIgnoreCase("POST") || method.equalsIgnoreCase("PUT")) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JOptionPane.showMessageDialog( + owner_, "The methods POST and PUT require at least one row of data."); + } + }); + return null; + } + + if (postData != null) { + for (int i = 0; i < postDataRows; i++) { + String value = (String) postDataModel.getValueAt(i, 0); + if (value.trim().isEmpty()) continue; + + CefPostDataElement elem = CefPostDataElement.create(); + if (elem != null) { + File f = new File(value); + if (f.isFile()) { + elem.setToFile(value); + } else { + byte[] byteStr = value.getBytes(); + elem.setToBytes(byteStr.length, byteStr); + } + postData.addElement(elem); + } + } + } + + Map headerMap = null; + int headerRows = headerTblModel.getRowCount(); + if (headerRows > 0) { + headerMap = new HashMap<>(); + for (int i = 0; i < headerRows; i++) { + String key = (String) headerTblModel.getValueAt(i, 0); + String value = (String) headerTblModel.getValueAt(i, 1); + if (key.trim().isEmpty()) continue; + + headerMap.put(key, value); + } + } + + int flags = 0; + Set> entrySet = requestFlags.entrySet(); + for (Entry entry : entrySet) { + if (entry.getKey().isSelected()) { + flags |= entry.getValue(); + } + } + + request.set(url, method, postData, headerMap); + request.setFirstPartyForCookies(firstPartyForCookie); + request.setFlags(flags); + return request; + } + + public UrlRequestDialog(Frame owner, String title) { + super(owner, title, false); + setSize(1200, 600); + setLayout(new BorderLayout()); + + owner_ = owner; + + // URL for the request + urlField = new JTextField("http://"); + JPanel urlPanel = createPanelWithTitle("Request URL", 1, 0); + urlPanel.add(urlField); + + // URL for the cookies + cookieUrl = new JTextField("http://"); + JPanel cookiePanel = createPanelWithTitle("Cookie-URL", 1, 0); + cookiePanel.add(cookieUrl); + + // Radio buttons for the request method + ButtonGroup requestModeGrp = new ButtonGroup(); + JPanel requestModePanel = createPanelWithTitle("HTTP Request Mode", 1, 0); + addRequestMode(requestModePanel, requestModeGrp, "GET", true); + addRequestMode(requestModePanel, requestModeGrp, "HEAD", false); + addRequestMode(requestModePanel, requestModeGrp, "POST", false); + addRequestMode(requestModePanel, requestModeGrp, "PUT", false); + addRequestMode(requestModePanel, requestModeGrp, "DELETE", false); + + // Checkboxes for the flags + JPanel flagsPanel = createPanelWithTitle("Flags", 0, 1); + addRequestFlag(flagsPanel, "Skip cache", CefUrlRequestFlags.UR_FLAG_SKIP_CACHE, + "If set the cache will be skipped when handling the request", false); + addRequestFlag(flagsPanel, "Allow cached credentials", + CefUrlRequestFlags.UR_FLAG_ALLOW_CACHED_CREDENTIALS, + "If set user name, password, and cookies may be sent with the request, " + + "and cookies may be saved from the response.", + false); + addRequestFlag(flagsPanel, "Report Upload Progress", + CefUrlRequestFlags.UR_FLAG_REPORT_UPLOAD_PROGRESS, + "If set upload progress events will be generated when a request has a body", false); + addRequestFlag(flagsPanel, "Report RawHeaders", + CefUrlRequestFlags.UR_FLAG_REPORT_RAW_HEADERS, + "If set the headers sent and received for the request will be recorded", false); + addRequestFlag(flagsPanel, "No download data", CefUrlRequestFlags.UR_FLAG_NO_DOWNLOAD_DATA, + "If set the CefURLRequestClient.onDownloadData method will not be called", false); + addRequestFlag(flagsPanel, "No retry on 5xx", CefUrlRequestFlags.UR_FLAG_NO_RETRY_ON_5XX, + "If set 5XX redirect errors will be propagated to the observer instead of automatically re-tried.", + false); + + // Table for header values + JPanel headerValues = createPanelWithTable("Header Values", headerTblModel); + headerTblModel.addEntry("User-Agent", "Mozilla/5.0 JCEF Example Agent"); + headerTblModel.addEntry("Accept", + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); + + // Table for post-data + JPanel postData = createPanelWithTable("Post Data", postDataModel); + + // Create view + JPanel headerPanel = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 0.5; + c.gridx = 0; + c.gridy = 0; + headerPanel.add(urlPanel, c); + c.gridx = 1; + headerPanel.add(cookiePanel, c); + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 2; + c.weightx = 0.0; + headerPanel.add(requestModePanel, c); + + JPanel centerPanel = new JPanel(new GridLayout(2, 0)); + centerPanel.add(headerValues); + centerPanel.add(postData); + + JButton abortButton = new JButton("Abort"); + abortButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setVisible(false); + dispose(); + } + }); + + JButton sendButton = new JButton("Send"); + sendButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + CefRequest request = createRequest(); + if (request == null) return; + + UrlRequestDialogReply handleRequest = + new UrlRequestDialogReply(owner_, getTitle() + " - Result"); + handleRequest.send(request); + handleRequest.setVisible(true); + setVisible(false); + dispose(); + } + }); + + JPanel bottomPanel = new JPanel(new GridLayout(0, 2)); + bottomPanel.add(abortButton); + bottomPanel.add(sendButton); + + add(headerPanel, BorderLayout.PAGE_START); + add(flagsPanel, BorderLayout.LINE_START); + add(centerPanel, BorderLayout.CENTER); + add(bottomPanel, BorderLayout.PAGE_END); + } + + private void addRequestMode( + JPanel panel, ButtonGroup buttonGrp, String requestMode, boolean selected) { + JRadioButton button = new JRadioButton(requestMode, selected); + buttonGrp.add(button); + panel.add(button); + requestMethods.addElement(button); + } + + private void addRequestFlag( + JPanel panel, String flag, int value, String tooltip, boolean selected) { + JCheckBox checkBox = new JCheckBox(flag, selected); + checkBox.setToolTipText(tooltip); + panel.add(checkBox); + requestFlags.put(checkBox, value); + } + + private JPanel createPanelWithTitle(String title, int rows, int cols) { + JPanel result = new JPanel(new GridLayout(rows, cols)); + result.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(title), + BorderFactory.createEmptyBorder(10, 10, 10, 10))); + return result; + } + + private JPanel createPanelWithTable(String title, TableModel tblModel) { + final TableModel localTblModel = tblModel; + JPanel result = new JPanel(new BorderLayout()); + result.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(title), + BorderFactory.createEmptyBorder(10, 10, 10, 10))); + + JTable table = new JTable(tblModel); + table.setFillsViewportHeight(true); + JScrollPane scrollPane = new JScrollPane(table); + + JPanel buttonPane = new JPanel(new GridLayout(0, 2)); + JButton addButton = new JButton("Add entry"); + addButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + localTblModel.newDefaultEntry(); + } + }); + buttonPane.add(addButton); + + JButton delButton = new JButton("Remove entry"); + delButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + localTblModel.removeSelected(); + } + }); + buttonPane.add(delButton); + + result.add(scrollPane, BorderLayout.CENTER); + result.add(buttonPane, BorderLayout.PAGE_END); + + return result; + } + + private class TableModel extends AbstractTableModel { + private final String[] columnNames; + private Vector rowData = new Vector<>(); + private final boolean hasKeyColumn_; + + public TableModel(boolean hasKeyColumn) { + super(); + hasKeyColumn_ = hasKeyColumn; + if (hasKeyColumn) + columnNames = new String[] {"Key", "Value", ""}; + else + columnNames = new String[] {"Value", ""}; + } + + public void newDefaultEntry() { + int row = rowData.size(); + if (hasKeyColumn_) { + Object[] rowEntry = {"key", "value", new Boolean(false)}; + rowData.addElement(rowEntry); + } else { + Object[] rowEntry = {"value", new Boolean(false)}; + rowData.addElement(rowEntry); + } + fireTableRowsInserted(row, row); + } + + public void removeSelected() { + int idx = hasKeyColumn_ ? 2 : 1; + for (int i = 0; i < rowData.size(); ++i) { + if ((Boolean) rowData.get(i)[idx]) { + rowData.remove(i); + fireTableRowsDeleted(i, i); + i--; + } + } + } + + public void addEntry(String key, String value) { + int row = rowData.size(); + if (hasKeyColumn_) { + Object[] rowEntry = {key, value, new Boolean(false)}; + rowData.addElement(rowEntry); + } else { + Object[] rowEntry = {value, new Boolean(false)}; + rowData.addElement(rowEntry); + } + fireTableRowsInserted(row, row); + } + + @Override + public int getRowCount() { + return rowData.size(); + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public String getColumnName(int column) { + return columnNames[column]; + } + + @Override + public Class getColumnClass(int columnIndex) { + if (rowData.size() > 0) return rowData.get(0)[columnIndex].getClass(); + return Object.class; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return true; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + return rowData.get(rowIndex)[columnIndex]; + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + rowData.get(rowIndex)[columnIndex] = aValue; + fireTableCellUpdated(rowIndex, columnIndex); + } + } +} diff --git a/lib/jcef/java/tests/detailed/dialog/UrlRequestDialogReply.java b/lib/jcef/java/tests/detailed/dialog/UrlRequestDialogReply.java new file mode 100644 index 0000000..c391290 --- /dev/null +++ b/lib/jcef/java/tests/detailed/dialog/UrlRequestDialogReply.java @@ -0,0 +1,188 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.dialog; + +import org.cef.callback.CefAuthCallback; +import org.cef.callback.CefURLRequestClient; +import org.cef.network.CefRequest; +import org.cef.network.CefResponse; +import org.cef.network.CefURLRequest; +import org.cef.network.CefURLRequest.Status; + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +@SuppressWarnings("serial") +public class UrlRequestDialogReply extends JDialog implements CefURLRequestClient { + private long nativeRef_ = 0; + private final JLabel statusLabel_ = new JLabel("HTTP-Request status: "); + private final JTextArea sentRequest_ = new JTextArea(); + private final JTextArea repliedResult_ = new JTextArea(); + private final JButton cancelButton_ = new JButton("Cancel"); + private CefURLRequest urlRequest_ = null; + private final Frame owner_; + private ByteArrayOutputStream byteStream_ = new ByteArrayOutputStream(); + + public UrlRequestDialogReply(Frame owner, String title) { + super(owner, title, false); + setLayout(new BorderLayout()); + setSize(800, 600); + + owner_ = owner; + + JPanel controlPanel = new JPanel(); + controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS)); + JButton doneButton = new JButton("Done"); + doneButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + urlRequest_.dispose(); + setVisible(false); + dispose(); + } + }); + controlPanel.add(doneButton); + + cancelButton_.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (urlRequest_ != null) { + urlRequest_.cancel(); + } + } + }); + cancelButton_.setEnabled(false); + controlPanel.add(cancelButton_); + + JPanel requestPane = createPanelWithTitle("Sent HTTP-Request", 1, 0); + requestPane.add(new JScrollPane(sentRequest_)); + + JPanel replyPane = createPanelWithTitle("Reply from the server", 1, 0); + replyPane.add(new JScrollPane(repliedResult_)); + + JPanel contentPane = new JPanel(new GridLayout(2, 0)); + contentPane.add(requestPane); + contentPane.add(replyPane); + + add(statusLabel_, BorderLayout.PAGE_START); + add(contentPane, BorderLayout.CENTER); + add(controlPanel, BorderLayout.PAGE_END); + } + + private JPanel createPanelWithTitle(String title, int rows, int cols) { + JPanel result = new JPanel(new GridLayout(rows, cols)); + result.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(title), + BorderFactory.createEmptyBorder(10, 10, 10, 10))); + return result; + } + + public void send(CefRequest request) { + if (request == null) { + statusLabel_.setText("HTTP-Request status: FAILED"); + sentRequest_.append("Can't send CefRequest because it is NULL"); + cancelButton_.setEnabled(false); + return; + } + + urlRequest_ = CefURLRequest.create(request, this); + if (urlRequest_ == null) { + statusLabel_.setText("HTTP-Request status: FAILED"); + sentRequest_.append("Can't send CefRequest because creation of CefURLRequest failed."); + repliedResult_.append( + "The native code (CEF) returned a NULL-Pointer for CefURLRequest."); + cancelButton_.setEnabled(false); + } else { + sentRequest_.append(request.toString()); + cancelButton_.setEnabled(true); + updateStatus("", false); + } + } + + private void updateStatus(final String updateMsg, final boolean printByteStream) { + final Status status = urlRequest_.getRequestStatus(); + Runnable runnable = new Runnable() { + @Override + public void run() { + statusLabel_.setText("HTTP-Request status: " + status); + if (status != Status.UR_UNKNOWN && status != Status.UR_IO_PENDING) { + cancelButton_.setEnabled(false); + } + repliedResult_.append(updateMsg); + if (printByteStream) { + try { + repliedResult_.append("\n\n" + byteStream_.toString("UTF-8")); + } catch (UnsupportedEncodingException e) { + repliedResult_.append("\n\n" + byteStream_.toString()); + } + } + } + }; + + if (SwingUtilities.isEventDispatchThread()) { + runnable.run(); + } else { + SwingUtilities.invokeLater(runnable); + } + } + + // CefURLRequestClient + + @Override + public void setNativeRef(String identifer, long nativeRef) { + nativeRef_ = nativeRef; + } + + @Override + public long getNativeRef(String identifer) { + return nativeRef_; + } + + @Override + public void onRequestComplete(CefURLRequest request) { + String updateStr = "onRequestCompleted\n\n"; + CefResponse response = request.getResponse(); + boolean isText = response.getHeaderByName("Content-Type").startsWith("text"); + updateStr += response.toString(); + updateStatus(updateStr, isText); + } + + @Override + public void onUploadProgress(CefURLRequest request, int current, int total) { + updateStatus("onUploadProgress: " + current + "/" + total + " bytes\n", false); + } + + @Override + public void onDownloadProgress(CefURLRequest request, int current, int total) { + updateStatus("onDownloadProgress: " + current + "/" + total + " bytes\n", false); + } + + @Override + public void onDownloadData(CefURLRequest request, byte[] data, int data_length) { + byteStream_.write(data, 0, data_length); + updateStatus("onDownloadData: " + data_length + " bytes\n", false); + } + + @Override + public boolean getAuthCredentials(boolean isProxy, String host, int port, String realm, + String scheme, CefAuthCallback callback) { + SwingUtilities.invokeLater(new PasswordDialog(owner_, callback)); + return true; + } +} diff --git a/lib/jcef/java/tests/detailed/handler/AppHandler.java b/lib/jcef/java/tests/detailed/handler/AppHandler.java new file mode 100644 index 0000000..f5f7196 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/AppHandler.java @@ -0,0 +1,80 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.handler; + +import org.cef.CefApp; +import org.cef.CefApp.CefAppState; +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefSchemeHandlerFactory; +import org.cef.callback.CefSchemeRegistrar; +import org.cef.handler.CefAppHandlerAdapter; +import org.cef.handler.CefResourceHandler; +import org.cef.network.CefRequest; + +public class AppHandler extends CefAppHandlerAdapter { + // We're registering our own schemes to demonstrate how to use + // CefAppHandler.onRegisterCustomSchemes() in combination with + // CefApp.registerSchemeHandlerFactory(). + public AppHandler(String[] args) { + super(args); + } + + // (1) First of all we have to register our custom schemes by implementing + // the method "onRegisterCustomSchemes. The scheme names are added by + // calling CefSchemeRegistrar.addCustomScheme. + @Override + public void onRegisterCustomSchemes(CefSchemeRegistrar registrar) { + if (registrar.addCustomScheme( + SearchSchemeHandler.scheme, true, false, false, false, true, false, false)) { + System.out.println("Added scheme " + SearchSchemeHandler.scheme + "://"); + } + if (registrar.addCustomScheme( + ClientSchemeHandler.scheme, true, false, false, false, true, false, false)) { + System.out.println("Added scheme " + ClientSchemeHandler.scheme + "://"); + } + } + + // (2) At the next step we have to register a SchemeHandlerFactory which is + // called if an user enters our registered scheme. + // + // This is done via the CefApp.registerSchemeHandlerFactory() method. + // A good place to call this function is from + // CefAppHandler.onContextInitialized(). + // + // The empty |domain_name| value will cause the factory to match all + // domain names. A set |domain_name| will only be valid for the entered + // domain. + @Override + public void onContextInitialized() { + CefApp cefApp = CefApp.getInstance(); + cefApp.registerSchemeHandlerFactory( + SearchSchemeHandler.scheme, SearchSchemeHandler.domain, new SchemeHandlerFactory()); + cefApp.registerSchemeHandlerFactory( + ClientSchemeHandler.scheme, ClientSchemeHandler.domain, new SchemeHandlerFactory()); + } + + // (3) The SchemeHandlerFactory creates a new ResourceHandler instance for each + // request the user has send to the browser. The ResourceHandler is the + // responsible class to process and return the result of a received + // request. + private class SchemeHandlerFactory implements CefSchemeHandlerFactory { + @Override + public CefResourceHandler create( + CefBrowser browser, CefFrame frame, String schemeName, CefRequest request) { + if (schemeName.equals(SearchSchemeHandler.scheme)) + return new SearchSchemeHandler(browser); + else if (schemeName.equals(ClientSchemeHandler.scheme)) + return new ClientSchemeHandler(); + return null; + } + } + + @Override + public void stateHasChanged(CefAppState state) { + System.out.println("AppHandler.stateHasChanged: " + state); + if (state == CefAppState.TERMINATED) System.exit(0); + } +} diff --git a/lib/jcef/java/tests/detailed/handler/ClientSchemeHandler.java b/lib/jcef/java/tests/detailed/handler/ClientSchemeHandler.java new file mode 100644 index 0000000..c3e5ecb --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/ClientSchemeHandler.java @@ -0,0 +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 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/lib/jcef/java/tests/detailed/handler/ContextMenuHandler.java b/lib/jcef/java/tests/detailed/handler/ContextMenuHandler.java new file mode 100644 index 0000000..c18c76b --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/ContextMenuHandler.java @@ -0,0 +1,101 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefContextMenuParams; +import org.cef.callback.CefMenuModel; +import org.cef.callback.CefMenuModel.MenuId; +import org.cef.handler.CefContextMenuHandler; + +import java.awt.Frame; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + +import tests.detailed.dialog.SearchDialog; +import tests.detailed.dialog.ShowTextDialog; + +public class ContextMenuHandler implements CefContextMenuHandler { + private final Frame owner_; + private Map suggestions_ = new HashMap(); + + public ContextMenuHandler(Frame owner) { + owner_ = owner; + } + + @Override + public void onBeforeContextMenu( + CefBrowser browser, CefFrame frame, CefContextMenuParams params, CefMenuModel model) { + model.clear(); + + // Navigation menu + model.addItem(MenuId.MENU_ID_BACK, "Back"); + model.setEnabled(MenuId.MENU_ID_BACK, browser.canGoBack()); + + model.addItem(MenuId.MENU_ID_FORWARD, "Forward"); + model.setEnabled(MenuId.MENU_ID_FORWARD, browser.canGoForward()); + + model.addSeparator(); + model.addItem(MenuId.MENU_ID_FIND, "Find..."); + if (params.hasImageContents() && params.getSourceUrl() != null) + model.addItem(MenuId.MENU_ID_USER_FIRST, "Download Image..."); + model.addItem(MenuId.MENU_ID_VIEW_SOURCE, "View Source..."); + + Vector suggestions = new Vector(); + params.getDictionarySuggestions(suggestions); + + // Spell checking menu + model.addSeparator(); + if (suggestions.size() == 0) { + model.addItem(MenuId.MENU_ID_NO_SPELLING_SUGGESTIONS, "No suggestions"); + model.setEnabled(MenuId.MENU_ID_NO_SPELLING_SUGGESTIONS, false); + return; + } + + int id = MenuId.MENU_ID_SPELLCHECK_SUGGESTION_0; + for (String suggestedWord : suggestions) { + model.addItem(id, suggestedWord); + suggestions_.put(id, suggestedWord); + if (++id > MenuId.MENU_ID_SPELLCHECK_SUGGESTION_LAST) break; + } + } + + @Override + public boolean onContextMenuCommand(CefBrowser browser, CefFrame frame, + CefContextMenuParams params, int commandId, int eventFlags) { + switch (commandId) { + case MenuId.MENU_ID_VIEW_SOURCE: + ShowTextDialog visitor = + new ShowTextDialog(owner_, "Source of \"" + browser.getURL() + "\""); + browser.getSource(visitor); + return true; + case MenuId.MENU_ID_FIND: + SearchDialog search = new SearchDialog(owner_, browser); + search.setVisible(true); + return true; + case MenuId.MENU_ID_USER_FIRST: + browser.startDownload(params.getSourceUrl()); + return true; + default: + if (commandId >= MenuId.MENU_ID_SPELLCHECK_SUGGESTION_0) { + String newWord = suggestions_.get(commandId); + if (newWord != null) { + System.err.println( + "replacing " + params.getMisspelledWord() + " with " + newWord); + browser.replaceMisspelling(newWord); + return true; + } + } + return false; + } + } + + @Override + public void onContextMenuDismissed(CefBrowser browser, CefFrame frame) { + suggestions_.clear(); + } +} diff --git a/lib/jcef/java/tests/detailed/handler/DragHandler.java b/lib/jcef/java/tests/detailed/handler/DragHandler.java new file mode 100644 index 0000000..b202577 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/DragHandler.java @@ -0,0 +1,31 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefDragData; +import org.cef.handler.CefDragHandler; + +public class DragHandler implements CefDragHandler { + @Override + public boolean onDragEnter(CefBrowser browser, CefDragData dragData, int mask) { + System.out.println("DRAG:"); + System.out.print(" flags:"); + if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_COPY) != 0) + System.out.print(" COPY"); + if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_LINK) != 0) + System.out.print(" LINK"); + if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_GENERIC) != 0) + System.out.print(" GENERIC"); + if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_PRIVATE) != 0) + System.out.print(" PRIVATE"); + if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_MOVE) != 0) + System.out.print(" MOVE"); + if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_DELETE) != 0) + System.out.print(" DELETE"); + System.out.println("\n " + dragData); + return false; + } +} diff --git a/lib/jcef/java/tests/detailed/handler/JSDialogHandler.java b/lib/jcef/java/tests/detailed/handler/JSDialogHandler.java new file mode 100644 index 0000000..0238bf1 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/JSDialogHandler.java @@ -0,0 +1,26 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefJSDialogCallback; +import org.cef.handler.CefJSDialogHandlerAdapter; +import org.cef.misc.BoolRef; + +public class JSDialogHandler extends CefJSDialogHandlerAdapter { + @Override + public boolean onJSDialog(CefBrowser browser, String origin_url, JSDialogType dialog_type, + String message_text, String default_prompt_text, CefJSDialogCallback callback, + BoolRef suppress_message) { + if (message_text.equalsIgnoreCase("Never displayed")) { + suppress_message.set(true); + System.out.println( + "The " + dialog_type + " from origin \"" + origin_url + "\" was suppressed."); + System.out.println( + " The content of the suppressed dialog was: \"" + message_text + "\""); + } + return false; + } +} diff --git a/lib/jcef/java/tests/detailed/handler/KeyboardHandler.java b/lib/jcef/java/tests/detailed/handler/KeyboardHandler.java new file mode 100644 index 0000000..95ea69f --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/KeyboardHandler.java @@ -0,0 +1,52 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.handler; + +import org.cef.browser.CefBrowser; +import org.cef.handler.CefKeyboardHandlerAdapter; + +public class KeyboardHandler extends CefKeyboardHandlerAdapter { + @Override + public boolean onKeyEvent(CefBrowser browser, CefKeyEvent event) { + if (!event.focus_on_editable_field && event.windows_key_code == 0x20) { + // Special handling for the space character when an input element does not + // have focus. Handling the event in OnPreKeyEvent() keeps the event from + // being processed in the renderer. If we instead handled the event in the + // OnKeyEvent() method the space key would cause the window to scroll in + // addition to showing the alert box. + if (event.type == CefKeyEvent.EventType.KEYEVENT_RAWKEYDOWN) { + browser.executeJavaScript("alert('You pressed the space bar!');", "", 0); + } + return true; + } 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/lib/jcef/java/tests/detailed/handler/MessageRouterHandler.java b/lib/jcef/java/tests/detailed/handler/MessageRouterHandler.java new file mode 100644 index 0000000..1d37c85 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/MessageRouterHandler.java @@ -0,0 +1,25 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefQueryCallback; +import org.cef.handler.CefMessageRouterHandlerAdapter; + +public class MessageRouterHandler extends CefMessageRouterHandlerAdapter { + @Override + public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String request, + boolean persistent, CefQueryCallback callback) { + if (request.indexOf("BindingTest:") == 0) { + // Reverse the message and return it to the JavaScript caller. + String msg = request.substring(12); + callback.success(new StringBuilder(msg).reverse().toString()); + return true; + } + // Not handled. + return false; + } +} diff --git a/lib/jcef/java/tests/detailed/handler/MessageRouterHandlerEx.java b/lib/jcef/java/tests/detailed/handler/MessageRouterHandlerEx.java new file mode 100644 index 0000000..bc4b780 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/MessageRouterHandlerEx.java @@ -0,0 +1,68 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.handler; + +import org.cef.CefClient; +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.browser.CefMessageRouter; +import org.cef.browser.CefMessageRouter.CefMessageRouterConfig; +import org.cef.callback.CefQueryCallback; +import org.cef.handler.CefMessageRouterHandlerAdapter; + +public class MessageRouterHandlerEx extends CefMessageRouterHandlerAdapter { + private final CefClient client_; + private final CefMessageRouterConfig config_ = + new CefMessageRouterConfig("myQuery", "myQueryAbort"); + private CefMessageRouter router_ = null; + + public MessageRouterHandlerEx(final CefClient client) { + client_ = client; + } + + @Override + public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String request, + boolean persistent, CefQueryCallback callback) { + if (request.startsWith("hasExtension")) { + if (router_ != null) + callback.success(""); + else + callback.failure(0, ""); + } else if (request.startsWith("enableExt")) { + if (router_ != null) { + callback.failure(-1, "Already enabled"); + } else { + router_ = CefMessageRouter.create(config_, new JavaVersionMessageRouter()); + client_.addMessageRouter(router_); + callback.success(""); + } + } else if (request.startsWith("disableExt")) { + if (router_ == null) { + callback.failure(-2, "Already disabled"); + } else { + client_.removeMessageRouter(router_); + router_.dispose(); + router_ = null; + callback.success(""); + } + } else { + // not handled + return false; + } + return true; + } + + private class JavaVersionMessageRouter extends CefMessageRouterHandlerAdapter { + @Override + public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String request, + boolean persistent, CefQueryCallback callback) { + if (request.startsWith("jcefJava")) { + callback.success(System.getProperty("java.version")); + return true; + } + return false; + }; + } +} diff --git a/lib/jcef/java/tests/detailed/handler/RequestHandler.java b/lib/jcef/java/tests/detailed/handler/RequestHandler.java new file mode 100644 index 0000000..44d102a --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/RequestHandler.java @@ -0,0 +1,169 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.handler; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefAuthCallback; +import org.cef.callback.CefCallback; +import org.cef.handler.CefLoadHandler.ErrorCode; +import org.cef.handler.CefRequestHandler; +import org.cef.handler.CefResourceHandler; +import org.cef.handler.CefResourceRequestHandler; +import org.cef.handler.CefResourceRequestHandlerAdapter; +import org.cef.misc.BoolRef; +import org.cef.network.CefPostData; +import org.cef.network.CefPostDataElement; +import org.cef.network.CefRequest; + +import java.awt.Frame; +import java.util.HashMap; +import java.util.Vector; + +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +import tests.detailed.dialog.CertErrorDialog; +import tests.detailed.dialog.PasswordDialog; + +public class RequestHandler extends CefResourceRequestHandlerAdapter implements CefRequestHandler { + private final Frame owner_; + + public RequestHandler(Frame owner) { + owner_ = owner; + } + + @Override + public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, + boolean user_gesture, boolean is_redirect) { + CefPostData postData = request.getPostData(); + if (postData != null) { + Vector elements = new Vector(); + postData.getElements(elements); + for (CefPostDataElement el : elements) { + int numBytes = el.getBytesCount(); + if (numBytes <= 0) continue; + + byte[] readBytes = new byte[numBytes]; + if (el.getBytes(numBytes, readBytes) <= 0) continue; + + String readString = new String(readBytes); + if (readString.indexOf("ignore") > -1) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JOptionPane.showMessageDialog(owner_, + "The request was rejected because you've entered \"ignore\" into the form."); + } + }); + return true; + } + } + } + return false; + } + + @Override + public boolean onOpenURLFromTab( + CefBrowser browser, CefFrame frame, String target_url, boolean user_gesture) { + return false; + } + + @Override + public CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame, + CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator, + BoolRef disableDefaultHandling) { + return this; + } + + @Override + public boolean onBeforeResourceLoad(CefBrowser browser, CefFrame frame, CefRequest request) { + // If you send a HTTP-POST request to http://www.google.com/ + // google rejects your request because they don't allow HTTP-POST. + // + // This test extracts the value of the test form. + // (see "Show Form" entry within BrowserMenuBar) + // and sends its value as HTTP-GET request to Google. + if (request.getMethod().equalsIgnoreCase("POST") + && request.getURL().equals("http://www.google.com/")) { + String forwardTo = "http://www.google.com/#q="; + CefPostData postData = request.getPostData(); + boolean sendAsGet = false; + if (postData != null) { + Vector elements = new Vector(); + postData.getElements(elements); + for (CefPostDataElement el : elements) { + int numBytes = el.getBytesCount(); + if (numBytes <= 0) continue; + + byte[] readBytes = new byte[numBytes]; + if (el.getBytes(numBytes, readBytes) <= 0) continue; + + String readString = new String(readBytes).trim(); + String[] stringPairs = readString.split("&"); + for (String s : stringPairs) { + int startPos = s.indexOf('='); + if (s.startsWith("searchFor")) + forwardTo += s.substring(startPos + 1); + else if (s.startsWith("sendAsGet")) { + sendAsGet = true; + } + } + } + if (sendAsGet) postData.removeElements(); + } + if (sendAsGet) { + request.setFlags(0); + request.setMethod("GET"); + request.setURL(forwardTo); + request.setFirstPartyForCookies(forwardTo); + HashMap headerMap = new HashMap<>(); + request.getHeaderMap(headerMap); + headerMap.remove("Content-Type"); + headerMap.remove("Origin"); + request.setHeaderMap(headerMap); + } + } + return false; + } + + @Override + public CefResourceHandler getResourceHandler( + CefBrowser browser, CefFrame frame, CefRequest request) { + // the non existing domain "foo.bar" is handled by the ResourceHandler implementation + // E.g. if you try to load the URL http://www.foo.bar, you'll be forwarded + // to the ResourceHandler class. + if (request.getURL().endsWith("foo.bar/")) { + return new ResourceHandler(); + } + + if (request.getURL().endsWith("seterror.test/")) { + return new ResourceSetErrorHandler(); + } + + return null; + } + + @Override + public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy, + String host, int port, String realm, String scheme, CefAuthCallback callback) { + SwingUtilities.invokeLater(new PasswordDialog(owner_, callback)); + return true; + } + + @Override + public boolean onCertificateError( + CefBrowser browser, ErrorCode cert_error, String request_url, CefCallback callback) { + SwingUtilities.invokeLater(new CertErrorDialog(owner_, cert_error, request_url, callback)); + return true; + } + + @Override + public void onRenderProcessTerminated( + CefBrowser browser, TerminationStatus status, int error_code, String error_string) { + System.out.println("render process terminated: " + status + " errorCode: " + error_code + + " errorString: " + error_string); + } +} diff --git a/lib/jcef/java/tests/detailed/handler/ResourceHandler.java b/lib/jcef/java/tests/detailed/handler/ResourceHandler.java new file mode 100644 index 0000000..5bc5530 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/ResourceHandler.java @@ -0,0 +1,74 @@ +package tests.detailed.handler; + +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" + + " \n" + + " ResourceHandler Test\n" + + " \n" + + " \n" + + "

ResourceHandler Test

\n" + + "

You have entered the URL: http://www.foo.bar. This page is generated by the application itself and
\n" + + " no HTTP request was sent to the internet.\n" + + "

See class tests.handler.ResourceHandler and the RequestHandler implementation for details.

\n" + + " \n" + + ""); + + @Override + public boolean open(CefRequest request, BoolRef handleRequest, CefCallback callback) { + System.out.println("processRequest: " + request); + + startPos = 0; + handleRequest.set(true); + return true; + } + + @Override + public void getResponseHeaders( + CefResponse response, IntRef response_length, StringRef redirectUrl) { + System.out.println("getResponseHeaders: " + response); + + response_length.set(html.length()); + response.setMimeType("text/html"); + response.setStatus(200); + } + + @Override + public boolean read(byte[] data_out, int bytes_to_read, IntRef bytes_read, + CefResourceReadCallback callback) { + int length = html.length(); + if (startPos >= length) return false; + + // Extract up to bytes_to_read bytes from the html data + int endPos = startPos + bytes_to_read; + String dataToSend = + (endPos > length) ? html.substring(startPos) : html.substring(startPos, endPos); + + // Copy extracted bytes into data_out and set the read length + // to bytes_read. + ByteBuffer result = ByteBuffer.wrap(data_out); + result.put(dataToSend.getBytes()); + bytes_read.set(dataToSend.length()); + + startPos = endPos; + return true; + } + + @Override + public void cancel() { + System.out.println("cancel"); + startPos = 0; + } +} diff --git a/lib/jcef/java/tests/detailed/handler/ResourceSetErrorHandler.java b/lib/jcef/java/tests/detailed/handler/ResourceSetErrorHandler.java new file mode 100644 index 0000000..005cb70 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/ResourceSetErrorHandler.java @@ -0,0 +1,26 @@ +package tests.detailed.handler; + +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; +import org.cef.network.CefResponse; + +public class ResourceSetErrorHandler extends CefResourceHandlerAdapter { + @Override + public boolean open(CefRequest request, BoolRef handleRequest, CefCallback callback) { + System.out.println("processRequest: " + request); + handleRequest.set(true); + return true; + } + + @Override + public void getResponseHeaders( + CefResponse response, IntRef response_length, StringRef redirectUrl) { + response.setError(ErrorCode.ERR_NOT_IMPLEMENTED); + System.out.println("getResponseHeaders: " + response); + } +} \ No newline at end of file diff --git a/lib/jcef/java/tests/detailed/handler/SearchSchemeHandler.java b/lib/jcef/java/tests/detailed/handler/SearchSchemeHandler.java new file mode 100644 index 0000000..0783973 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/SearchSchemeHandler.java @@ -0,0 +1,50 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.handler; + +import org.cef.browser.CefBrowser; +import org.cef.callback.CefCallback; +import org.cef.handler.CefResourceHandlerAdapter; +import org.cef.misc.BoolRef; +import org.cef.network.CefRequest; + +/** + * In this case we create a new CefRequest object with + * http://www.google.com/#q= + * as target and forward it to the CefBrowser instance. + * The "search://"-request is aborted by returning false. + */ +public class SearchSchemeHandler extends CefResourceHandlerAdapter { + public static final String scheme = "search"; + public static final String domain = ""; + + private final CefBrowser browser_; + + public SearchSchemeHandler(CefBrowser browser) { + browser_ = browser; + } + + @Override + public boolean open(CefRequest request, BoolRef handleRequest, CefCallback callback) { + // cut away "scheme://" + String requestUrl = request.getURL(); + String newUrl = requestUrl.substring(scheme.length() + 3); + // cut away a trailing "/" if any + if (newUrl.indexOf('/') == newUrl.length() - 1) { + newUrl = newUrl.substring(0, newUrl.length() - 1); + } + newUrl = "http://www.google.com/#q=" + newUrl; + + CefRequest newRequest = CefRequest.create(); + if (newRequest != null) { + newRequest.setMethod("GET"); + newRequest.setURL(newUrl); + newRequest.setFirstPartyForCookies(newUrl); + browser_.loadRequest(newRequest); + } + handleRequest.set(true); + return false; + } +} diff --git a/lib/jcef/java/tests/detailed/handler/binding_test.html b/lib/jcef/java/tests/detailed/handler/binding_test.html new file mode 100644 index 0000000..9ee0775 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/binding_test.html @@ -0,0 +1,28 @@ + + +Binding Test + + + + +
+Message: +
+
You should see the reverse of your message below: +
+
+ + diff --git a/lib/jcef/java/tests/detailed/handler/binding_test2.html b/lib/jcef/java/tests/detailed/handler/binding_test2.html new file mode 100644 index 0000000..8a61a96 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/binding_test2.html @@ -0,0 +1,81 @@ + + +Binding Test - Part 2 + + + + + +
+

JavaScript Binding Test - Part 2

+

While this page was loaded, the JavaScript function +

window.cefRequest(request: 'hasExtension')
+was executed for enabling/disabling the buttons below. +
 
+If you press "Enable myQuery", the JavaScript function +
window.cefRequest(request: 'enableExt')
+is executed. This causes Java to create a second instance of +
CefMessageRouter
+In this case the name of the JavaScript query function is set to "myQuery" and +
a handler for the request 'jcefJava' is registered. Pressing the "Test" +
button will execute the JavaScript code +
window.myRequest(request: 'jcefJava')
+which returns your current Java version on success or an error message in case +
of an error. +

+

Please note: If you leave this page (myQuery enabled) and you return +
after a while - without closing the browser - the JavaScript binding is +
still enabled.

+Second message router: + + +
+ +
+ + + diff --git a/lib/jcef/java/tests/detailed/handler/localstorage.html b/lib/jcef/java/tests/detailed/handler/localstorage.html new file mode 100644 index 0000000..87c6e68 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/localstorage.html @@ -0,0 +1,24 @@ + + + +Click the "Add Line" button to add a line or the "Clear" button to clear.
+This data will persist across sessions if a cache path was specified.
+ + +
+ + + diff --git a/lib/jcef/java/tests/detailed/handler/logo.png b/lib/jcef/java/tests/detailed/handler/logo.png new file mode 100644 index 0000000..a2a15f4 Binary files /dev/null and b/lib/jcef/java/tests/detailed/handler/logo.png differ diff --git a/lib/jcef/java/tests/detailed/handler/spellcheck.html b/lib/jcef/java/tests/detailed/handler/spellcheck.html new file mode 100644 index 0000000..6334135 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/spellcheck.html @@ -0,0 +1,14 @@ + + +Spellcheck Test + + + +The next paragraph contains some text to be validated against the spell-checker. +
Click into the following box. To replace a misspelled word use the +right-mouse-click.
+

+This is a misspelled paragrapph. Withh maany errors
Click into this bogx +to ttest it.

+ + diff --git a/lib/jcef/java/tests/detailed/handler/transparency.html b/lib/jcef/java/tests/detailed/handler/transparency.html new file mode 100644 index 0000000..a8dd3b4 --- /dev/null +++ b/lib/jcef/java/tests/detailed/handler/transparency.html @@ -0,0 +1,63 @@ + + + +Transparency Examples + + + + +

Image Transparency

+Hover over an image to make it fully opaque.
+klematis +klematis + +

Block Transparency

+White 0% White 25% White 50% White 75% White 100% +
+Black 0% Black 25% Black 50% Black 75% Black 100% + + + diff --git a/lib/jcef/java/tests/detailed/ui/ControlPanel.java b/lib/jcef/java/tests/detailed/ui/ControlPanel.java new file mode 100644 index 0000000..c3923dc --- /dev/null +++ b/lib/jcef/java/tests/detailed/ui/ControlPanel.java @@ -0,0 +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 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/lib/jcef/java/tests/detailed/ui/MenuBar.java b/lib/jcef/java/tests/detailed/ui/MenuBar.java new file mode 100644 index 0000000..79ecc09 --- /dev/null +++ b/lib/jcef/java/tests/detailed/ui/MenuBar.java @@ -0,0 +1,601 @@ +// 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 org.cef.browser.CefDevToolsClient; +import org.cef.callback.CefPdfPrintCallback; +import org.cef.callback.CefRunFileDialogCallback; +import org.cef.callback.CefStringVisitor; +import org.cef.handler.CefDialogHandler.FileDialogMode; +import org.cef.misc.CefPdfPrintSettings; +import org.cef.network.CefCookieManager; +import org.cef.network.CefRequest; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.Vector; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRootPane; +import javax.swing.SwingUtilities; + +import tests.detailed.BrowserFrame; +import tests.detailed.MainFrame; +import tests.detailed.dialog.CookieManagerDialog; +import tests.detailed.dialog.DownloadDialog; +import tests.detailed.dialog.SearchDialog; +import tests.detailed.dialog.ShowTextDialog; +import tests.detailed.dialog.UrlRequestDialog; +import tests.detailed.util.DataUri; + +@SuppressWarnings("serial") +public class MenuBar extends JMenuBar { + class SaveAs implements CefStringVisitor { + private final PrintWriter fileWriter_; + + public SaveAs(String fName) throws FileNotFoundException, UnsupportedEncodingException { + fileWriter_ = new PrintWriter(fName, "UTF-8"); + } + + @Override + public void visit(String string) { + fileWriter_.write(string); + fileWriter_.close(); + } + } + + private final MainFrame owner_; + private final CefBrowser browser_; + private String last_selected_file_ = ""; + private final JMenu bookmarkMenu_; + private final ControlPanel control_pane_; + private final DownloadDialog downloadDialog_; + private final CefCookieManager cookieManager_; + private boolean reparentPending_ = false; + private CefDevToolsClient devToolsClient_; + + public MenuBar(MainFrame owner, CefBrowser browser, ControlPanel control_pane, + DownloadDialog downloadDialog, CefCookieManager cookieManager) { + owner_ = owner; + browser_ = browser; + control_pane_ = control_pane; + downloadDialog_ = downloadDialog; + cookieManager_ = cookieManager; + + setEnabled(browser_ != null); + + JMenu fileMenu = new JMenu("File"); + + JMenuItem openFileItem = new JMenuItem("Open file..."); + openFileItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + JFileChooser fc = new JFileChooser(new File(last_selected_file_)); + // Show open dialog; this method does not return until the dialog is closed. + fc.showOpenDialog(owner_); + File selectedFile = fc.getSelectedFile(); + if (selectedFile != null) { + last_selected_file_ = selectedFile.getAbsolutePath(); + browser_.loadURL("file:///" + selectedFile.getAbsolutePath()); + } + } + }); + fileMenu.add(openFileItem); + + JMenuItem openFileDialog = new JMenuItem("Save as..."); + openFileDialog.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + CefRunFileDialogCallback callback = new CefRunFileDialogCallback() { + @Override + public void onFileDialogDismissed(Vector filePaths) { + if (!filePaths.isEmpty()) { + try { + SaveAs saveContent = new SaveAs(filePaths.get(0)); + browser_.getSource(saveContent); + } catch (FileNotFoundException | UnsupportedEncodingException e) { + browser_.executeJavaScript("alert(\"Can't save file\");", + control_pane_.getAddress(), 0); + } + } + } + }; + browser_.runFileDialog(FileDialogMode.FILE_DIALOG_SAVE, owner_.getTitle(), + "index.html", null, 0, callback); + } + }); + fileMenu.add(openFileDialog); + + JMenuItem printItem = new JMenuItem("Print..."); + printItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + browser_.print(); + } + }); + fileMenu.add(printItem); + + JMenuItem printToPdfItem = new JMenuItem("Print to PDF"); + printToPdfItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser fc = new JFileChooser(); + fc.showSaveDialog(owner_); + File selectedFile = fc.getSelectedFile(); + if (selectedFile != null) { + CefPdfPrintSettings pdfSettings = new CefPdfPrintSettings(); + pdfSettings.display_header_footer = true; + // letter page size + pdfSettings.paper_width = 8.5; + pdfSettings.paper_height = 11; + browser.printToPDF( + selectedFile.getAbsolutePath(), pdfSettings, new CefPdfPrintCallback() { + @Override + public void onPdfPrintFinished(String path, boolean ok) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (ok) { + JOptionPane.showMessageDialog(owner_, + "PDF saved to " + path, "Success", + JOptionPane.INFORMATION_MESSAGE); + } else { + JOptionPane.showMessageDialog(owner_, "PDF failed", + "Failed", JOptionPane.ERROR_MESSAGE); + } + } + }); + } + }); + } + } + }); + fileMenu.add(printToPdfItem); + + JMenuItem searchItem = new JMenuItem("Search..."); + searchItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + new SearchDialog(owner_, browser_).setVisible(true); + } + }); + fileMenu.add(searchItem); + + fileMenu.addSeparator(); + + JMenuItem viewSource = new JMenuItem("View source"); + viewSource.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + browser_.viewSource(); + } + }); + fileMenu.add(viewSource); + + JMenuItem getSource = new JMenuItem("Get source..."); + getSource.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ShowTextDialog visitor = new ShowTextDialog( + owner_, "Source of \"" + control_pane_.getAddress() + "\""); + browser_.getSource(visitor); + } + }); + fileMenu.add(getSource); + + JMenuItem getText = new JMenuItem("Get text..."); + getText.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ShowTextDialog visitor = new ShowTextDialog( + owner_, "Content of \"" + control_pane_.getAddress() + "\""); + browser_.getText(visitor); + } + }); + fileMenu.add(getText); + + fileMenu.addSeparator(); + + JMenuItem showDownloads = new JMenuItem("Show Downloads"); + showDownloads.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + downloadDialog_.setVisible(true); + } + }); + fileMenu.add(showDownloads); + + JMenuItem showCookies = new JMenuItem("Show Cookies"); + showCookies.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + CookieManagerDialog cookieManager = + new CookieManagerDialog(owner_, "Cookie Manager", cookieManager_); + cookieManager.setVisible(true); + } + }); + fileMenu.add(showCookies); + + fileMenu.addSeparator(); + + JMenuItem exitItem = new JMenuItem("Exit"); + exitItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + owner_.dispatchEvent(new WindowEvent(owner_, WindowEvent.WINDOW_CLOSING)); + } + }); + fileMenu.add(exitItem); + + bookmarkMenu_ = new JMenu("Bookmarks"); + + JMenuItem addBookmarkItem = new JMenuItem("Add bookmark"); + addBookmarkItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + addBookmark(owner_.getTitle(), control_pane_.getAddress()); + } + }); + bookmarkMenu_.add(addBookmarkItem); + bookmarkMenu_.addSeparator(); + + JMenu testMenu = new JMenu("Tests"); + + JMenuItem testJSItem = new JMenuItem("JavaScript alert"); + testJSItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + browser_.executeJavaScript("alert('Hello World');", control_pane_.getAddress(), 1); + } + }); + testMenu.add(testJSItem); + + JMenuItem jsAlertItem = new JMenuItem("JavaScript alert (will be suppressed)"); + jsAlertItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + browser_.executeJavaScript("alert('Never displayed');", "http://dontshow.me", 1); + } + }); + testMenu.add(jsAlertItem); + + JMenuItem testShowText = new JMenuItem("Show Text"); + testShowText.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + browser_.loadURL(DataUri.create( + "text/html", "

Hello World

")); + } + }); + testMenu.add(testShowText); + + JMenuItem showForm = new JMenuItem("RequestHandler Test"); + showForm.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String form = "RequestHandler test"; + form += "

RequestHandler test

"; + form += "
"; + form += ""; + form += "
"; + form += " Use GET instead of POST"; + form += "

This form tries to send the content of the text field as HTTP-POST request to http://www.google.com.

"; + form += "

Testcase 1

"; + form += "Try to enter the word \"ignore\" into the text field and press \"submit\".
"; + form += "The request will be rejected by the application."; + form += "

See implementation of tests.RequestHandler.onBeforeBrowse(CefBrowser, CefRequest, boolean) for details

"; + form += "

Testcase 2

"; + form += "Due Google doesn't allow the POST method, the server replies with a 405 error.
"; + form += "If you activate the checkbox \"Use GET instead of POST\", the application will change the POST request into a GET request."; + form += "

See implementation of tests.RequestHandler.onBeforeResourceLoad(CefBrowser, CefRequest) for details

"; + form += "
"; + form += ""; + browser_.loadURL(DataUri.create("text/html", form)); + } + }); + testMenu.add(showForm); + + JMenuItem httpRequest = new JMenuItem("Manual HTTP request"); + httpRequest.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String searchFor = JOptionPane.showInputDialog(owner_, "Search on google:"); + if (searchFor != null && !searchFor.isEmpty()) { + CefRequest myRequest = CefRequest.create(); + myRequest.setMethod("GET"); + myRequest.setURL("http://www.google.com/#q=" + searchFor); + myRequest.setFirstPartyForCookies("http://www.google.com/#q=" + searchFor); + browser_.loadRequest(myRequest); + } + } + }); + testMenu.add(httpRequest); + + JMenuItem showInfo = new JMenuItem("Show Info"); + showInfo.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String info = "Browser status"; + info += "

Browser status

"; + info += ""; + info += ""; + info += ""; + info += ""; + info += ""; + info += ""; + info += ""; + info += "
CanGoBack" + browser_.canGoBack() + "
CanGoForward" + browser_.canGoForward() + "
IsLoading" + browser_.isLoading() + "
isPopup" + browser_.isPopup() + "
hasDocument" + browser_.hasDocument() + "
Url" + browser_.getURL() + "
Zoom-Level" + browser_.getZoomLevel() + "
"; + String js = "var x=window.open(); x.document.open(); x.document.write('" + info + + "'); x.document.close();"; + browser_.executeJavaScript(js, "", 0); + } + }); + testMenu.add(showInfo); + + final JMenuItem showDevTools = new JMenuItem("Show DevTools"); + showDevTools.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + 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 + public void actionPerformed(ActionEvent e) { + UrlRequestDialog dlg = new UrlRequestDialog(owner_, "URL Request Test"); + dlg.setVisible(true); + } + }); + testMenu.add(testURLRequest); + + JMenuItem reparent = new JMenuItem("Reparent"); + reparent.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final BrowserFrame newFrame = new BrowserFrame("New Window"); + newFrame.setLayout(new BorderLayout()); + final JButton reparentButton = new JButton("Reparent <"); + reparentButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (reparentPending_) { + return; + } + reparentPending_ = true; + + if (reparentButton.getText().equals("Reparent <")) { + owner_.removeBrowser(new Runnable() { + @Override + public void run() { + newFrame.add(browser_.getUIComponent(), BorderLayout.CENTER); + newFrame.setBrowser(browser_); + reparentButton.setText("Reparent >"); + reparentPending_ = false; + } + }); + } else { + newFrame.removeBrowser(new Runnable() { + @Override + public void run() { + JRootPane rootPane = (JRootPane) owner_.getComponent(0); + Container container = rootPane.getContentPane(); + JPanel panel = (JPanel) container.getComponent(0); + panel.add(browser_.getUIComponent()); + owner_.setBrowser(browser_); + owner_.revalidate(); + reparentButton.setText("Reparent <"); + reparentPending_ = false; + } + }); + } + } + }); + newFrame.add(reparentButton, BorderLayout.NORTH); + newFrame.setSize(400, 400); + newFrame.setVisible(true); + } + }); + testMenu.add(reparent); + + JMenuItem newwindow = new JMenuItem("New window"); + newwindow.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final MainFrame frame = new MainFrame(OS.isLinux(), false, false, 0, null); + frame.setSize(800, 600); + frame.setVisible(true); + } + }); + testMenu.add(newwindow); + + JMenuItem screenshotSync = new JMenuItem("Screenshot (on AWT thread, native res)"); + screenshotSync.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + long start = System.nanoTime(); + CompletableFuture shot = browser.createScreenshot(true); + System.out.println("Took screenshot from the AWT event thread in " + + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " msecs"); + try { + displayScreenshot(shot.get()); + } catch (InterruptedException | ExecutionException exc) { + // cannot happen, future is already resolved in this case + } + } + }); + screenshotSync.setEnabled(owner.isOsrEnabled()); + testMenu.add(screenshotSync); + + JMenuItem screenshotSyncScaled = new JMenuItem("Screenshot (on AWT thread, scaled)"); + screenshotSyncScaled.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + long start = System.nanoTime(); + CompletableFuture shot = browser.createScreenshot(false); + System.out.println("Took screenshot from the AWT event thread in " + + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " msecs"); + try { + displayScreenshot(shot.get()); + } catch (InterruptedException | ExecutionException exc) { + // cannot happen, future is already resolved in this case + } + } + }); + screenshotSyncScaled.setEnabled(owner.isOsrEnabled()); + testMenu.add(screenshotSyncScaled); + + JMenuItem screenshotAsync = new JMenuItem("Screenshot (from other thread, scaled)"); + screenshotAsync.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + long start = System.nanoTime(); + CompletableFuture shot = browser.createScreenshot(false); + shot.thenAccept((image) -> { + System.out.println("Took screenshot asynchronously in " + + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " msecs"); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + displayScreenshot(image); + } + }); + }); + } + }); + screenshotAsync.setEnabled(owner.isOsrEnabled()); + testMenu.add(screenshotAsync); + + add(fileMenu); + add(bookmarkMenu_); + add(testMenu); + } + + public void addBookmark(String name, String URL) { + if (bookmarkMenu_ == null) { + return; + } + + // Test if the bookmark already exists. If yes, update URL + Component[] entries = bookmarkMenu_.getMenuComponents(); + for (Component itemEntry : entries) { + if (!(itemEntry instanceof JMenuItem)) { + continue; + } + + JMenuItem item = (JMenuItem) itemEntry; + if (item.getText().equals(name)) { + item.setActionCommand(URL); + return; + } + } + + JMenuItem menuItem = new JMenuItem(name); + menuItem.setActionCommand(URL); + menuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + browser_.loadURL(e.getActionCommand()); + } + }); + bookmarkMenu_.add(menuItem); + validate(); + } + + private void displayScreenshot(BufferedImage aScreenshot) { + JFrame frame = new JFrame("Screenshot"); + ImageIcon image = new ImageIcon(); + image.setImage(aScreenshot); + frame.setLayout(new FlowLayout()); + JLabel label = new JLabel(image); + label.setPreferredSize(new Dimension(aScreenshot.getWidth(), aScreenshot.getHeight())); + frame.add(label); + frame.setVisible(true); + frame.pack(); + } + + 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/lib/jcef/java/tests/detailed/ui/StatusPanel.java b/lib/jcef/java/tests/detailed/ui/StatusPanel.java new file mode 100644 index 0000000..8268d2f --- /dev/null +++ b/lib/jcef/java/tests/detailed/ui/StatusPanel.java @@ -0,0 +1,48 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.ui; + +import java.awt.Dimension; + +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; + +@SuppressWarnings("serial") +public class StatusPanel extends JPanel { + private final JProgressBar progressBar_; + private final JLabel status_field_; + + public StatusPanel() { + setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + + add(Box.createHorizontalStrut(5)); + add(Box.createHorizontalStrut(5)); + + progressBar_ = new JProgressBar(); + Dimension progressBarSize = progressBar_.getMaximumSize(); + progressBarSize.width = 100; + progressBar_.setMinimumSize(progressBarSize); + progressBar_.setMaximumSize(progressBarSize); + add(progressBar_); + add(Box.createHorizontalStrut(5)); + + status_field_ = new JLabel("Info"); + status_field_.setAlignmentX(LEFT_ALIGNMENT); + add(status_field_); + add(Box.createHorizontalStrut(5)); + add(Box.createVerticalStrut(21)); + } + + public void setIsInProgress(boolean inProgress) { + progressBar_.setIndeterminate(inProgress); + } + + public void setStatusText(String text) { + status_field_.setText(text); + } +} diff --git a/lib/jcef/java/tests/detailed/util/DataUri.java b/lib/jcef/java/tests/detailed/util/DataUri.java new file mode 100644 index 0000000..895ad85 --- /dev/null +++ b/lib/jcef/java/tests/detailed/util/DataUri.java @@ -0,0 +1,15 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.detailed.util; + +/** + * Utility class for creating data: URIs that can be passed to CefBrowser.loadURL. + */ +public class DataUri { + public static String create(String mimeType, String contents) { + return "data:" + mimeType + ";base64," + + java.util.Base64.getEncoder().encodeToString(contents.getBytes()); + } +}; diff --git a/lib/jcef/java/tests/junittests/DisplayHandlerTest.java b/lib/jcef/java/tests/junittests/DisplayHandlerTest.java new file mode 100644 index 0000000..81b873a --- /dev/null +++ b/lib/jcef/java/tests/junittests/DisplayHandlerTest.java @@ -0,0 +1,81 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.junittests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.handler.CefDisplayHandlerAdapter; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +// Test the DisplayHandler implementation. +@ExtendWith(TestSetupExtension.class) +class DisplayHandlerTest { + private final String testUrl_ = "http://test.com/test.html"; + private final String testContent_ = + "Test TitleTest!"; + + private boolean gotCallback_ = false; + + @Test + void onTitleChange() { + TestFrame frame = new TestFrame() { + @Override + protected void setupTest() { + client_.addDisplayHandler(new CefDisplayHandlerAdapter() { + @Override + public void onTitleChange(CefBrowser browser, String title) { + assertFalse(gotCallback_); + gotCallback_ = true; + assertEquals("Test Title", title); + terminateTest(); + } + }); + + addResource(testUrl_, testContent_, "text/html"); + + createBrowser(testUrl_); + + super.setupTest(); + } + }; + + frame.awaitCompletion(); + + assertTrue(gotCallback_); + } + + @Test + void onAddressChange() { + TestFrame frame = new TestFrame() { + @Override + protected void setupTest() { + client_.addDisplayHandler(new CefDisplayHandlerAdapter() { + @Override + public void onAddressChange(CefBrowser browser, CefFrame frame, String url) { + assertFalse(gotCallback_); + gotCallback_ = true; + assertEquals(url, testUrl_); + terminateTest(); + } + }); + + addResource(testUrl_, testContent_, "text/html"); + + createBrowser(testUrl_); + + super.setupTest(); + } + }; + + frame.awaitCompletion(); + + assertTrue(gotCallback_); + } +} diff --git a/lib/jcef/java/tests/junittests/DragDataTest.java b/lib/jcef/java/tests/junittests/DragDataTest.java new file mode 100644 index 0000000..bd90430 --- /dev/null +++ b/lib/jcef/java/tests/junittests/DragDataTest.java @@ -0,0 +1,165 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.junittests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.cef.callback.CefDragData; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.util.Vector; + +// Test the TestFrame implementation. +@ExtendWith(TestSetupExtension.class) +class DragDataTest { + @Test + void createEmpty() { + CefDragData dragData = CefDragData.create(); + assertNotNull(dragData); + assertFalse(dragData.isReadOnly()); + + assertFalse(dragData.isLink()); + assertFalse(dragData.isFile()); + assertTrue(dragData.isFragment()); // Default state. + + assertEquals("", dragData.getLinkURL()); + assertEquals("", dragData.getLinkTitle()); + assertEquals("", dragData.getLinkMetadata()); + assertEquals("", dragData.getFragmentText()); + assertEquals("", dragData.getFragmentHtml()); + assertEquals("", dragData.getFragmentBaseURL()); + assertEquals(0, dragData.getFileContents(null)); + assertEquals("", dragData.getFileName()); + assertFalse(dragData.getFileNames(null)); + + // Explicit cleanup to avoid memory leaks. + dragData.dispose(); + } + + @Test + void createLink() { + CefDragData dragData = CefDragData.create(); + assertNotNull(dragData); + assertFalse(dragData.isReadOnly()); + + final String linkURL = "http://test.com/test.html"; + dragData.setLinkURL(linkURL); + assertEquals(linkURL, dragData.getLinkURL()); + + final String linkTitle = "Test Title"; + dragData.setLinkTitle(linkTitle); + assertEquals(linkTitle, dragData.getLinkTitle()); + + final String linkMetadata = "something"; + dragData.setLinkMetadata(linkMetadata); + assertEquals(linkMetadata, dragData.getLinkMetadata()); + + assertTrue(dragData.isLink()); + assertFalse(dragData.isFile()); + assertFalse(dragData.isFragment()); + + // Explicit cleanup to avoid memory leaks. + dragData.dispose(); + } + + @Test + void createFile() { + CefDragData dragData = CefDragData.create(); + assertNotNull(dragData); + assertFalse(dragData.isReadOnly()); + + final String path1 = "/path/to/file1.txt"; + final String path2 = "/path/to/file2.txt"; + + dragData.addFile(path1, "File 1"); + dragData.addFile(path2, "File 2"); + + Vector fileNames = new Vector<>(); + assertTrue(dragData.getFileNames(fileNames)); + + assertEquals(2, fileNames.size()); + assertEquals(path1, fileNames.get(0)); + assertEquals(path2, fileNames.get(1)); + + assertFalse(dragData.isLink()); + assertTrue(dragData.isFile()); + assertFalse(dragData.isFragment()); + + // Explicit cleanup to avoid memory leaks. + dragData.dispose(); + } + + @Test + void createFragment() { + CefDragData dragData = CefDragData.create(); + assertNotNull(dragData); + assertFalse(dragData.isReadOnly()); + + final String fragmentText = "something"; + dragData.setFragmentText(fragmentText); + assertEquals(fragmentText, dragData.getFragmentText()); + + final String fragmentHtml = "something"; + dragData.setFragmentHtml(fragmentHtml); + assertEquals(fragmentHtml, dragData.getFragmentHtml()); + + final String fragmentBaseURL = "http://test.com/test.html"; + dragData.setFragmentBaseURL(fragmentBaseURL); + assertEquals(fragmentBaseURL, dragData.getFragmentBaseURL()); + + assertFalse(dragData.isLink()); + assertFalse(dragData.isFile()); + assertTrue(dragData.isFragment()); + + // Explicit cleanup to avoid memory leaks. + dragData.dispose(); + } + + @Test + void cloneObject() { + CefDragData dragData = CefDragData.create(); + assertNotNull(dragData); + assertFalse(dragData.isReadOnly()); + + final String fragmentText = "something"; + final String fragmentBaseURL = "http://test.com/test.html"; + dragData.setFragmentText(fragmentText); + dragData.setFragmentBaseURL(fragmentBaseURL); + + CefDragData dragData2 = dragData.clone(); + assertFalse(dragData2.isReadOnly()); + assertEquals(fragmentText, dragData2.getFragmentText()); + assertEquals(fragmentBaseURL, dragData2.getFragmentBaseURL()); + + assertFalse(dragData2.isLink()); + assertFalse(dragData2.isFile()); + assertTrue(dragData2.isFragment()); + + // Explicit cleanup to avoid memory leaks. + dragData.dispose(); + dragData2.dispose(); + } + + @Test + void disposeObject() { + CefDragData dragData = CefDragData.create(); + assertNotNull(dragData); + assertFalse(dragData.isReadOnly()); + + final String fragmentText = "something"; + dragData.setFragmentText(fragmentText); + assertEquals(fragmentText, dragData.getFragmentText()); + + // Explicit cleanup to avoid memory leaks. + // After dispose() the Java object is no longer backed by a CEF object. + dragData.dispose(); + + assertEquals(null, dragData.getFragmentText()); + } +} diff --git a/lib/jcef/java/tests/junittests/TestFrame.java b/lib/jcef/java/tests/junittests/TestFrame.java new file mode 100644 index 0000000..eee3630 --- /dev/null +++ b/lib/jcef/java/tests/junittests/TestFrame.java @@ -0,0 +1,299 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.junittests; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import static tests.junittests.TestSetupContext.debugPrint; + +import org.cef.CefApp; +import org.cef.CefClient; +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.callback.CefAuthCallback; +import org.cef.callback.CefCallback; +import org.cef.handler.CefCookieAccessFilter; +import org.cef.handler.CefLifeSpanHandler; +import org.cef.handler.CefLoadHandler; +import org.cef.handler.CefRequestHandler; +import org.cef.handler.CefResourceHandler; +import org.cef.handler.CefResourceRequestHandler; +import org.cef.misc.BoolRef; +import org.cef.misc.StringRef; +import org.cef.network.CefRequest; +import org.cef.network.CefRequest.TransitionType; +import org.cef.network.CefResponse; +import org.cef.network.CefURLRequest; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.HashMap; +import java.util.concurrent.CountDownLatch; + +import javax.swing.JFrame; + +// Base class for browsers that run tests. +class TestFrame extends JFrame implements CefLifeSpanHandler, CefLoadHandler, CefRequestHandler, + CefResourceRequestHandler { + private static final long serialVersionUID = -5570653778104813836L; + private boolean isClosed_ = false; + private CountDownLatch countdown_ = new CountDownLatch(1); + + // Resources that have been populated for the test. + private class ResourceContent { + String content; + String mimeType; + HashMap headerMap; + } + private HashMap resourceMap_ = null; + + protected final CefClient client_; + protected CefBrowser browser_ = null; + + TestFrame() { + client_ = CefApp.getInstance().createClient(); + assertNotNull(client_); + + // Browser window closing works as follows: + // 1. Sending WindowEvent.WINDOW_CLOSING calls WindowAdapter.windowClosing. + // 2. WindowAdapter.windowClosing calls CefBrowser.close(false). + // 3. CEF calls CefLifeSpanHandler.doClose() which calls CefBrowser.doClose() + // which returns true (canceling the close). + // 4. CefBrowser.doClose() triggers another call to WindowAdapter.windowClosing. + // 5. WindowAdapter.windowClosing calls CefBrowser.close(true). + // 6. For windowed browsers CEF destroys the native window handle. For OSR + // browsers CEF calls CefLifeSpanHandler.doClose() which calls + // CefBrowser.doClose() again which returns false (allowing the close). + // 7. CEF calls CefLifeSpanHandler.onBeforeClose and the browser is destroyed. + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + boolean isClosed = isClosed_; + + if (isClosed) { + // Cause browser.doClose() to return false so that OSR browsers + // can close. + browser_.setCloseAllowed(); + } + + // Results in another call to this method. + if (debugPrint()) + System.out.println("windowClosing CefBrowser.close(" + isClosed + ")"); + browser_.close(isClosed); + if (!isClosed_) { + isClosed_ = true; + } + if (isClosed) { + // Dispose after the 2nd call to this method. + if (debugPrint()) System.out.println("windowClosing Frame.dispose"); + dispose(); + } + } + }); + + client_.addLifeSpanHandler(this); + client_.addLoadHandler(this); + client_.addRequestHandler(this); + + setupTest(); + } + + protected void createBrowser(String startURL) { + assertNull(browser_); + browser_ = client_.createBrowser(startURL, false /* useOSR */, false /* isTransparent */); + assertNotNull(browser_); + + getContentPane().add(browser_.getUIComponent(), BorderLayout.CENTER); + pack(); + setSize(800, 600); + setVisible(true); + } + + // Override this method to perform test setup. + protected void setupTest() {} + + // Override this method to perform test cleanup. + protected void cleanupTest() { + if (debugPrint()) System.out.println("cleanupTest"); + client_.dispose(); + // Allow the test to complete. + countdown_.countDown(); + } + + // Call this method to terminate the test by dispatching a window close event. + protected final void terminateTest() { + if (debugPrint()) System.out.println("terminateTest"); + if (!isClosed_) { + dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING)); + } + } + + // Block until the test completes. + public final void awaitCompletion() { + try { + countdown_.await(); + } catch (InterruptedException e) { + } + if (debugPrint()) System.out.println("awaitCompletion returned"); + } + + protected void addResource(String url, String content, String mimeType) { + addResource(url, content, mimeType, null); + } + + // Add a resource that will be returned via getResourceHandler(). + protected void addResource( + String url, String content, String mimeType, HashMap headerMap) { + if (resourceMap_ == null) resourceMap_ = new HashMap<>(); + + assertNull(resourceMap_.get(url)); + + ResourceContent rc = new ResourceContent(); + rc.content = content; + rc.mimeType = mimeType; + rc.headerMap = headerMap; + + resourceMap_.put(url, rc); + } + + // CefLifeSpanHandler methods: + + @Override + public void onAfterCreated(CefBrowser browser) { + if (debugPrint()) System.out.println("onAfterCreated id=" + browser.getIdentifier()); + } + + @Override + public boolean onBeforePopup( + CefBrowser browser, CefFrame frame, String target_url, String target_frame_name) { + return false; + } + + @Override + public void onAfterParentChanged(CefBrowser browser) {} + + @Override + public boolean doClose(CefBrowser browser) { + boolean result = browser.doClose(); + if (debugPrint()) { + System.out.println( + "doClose id=" + browser.getIdentifier() + " CefBrowser.doClose=" + result); + } + return result; + } + + @Override + public void onBeforeClose(CefBrowser browser) { + if (debugPrint()) System.out.println("onBeforeClose id=" + browser.getIdentifier()); + cleanupTest(); + } + + // CefLoadHandler methods: + + @Override + public void onLoadingStateChange( + CefBrowser browser, boolean isLoading, boolean canGoBack, boolean canGoForward) {} + + @Override + public void onLoadStart(CefBrowser browser, CefFrame frame, TransitionType transitionType) {} + + @Override + public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) {} + + @Override + public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, + String errorText, String failedUrl) {} + + // CefRequestHandler methods: + + @Override + public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, + boolean user_gesture, boolean is_redirect) { + return false; + } + + @Override + public boolean onOpenURLFromTab( + CefBrowser browser, CefFrame frame, String target_url, boolean user_gesture) { + return false; + } + + @Override + public CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame, + CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator, + BoolRef disableDefaultHandling) { + return this; + } + + @Override + public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy, + String host, int port, String realm, String scheme, CefAuthCallback callback) { + return false; + } + + @Override + public boolean onCertificateError(CefBrowser browser, CefLoadHandler.ErrorCode cert_error, + String request_url, CefCallback callback) { + return false; + } + + @Override + public void onRenderProcessTerminated( + CefBrowser browser, TerminationStatus status, int error_code, String error_string) {} + + // CefResourceRequestHandler methods: + + @Override + public CefCookieAccessFilter getCookieAccessFilter( + CefBrowser browser, CefFrame frame, CefRequest request) { + return null; + } + + @Override + public boolean onBeforeResourceLoad(CefBrowser browser, CefFrame frame, CefRequest request) { + return false; + } + + @Override + public CefResourceHandler getResourceHandler( + CefBrowser browser, CefFrame frame, CefRequest request) { + if (resourceMap_ != null) { + String url = request.getURL(); + + // Ignore the query component, if any. + int idx = url.indexOf('?'); + if (idx > 0) url = url.substring(0, idx); + + ResourceContent rc = resourceMap_.get(url); + if (rc != null) { + if (debugPrint()) System.out.println("Found resource for: " + url); + return new TestResourceHandler(rc.content, rc.mimeType, rc.headerMap); + } + } + + return null; + } + + @Override + public void onResourceRedirect(CefBrowser browser, CefFrame frame, CefRequest request, + CefResponse response, StringRef new_url) {} + + @Override + public boolean onResourceResponse( + CefBrowser browser, CefFrame frame, CefRequest request, CefResponse response) { + return false; + } + + @Override + public void onResourceLoadComplete(CefBrowser browser, CefFrame frame, CefRequest request, + CefResponse response, CefURLRequest.Status status, long receivedContentLength) {} + + @Override + public void onProtocolExecution( + CefBrowser browser, CefFrame frame, CefRequest request, BoolRef allowOsExecution) {} +} diff --git a/lib/jcef/java/tests/junittests/TestFrameTest.java b/lib/jcef/java/tests/junittests/TestFrameTest.java new file mode 100644 index 0000000..e8f36c1 --- /dev/null +++ b/lib/jcef/java/tests/junittests/TestFrameTest.java @@ -0,0 +1,63 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.junittests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.cef.browser.CefBrowser; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +// Test the TestFrame implementation. +@ExtendWith(TestSetupExtension.class) +class TestFrameTest { + private boolean gotSetupTest_ = false; + private boolean gotCleanupTest_ = false; + private boolean gotLoadingStateChange_ = false; + + @Test + void minimal() { + final String testUrl = "http://test.com/test.html"; + TestFrame frame = new TestFrame() { + @Override + protected void setupTest() { + assertFalse(gotSetupTest_); + gotSetupTest_ = true; + + addResource(testUrl, "Test!", "text/html"); + + createBrowser(testUrl); + + super.setupTest(); + } + + @Override + protected void cleanupTest() { + assertFalse(gotCleanupTest_); + gotCleanupTest_ = true; + + super.cleanupTest(); + } + + @Override + public void onLoadingStateChange(CefBrowser browser, boolean isLoading, + boolean canGoBack, boolean canGoForward) { + if (!isLoading) { + assertFalse(gotLoadingStateChange_); + gotLoadingStateChange_ = true; + terminateTest(); + } + } + }; + + frame.awaitCompletion(); + + assertTrue(gotSetupTest_); + assertTrue(gotLoadingStateChange_); + assertTrue(gotCleanupTest_); + } +} diff --git a/lib/jcef/java/tests/junittests/TestResourceHandler.java b/lib/jcef/java/tests/junittests/TestResourceHandler.java new file mode 100644 index 0000000..23594f4 --- /dev/null +++ b/lib/jcef/java/tests/junittests/TestResourceHandler.java @@ -0,0 +1,69 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.junittests; + +import org.cef.callback.CefCallback; +import org.cef.handler.CefResourceHandlerAdapter; +import org.cef.misc.IntRef; +import org.cef.misc.StringRef; +import org.cef.network.CefRequest; +import org.cef.network.CefResponse; + +import java.nio.ByteBuffer; +import java.util.HashMap; + +class TestResourceHandler extends CefResourceHandlerAdapter { + private int offset_ = 0; + private final String content_; + private final String mimeType_; + private final HashMap headerMap_; + + TestResourceHandler(String content, String mimeType, HashMap headerMap) { + content_ = content; + mimeType_ = mimeType; + headerMap_ = headerMap; + } + + @Override + public boolean processRequest(CefRequest request, CefCallback callback) { + callback.Continue(); + return true; + } + + @Override + public void getResponseHeaders( + CefResponse response, IntRef response_length, StringRef redirectUrl) { + response_length.set(content_.length()); + response.setMimeType(mimeType_); + response.setStatus(200); + + if (headerMap_ != null) { + HashMap headerMap = new HashMap<>(); + response.getHeaderMap(headerMap); + headerMap.putAll(headerMap_); + response.setHeaderMap(headerMap); + } + } + + @Override + public boolean readResponse( + byte[] data_out, int bytes_to_read, IntRef bytes_read, CefCallback callback) { + int length = content_.length(); + if (offset_ >= length) return false; + + // Extract up to |bytes_to_read| bytes from |content_|. + int endPos = offset_ + bytes_to_read; + String dataToSend = (endPos > length) ? content_.substring(offset_) + : content_.substring(offset_, endPos); + + // Copy extracted bytes into |data_out| and set the read length to |bytes_read|. + ByteBuffer result = ByteBuffer.wrap(data_out); + result.put(dataToSend.getBytes()); + bytes_read.set(dataToSend.length()); + + offset_ = endPos; + return true; + } +} diff --git a/lib/jcef/java/tests/junittests/TestSetupContext.java b/lib/jcef/java/tests/junittests/TestSetupContext.java new file mode 100644 index 0000000..758fbff --- /dev/null +++ b/lib/jcef/java/tests/junittests/TestSetupContext.java @@ -0,0 +1,27 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.junittests; + +import org.junit.jupiter.api.extension.ExtensionContext; + +import java.util.Optional; + +// Stores global test setup state for access from package classes. +class TestSetupContext { + private static boolean debugPrint_ = false; + + // Debug print statements may be enabled via `--config debugPrint=true`. + static boolean debugPrint() { + return debugPrint_; + } + + // Initialize from global configuration parameters. + static void initialize(ExtensionContext context) { + Optional debugPrint = context.getConfigurationParameter("debugPrint"); + if (debugPrint.isPresent() && debugPrint.get().equalsIgnoreCase("true")) { + debugPrint_ = true; + } + } +} diff --git a/lib/jcef/java/tests/junittests/TestSetupExtension.java b/lib/jcef/java/tests/junittests/TestSetupExtension.java new file mode 100644 index 0000000..6688771 --- /dev/null +++ b/lib/jcef/java/tests/junittests/TestSetupExtension.java @@ -0,0 +1,90 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.junittests; + +import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL; + +import org.cef.CefApp; +import org.cef.CefApp.CefAppState; +import org.cef.CefSettings; +import org.cef.handler.CefAppHandlerAdapter; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +import java.util.concurrent.CountDownLatch; + +// All test cases must install this extension for CEF to be properly initialized +// and shut down. +// +// For example: +// +// @ExtendWith(TestSetupExtension.class) +// class FooTest { +// @Test +// void testCaseThatRequiresCEF() {} +// } +// +// This code is based on https://stackoverflow.com/a/51556718. +public class TestSetupExtension + implements BeforeAllCallback, ExtensionContext.Store.CloseableResource { + private static boolean initialized_ = false; + private static CountDownLatch countdown_ = new CountDownLatch(1); + + @Override + public void beforeAll(ExtensionContext context) { + if (!initialized_) { + initialized_ = true; + initialize(context); + } + } + + // Executed before any tests are run. + private void initialize(ExtensionContext context) { + TestSetupContext.initialize(context); + + if (TestSetupContext.debugPrint()) { + System.out.println("TestSetupExtension.initialize"); + } + + // Register a callback hook for when the root test context is shut down. + context.getRoot().getStore(GLOBAL).put("jcef_test_setup", this); + + // Perform startup initialization on platforms that require it. + if (!CefApp.startup(null)) { + System.out.println("Startup initialization failed!"); + return; + } + + CefApp.addAppHandler(new CefAppHandlerAdapter(null) { + @Override + public void stateHasChanged(org.cef.CefApp.CefAppState state) { + if (state == CefAppState.TERMINATED) { + // Signal completion of CEF shutdown. + countdown_.countDown(); + } + } + }); + + // Initialize the singleton CefApp instance. + CefSettings settings = new CefSettings(); + CefApp.getInstance(settings); + } + + // Executed after all tests have completed. + @Override + public void close() { + if (TestSetupContext.debugPrint()) { + System.out.println("TestSetupExtension.close"); + } + + CefApp.getInstance().dispose(); + + // Wait for CEF shutdown to complete. + try { + countdown_.await(); + } catch (InterruptedException e) { + } + } +} diff --git a/lib/jcef/java/tests/simple/MainFrame.java b/lib/jcef/java/tests/simple/MainFrame.java new file mode 100644 index 0000000..44035d0 --- /dev/null +++ b/lib/jcef/java/tests/simple/MainFrame.java @@ -0,0 +1,229 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package tests.simple; + +import org.cef.CefApp; +import org.cef.CefApp.CefAppState; +import org.cef.CefClient; +import org.cef.CefSettings; +import org.cef.OS; +import org.cef.browser.CefBrowser; +import org.cef.browser.CefFrame; +import org.cef.handler.CefAppHandlerAdapter; +import org.cef.handler.CefDisplayHandlerAdapter; +import org.cef.handler.CefFocusHandlerAdapter; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.GraphicsConfiguration; +import java.awt.KeyboardFocusManager; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; + +/** + * This is a simple example application using JCEF. + * It displays a JFrame with a JTextField at its top and a CefBrowser in its + * center. The JTextField is used to enter and assign an URL to the browser UI. + * No additional handlers or callbacks are used in this example. + * + * The number of used JCEF classes is reduced (nearly) to its minimum and should + * assist you to get familiar with JCEF. + * + * For a more feature complete example have also a look onto the example code + * within the package "tests.detailed". + */ +public class MainFrame extends JFrame { + private static final long serialVersionUID = -5570653778104813836L; + private final JTextField address_; + private final CefApp cefApp_; + private final CefClient client_; + private final CefBrowser browser_; + private final Component browserUI_; + private boolean browserFocus_ = true; + private JFrame fullscreenFrame_; + + /** + * To display a simple browser window, it suffices completely to create an + * instance of the class CefBrowser and to assign its UI component to your + * application (e.g. to your content pane). + * But to be more verbose, this CTOR keeps an instance of each object on the + * way to the browser UI. + */ + private MainFrame(String startURL, boolean useOSR, boolean isTransparent) { + // (1) The entry point to JCEF is always the class CefApp. There is only one + // instance per application and therefore you have to call the method + // "getInstance()" instead of a CTOR. + // + // CefApp is responsible for the global CEF context. It loads all + // required native libraries, initializes CEF accordingly, starts a + // background task to handle CEF's message loop and takes care of + // shutting down CEF after disposing it. + CefApp.addAppHandler(new CefAppHandlerAdapter(null) { + @Override + public void stateHasChanged(org.cef.CefApp.CefAppState state) { + // Shutdown the app if the native CEF part is terminated + if (state == CefAppState.TERMINATED) System.exit(0); + } + }); + CefSettings settings = new CefSettings(); + settings.windowless_rendering_enabled = useOSR; + cefApp_ = CefApp.getInstance(settings); + + // (2) JCEF can handle one to many browser instances simultaneous. These + // browser instances are logically grouped together by an instance of + // the class CefClient. In your application you can create one to many + // instances of CefClient with one to many CefBrowser instances per + // client. To get an instance of CefClient you have to use the method + // "createClient()" of your CefApp instance. Calling an CTOR of + // CefClient is not supported. + // + // CefClient is a connector to all possible events which come from the + // CefBrowser instances. Those events could be simple things like the + // change of the browser title or more complex ones like context menu + // events. By assigning handlers to CefClient you can control the + // behavior of the browser. See tests.detailed.MainFrame for an example + // of how to use these handlers. + client_ = cefApp_.createClient(); + + // (3) One CefBrowser instance is responsible to control what you'll see on + // the UI component of the instance. It can be displayed off-screen + // rendered or windowed rendered. To get an instance of CefBrowser you + // have to call the method "createBrowser()" of your CefClient + // instances. + // + // CefBrowser has methods like "goBack()", "goForward()", "loadURL()", + // and many more which are used to control the behavior of the displayed + // content. The UI is held within a UI-Compontent which can be accessed + // by calling the method "getUIComponent()" on the instance of CefBrowser. + // The UI component is inherited from a java.awt.Component and therefore + // it can be embedded into any AWT UI. + browser_ = client_.createBrowser(startURL, useOSR, isTransparent); + 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 + // of the URL. To respond to the input of the user, we're registering an + // anonymous ActionListener. This listener is performed each time the + // user presses the "ENTER" key within the address field. + // If this happens, the entered value is passed to the CefBrowser + // instance to be loaded as URL. + address_ = new JTextField(startURL, 100); + address_.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + browser_.loadURL(address_.getText()); + } + }); + + // Update the address field when the browser URL changes. + client_.addDisplayHandler(new CefDisplayHandlerAdapter() { + @Override + public void onAddressChange(CefBrowser browser, CefFrame frame, String url) { + address_.setText(url); + } + @Override + public void onFullscreenModeChange(CefBrowser browser, boolean fullscreen) { + setBrowserFullscreen(fullscreen); + } + }); + + // Clear focus from the browser when the address field gains focus. + address_.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + if (!browserFocus_) return; + browserFocus_ = false; + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + address_.requestFocus(); + } + }); + + // Clear focus from the address field when the browser gains focus. + client_.addFocusHandler(new CefFocusHandlerAdapter() { + @Override + public void onGotFocus(CefBrowser browser) { + if (browserFocus_) return; + browserFocus_ = true; + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + browser.setFocus(true); + } + + @Override + public void onTakeFocus(CefBrowser browser, boolean next) { + browserFocus_ = false; + } + }); + + // (5) All UI components are assigned to the default content pane of this + // JFrame and afterwards the frame is made visible to the user. + getContentPane().add(address_, BorderLayout.NORTH); + getContentPane().add(browserUI_, BorderLayout.CENTER); + pack(); + setSize(800, 600); + setVisible(true); + + // (6) To take care of shutting down CEF accordingly, it's important to call + // the method "dispose()" of the CefApp instance if the Java + // application will be closed. Otherwise you'll get asserts from CEF. + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + CefApp.getInstance().dispose(); + dispose(); + } + }); + } + + public 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)) { + System.out.println("Startup initialization failed!"); + return; + } + + // The simple example application is created as anonymous class and points + // to Google as the very first loaded page. Windowed rendering mode is used by + // default. If you want to test OSR mode set |useOsr| to true and recompile. + boolean useOsr = false; + new MainFrame("http://www.google.com", useOsr, false); + } +} diff --git a/lib/jcef/native/CMakeLists.txt b/lib/jcef/native/CMakeLists.txt new file mode 100644 index 0000000..cdcd1ef --- /dev/null +++ b/lib/jcef/native/CMakeLists.txt @@ -0,0 +1,430 @@ +# 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. + +# +# Source files. +# + +# jcef sources. +set(JCEF_SRCS + CefApp.cpp + CefApp.h + CefAuthCallback_N.cpp + CefAuthCallback_N.h + CefBeforeDownloadCallback_N.cpp + CefBeforeDownloadCallback_N.h + CefBrowser_N.cpp + CefBrowser_N.h + CefCallback_N.cpp + CefCallback_N.h + CefClientHandler.cpp + CefClientHandler.h + CefCommandLine_N.cpp + CefCommandLine_N.h + CefContextMenuParams_N.cpp + CefContextMenuParams_N.h + CefCookieManager_N.cpp + CefCookieManager_N.h + CefDownloadItemCallback_N.cpp + CefDownloadItemCallback_N.h + CefDownloadItem_N.cpp + CefDownloadItem_N.h + CefDragData_N.cpp + CefDragData_N.h + CefFileDialogCallback_N.cpp + CefFileDialogCallback_N.h + CefFrame_N.cpp + CefFrame_N.h + CefJSDialogCallback_N.h + CefJSDialogCallback_N.cpp + CefMenuModel_N.cpp + CefMenuModel_N.h + CefMessageRouter_N.cpp + CefMessageRouter_N.h + CefPostData_N.cpp + CefPostData_N.h + CefPostDataElement_N.cpp + CefPostDataElement_N.h + CefPrintDialogCallback_N.cpp + CefPrintDialogCallback_N.h + CefPrintJobCallback_N.cpp + CefPrintJobCallback_N.h + CefPrintSettings_N.cpp + 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 + CefSchemeRegistrar_N.h + CefURLRequest_N.cpp + CefURLRequest_N.h + browser_process_handler.cpp + browser_process_handler.h + client_app.cpp + client_app.h + client_handler.cpp + client_handler.h + completion_callback.cpp + completion_callback.h + context.cpp + context.h + context_menu_handler.cpp + context_menu_handler.h + cookie_access_filter.cpp + cookie_access_filter.h + 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 + display_handler.h + download_handler.cpp + download_handler.h + drag_handler.cpp + 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 + jni_util.h + jni_util.cpp + jsdialog_handler.cpp + jsdialog_handler.h + keyboard_handler.cpp + keyboard_handler.h + life_span_handler.cpp + life_span_handler.h + load_handler.cpp + load_handler.h + message_router_handler.cpp + message_router_handler.h + pdf_print_callback.cpp + pdf_print_callback.h + print_handler.cpp + print_handler.h + render_handler.cpp + render_handler.h + request_context_handler.cpp + request_context_handler.h + request_handler.cpp + request_handler.h + resource_handler.cpp + resource_handler.h + resource_request_handler.cpp + resource_request_handler.h + run_file_dialog_callback.cpp + run_file_dialog_callback.h + scheme_handler_factory.cpp + scheme_handler_factory.h + string_visitor.cpp + string_visitor.h + temp_window.h + url_request_client.cpp + url_request_client.h + util.h + window_handler.cpp + window_handler.h + write_handler.cpp + write_handler.h + ) +set(JCEF_SRCS_LINUX + critical_wait_posix.cpp + jni_util_linux.cpp + temp_window_x11.cc + temp_window_x11.h + util_linux.cpp + util_posix.cpp + ) +set(JCEF_SRCS_MAC + critical_wait_posix.cpp + temp_window_mac.h + temp_window_mac.mm + util_mac.h + util_mac.mm + util_posix.cpp + ) +set(JCEF_SRCS_WINDOWS + critical_wait_win.cpp + jni_util_win.cpp + jcef_dll.rc + temp_window_win.cc + temp_window_win.h + util_win.cpp + ) +APPEND_PLATFORM_SOURCES(JCEF_SRCS) +source_group(jcef FILES ${JCEF_SRCS}) + +# jcef_helper sources. +set(JCEF_HELPER_SRCS + jcef_helper.cpp + util.h + ) +set(JCEF_HELPER_SRCS_LINUX + util_posix.cpp + ) +set(JCEF_HELPER_SRCS_MAC + util_posix.cpp + ) +set(JCEF_HELPER_SRCS_WINDOWS + jcef_helper.rc + util_win.cpp + ) +APPEND_PLATFORM_SOURCES(JCEF_HELPER_SRCS) +source_group(jcef FILES ${JCEF_HELPER_SRCS}) + + +# +# Shared configuration. +# + +# Target binary names. +set(JCEF_TARGET "jcef") +if(OS_MAC) + set(JCEF_APP_NAME "jcef_app") + set(JCEF_HELPER_TARGET "jcef_Helper") + set(JCEF_HELPER_OUTPUT_NAME "jcef Helper") +else() + set(JCEF_HELPER_TARGET "jcef_helper") +endif() + +if(OS_LINUX OR OS_WINDOWS) + # Logical target used to link the libcef library on Linux and Windows. + # On macOS the CEF framework is loaded dynamically at startup. + ADD_LOGICAL_TARGET("libcef_lib" "${CEF_LIB_DEBUG}" "${CEF_LIB_RELEASE}") +endif() + +# Determine the target output directory. +SET_CEF_TARGET_OUT_DIR() + + +# +# Linux configuration. +# + +if(OS_LINUX) + # Helper executable target. + add_executable(${JCEF_HELPER_TARGET} ${JCEF_HELPER_SRCS}) + SET_EXECUTABLE_TARGET_PROPERTIES(${JCEF_HELPER_TARGET}) + add_dependencies(${JCEF_HELPER_TARGET} libcef_dll_wrapper) + target_link_libraries(${JCEF_HELPER_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS}) + + # Set rpath so that libraries can be placed next to the executable. + set_target_properties(${JCEF_HELPER_TARGET} PROPERTIES INSTALL_RPATH "$ORIGIN") + set_target_properties(${JCEF_HELPER_TARGET} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE) + + # JCEF library target. + add_library(${JCEF_TARGET} SHARED ${JCEF_SRCS}) + SET_LIBRARY_TARGET_PROPERTIES(${JCEF_TARGET}) + add_dependencies(${JCEF_TARGET} libcef_dll_wrapper ${JCEF_HELPER_TARGET}) + target_link_libraries(${JCEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS} ${JNI_LIBRARIES}) + target_include_directories(${JCEF_TARGET} PUBLIC ${JNI_INCLUDE_DIRS}) + + # Compile flags specific to the JCEF library target. + # USING_JAVA = Add the USING_JAVA define. + target_compile_definitions(${JCEF_TARGET} PRIVATE "USING_JAVA") + + # -fvisibility=default = Give default visibility to declarations that are not explicitly marked as visible. + # Necessary so that JNI symbols are properly exported when building with GCC. + # Related discussion: http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-February/014446.html + # Test symbol export with: nm -D --defined-only libjcef.so | grep Java + set_target_properties(${JCEF_TARGET} PROPERTIES + COMPILE_FLAGS -fvisibility=default + ) + + # Set rpath so that libraries can be placed next to the library. + set_target_properties(${JCEF_TARGET} PROPERTIES INSTALL_RPATH "$ORIGIN") + set_target_properties(${JCEF_TARGET} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE) + + # Copy binary and resource files to the target output directory. + COPY_FILES("${JCEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}") + 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://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}/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 + ) +endif() + + +# +# Mac OS X configuration. +# + +if(OS_MAC) + # Find the ant executable, including Homebrew paths. + find_program(ANT_EXECUTABLE ant + HINTS /opt/homebrew/bin /usr/local/bin + ) + if(NOT ANT_EXECUTABLE) + message(FATAL_ERROR "ant not found. Install with: brew install ant") + endif() + message(STATUS "Using ant: ${ANT_EXECUTABLE}") + + # Avoid CMP0042 policy errors. + set(CMAKE_MACOSX_RPATH 1) + + # Avoid CMP0068 policy errors. + if(POLICY CMP0068) + cmake_policy(SET CMP0068 NEW) + endif() + + # Output path for the main app bundle. + set(JCEF_APP "${CEF_TARGET_OUT_DIR}/${JCEF_APP_NAME}.app") + + # Variable referenced from Info.plist files. + set(EXECUTABLE_NAME "${JCEF_APP_NAME}") + set(PRODUCT_NAME "${JCEF_APP_NAME}") + + # JCEF library target. + add_library(${JCEF_TARGET} SHARED ${JCEF_RESOURCES_SRCS} ${JCEF_SRCS}) + SET_EXECUTABLE_TARGET_PROPERTIES(${JCEF_TARGET}) + add_dependencies(${JCEF_TARGET} libcef_dll_wrapper) + target_link_libraries(${JCEF_TARGET} libcef_dll_wrapper ${CEF_STANDARD_LIBS} ${JNI_LIBRARIES}) + target_include_directories(${JCEF_TARGET} PUBLIC ${JNI_INCLUDE_DIRS}) + + # Use ad-hoc code signing for the dynamic library (required by Xcode 14+). + set_target_properties(${JCEF_TARGET} PROPERTIES + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "-" + ) + + # Compile flags specific to the JCEF library target. + # USING_JAVA = Add the USING_JAVA define. + target_compile_definitions(${JCEF_TARGET} PRIVATE "USING_JAVA") + + # Name and location of the JCEF library in the main app bundle. + set(JCEF_TARGET_LIBRARY "lib${JCEF_TARGET}.dylib") + set(JCEF_TARGET_LIBRARY_APP_PATH "${JCEF_APP}/Contents/Java/${JCEF_TARGET_LIBRARY}") + + add_custom_command( + TARGET ${JCEF_TARGET} + POST_BUILD + # Build the main app bundle. + COMMAND ${ANT_EXECUTABLE} + -buildfile ${CMAKE_SOURCE_DIR} + -Djdk7.path=${JAVA_DIR} + -Dout.path=${CEF_TARGET_OUT_DIR} + -Dout.name=${JCEF_APP_NAME} + -Dout.id=org.jcef.jcef + -Dout.mainclass=tests.detailed.MainFrame + bundle + # Copy the CEF framework into the main app bundle. + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CEF_BINARY_DIR}/Chromium Embedded Framework.framework" + "${JCEF_APP}/Contents/Frameworks/Chromium Embedded Framework.framework" + # Copy the JCEF library into the main app bindle. + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CEF_TARGET_OUT_DIR}/${JCEF_TARGET_LIBRARY}" + "${JCEF_TARGET_LIBRARY_APP_PATH}" + VERBATIM + ) + + # Create the multiple Helper app bundle targets. + foreach(_suffix_list ${CEF_HELPER_APP_SUFFIXES}) + # Convert to a list and extract the suffix values. + string(REPLACE ":" ";" _suffix_list ${_suffix_list}) + list(GET _suffix_list 0 _name_suffix) + list(GET _suffix_list 1 _target_suffix) + list(GET _suffix_list 2 _plist_suffix) + + # Define Helper target and output names. + set(_helper_target "${JCEF_HELPER_TARGET}${_target_suffix}") + set(_helper_output_name "${JCEF_HELPER_OUTPUT_NAME}${_name_suffix}") + + # Create Helper-specific variants of the helper-Info.plist file. Do this + # manually because the configure_file command (which is executed as part of + # MACOSX_BUNDLE_INFO_PLIST) uses global env variables and would insert the + # wrong values with multiple targets. + set(_helper_info_plist "${CMAKE_CURRENT_BINARY_DIR}/jcef-Info${_target_suffix}.plist") + file(READ "${CMAKE_CURRENT_SOURCE_DIR}/resources/jcef-Info.plist" _plist_contents) + string(REPLACE "\${EXECUTABLE_NAME}" "${_helper_output_name}" _plist_contents ${_plist_contents}) + string(REPLACE "\${PRODUCT_NAME}" "${_helper_output_name}" _plist_contents ${_plist_contents}) + string(REPLACE "\${BUNDLE_ID_SUFFIX}" "${_plist_suffix}" _plist_contents ${_plist_contents}) + file(WRITE ${_helper_info_plist} ${_plist_contents}) + + # Create Helper executable target. + add_executable(${_helper_target} MACOSX_BUNDLE ${JCEF_HELPER_SRCS}) + SET_EXECUTABLE_TARGET_PROPERTIES(${_helper_target}) + add_dependencies(${_helper_target} libcef_dll_wrapper) + target_link_libraries(${_helper_target} libcef_dll_wrapper ${CEF_STANDARD_LIBS}) + set_target_properties(${_helper_target} PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${_helper_info_plist} + OUTPUT_NAME ${_helper_output_name} + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "-" + ) + + # Add the Helper as a dependency of the main executable target. + add_dependencies(${JCEF_TARGET} "${_helper_target}") + + # Copy the Helper app bundle into the Frameworks directory. + add_custom_command( + TARGET ${JCEF_TARGET} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CEF_TARGET_OUT_DIR}/${_helper_output_name}.app" + "${JCEF_APP}/Contents/Frameworks/${_helper_output_name}.app" + VERBATIM + ) + endforeach() +endif() + + +# +# Windows configuration. +# + +if(OS_WINDOWS) + # Helper executable target. + add_executable(${JCEF_HELPER_TARGET} WIN32 ${JCEF_HELPER_SRCS}) + SET_EXECUTABLE_TARGET_PROPERTIES(${JCEF_HELPER_TARGET}) + add_dependencies(${JCEF_HELPER_TARGET} libcef_dll_wrapper) + target_link_libraries(${JCEF_HELPER_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS}) + + # JCEF library target. + add_library(${JCEF_TARGET} SHARED ${JCEF_SRCS}) + SET_LIBRARY_TARGET_PROPERTIES(${JCEF_TARGET}) + add_dependencies(${JCEF_TARGET} libcef_dll_wrapper ${JCEF_HELPER_TARGET}) + target_link_libraries(${JCEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS} ${JNI_LIBRARIES}) + target_include_directories(${JCEF_TARGET} PUBLIC ${JNI_INCLUDE_DIRS}) + + # Compile flags specific to the JCEF library target. + # USING_JAVA = Add the USING_JAVA define. + target_compile_definitions(${JCEF_TARGET} PRIVATE "USING_JAVA") + + # Add the custom manifest files to the DLL and helper EXE. + ADD_WINDOWS_MANIFEST("${CMAKE_CURRENT_SOURCE_DIR}" "${JCEF_TARGET}" "dll") + ADD_WINDOWS_MANIFEST("${CMAKE_CURRENT_SOURCE_DIR}" "${JCEF_HELPER_TARGET}" "exe") + + # Copy binary and resource files to the target output directory. + COPY_FILES("${JCEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}") + COPY_FILES("${JCEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}") +endif() + diff --git a/lib/jcef/native/CefApp.cpp b/lib/jcef/native/CefApp.cpp new file mode 100644 index 0000000..3adb696 --- /dev/null +++ b/lib/jcef/native/CefApp.cpp @@ -0,0 +1,118 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "CefApp.h" + +#include + +#include "include/cef_app.h" +#include "include/cef_version_info.h" + +#include "context.h" +#include "jcef_version.h" +#include "jni_util.h" +#include "scheme_handler_factory.h" +#include "util.h" + +#if defined(OS_LINUX) +#include +#endif + +JNIEXPORT jboolean JNICALL Java_org_cef_CefApp_N_1PreInitialize(JNIEnv* env, + jobject c) { +#if !defined(OS_MACOSX) + // On macOS this is called from Startup(). + Context::Create(); +#endif + return Context::GetInstance()->PreInitialize(env, c) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_CefApp_N_1Initialize(JNIEnv* env, + jobject c, + jobject appHandler, + jobject jsettings) { + return Context::GetInstance()->Initialize(env, c, appHandler, jsettings) + ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT void JNICALL Java_org_cef_CefApp_N_1Shutdown(JNIEnv* env, jobject) { + Context::GetInstance()->Shutdown(); + Context::Destroy(); +} + +JNIEXPORT void JNICALL Java_org_cef_CefApp_N_1DoMessageLoopWork(JNIEnv* env, + jobject) { + Context::GetInstance()->DoMessageLoopWork(); +} + +JNIEXPORT jobject JNICALL Java_org_cef_CefApp_N_1GetVersion(JNIEnv* env, + jobject obj) { + return NewJNIObject(env, "org/cef/CefApp$CefVersion", + "(Lorg/cef/CefApp;IIIIIIIII)V", obj, JCEF_COMMIT_NUMBER, + cef_version_info(0), // CEF_VERSION_MAJOR + cef_version_info(1), // CEF_VERSION_MINOR + cef_version_info(2), // CEF_VERSION_PATCH + cef_version_info(3), // CEF_COMMIT_NUMBER + cef_version_info(4), // CHROME_VERSION_MAJOR + cef_version_info(5), // CHROME_VERSION_MINOR + cef_version_info(6), // CHROME_VERSION_BUILD + cef_version_info(7)); // CHROME_VERSION_PATCH +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_CefApp_N_1RegisterSchemeHandlerFactory(JNIEnv* env, + jobject, + jstring jSchemeName, + jstring jDomainName, + jobject jFactory) { + if (!jFactory) + return JNI_FALSE; + + CefRefPtr factory = + new SchemeHandlerFactory(env, jFactory); + if (!factory) + return JNI_FALSE; + + bool result = CefRegisterSchemeHandlerFactory(GetJNIString(env, jSchemeName), + GetJNIString(env, jDomainName), + factory.get()); + return result ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_CefApp_N_1ClearSchemeHandlerFactories(JNIEnv*, jobject) { + return CefClearSchemeHandlerFactories() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_CefApp_N_1Startup(JNIEnv* env, + jclass, + jstring pathToCefFramework) { +#if defined(OS_LINUX) + XInitThreads(); +#elif defined(OS_MACOSX) + // Can't use GetJNIString before the CEF library is loaded. + std::string framework_path; + if (pathToCefFramework) { + const char* chr = env->GetStringUTFChars(pathToCefFramework, nullptr); + if (chr) { + framework_path = chr; + env->ReleaseStringUTFChars(pathToCefFramework, chr); + } + } + framework_path += "/Chromium Embedded Framework"; + + // Load the CEF framework library at runtime instead of linking directly + // as required by the macOS sandbox implementation. + if (!cef_load_library(framework_path.c_str())) + return JNI_FALSE; + + // The Context object has members that can't be initialized until after the + // CEF framework is loaded. + Context::Create(); +#endif // defined(OS_MACOSX) + return JNI_TRUE; +} diff --git a/lib/jcef/native/CefApp.h b/lib/jcef/native/CefApp.h new file mode 100644 index 0000000..063639c --- /dev/null +++ b/lib/jcef/native/CefApp.h @@ -0,0 +1,105 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_CefApp */ + +#ifndef _Included_org_cef_CefApp +#define _Included_org_cef_CefApp +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_CefApp + * Method: N_Startup + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_org_cef_CefApp_N_1Startup(JNIEnv*, + jclass, + jstring); + +/* + * Class: org_cef_CefApp + * Method: N_PreInitialize + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_org_cef_CefApp_N_1PreInitialize(JNIEnv*, + jobject); + +/* + * Class: org_cef_CefApp + * Method: N_Initialize + * Signature: (Lorg/cef/handler/CefAppHandler;Lorg/cef/CefSettings;)Z + */ +JNIEXPORT jboolean JNICALL Java_org_cef_CefApp_N_1Initialize(JNIEnv*, + jobject, + jobject, + jobject); + +/* + * Class: org_cef_CefApp + * Method: N_Shutdown + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_cef_CefApp_N_1Shutdown(JNIEnv*, jobject); + +/* + * Class: org_cef_CefApp + * Method: N_DoMessageLoopWork + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_cef_CefApp_N_1DoMessageLoopWork(JNIEnv*, + jobject); + +/* + * Class: org_cef_CefApp + * Method: N_GetVersion + * Signature: ()Lorg/cef/CefApp/CefVersion; + */ +JNIEXPORT jobject JNICALL Java_org_cef_CefApp_N_1GetVersion(JNIEnv*, jobject); + +/* + * Class: org_cef_CefApp + * Method: N_RegisterSchemeHandlerFactory + * Signature: + * (Ljava/lang/String;Ljava/lang/String;Lorg/cef/callback/CefSchemeHandlerFactory;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_CefApp_N_1RegisterSchemeHandlerFactory(JNIEnv*, + jobject, + jstring, + jstring, + jobject); + +/* + * Class: org_cef_CefApp + * Method: N_ClearSchemeHandlerFactories + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_CefApp_N_1ClearSchemeHandlerFactories(JNIEnv*, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class org_cef_CefApp_CefAppState */ + +#ifndef _Included_org_cef_CefApp_CefAppState +#define _Included_org_cef_CefApp_CefAppState +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class org_cef_CefApp_CefVersion */ + +#ifndef _Included_org_cef_CefApp_CefVersion +#define _Included_org_cef_CefApp_CefVersion +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefAuthCallback_N.cpp b/lib/jcef/native/CefAuthCallback_N.cpp new file mode 100644 index 0000000..aee7765 --- /dev/null +++ b/lib/jcef/native/CefAuthCallback_N.cpp @@ -0,0 +1,45 @@ +// 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 "CefAuthCallback_N.h" +#include "include/cef_request_handler.h" +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +void ClearSelf(JNIEnv* env, jobject obj) { + // Clear the reference added in RequestHandler::GetAuthCredentials. + SetCefForJNIObject(env, obj, nullptr, "CefAuthCallback"); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefAuthCallback_1N_N_1Continue(JNIEnv* env, + jobject obj, + jlong self, + jstring username, + jstring password) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Continue(GetJNIString(env, username), GetJNIString(env, password)); + ClearSelf(env, obj); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefAuthCallback_1N_N_1Cancel(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Cancel(); + ClearSelf(env, obj); +} diff --git a/lib/jcef/native/CefAuthCallback_N.h b/lib/jcef/native/CefAuthCallback_N.h new file mode 100644 index 0000000..58ea37b --- /dev/null +++ b/lib/jcef/native/CefAuthCallback_N.h @@ -0,0 +1,33 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefAuthCallback_N */ + +#ifndef _Included_org_cef_callback_CefAuthCallback_N +#define _Included_org_cef_callback_CefAuthCallback_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefAuthCallback_N + * Method: N_Continue + * Signature: (JLjava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefAuthCallback_1N_N_1Continue(JNIEnv*, + jobject, + jlong, + jstring, + jstring); + +/* + * Class: org_cef_callback_CefAuthCallback_N + * Method: N_Cancel + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefAuthCallback_1N_N_1Cancel(JNIEnv*, jobject, jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefBeforeDownloadCallback_N.cpp b/lib/jcef/native/CefBeforeDownloadCallback_N.cpp new file mode 100644 index 0000000..015c97b --- /dev/null +++ b/lib/jcef/native/CefBeforeDownloadCallback_N.cpp @@ -0,0 +1,37 @@ +// 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 "CefBeforeDownloadCallback_N.h" +#include "include/cef_download_handler.h" +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +void ClearSelf(JNIEnv* env, jobject obj) { + // Clear the reference added in DownloadHandler::OnBeforeDownload. + SetCefForJNIObject(env, obj, nullptr, + "CefBeforeDownloadCallback"); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefBeforeDownloadCallback_1N_N_1Continue( + JNIEnv* env, + jobject obj, + jlong self, + jstring jdownloadPath, + jboolean jshowDialog) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Continue(GetJNIString(env, jdownloadPath), + jshowDialog != JNI_FALSE); + ClearSelf(env, obj); +} diff --git a/lib/jcef/native/CefBeforeDownloadCallback_N.h b/lib/jcef/native/CefBeforeDownloadCallback_N.h new file mode 100644 index 0000000..35c8b02 --- /dev/null +++ b/lib/jcef/native/CefBeforeDownloadCallback_N.h @@ -0,0 +1,25 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefBeforeDownloadCallback_N */ + +#ifndef _Included_org_cef_callback_CefBeforeDownloadCallback_N +#define _Included_org_cef_callback_CefBeforeDownloadCallback_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefBeforeDownloadCallback_N + * Method: N_Continue + * Signature: (JLjava/lang/String;Z)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefBeforeDownloadCallback_1N_N_1Continue(JNIEnv*, + jobject, + jlong, + jstring, + jboolean); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefBrowser_N.cpp b/lib/jcef/native/CefBrowser_N.cpp new file mode 100644 index 0000000..ceea3a6 --- /dev/null +++ b/lib/jcef/native/CefBrowser_N.cpp @@ -0,0 +1,2201 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "CefBrowser_N.h" + +#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" +#include "render_handler.h" +#include "run_file_dialog_callback.h" +#include "string_visitor.h" +#include "temp_window.h" +#include "window_handler.h" + +#if defined(OS_LINUX) +#define XK_3270 // for XK_3270_BackTab +#include +#include +#include +#endif + +#if defined(OS_MACOSX) +#include +#include "util_mac.h" +#endif + +#if defined(OS_WIN) +#include +#undef MOUSE_MOVED +#endif + +namespace { + +int GetCefModifiers(JNIEnv* env, jclass cls, int modifiers) { + JNI_STATIC_DEFINE_INT_RV(env, cls, ALT_DOWN_MASK, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, BUTTON1_DOWN_MASK, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, BUTTON2_DOWN_MASK, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, BUTTON3_DOWN_MASK, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, CTRL_DOWN_MASK, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, META_DOWN_MASK, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, SHIFT_DOWN_MASK, 0); + + int cef_modifiers = 0; + if (modifiers & JNI_STATIC(ALT_DOWN_MASK)) + cef_modifiers |= EVENTFLAG_ALT_DOWN; + if (modifiers & JNI_STATIC(BUTTON1_DOWN_MASK)) + cef_modifiers |= EVENTFLAG_LEFT_MOUSE_BUTTON; + if (modifiers & JNI_STATIC(BUTTON2_DOWN_MASK)) + cef_modifiers |= EVENTFLAG_MIDDLE_MOUSE_BUTTON; + if (modifiers & JNI_STATIC(BUTTON3_DOWN_MASK)) + cef_modifiers |= EVENTFLAG_RIGHT_MOUSE_BUTTON; + if (modifiers & JNI_STATIC(CTRL_DOWN_MASK)) + cef_modifiers |= EVENTFLAG_CONTROL_DOWN; + if (modifiers & JNI_STATIC(META_DOWN_MASK)) + cef_modifiers |= EVENTFLAG_COMMAND_DOWN; + if (modifiers & JNI_STATIC(SHIFT_DOWN_MASK)) + cef_modifiers |= EVENTFLAG_SHIFT_DOWN; + + return cef_modifiers; +} + +#if defined(OS_LINUX) + +// From ui/events/keycodes/keyboard_codes_posix.h. +enum KeyboardCode { + VKEY_BACK = 0x08, + VKEY_TAB = 0x09, + VKEY_BACKTAB = 0x0A, + VKEY_CLEAR = 0x0C, + VKEY_RETURN = 0x0D, + VKEY_SHIFT = 0x10, + VKEY_CONTROL = 0x11, + VKEY_MENU = 0x12, + VKEY_PAUSE = 0x13, + VKEY_CAPITAL = 0x14, + VKEY_KANA = 0x15, + VKEY_HANGUL = 0x15, + VKEY_JUNJA = 0x17, + VKEY_FINAL = 0x18, + VKEY_HANJA = 0x19, + VKEY_KANJI = 0x19, + VKEY_ESCAPE = 0x1B, + VKEY_CONVERT = 0x1C, + VKEY_NONCONVERT = 0x1D, + VKEY_ACCEPT = 0x1E, + VKEY_MODECHANGE = 0x1F, + VKEY_SPACE = 0x20, + VKEY_PRIOR = 0x21, + VKEY_NEXT = 0x22, + VKEY_END = 0x23, + VKEY_HOME = 0x24, + VKEY_LEFT = 0x25, + VKEY_UP = 0x26, + VKEY_RIGHT = 0x27, + VKEY_DOWN = 0x28, + VKEY_SELECT = 0x29, + VKEY_PRINT = 0x2A, + VKEY_EXECUTE = 0x2B, + VKEY_SNAPSHOT = 0x2C, + VKEY_INSERT = 0x2D, + VKEY_DELETE = 0x2E, + VKEY_HELP = 0x2F, + VKEY_0 = 0x30, + VKEY_1 = 0x31, + VKEY_2 = 0x32, + VKEY_3 = 0x33, + VKEY_4 = 0x34, + VKEY_5 = 0x35, + VKEY_6 = 0x36, + VKEY_7 = 0x37, + VKEY_8 = 0x38, + VKEY_9 = 0x39, + VKEY_A = 0x41, + VKEY_B = 0x42, + VKEY_C = 0x43, + VKEY_D = 0x44, + VKEY_E = 0x45, + VKEY_F = 0x46, + VKEY_G = 0x47, + VKEY_H = 0x48, + VKEY_I = 0x49, + VKEY_J = 0x4A, + VKEY_K = 0x4B, + VKEY_L = 0x4C, + VKEY_M = 0x4D, + VKEY_N = 0x4E, + VKEY_O = 0x4F, + VKEY_P = 0x50, + VKEY_Q = 0x51, + VKEY_R = 0x52, + VKEY_S = 0x53, + VKEY_T = 0x54, + VKEY_U = 0x55, + VKEY_V = 0x56, + VKEY_W = 0x57, + VKEY_X = 0x58, + VKEY_Y = 0x59, + VKEY_Z = 0x5A, + VKEY_LWIN = 0x5B, + VKEY_COMMAND = VKEY_LWIN, // Provide the Mac name for convenience. + VKEY_RWIN = 0x5C, + VKEY_APPS = 0x5D, + VKEY_SLEEP = 0x5F, + VKEY_NUMPAD0 = 0x60, + VKEY_NUMPAD1 = 0x61, + VKEY_NUMPAD2 = 0x62, + VKEY_NUMPAD3 = 0x63, + VKEY_NUMPAD4 = 0x64, + VKEY_NUMPAD5 = 0x65, + VKEY_NUMPAD6 = 0x66, + VKEY_NUMPAD7 = 0x67, + VKEY_NUMPAD8 = 0x68, + VKEY_NUMPAD9 = 0x69, + VKEY_MULTIPLY = 0x6A, + VKEY_ADD = 0x6B, + VKEY_SEPARATOR = 0x6C, + VKEY_SUBTRACT = 0x6D, + VKEY_DECIMAL = 0x6E, + VKEY_DIVIDE = 0x6F, + VKEY_F1 = 0x70, + VKEY_F2 = 0x71, + VKEY_F3 = 0x72, + VKEY_F4 = 0x73, + VKEY_F5 = 0x74, + VKEY_F6 = 0x75, + VKEY_F7 = 0x76, + VKEY_F8 = 0x77, + VKEY_F9 = 0x78, + VKEY_F10 = 0x79, + VKEY_F11 = 0x7A, + VKEY_F12 = 0x7B, + VKEY_F13 = 0x7C, + VKEY_F14 = 0x7D, + VKEY_F15 = 0x7E, + VKEY_F16 = 0x7F, + VKEY_F17 = 0x80, + VKEY_F18 = 0x81, + VKEY_F19 = 0x82, + VKEY_F20 = 0x83, + VKEY_F21 = 0x84, + VKEY_F22 = 0x85, + VKEY_F23 = 0x86, + VKEY_F24 = 0x87, + VKEY_NUMLOCK = 0x90, + VKEY_SCROLL = 0x91, + VKEY_LSHIFT = 0xA0, + VKEY_RSHIFT = 0xA1, + VKEY_LCONTROL = 0xA2, + VKEY_RCONTROL = 0xA3, + VKEY_LMENU = 0xA4, + VKEY_RMENU = 0xA5, + VKEY_BROWSER_BACK = 0xA6, + VKEY_BROWSER_FORWARD = 0xA7, + VKEY_BROWSER_REFRESH = 0xA8, + VKEY_BROWSER_STOP = 0xA9, + VKEY_BROWSER_SEARCH = 0xAA, + VKEY_BROWSER_FAVORITES = 0xAB, + VKEY_BROWSER_HOME = 0xAC, + VKEY_VOLUME_MUTE = 0xAD, + VKEY_VOLUME_DOWN = 0xAE, + VKEY_VOLUME_UP = 0xAF, + VKEY_MEDIA_NEXT_TRACK = 0xB0, + VKEY_MEDIA_PREV_TRACK = 0xB1, + VKEY_MEDIA_STOP = 0xB2, + VKEY_MEDIA_PLAY_PAUSE = 0xB3, + VKEY_MEDIA_LAUNCH_MAIL = 0xB4, + VKEY_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5, + VKEY_MEDIA_LAUNCH_APP1 = 0xB6, + VKEY_MEDIA_LAUNCH_APP2 = 0xB7, + VKEY_OEM_1 = 0xBA, + VKEY_OEM_PLUS = 0xBB, + VKEY_OEM_COMMA = 0xBC, + VKEY_OEM_MINUS = 0xBD, + VKEY_OEM_PERIOD = 0xBE, + VKEY_OEM_2 = 0xBF, + VKEY_OEM_3 = 0xC0, + VKEY_OEM_4 = 0xDB, + VKEY_OEM_5 = 0xDC, + VKEY_OEM_6 = 0xDD, + VKEY_OEM_7 = 0xDE, + VKEY_OEM_8 = 0xDF, + VKEY_OEM_102 = 0xE2, + VKEY_OEM_103 = 0xE3, // GTV KEYCODE_MEDIA_REWIND + VKEY_OEM_104 = 0xE4, // GTV KEYCODE_MEDIA_FAST_FORWARD + VKEY_PROCESSKEY = 0xE5, + VKEY_PACKET = 0xE7, + VKEY_DBE_SBCSCHAR = 0xF3, + VKEY_DBE_DBCSCHAR = 0xF4, + VKEY_ATTN = 0xF6, + VKEY_CRSEL = 0xF7, + VKEY_EXSEL = 0xF8, + VKEY_EREOF = 0xF9, + VKEY_PLAY = 0xFA, + VKEY_ZOOM = 0xFB, + VKEY_NONAME = 0xFC, + VKEY_PA1 = 0xFD, + VKEY_OEM_CLEAR = 0xFE, + VKEY_UNKNOWN = 0, + + // POSIX specific VKEYs. Note that as of Windows SDK 7.1, 0x97-9F, 0xD8-DA, + // and 0xE8 are unassigned. + VKEY_WLAN = 0x97, + VKEY_POWER = 0x98, + VKEY_BRIGHTNESS_DOWN = 0xD8, + VKEY_BRIGHTNESS_UP = 0xD9, + VKEY_KBD_BRIGHTNESS_DOWN = 0xDA, + VKEY_KBD_BRIGHTNESS_UP = 0xE8, + + // Windows does not have a specific key code for AltGr. We use the unused 0xE1 + // (VK_OEM_AX) code to represent AltGr, matching the behaviour of Firefox on + // Linux. + VKEY_ALTGR = 0xE1, + // Windows does not have a specific key code for Compose. We use the unused + // 0xE6 (VK_ICO_CLEAR) code to represent Compose. + VKEY_COMPOSE = 0xE6, +}; + +// From ui/events/keycodes/keyboard_code_conversion_x.cc. +KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym) { + switch (keysym) { + case XK_BackSpace: + return VKEY_BACK; + case XK_Delete: + case XK_KP_Delete: + return VKEY_DELETE; + case XK_Tab: + case XK_KP_Tab: + case XK_ISO_Left_Tab: + case XK_3270_BackTab: + return VKEY_TAB; + case XK_Linefeed: + case XK_Return: + case XK_KP_Enter: + case XK_ISO_Enter: + return VKEY_RETURN; + case XK_Clear: + case XK_KP_Begin: // NumPad 5 without Num Lock, for crosbug.com/29169. + return VKEY_CLEAR; + case XK_KP_Space: + case XK_space: + return VKEY_SPACE; + case XK_Home: + case XK_KP_Home: + return VKEY_HOME; + case XK_End: + case XK_KP_End: + return VKEY_END; + case XK_Page_Up: + case XK_KP_Page_Up: // aka XK_KP_Prior + return VKEY_PRIOR; + case XK_Page_Down: + case XK_KP_Page_Down: // aka XK_KP_Next + return VKEY_NEXT; + case XK_Left: + case XK_KP_Left: + return VKEY_LEFT; + case XK_Right: + case XK_KP_Right: + return VKEY_RIGHT; + case XK_Down: + case XK_KP_Down: + return VKEY_DOWN; + case XK_Up: + case XK_KP_Up: + return VKEY_UP; + case XK_Escape: + return VKEY_ESCAPE; + case XK_Kana_Lock: + case XK_Kana_Shift: + return VKEY_KANA; + case XK_Hangul: + return VKEY_HANGUL; + case XK_Hangul_Hanja: + return VKEY_HANJA; + case XK_Kanji: + return VKEY_KANJI; + case XK_Henkan: + return VKEY_CONVERT; + case XK_Muhenkan: + return VKEY_NONCONVERT; + case XK_Zenkaku_Hankaku: + return VKEY_DBE_DBCSCHAR; + case XK_A: + case XK_a: + return VKEY_A; + case XK_B: + case XK_b: + return VKEY_B; + case XK_C: + case XK_c: + return VKEY_C; + case XK_D: + case XK_d: + return VKEY_D; + case XK_E: + case XK_e: + return VKEY_E; + case XK_F: + case XK_f: + return VKEY_F; + case XK_G: + case XK_g: + return VKEY_G; + case XK_H: + case XK_h: + return VKEY_H; + case XK_I: + case XK_i: + return VKEY_I; + case XK_J: + case XK_j: + return VKEY_J; + case XK_K: + case XK_k: + return VKEY_K; + case XK_L: + case XK_l: + return VKEY_L; + case XK_M: + case XK_m: + return VKEY_M; + case XK_N: + case XK_n: + return VKEY_N; + case XK_O: + case XK_o: + return VKEY_O; + case XK_P: + case XK_p: + return VKEY_P; + case XK_Q: + case XK_q: + return VKEY_Q; + case XK_R: + case XK_r: + return VKEY_R; + case XK_S: + case XK_s: + return VKEY_S; + case XK_T: + case XK_t: + return VKEY_T; + case XK_U: + case XK_u: + return VKEY_U; + case XK_V: + case XK_v: + return VKEY_V; + case XK_W: + case XK_w: + return VKEY_W; + case XK_X: + case XK_x: + return VKEY_X; + case XK_Y: + case XK_y: + return VKEY_Y; + case XK_Z: + case XK_z: + return VKEY_Z; + + case XK_0: + case XK_1: + case XK_2: + case XK_3: + case XK_4: + case XK_5: + case XK_6: + case XK_7: + case XK_8: + case XK_9: + return static_cast(VKEY_0 + (keysym - XK_0)); + + case XK_parenright: + return VKEY_0; + case XK_exclam: + return VKEY_1; + case XK_at: + return VKEY_2; + case XK_numbersign: + return VKEY_3; + case XK_dollar: + return VKEY_4; + case XK_percent: + return VKEY_5; + case XK_asciicircum: + return VKEY_6; + case XK_ampersand: + return VKEY_7; + case XK_asterisk: + return VKEY_8; + case XK_parenleft: + return VKEY_9; + + case XK_KP_0: + case XK_KP_1: + case XK_KP_2: + case XK_KP_3: + case XK_KP_4: + case XK_KP_5: + case XK_KP_6: + case XK_KP_7: + case XK_KP_8: + case XK_KP_9: + return static_cast(VKEY_NUMPAD0 + (keysym - XK_KP_0)); + + case XK_multiply: + case XK_KP_Multiply: + return VKEY_MULTIPLY; + case XK_KP_Add: + return VKEY_ADD; + case XK_KP_Separator: + return VKEY_SEPARATOR; + case XK_KP_Subtract: + return VKEY_SUBTRACT; + case XK_KP_Decimal: + return VKEY_DECIMAL; + case XK_KP_Divide: + return VKEY_DIVIDE; + case XK_KP_Equal: + case XK_equal: + case XK_plus: + return VKEY_OEM_PLUS; + case XK_comma: + case XK_less: + return VKEY_OEM_COMMA; + case XK_minus: + case XK_underscore: + return VKEY_OEM_MINUS; + case XK_greater: + case XK_period: + return VKEY_OEM_PERIOD; + case XK_colon: + case XK_semicolon: + return VKEY_OEM_1; + case XK_question: + case XK_slash: + return VKEY_OEM_2; + case XK_asciitilde: + case XK_quoteleft: + return VKEY_OEM_3; + case XK_bracketleft: + case XK_braceleft: + return VKEY_OEM_4; + case XK_backslash: + case XK_bar: + return VKEY_OEM_5; + case XK_bracketright: + case XK_braceright: + return VKEY_OEM_6; + case XK_quoteright: + case XK_quotedbl: + return VKEY_OEM_7; + case XK_ISO_Level5_Shift: + return VKEY_OEM_8; + case XK_Shift_L: + case XK_Shift_R: + return VKEY_SHIFT; + case XK_Control_L: + case XK_Control_R: + return VKEY_CONTROL; + case XK_Meta_L: + case XK_Meta_R: + case XK_Alt_L: + case XK_Alt_R: + return VKEY_MENU; + case XK_ISO_Level3_Shift: + return VKEY_ALTGR; + case XK_Multi_key: + return VKEY_COMPOSE; + case XK_Pause: + return VKEY_PAUSE; + case XK_Caps_Lock: + return VKEY_CAPITAL; + case XK_Num_Lock: + return VKEY_NUMLOCK; + case XK_Scroll_Lock: + return VKEY_SCROLL; + case XK_Select: + return VKEY_SELECT; + case XK_Print: + return VKEY_PRINT; + case XK_Execute: + return VKEY_EXECUTE; + case XK_Insert: + case XK_KP_Insert: + return VKEY_INSERT; + case XK_Help: + return VKEY_HELP; + case XK_Super_L: + return VKEY_LWIN; + case XK_Super_R: + return VKEY_RWIN; + case XK_Menu: + return VKEY_APPS; + case XK_F1: + case XK_F2: + case XK_F3: + case XK_F4: + case XK_F5: + case XK_F6: + case XK_F7: + case XK_F8: + case XK_F9: + case XK_F10: + case XK_F11: + case XK_F12: + case XK_F13: + case XK_F14: + case XK_F15: + case XK_F16: + case XK_F17: + case XK_F18: + case XK_F19: + case XK_F20: + case XK_F21: + case XK_F22: + case XK_F23: + case XK_F24: + return static_cast(VKEY_F1 + (keysym - XK_F1)); + case XK_KP_F1: + case XK_KP_F2: + case XK_KP_F3: + case XK_KP_F4: + return static_cast(VKEY_F1 + (keysym - XK_KP_F1)); + + case XK_guillemotleft: + case XK_guillemotright: + case XK_degree: + // In the case of canadian multilingual keyboard layout, VKEY_OEM_102 is + // assigned to ugrave key. + case XK_ugrave: + case XK_Ugrave: + case XK_brokenbar: + return VKEY_OEM_102; // international backslash key in 102 keyboard. + + // When evdev is in use, /usr/share/X11/xkb/symbols/inet maps F13-18 keys + // to the special XF86XK symbols to support Microsoft Ergonomic keyboards: + // https://bugs.freedesktop.org/show_bug.cgi?id=5783 + // In Chrome, we map these X key symbols back to F13-18 since we don't have + // VKEYs for these XF86XK symbols. + case XF86XK_Tools: + return VKEY_F13; + case XF86XK_Launch5: + return VKEY_F14; + case XF86XK_Launch6: + return VKEY_F15; + case XF86XK_Launch7: + return VKEY_F16; + case XF86XK_Launch8: + return VKEY_F17; + case XF86XK_Launch9: + return VKEY_F18; + case XF86XK_Refresh: + case XF86XK_History: + case XF86XK_OpenURL: + case XF86XK_AddFavorite: + case XF86XK_Go: + case XF86XK_ZoomIn: + case XF86XK_ZoomOut: + // ui::AcceleratorGtk tries to convert the XF86XK_ keysyms on Chrome + // startup. It's safe to return VKEY_UNKNOWN here since ui::AcceleratorGtk + // also checks a Gdk keysym. http://crbug.com/109843 + return VKEY_UNKNOWN; + // For supporting multimedia buttons on a USB keyboard. + case XF86XK_Back: + return VKEY_BROWSER_BACK; + case XF86XK_Forward: + return VKEY_BROWSER_FORWARD; + case XF86XK_Reload: + return VKEY_BROWSER_REFRESH; + case XF86XK_Stop: + return VKEY_BROWSER_STOP; + case XF86XK_Search: + return VKEY_BROWSER_SEARCH; + case XF86XK_Favorites: + return VKEY_BROWSER_FAVORITES; + case XF86XK_HomePage: + return VKEY_BROWSER_HOME; + case XF86XK_AudioMute: + return VKEY_VOLUME_MUTE; + case XF86XK_AudioLowerVolume: + return VKEY_VOLUME_DOWN; + case XF86XK_AudioRaiseVolume: + return VKEY_VOLUME_UP; + case XF86XK_AudioNext: + return VKEY_MEDIA_NEXT_TRACK; + case XF86XK_AudioPrev: + return VKEY_MEDIA_PREV_TRACK; + case XF86XK_AudioStop: + return VKEY_MEDIA_STOP; + case XF86XK_AudioPlay: + return VKEY_MEDIA_PLAY_PAUSE; + case XF86XK_Mail: + return VKEY_MEDIA_LAUNCH_MAIL; + case XF86XK_LaunchA: // F3 on an Apple keyboard. + return VKEY_MEDIA_LAUNCH_APP1; + case XF86XK_LaunchB: // F4 on an Apple keyboard. + case XF86XK_Calculator: + return VKEY_MEDIA_LAUNCH_APP2; + case XF86XK_WLAN: + return VKEY_WLAN; + case XF86XK_PowerOff: + return VKEY_POWER; + case XF86XK_MonBrightnessDown: + return VKEY_BRIGHTNESS_DOWN; + case XF86XK_MonBrightnessUp: + return VKEY_BRIGHTNESS_UP; + case XF86XK_KbdBrightnessDown: + return VKEY_KBD_BRIGHTNESS_DOWN; + case XF86XK_KbdBrightnessUp: + return VKEY_KBD_BRIGHTNESS_UP; + + // TODO(sad): some keycodes are still missing. + } + return VKEY_UNKNOWN; +} + +// From content/browser/renderer_host/input/web_input_event_util_posix.cc. +KeyboardCode GetWindowsKeyCodeWithoutLocation(KeyboardCode key_code) { + switch (key_code) { + case VKEY_LCONTROL: + case VKEY_RCONTROL: + return VKEY_CONTROL; + case VKEY_LSHIFT: + case VKEY_RSHIFT: + return VKEY_SHIFT; + case VKEY_LMENU: + case VKEY_RMENU: + return VKEY_MENU; + default: + return key_code; + } +} + +// From content/browser/renderer_host/input/web_input_event_builders_gtk.cc. +// Gets the corresponding control character of a specified key code. See: +// http://en.wikipedia.org/wiki/Control_characters +// We emulate Windows behavior here. +int GetControlCharacter(KeyboardCode windows_key_code, bool shift) { + if (windows_key_code >= VKEY_A && windows_key_code <= VKEY_Z) { + // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A + return windows_key_code - VKEY_A + 1; + } + if (shift) { + // following graphics chars require shift key to input. + switch (windows_key_code) { + // ctrl-@ maps to \x00 (Null byte) + case VKEY_2: + return 0; + // ctrl-^ maps to \x1E (Record separator, Information separator two) + case VKEY_6: + return 0x1E; + // ctrl-_ maps to \x1F (Unit separator, Information separator one) + case VKEY_OEM_MINUS: + return 0x1F; + // Returns 0 for all other keys to avoid inputting unexpected chars. + default: + return 0; + } + } else { + switch (windows_key_code) { + // ctrl-[ maps to \x1B (Escape) + case VKEY_OEM_4: + return 0x1B; + // ctrl-\ maps to \x1C (File separator, Information separator four) + case VKEY_OEM_5: + return 0x1C; + // ctrl-] maps to \x1D (Group separator, Information separator three) + case VKEY_OEM_6: + return 0x1D; + // ctrl-Enter maps to \x0A (Line feed) + case VKEY_RETURN: + return 0x0A; + // Returns 0 for all other keys to avoid inputting unexpected chars. + default: + return 0; + } + } +} + +#endif // defined(OS_LINUX) + +#if defined(OS_MACOSX) +// A convenient array for getting symbol characters on the number keys. +const char kShiftCharsForNumberKeys[] = ")!@#$%^&*("; + +// Convert an ANSI character to a Mac key code. +int GetMacKeyCodeFromChar(int key_char) { + switch (key_char) { + case ' ': + return kVK_Space; + + case '0': + case ')': + return kVK_ANSI_0; + case '1': + case '!': + return kVK_ANSI_1; + case '2': + case '@': + return kVK_ANSI_2; + case '3': + case '#': + return kVK_ANSI_3; + case '4': + case '$': + return kVK_ANSI_4; + case '5': + case '%': + return kVK_ANSI_5; + case '6': + case '^': + return kVK_ANSI_6; + case '7': + case '&': + return kVK_ANSI_7; + case '8': + case '*': + return kVK_ANSI_8; + case '9': + case '(': + return kVK_ANSI_9; + + case 'a': + case 'A': + return kVK_ANSI_A; + case 'b': + case 'B': + return kVK_ANSI_B; + case 'c': + case 'C': + return kVK_ANSI_C; + case 'd': + case 'D': + return kVK_ANSI_D; + case 'e': + case 'E': + return kVK_ANSI_E; + case 'f': + case 'F': + return kVK_ANSI_F; + case 'g': + case 'G': + return kVK_ANSI_G; + case 'h': + case 'H': + return kVK_ANSI_H; + case 'i': + case 'I': + return kVK_ANSI_I; + case 'j': + case 'J': + return kVK_ANSI_J; + case 'k': + case 'K': + return kVK_ANSI_K; + case 'l': + case 'L': + return kVK_ANSI_L; + case 'm': + case 'M': + return kVK_ANSI_M; + case 'n': + case 'N': + return kVK_ANSI_N; + case 'o': + case 'O': + return kVK_ANSI_O; + case 'p': + case 'P': + return kVK_ANSI_P; + case 'q': + case 'Q': + return kVK_ANSI_Q; + case 'r': + case 'R': + return kVK_ANSI_R; + case 's': + case 'S': + return kVK_ANSI_S; + case 't': + case 'T': + return kVK_ANSI_T; + case 'u': + case 'U': + return kVK_ANSI_U; + case 'v': + case 'V': + return kVK_ANSI_V; + case 'w': + case 'W': + return kVK_ANSI_W; + case 'x': + case 'X': + return kVK_ANSI_X; + case 'y': + case 'Y': + return kVK_ANSI_Y; + case 'z': + case 'Z': + return kVK_ANSI_Z; + + // U.S. Specific mappings. Mileage may vary. + case ';': + case ':': + return kVK_ANSI_Semicolon; + case '=': + case '+': + return kVK_ANSI_Equal; + case ',': + case '<': + return kVK_ANSI_Comma; + case '-': + case '_': + return kVK_ANSI_Minus; + case '.': + case '>': + return kVK_ANSI_Period; + case '/': + case '?': + return kVK_ANSI_Slash; + case '`': + case '~': + return kVK_ANSI_Grave; + case '[': + case '{': + return kVK_ANSI_LeftBracket; + case '\\': + case '|': + return kVK_ANSI_Backslash; + case ']': + case '}': + return kVK_ANSI_RightBracket; + case '\'': + case '"': + return kVK_ANSI_Quote; + } + + return -1; +} +#endif // defined(OS_MACOSX) + +struct JNIObjectsForCreate { + public: + ScopedJNIObjectGlobal jbrowser; + ScopedJNIObjectGlobal jparentBrowser; + ScopedJNIObjectGlobal jclientHandler; + ScopedJNIObjectGlobal url; + ScopedJNIObjectGlobal canvas; + ScopedJNIObjectGlobal jcontext; + ScopedJNIObjectGlobal jinspectAt; + ScopedJNIObjectGlobal jbrowserSettings; + + JNIObjectsForCreate(JNIEnv* env, + jobject _jbrowser, + jobject _jparentBrowser, + jobject _jclientHandler, + jstring _url, + jobject _canvas, + jobject _jcontext, + jobject _jinspectAt, + jobject _browserSettings) + : + + jbrowser(env, _jbrowser), + jparentBrowser(env, _jparentBrowser), + jclientHandler(env, _jclientHandler), + url(env, _url), + canvas(env, _canvas), + jcontext(env, _jcontext), + jinspectAt(env, _jinspectAt), + jbrowserSettings(env, _browserSettings) {} +}; + +void create(std::shared_ptr objs, + jlong windowHandle, + jboolean osr, + jboolean transparent) { + ScopedJNIEnv env; + CefRefPtr clientHandler = GetCefFromJNIObject( + env, objs->jclientHandler, "CefClientHandler"); + if (!clientHandler.get()) + return; + + CefRefPtr lifeSpanHandler = + (LifeSpanHandler*)clientHandler->GetLifeSpanHandler().get(); + 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 = + (WindowHandler*)clientHandler->GetWindowHandler().get(); + if (windowHandler.get()) { + windowHandler->GetRect(objs->jbrowser, rect); + } +#if defined(OS_WIN) + CefWindowHandle parent = TempWindow::GetWindowHandle(); + if (objs->canvas != nullptr) { + parent = GetHwndOfCanvas(objs->canvas, env); + } else { + // Do not activate hidden browser windows on creation. + windowInfo.ex_style |= WS_EX_NOACTIVATE; + } + windowInfo.SetAsChild(parent, rect); +#elif defined(OS_MACOSX) + NSWindow* parent = nullptr; + if (windowHandle != 0) { + parent = (NSWindow*)windowHandle; + } else { + parent = TempWindow::GetWindow(); + } + CefWindowHandle browserContentView = + util_mac::CreateBrowserContentView(parent, rect); + windowInfo.SetAsChild(browserContentView, rect); +#elif defined(OS_LINUX) + CefWindowHandle parent = TempWindow::GetWindowHandle(); + if (objs->canvas != nullptr) { + parent = GetDrawableOfCanvas(objs->canvas, env); + } + windowInfo.SetAsChild(parent, rect); +#endif + } else { + windowInfo.SetAsWindowless((CefWindowHandle)windowHandle); + } + + 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"); + + // Add a global ref that will be released in LifeSpanHandler::OnAfterCreated. + jobject globalRef = env->NewGlobalRef(objs->jbrowser); + lifeSpanHandler->registerJBrowser(globalRef); + + CefRefPtr extra_info; + auto router_configs = BrowserProcessHandler::GetMessageRouterConfigs(); + if (router_configs) { + // Send the message router config to CefHelperApp::OnBrowserCreated. + extra_info = CefDictionaryValue::Create(); + 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) { + lifeSpanHandler->unregisterJBrowser(globalRef); + env->DeleteGlobalRef(globalRef); + return; + } + JNI_CALL_VOID_METHOD(env, objs->jbrowser, "notifyBrowserCreated", "()V"); +} + +void getZoomLevel(CefRefPtr host, + CriticalWait* waitCond, + double* result) { + if (waitCond && result) { + waitCond->lock()->Lock(); + *result = host->GetZoomLevel(); + waitCond->WakeUp(); + waitCond->lock()->Unlock(); + } +} + +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)); + return; + } + + if (browser->GetHost()->GetClient()) { + CefRefPtr lifeSpanHandler = + (LifeSpanHandler*)browser->GetHost() + ->GetClient() + ->GetLifeSpanHandler() + .get(); + if (lifeSpanHandler) { + lifeSpanHandler->OnAfterParentChanged(browser); + } + } +} + +CefPdfPrintSettings GetJNIPdfPrintSettings(JNIEnv* env, jobject obj) { + CefString tmp; + CefPdfPrintSettings settings; + if (!obj) + return settings; + + ScopedJNIClass cls(env, "org/cef/misc/CefPdfPrintSettings"); + if (!cls) + return settings; + + GetJNIFieldBoolean(env, cls, obj, "landscape", &settings.landscape); + + GetJNIFieldBoolean(env, cls, obj, "print_background", + &settings.print_background); + + GetJNIFieldDouble(env, cls, obj, "scale", &settings.scale); + + GetJNIFieldDouble(env, cls, obj, "paper_width", &settings.paper_width); + GetJNIFieldDouble(env, cls, obj, "paper_height", &settings.paper_height); + + 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, + "Lorg/cef/misc/CefPdfPrintSettings$MarginType;")) { + ScopedJNIObjectLocal margin_type(env, obj_margin_type); + if (IsJNIEnumValue(env, margin_type, + "org/cef/misc/CefPdfPrintSettings$MarginType", + "DEFAULT")) { + settings.margin_type = PDF_PRINT_MARGIN_DEFAULT; + } else if (IsJNIEnumValue(env, margin_type, + "org/cef/misc/CefPdfPrintSettings$MarginType", + "NONE")) { + settings.margin_type = PDF_PRINT_MARGIN_NONE; + } else if (IsJNIEnumValue(env, margin_type, + "org/cef/misc/CefPdfPrintSettings$MarginType", + "CUSTOM")) { + settings.margin_type = PDF_PRINT_MARGIN_CUSTOM; + } + } + + 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 +Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv* env, + jobject jbrowser, + jobject jclientHandler, + jlong windowHandle, + jstring url, + jboolean osr, + jboolean transparent, + jobject canvas, + 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 { + CefPostTask(TID_UI, + base::BindOnce(&create, objs, windowHandle, osr, transparent)); + } + return JNI_FALSE; // set asynchronously +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv* env, + jobject jbrowser, + jobject jparent, + jobject jclientHandler, + jlong windowHandle, + jboolean osr, + jboolean transparent, + jobject canvas, + jobject inspect) { + std::shared_ptr objs( + new JNIObjectsForCreate(env, jbrowser, jparent, jclientHandler, nullptr, + canvas, nullptr, inspect, nullptr)); + if (CefCurrentlyOn(TID_UI)) { + create(objs, windowHandle, osr, transparent); + } else { + CefPostTask(TID_UI, + base::BindOnce(&create, objs, windowHandle, osr, transparent)); + } + 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, + jlong displayHandle) { + CefWindowHandle windowHandle = kNullWindowHandle; +#if defined(OS_WIN) + windowHandle = ::WindowFromDC((HDC)displayHandle); +#elif defined(OS_LINUX) + return displayHandle; +#elif defined(OS_MACOSX) + ASSERT(util_mac::IsNSView((void*)displayHandle)); +#endif + return (jlong)windowHandle; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1CanGoBack(JNIEnv* env, jobject obj) { + CefRefPtr browser = + JNI_GET_BROWSER_OR_RETURN(env, obj, JNI_FALSE); + return browser->CanGoBack() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GoBack(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GoBack(); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1CanGoForward(JNIEnv* env, jobject obj) { + CefRefPtr browser = + JNI_GET_BROWSER_OR_RETURN(env, obj, JNI_FALSE); + return browser->CanGoForward() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GoForward(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GoForward(); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1IsLoading(JNIEnv* env, jobject obj) { + CefRefPtr browser = + JNI_GET_BROWSER_OR_RETURN(env, obj, JNI_FALSE); + return browser->IsLoading() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1Reload(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->Reload(); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1ReloadIgnoreCache(JNIEnv* env, + jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->ReloadIgnoreCache(); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1StopLoad(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->StopLoad(); +} + +JNIEXPORT jint JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetIdentifier(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, -1); + return browser->GetIdentifier(); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetMainFrame(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr); + CefRefPtr frame = browser->GetMainFrame(); + if (!frame) + return nullptr; + ScopedJNIFrame jframe(env, frame); + return jframe.Release(); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetFocusedFrame(JNIEnv* env, + jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr); + CefRefPtr frame = browser->GetFocusedFrame(); + if (!frame) + return nullptr; + ScopedJNIFrame jframe(env, frame); + return jframe.Release(); +} + +JNIEXPORT jobject JNICALL +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->GetFrameByIdentifier(GetJNIString(env, identifier)); + if (!frame) + return nullptr; + ScopedJNIFrame jframe(env, frame); + return jframe.Release(); +} + +JNIEXPORT jobject JNICALL +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->GetFrameByName(GetJNIString(env, name)); + if (!frame) + return nullptr; + ScopedJNIFrame jframe(env, frame); + return jframe.Release(); +} + +JNIEXPORT jint JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameCount(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, -1); + return (jint)browser->GetFrameCount(); +} + +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; + browser->GetFrameIdentifiers(identifiers); + return NewJNIStringVector(env, identifiers); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameNames(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr); + std::vector names; + browser->GetFrameNames(names); + return NewJNIStringVector(env, names); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1IsPopup(JNIEnv* env, jobject obj) { + CefRefPtr browser = + JNI_GET_BROWSER_OR_RETURN(env, obj, JNI_FALSE); + return browser->IsPopup() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1HasDocument(JNIEnv* env, jobject obj) { + CefRefPtr browser = + JNI_GET_BROWSER_OR_RETURN(env, obj, JNI_FALSE); + return browser->HasDocument() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1ViewSource(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + CefRefPtr mainFrame = browser->GetMainFrame(); + CefPostTask(TID_UI, base::BindOnce(&CefFrame::ViewSource, mainFrame.get())); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetSource(JNIEnv* env, + jobject obj, + jobject jvisitor) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetMainFrame()->GetSource(new StringVisitor(env, jvisitor)); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetText(JNIEnv* env, + jobject obj, + jobject jvisitor) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetMainFrame()->GetText(new StringVisitor(env, jvisitor)); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1LoadRequest(JNIEnv* env, + jobject obj, + jobject jrequest) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + ScopedJNIRequest requestObj(env); + requestObj.SetHandle(jrequest, false /* should_delete */); + CefRefPtr request = requestObj.GetCefObject(); + if (!request) + return; + browser->GetMainFrame()->LoadRequest(request); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1LoadURL(JNIEnv* env, + jobject obj, + jstring url) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetMainFrame()->LoadURL(GetJNIString(env, url)); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1ExecuteJavaScript(JNIEnv* env, + jobject obj, + jstring code, + jstring url, + jint line) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetMainFrame()->ExecuteJavaScript(GetJNIString(env, code), + GetJNIString(env, url), line); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetURL(JNIEnv* env, jobject obj) { + jstring tmp = NewJNIString(env, ""); + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, tmp); + return NewJNIString(env, browser->GetMainFrame()->GetURL()); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1Close(JNIEnv* env, + jobject obj, + jboolean force) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + if (force != JNI_FALSE) { + if (browser->GetHost()->IsWindowRenderingDisabled()) { + browser->GetHost()->CloseBrowser(true); + } else { + // Destroy the native window representation. + if (CefCurrentlyOn(TID_UI)) + util::DestroyCefBrowser(browser); + else + CefPostTask(TID_UI, base::BindOnce(&util::DestroyCefBrowser, browser)); + } + } else { + browser->GetHost()->CloseBrowser(false); + } +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SetFocus(JNIEnv* env, + jobject obj, + jboolean enable) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->SetFocus(enable != JNI_FALSE); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SetWindowVisibility(JNIEnv* env, + jobject obj, + jboolean visible) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + +#if defined(OS_MACOSX) + if (!browser->GetHost()->IsWindowRenderingDisabled()) { + util_mac::SetVisibility(browser->GetHost()->GetWindowHandle(), + visible != JNI_FALSE); + } +#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); + CefRefPtr host = browser->GetHost(); + double result = 0.0; + if (CefCurrentlyOn(TID_UI)) + result = host->GetZoomLevel(); + else { + CriticalLock lock; + CriticalWait waitCond(&lock); + lock.Lock(); + CefPostTask(TID_UI, base::BindOnce(getZoomLevel, host, &waitCond, &result)); + waitCond.Wait(1000); + lock.Unlock(); + } + return result; +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SetZoomLevel(JNIEnv* env, + jobject obj, + jdouble zoom) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->SetZoomLevel(zoom); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1RunFileDialog(JNIEnv* env, + jobject obj, + jobject jmode, + jstring jtitle, + jstring jdefaultFilePath, + jobject jacceptFilters, + jint selectedAcceptFilter, + jobject jcallback) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + + std::vector accept_types; + GetJNIStringVector(env, jacceptFilters, accept_types); + + CefBrowserHost::FileDialogMode mode; + if (IsJNIEnumValue(env, jmode, + "org/cef/handler/CefDialogHandler$FileDialogMode", + "FILE_DIALOG_OPEN")) { + mode = FILE_DIALOG_OPEN; + } else if (IsJNIEnumValue(env, jmode, + "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")) { + mode = FILE_DIALOG_SAVE; + } else { + mode = FILE_DIALOG_OPEN; + } + + browser->GetHost()->RunFileDialog( + mode, GetJNIString(env, jtitle), GetJNIString(env, jdefaultFilePath), + accept_types, new RunFileDialogCallback(env, jcallback)); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1StartDownload(JNIEnv* env, + jobject obj, + jstring url) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->StartDownload(GetJNIString(env, url)); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1Print(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->Print(); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1PrintToPDF(JNIEnv* env, + jobject obj, + jstring jpath, + jobject jsettings, + jobject jcallback) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + + CefPdfPrintSettings settings = GetJNIPdfPrintSettings(env, jsettings); + + browser->GetHost()->PrintToPDF(GetJNIString(env, jpath), settings, + new PdfPrintCallback(env, jcallback)); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1Find(JNIEnv* env, + jobject obj, + jstring searchText, + jboolean forward, + jboolean matchCase, + jboolean findNext) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->Find(GetJNIString(env, searchText), + (forward != JNI_FALSE), (matchCase != JNI_FALSE), + (findNext != JNI_FALSE)); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1StopFinding(JNIEnv* env, + jobject obj, + jboolean clearSelection) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->StopFinding(clearSelection != JNI_FALSE); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1CloseDevTools(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->CloseDevTools(); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1ReplaceMisspelling(JNIEnv* env, + jobject obj, + jstring jword) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->ReplaceMisspelling(GetJNIString(env, jword)); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1WasResized(JNIEnv* env, + jobject obj, + jint width, + jint height) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + if (browser->GetHost()->IsWindowRenderingDisabled()) { + browser->GetHost()->WasResized(); + } +#if (defined(OS_WIN) || defined(OS_LINUX)) + else { + CefWindowHandle browserHandle = browser->GetHost()->GetWindowHandle(); + if (CefCurrentlyOn(TID_UI)) { + util::SetWindowSize(browserHandle, width, height); + } else { + CefPostTask(TID_UI, base::BindOnce(util::SetWindowSize, browserHandle, + (int)width, (int)height)); + } + } +#endif +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1Invalidate(JNIEnv* env, jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->Invalidate(PET_VIEW); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SendKeyEvent(JNIEnv* env, + jobject obj, + jobject key_event) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + ScopedJNIClass cls(env, env->GetObjectClass(key_event)); + if (!cls) + return; + + JNI_STATIC_DEFINE_INT(env, cls, KEY_PRESSED); + JNI_STATIC_DEFINE_INT(env, cls, KEY_RELEASED); + JNI_STATIC_DEFINE_INT(env, cls, KEY_TYPED); + + int event_type, modifiers; + 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)) { + return; + } + + CefKeyEvent cef_event; + cef_event.modifiers = GetCefModifiers(env, cls, modifiers); + +#if defined(OS_WIN) + + jlong scanCode = 0; + GetJNIFieldLong(env, cls, key_event, "scancode", &scanCode); + BYTE VkCode = LOBYTE(MapVirtualKey(scanCode, MAPVK_VSC_TO_VK)); + cef_event.native_key_code = (scanCode << 16) | // key scan code + 1; // key repeat count +#elif defined(OS_LINUX) || defined(OS_MACOSX) + int key_code; + if (!CallJNIMethodI_V(env, cls, key_event, "getKeyCode", &key_code)) { + return; + } + + JNI_STATIC_DEFINE_INT(env, cls, VK_BACK_SPACE); + JNI_STATIC_DEFINE_INT(env, cls, VK_DELETE); + JNI_STATIC_DEFINE_INT(env, cls, VK_DOWN); + JNI_STATIC_DEFINE_INT(env, cls, VK_ENTER); + JNI_STATIC_DEFINE_INT(env, cls, VK_ESCAPE); + JNI_STATIC_DEFINE_INT(env, cls, VK_LEFT); + JNI_STATIC_DEFINE_INT(env, cls, VK_RIGHT); + JNI_STATIC_DEFINE_INT(env, cls, VK_TAB); + JNI_STATIC_DEFINE_INT(env, cls, VK_UP); + +#if defined(OS_LINUX) + if (key_code == JNI_STATIC(VK_BACK_SPACE)) + cef_event.native_key_code = XK_BackSpace; + else if (key_code == JNI_STATIC(VK_DELETE)) + cef_event.native_key_code = XK_Delete; + else if (key_code == JNI_STATIC(VK_DOWN)) + cef_event.native_key_code = XK_Down; + else if (key_code == JNI_STATIC(VK_ENTER)) + cef_event.native_key_code = XK_Return; + else if (key_code == JNI_STATIC(VK_ESCAPE)) + cef_event.native_key_code = XK_Escape; + else if (key_code == JNI_STATIC(VK_LEFT)) + cef_event.native_key_code = XK_Left; + else if (key_code == JNI_STATIC(VK_RIGHT)) + cef_event.native_key_code = XK_Right; + else if (key_code == JNI_STATIC(VK_TAB)) + cef_event.native_key_code = XK_Tab; + else if (key_code == JNI_STATIC(VK_UP)) + cef_event.native_key_code = XK_Up; + else + cef_event.native_key_code = key_char; + + KeyboardCode windows_key_code = + KeyboardCodeFromXKeysym(cef_event.native_key_code); + cef_event.windows_key_code = + GetWindowsKeyCodeWithoutLocation(windows_key_code); + + if (cef_event.modifiers & EVENTFLAG_ALT_DOWN) + cef_event.is_system_key = true; + + if (windows_key_code == VKEY_RETURN) { + // We need to treat the enter key as a key press of character \r. This + // is apparently just how webkit handles it and what it expects. + cef_event.unmodified_character = '\r'; + } else { + cef_event.unmodified_character = cef_event.native_key_code; + } + + // If ctrl key is pressed down, then control character shall be input. + if (cef_event.modifiers & EVENTFLAG_CONTROL_DOWN) { + cef_event.character = GetControlCharacter( + windows_key_code, cef_event.modifiers & EVENTFLAG_SHIFT_DOWN); + } else { + cef_event.character = cef_event.unmodified_character; + } +#elif defined(OS_MACOSX) + if (key_code == JNI_STATIC(VK_BACK_SPACE)) { + cef_event.native_key_code = kVK_Delete; + cef_event.unmodified_character = kBackspaceCharCode; + } else if (key_code == JNI_STATIC(VK_DELETE)) { + cef_event.native_key_code = kVK_ForwardDelete; + cef_event.unmodified_character = kDeleteCharCode; + } else if (key_code == JNI_STATIC(VK_DOWN)) { + cef_event.native_key_code = kVK_DownArrow; + cef_event.unmodified_character = /* NSDownArrowFunctionKey */ 0xF701; + } else if (key_code == JNI_STATIC(VK_ENTER)) { + cef_event.native_key_code = kVK_Return; + cef_event.unmodified_character = kReturnCharCode; + } else if (key_code == JNI_STATIC(VK_ESCAPE)) { + cef_event.native_key_code = kVK_Escape; + cef_event.unmodified_character = kEscapeCharCode; + } else if (key_code == JNI_STATIC(VK_LEFT)) { + cef_event.native_key_code = kVK_LeftArrow; + cef_event.unmodified_character = /* NSLeftArrowFunctionKey */ 0xF702; + } else if (key_code == JNI_STATIC(VK_RIGHT)) { + cef_event.native_key_code = kVK_RightArrow; + cef_event.unmodified_character = /* NSRightArrowFunctionKey */ 0xF703; + } else if (key_code == JNI_STATIC(VK_TAB)) { + cef_event.native_key_code = kVK_Tab; + cef_event.unmodified_character = kTabCharCode; + } else if (key_code == JNI_STATIC(VK_UP)) { + cef_event.native_key_code = kVK_UpArrow; + cef_event.unmodified_character = /* NSUpArrowFunctionKey */ 0xF700; + } else { + cef_event.native_key_code = GetMacKeyCodeFromChar(key_char); + if (cef_event.native_key_code == -1) + return; + + cef_event.unmodified_character = key_char; + } + + cef_event.character = cef_event.unmodified_character; + + // Fill in |character| according to flags. + if (cef_event.modifiers & EVENTFLAG_SHIFT_DOWN) { + if (key_char >= '0' && key_char <= '9') { + cef_event.character = kShiftCharsForNumberKeys[key_char - '0']; + } else if (key_char >= 'A' && key_char <= 'Z') { + cef_event.character = 'A' + (key_char - 'A'); + } else { + switch (cef_event.native_key_code) { + case kVK_ANSI_Grave: + cef_event.character = '~'; + break; + case kVK_ANSI_Minus: + cef_event.character = '_'; + break; + case kVK_ANSI_Equal: + cef_event.character = '+'; + break; + case kVK_ANSI_LeftBracket: + cef_event.character = '{'; + break; + case kVK_ANSI_RightBracket: + cef_event.character = '}'; + break; + case kVK_ANSI_Backslash: + cef_event.character = '|'; + break; + case kVK_ANSI_Semicolon: + cef_event.character = ':'; + break; + case kVK_ANSI_Quote: + cef_event.character = '\"'; + break; + case kVK_ANSI_Comma: + cef_event.character = '<'; + break; + case kVK_ANSI_Period: + cef_event.character = '>'; + break; + case kVK_ANSI_Slash: + cef_event.character = '?'; + break; + default: + break; + } + } + } + + // Control characters. + if (cef_event.modifiers & EVENTFLAG_CONTROL_DOWN) { + if (key_char >= 'A' && key_char <= 'Z') + cef_event.character = 1 + key_char - 'A'; + else if (cef_event.native_key_code == kVK_ANSI_LeftBracket) + cef_event.character = 27; + else if (cef_event.native_key_code == kVK_ANSI_Backslash) + cef_event.character = 28; + else if (cef_event.native_key_code == kVK_ANSI_RightBracket) + cef_event.character = 29; + } +#endif // defined(OS_MACOSX) +#endif // defined(OS_LINUX) || defined(OS_MACOSX) + + if (event_type == JNI_STATIC(KEY_PRESSED)) { +#if defined(OS_WIN) + cef_event.windows_key_code = VkCode; +#endif + cef_event.type = KEYEVENT_RAWKEYDOWN; + } else if (event_type == JNI_STATIC(KEY_RELEASED)) { +#if defined(OS_WIN) + cef_event.windows_key_code = VkCode; + // bits 30 and 31 should always be 1 for WM_KEYUP + cef_event.native_key_code |= 0xC0000000; +#endif + cef_event.type = KEYEVENT_KEYUP; + } else if (event_type == JNI_STATIC(KEY_TYPED)) { +#if defined(OS_WIN) + cef_event.windows_key_code = key_char; +#endif + cef_event.type = KEYEVENT_CHAR; + } else { + return; + } + + browser->GetHost()->SendKeyEvent(cef_event); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SendMouseEvent(JNIEnv* env, + jobject obj, + jobject mouse_event) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + ScopedJNIClass cls(env, env->GetObjectClass(mouse_event)); + if (!cls) + return; + + JNI_STATIC_DEFINE_INT(env, cls, BUTTON1); + JNI_STATIC_DEFINE_INT(env, cls, BUTTON2); + JNI_STATIC_DEFINE_INT(env, cls, BUTTON3); + JNI_STATIC_DEFINE_INT(env, cls, MOUSE_DRAGGED); + JNI_STATIC_DEFINE_INT(env, cls, MOUSE_ENTERED); + JNI_STATIC_DEFINE_INT(env, cls, MOUSE_EXITED); + JNI_STATIC_DEFINE_INT(env, cls, MOUSE_MOVED); + JNI_STATIC_DEFINE_INT(env, cls, MOUSE_PRESSED); + JNI_STATIC_DEFINE_INT(env, cls, MOUSE_RELEASED); + + int event_type, x, y, modifiers; + if (!CallJNIMethodI_V(env, cls, mouse_event, "getID", &event_type) || + !CallJNIMethodI_V(env, cls, mouse_event, "getX", &x) || + !CallJNIMethodI_V(env, cls, mouse_event, "getY", &y) || + !CallJNIMethodI_V(env, cls, mouse_event, "getModifiersEx", &modifiers)) { + return; + } + + CefMouseEvent cef_event; + cef_event.x = x; + cef_event.y = y; + + cef_event.modifiers = GetCefModifiers(env, cls, modifiers); + + if (event_type == JNI_STATIC(MOUSE_PRESSED) || + event_type == JNI_STATIC(MOUSE_RELEASED)) { + int click_count, button; + if (!CallJNIMethodI_V(env, cls, mouse_event, "getClickCount", + &click_count) || + !CallJNIMethodI_V(env, cls, mouse_event, "getButton", &button)) { + return; + } + + CefBrowserHost::MouseButtonType cef_mbt; + if (button == JNI_STATIC(BUTTON1)) + cef_mbt = MBT_LEFT; + else if (button == JNI_STATIC(BUTTON2)) + cef_mbt = MBT_MIDDLE; + else if (button == JNI_STATIC(BUTTON3)) + cef_mbt = MBT_RIGHT; + else + return; + + browser->GetHost()->SendMouseClickEvent( + cef_event, cef_mbt, (event_type == JNI_STATIC(MOUSE_RELEASED)), + click_count); + } else if (event_type == JNI_STATIC(MOUSE_MOVED) || + event_type == JNI_STATIC(MOUSE_DRAGGED) || + event_type == JNI_STATIC(MOUSE_ENTERED) || + event_type == JNI_STATIC(MOUSE_EXITED)) { + browser->GetHost()->SendMouseMoveEvent( + cef_event, (event_type == JNI_STATIC(MOUSE_EXITED))); + } +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SendMouseWheelEvent( + JNIEnv* env, + jobject obj, + jobject mouse_wheel_event) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + ScopedJNIClass cls(env, env->GetObjectClass(mouse_wheel_event)); + if (!cls) + return; + + JNI_STATIC_DEFINE_INT(env, cls, WHEEL_UNIT_SCROLL); + + int scroll_type, delta, x, y, modifiers; + if (!CallJNIMethodI_V(env, cls, mouse_wheel_event, "getScrollType", + &scroll_type) || + !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getWheelRotation", + &delta) || + !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getX", &x) || + !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getY", &y) || + !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getModifiersEx", + &modifiers)) { + return; + } + + CefMouseEvent cef_event; + cef_event.x = x; + cef_event.y = y; + + cef_event.modifiers = GetCefModifiers(env, cls, modifiers); + + if (scroll_type == JNI_STATIC(WHEEL_UNIT_SCROLL)) { + // Use the smarter version that considers platform settings. + CallJNIMethodI_V(env, cls, mouse_wheel_event, "getUnitsToScroll", &delta); + } + + double deltaX = 0, deltaY = 0; + if (cef_event.modifiers & EVENTFLAG_SHIFT_DOWN) + deltaX = delta; + else + deltaY = delta; + + browser->GetHost()->SendMouseWheelEvent(cef_event, deltaX, deltaY); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDragEnter(JNIEnv* env, + jobject obj, + jobject jdragData, + jobject pos, + jint jmodifiers, + jint allowedOps) { + CefRefPtr drag_data = + GetCefFromJNIObject(env, jdragData, "CefDragData"); + if (!drag_data.get()) + return; + ScopedJNIClass cls(env, "java/awt/event/MouseEvent"); + if (!cls) + return; + + CefMouseEvent cef_event; + GetJNIPoint(env, pos, &cef_event.x, &cef_event.y); + cef_event.modifiers = GetCefModifiers(env, cls, jmodifiers); + + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->DragTargetDragEnter( + drag_data, cef_event, (CefBrowserHost::DragOperationsMask)allowedOps); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDragOver(JNIEnv* env, + jobject obj, + jobject pos, + jint jmodifiers, + jint allowedOps) { + ScopedJNIClass cls(env, "java/awt/event/MouseEvent"); + if (!cls) + return; + + CefMouseEvent cef_event; + GetJNIPoint(env, pos, &cef_event.x, &cef_event.y); + cef_event.modifiers = GetCefModifiers(env, cls, jmodifiers); + + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->DragTargetDragOver( + cef_event, (CefBrowserHost::DragOperationsMask)allowedOps); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDragLeave(JNIEnv* env, + jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->DragTargetDragLeave(); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDrop(JNIEnv* env, + jobject obj, + jobject pos, + jint jmodifiers) { + ScopedJNIClass cls(env, "java/awt/event/MouseEvent"); + if (!cls) + return; + + CefMouseEvent cef_event; + GetJNIPoint(env, pos, &cef_event.x, &cef_event.y); + cef_event.modifiers = GetCefModifiers(env, cls, jmodifiers); + + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->DragTargetDrop(cef_event); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragSourceEndedAt(JNIEnv* env, + jobject obj, + jobject pos, + jint operation) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + int x, y; + GetJNIPoint(env, pos, &x, &y); + browser->GetHost()->DragSourceEndedAt( + x, y, (CefBrowserHost::DragOperationsMask)operation); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragSourceSystemDragEnded(JNIEnv* env, + jobject obj) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + browser->GetHost()->DragSourceSystemDragEnded(); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1UpdateUI(JNIEnv* env, + jobject obj, + jobject jcontentRect, + jobject jbrowserRect) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + CefRect contentRect = GetJNIRect(env, jcontentRect); +#if defined(OS_MACOSX) + CefRect browserRect = GetJNIRect(env, jbrowserRect); + util_mac::UpdateView(browser->GetHost()->GetWindowHandle(), contentRect, + browserRect); +#else + CefWindowHandle windowHandle = browser->GetHost()->GetWindowHandle(); + if (CefCurrentlyOn(TID_UI)) { + util::SetWindowBounds(windowHandle, contentRect); + } else { + CefPostTask(TID_UI, base::BindOnce(util::SetWindowBounds, windowHandle, + contentRect)); + } +#endif +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SetParent(JNIEnv* env, + jobject obj, + jlong windowHandle, + jobject canvas) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + base::OnceClosure callback = base::BindOnce(&OnAfterParentChanged, browser); + +#if defined(OS_MACOSX) + util::SetParent(browser->GetHost()->GetWindowHandle(), windowHandle, + std::move(callback)); +#else + CefWindowHandle browserHandle = browser->GetHost()->GetWindowHandle(); + CefWindowHandle parentHandle = + canvas ? util::GetWindowHandle(env, canvas) : kNullWindowHandle; + if (CefCurrentlyOn(TID_UI)) { + util::SetParent(browserHandle, parentHandle, std::move(callback)); + } else { +#if defined(OS_LINUX) + CriticalLock lock; + CriticalWait waitCond(&lock); + lock.Lock(); + CefPostTask(TID_UI, + base::BindOnce(util::SetParentSync, browserHandle, parentHandle, + &waitCond, std::move(callback))); + waitCond.Wait(1000); + lock.Unlock(); +#else + CefPostTask(TID_UI, base::BindOnce(util::SetParent, browserHandle, + parentHandle, std::move(callback))); +#endif + } +#endif +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1NotifyMoveOrResizeStarted(JNIEnv* env, + jobject obj) { +#if (defined(OS_WIN) || defined(OS_LINUX)) + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); + if (!browser->GetHost()->IsWindowRenderingDisabled()) { + browser->GetHost()->NotifyMoveOrResizeStarted(); + } +#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/lib/jcef/native/CefBrowser_N.h b/lib/jcef/native/CefBrowser_N.h new file mode 100644 index 0000000..b0348d5 --- /dev/null +++ b/lib/jcef/native/CefBrowser_N.h @@ -0,0 +1,584 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_browser_CefBrowser_N */ + +#ifndef _Included_org_cef_browser_CefBrowser_N +#define _Included_org_cef_browser_CefBrowser_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_CreateBrowser + * Signature: + * (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*, + jobject, + jobject, + jlong, + jstring, + jboolean, + jboolean, + jobject, + jobject, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_CreateDevTools + * Signature: + * (Lorg/cef/browser/CefBrowser;Lorg/cef/handler/CefClientHandler;JZZLjava/awt/Component;Ljava/awt/Point;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv*, + jobject, + jobject, + jobject, + jlong, + jboolean, + jboolean, + 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 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetWindowHandle(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_CanGoBack + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1CanGoBack(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GoBack + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GoBack(JNIEnv*, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_CanGoForward + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1CanGoForward(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GoForward + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GoForward(JNIEnv*, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_IsLoading + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1IsLoading(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_Reload + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1Reload(JNIEnv*, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_ReloadIgnoreCache + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1ReloadIgnoreCache(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_StopLoad + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1StopLoad(JNIEnv*, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetIdentifier + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetIdentifier(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetMainFrame + * Signature: ()Lorg/cef/browser/CefFrame; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetMainFrame(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetFocusedFrame + * Signature: ()Lorg/cef/browser/CefFrame; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetFocusedFrame(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetFrameByIdentifier + * Signature: (Ljava/lang/String;)Lorg/cef/browser/CefFrame; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByIdentifier(JNIEnv*, + jobject, + jstring); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetFrameByName + * Signature: (Ljava/lang/String;)Lorg/cef/browser/CefFrame; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByName(JNIEnv*, jobject, jstring); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetFrameIdentifiers + * Signature: ()Ljava/util/Vector; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameIdentifiers(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetFrameNames + * Signature: ()Ljava/util/Vector; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameNames(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetFrameCount + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameCount(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_IsPopup + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1IsPopup(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_HasDocument + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1HasDocument(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_ViewSource + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1ViewSource(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetSource + * Signature: (Lorg/cef/callback/CefStringVisitor;)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetSource(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetText + * Signature: (Lorg/cef/callback/CefStringVisitor;)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetText(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_LoadRequest + * Signature: (Lorg/cef/network/CefRequest;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1LoadRequest(JNIEnv*, jobject, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_LoadURL + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1LoadURL(JNIEnv*, + jobject, + jstring); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_ExecuteJavaScript + * Signature: (Ljava/lang/String;Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1ExecuteJavaScript(JNIEnv*, + jobject, + jstring, + jstring, + jint); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetURL + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetURL(JNIEnv*, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_Close + * Signature: (Z)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1Close(JNIEnv*, + jobject, + jboolean); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_SetFocus + * Signature: (Z)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1SetFocus(JNIEnv*, + jobject, + jboolean); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_SetWindowVisibility + * Signature: (Z)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SetWindowVisibility(JNIEnv*, + jobject, + jboolean); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetZoomLevel + * Signature: ()D + */ +JNIEXPORT jdouble JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetZoomLevel(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_SetZoomLevel + * Signature: (D)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SetZoomLevel(JNIEnv*, jobject, jdouble); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_RunFileDialog + * Signature: + * (Lorg/cef/handler/CefDialogHandler/FileDialogMode;Ljava/lang/String;Ljava/lang/String;Ljava/util/Vector;ILorg/cef/callback/CefRunFileDialogCallback;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1RunFileDialog(JNIEnv*, + jobject, + jobject, + jstring, + jstring, + jobject, + jint, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_StartDownload + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1StartDownload(JNIEnv*, jobject, jstring); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_Print + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1Print(JNIEnv*, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_PrintToPDF + * Signature: + * (Ljava/lang/String;Lorg/cef/misc/CefPdfPrintSettings;Lorg/cef/callback/CefPdfPrintCallback;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1PrintToPDF(JNIEnv*, + jobject, + jstring, + jobject, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_Find + * Signature: (Ljava/lang/String;ZZZ)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1Find(JNIEnv*, + jobject, + jstring, + jboolean, + jboolean, + jboolean); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_StopFinding + * Signature: (Z)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1StopFinding(JNIEnv*, jobject, jboolean); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_CloseDevTools + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1CloseDevTools(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_ReplaceMisspelling + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1ReplaceMisspelling(JNIEnv*, + jobject, + jstring); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_WasResized + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1WasResized(JNIEnv*, + jobject, + jint, + jint); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_Invalidate + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1Invalidate(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_SendKeyEvent + * Signature: (Ljava/awt/event/KeyEvent;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SendKeyEvent(JNIEnv*, jobject, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_SendMouseEvent + * Signature: (Ljava/awt/event/MouseEvent;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SendMouseEvent(JNIEnv*, jobject, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_SendMouseWheelEvent + * Signature: (Ljava/awt/event/MouseWheelEvent;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SendMouseWheelEvent(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_DragTargetDragEnter + * Signature: (Lorg/cef/callback/CefDragData;Ljava/awt/Point;II)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDragEnter(JNIEnv*, + jobject, + jobject, + jobject, + jint, + jint); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_DragTargetDragOver + * Signature: (Ljava/awt/Point;II)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDragOver(JNIEnv*, + jobject, + jobject, + jint, + jint); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_DragTargetDragLeave + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDragLeave(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_DragTargetDrop + * Signature: (Ljava/awt/Point;I)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDrop(JNIEnv*, + jobject, + jobject, + jint); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_DragSourceEndedAt + * Signature: (Ljava/awt/Point;I)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragSourceEndedAt(JNIEnv*, + jobject, + jobject, + jint); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_DragSourceSystemDragEnded + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1DragSourceSystemDragEnded(JNIEnv*, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_UpdateUI + * Signature: (Ljava/awt/Rectangle;Ljava/awt/Rectangle;)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1UpdateUI(JNIEnv*, + jobject, + jobject, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_SetParent + * Signature: (JLjava/awt/Component;)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1SetParent(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_NotifyMoveOrResizeStarted + * Signature: ()V + */ +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 +#endif diff --git a/lib/jcef/native/CefCallback_N.cpp b/lib/jcef/native/CefCallback_N.cpp new file mode 100644 index 0000000..4c533c7 --- /dev/null +++ b/lib/jcef/native/CefCallback_N.cpp @@ -0,0 +1,42 @@ +// 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 "CefCallback_N.h" +#include "include/cef_callback.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, "CefCallback"); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefCallback_1N_N_1Continue(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Continue(); + ClearSelf(env, obj); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefCallback_1N_N_1Cancel(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Cancel(); + ClearSelf(env, obj); +} diff --git a/lib/jcef/native/CefCallback_N.h b/lib/jcef/native/CefCallback_N.h new file mode 100644 index 0000000..7ee8c61 --- /dev/null +++ b/lib/jcef/native/CefCallback_N.h @@ -0,0 +1,31 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefCallback_N */ + +#ifndef _Included_org_cef_callback_CefCallback_N +#define _Included_org_cef_callback_CefCallback_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefCallback_N + * Method: N_Continue + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_callback_CefCallback_1N_N_1Continue(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefCallback_N + * Method: N_Cancel + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_callback_CefCallback_1N_N_1Cancel(JNIEnv*, + jobject, + jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefClientHandler.cpp b/lib/jcef/native/CefClientHandler.cpp new file mode 100644 index 0000000..8abbaf6 --- /dev/null +++ b/lib/jcef/native/CefClientHandler.cpp @@ -0,0 +1,175 @@ +// 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 "CefClientHandler.h" +#include "client_handler.h" +#include "jni_util.h" +#include "message_router_handler.h" + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1CefClientHandler_1CTOR( + JNIEnv* env, + jobject clientHandler) { + CefRefPtr client = new ClientHandler(env, clientHandler); + SetCefForJNIObject(env, clientHandler, client.get(), "CefClientHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1addMessageRouter( + JNIEnv* env, + jobject clientHandler, + jobject jmessageRouter) { + CefRefPtr client = GetCefFromJNIObject( + env, clientHandler, "CefClientHandler"); + if (!client.get()) + return; + client->AddMessageRouter(env, jmessageRouter); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeContextMenuHandler( + JNIEnv* env, + jobject clientHandler, + jobject contextMenuHandler) { + SetCefForJNIObject(env, contextMenuHandler, nullptr, + "CefContextMenuHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeDialogHandler( + JNIEnv* env, + jobject clientHandler, + jobject dialogHandler) { + SetCefForJNIObject(env, dialogHandler, nullptr, + "CefDialogHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeDisplayHandler( + JNIEnv* env, + jobject clientHandler, + jobject displayHandler) { + SetCefForJNIObject(env, displayHandler, nullptr, + "CefDisplayHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeDownloadHandler( + JNIEnv* env, + jobject clientHandler, + jobject downloadHandler) { + SetCefForJNIObject(env, downloadHandler, nullptr, + "CefDownloadHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeDragHandler( + JNIEnv* env, + jobject clientHandler, + jobject dragHandler) { + SetCefForJNIObject(env, dragHandler, nullptr, + "CefDragHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeFocusHandler( + JNIEnv* env, + jobject clientHandler, + jobject focusHandler) { + SetCefForJNIObject(env, focusHandler, nullptr, + "CefFocusHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeJSDialogHandler( + JNIEnv* env, + jobject clientHandler, + jobject jsdialogHandler) { + SetCefForJNIObject(env, jsdialogHandler, nullptr, + "CefJSDialogHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeKeyboardHandler( + JNIEnv* env, + jobject clientHandler, + jobject keyboardHandler) { + SetCefForJNIObject(env, keyboardHandler, nullptr, + "CefKeyboardHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeLifeSpanHandler( + JNIEnv* env, + jobject clientHandler, + jobject lifeSpanHandler) { + SetCefForJNIObject(env, lifeSpanHandler, nullptr, + "CefLifeSpanHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeLoadHandler( + JNIEnv* env, + jobject clientHandler, + jobject loadHandler) { + SetCefForJNIObject(env, loadHandler, nullptr, + "CefLoadHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removePrintHandler( + JNIEnv* env, + jobject clientHandler, + jobject printHandler) { + SetCefForJNIObject(env, printHandler, nullptr, + "CefPrintHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeMessageRouter( + JNIEnv* env, + jobject clientHandler, + jobject jmessageRouter) { + CefRefPtr client = GetCefFromJNIObject( + env, clientHandler, "CefClientHandler"); + if (!client.get()) + return; + client->RemoveMessageRouter(env, jmessageRouter); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeRenderHandler( + JNIEnv* env, + jobject clientHandler, + jobject renderHandler) { + SetCefForJNIObject(env, renderHandler, nullptr, + "CefRenderHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeRequestHandler( + JNIEnv* env, + jobject clientHandler, + jobject requestHandler) { + SetCefForJNIObject(env, requestHandler, nullptr, + "CefRequestHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeWindowHandler( + JNIEnv* env, + jobject clientHandler, + jobject windowHandler) { + SetCefForJNIObject(env, windowHandler, nullptr, + "CefWindowHandler"); +} + +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1CefClientHandler_1DTOR( + JNIEnv* env, + jobject clientHandler) { + // delete reference to the native client handler + SetCefForJNIObject(env, clientHandler, nullptr, + "CefClientHandler"); +} diff --git a/lib/jcef/native/CefClientHandler.h b/lib/jcef/native/CefClientHandler.h new file mode 100644 index 0000000..9867c45 --- /dev/null +++ b/lib/jcef/native/CefClientHandler.h @@ -0,0 +1,191 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_handler_CefClientHandler */ + +#ifndef _Included_org_cef_handler_CefClientHandler +#define _Included_org_cef_handler_CefClientHandler +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_CefClientHandler_CTOR + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1CefClientHandler_1CTOR(JNIEnv*, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_addMessageRouter + * Signature: (Lorg/cef/browser/CefMessageRouter;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1addMessageRouter(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeContextMenuHandler + * Signature: (Lorg/cef/handler/CefContextMenuHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeContextMenuHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeDialogHandler + * Signature: (Lorg/cef/handler/CefDialogHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeDialogHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeDisplayHandler + * Signature: (Lorg/cef/handler/CefDisplayHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeDisplayHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeDownloadHandler + * Signature: (Lorg/cef/handler/CefDisplayHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeDownloadHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeDragHandler + * Signature: (Lorg/cef/handler/CefDragHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeDragHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeFocusHandler + * Signature: (Lorg/cef/handler/CefFocusHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeFocusHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeJSDialogHandler + * Signature: (Lorg/cef/handler/CefJSDialogHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeJSDialogHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeKeyboardHandler + * Signature: (Lorg/cef/handler/CefKeyboardHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeKeyboardHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeLifeSpanHandler + * Signature: (Lorg/cef/handler/CefLifeSpanHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeLifeSpanHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeLoadHandler + * Signature: (Lorg/cef/handler/CefLoadHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeLoadHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removePrintHandler + * Signature: (Lorg/cef/handler/CefPrintHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removePrintHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeMessageRouter + * Signature: (Lorg/cef/browser/CefMessageRouter;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeMessageRouter(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeRenderHandler + * Signature: (Lorg/cef/handler/CefRenderHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeRenderHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeRequestHandler + * Signature: (Lorg/cef/handler/CefRequestHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeRequestHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeWindowHandler + * Signature: (Lorg/cef/handler/CefWindowHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeWindowHandler(JNIEnv*, + jobject, + jobject); + +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_CefClientHandler_DTOR + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1CefClientHandler_1DTOR(JNIEnv*, + jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefCommandLine_N.cpp b/lib/jcef/native/CefCommandLine_N.cpp new file mode 100644 index 0000000..8dbe8ac --- /dev/null +++ b/lib/jcef/native/CefCommandLine_N.cpp @@ -0,0 +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. + +#include "CefCommandLine_N.h" +#include "include/cef_command_line.h" +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1Reset(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr commandLine = GetSelf(self); + if (!commandLine) + return; + commandLine->Reset(); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1GetProgram(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr commandLine = GetSelf(self); + if (!commandLine) + return env->NewStringUTF(""); + return NewJNIString(env, commandLine->GetProgram()); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1SetProgram(JNIEnv* env, + jobject obj, + jlong self, + jstring program) { + CefRefPtr commandLine = GetSelf(self); + if (!commandLine) + return; + commandLine->SetProgram(GetJNIString(env, program)); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1HasSwitches(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr commandLine = GetSelf(self); + if (!commandLine) + return JNI_FALSE; + return commandLine->HasSwitches() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1HasSwitch(JNIEnv* env, + jobject obj, + jlong self, + jstring name) { + CefRefPtr commandLine = GetSelf(self); + if (!commandLine) + return JNI_FALSE; + return commandLine->HasSwitch(GetJNIString(env, name)) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1GetSwitchValue(JNIEnv* env, + jobject obj, + jlong self, + jstring name) { + CefRefPtr commandLine = GetSelf(self); + if (!commandLine) + return env->NewStringUTF(""); + return NewJNIString(env, + commandLine->GetSwitchValue(GetJNIString(env, name))); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1GetSwitches(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr commandLine = GetSelf(self); + CefCommandLine::SwitchMap switches; + if (commandLine) + commandLine->GetSwitches(switches); + return NewJNIStringMap(env, switches); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1AppendSwitch(JNIEnv* env, + jobject obj, + jlong self, + jstring name) { + CefRefPtr commandLine = GetSelf(self); + if (!commandLine) + return; + commandLine->AppendSwitch(GetJNIString(env, name)); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1AppendSwitchWithValue( + JNIEnv* env, + jobject obj, + jlong self, + jstring name, + jstring value) { + CefRefPtr commandLine = GetSelf(self); + if (!commandLine) + return; + commandLine->AppendSwitchWithValue(GetJNIString(env, name), + GetJNIString(env, value)); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1HasArguments(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr commandLine = GetSelf(self); + if (!commandLine) + return JNI_FALSE; + return commandLine->HasArguments() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1GetArguments(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr commandLine = GetSelf(self); + CefCommandLine::ArgumentList arguments; + if (commandLine) + commandLine->GetArguments(arguments); + return NewJNIStringVector(env, arguments); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1AppendArgument(JNIEnv* env, + jobject obj, + jlong self, + jstring argument) { + CefRefPtr commandLine = GetSelf(self); + if (!commandLine) + return; + commandLine->AppendArgument(GetJNIString(env, argument)); +} diff --git a/lib/jcef/native/CefCommandLine_N.h b/lib/jcef/native/CefCommandLine_N.h new file mode 100644 index 0000000..1a289b0 --- /dev/null +++ b/lib/jcef/native/CefCommandLine_N.h @@ -0,0 +1,133 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefCommandLine_N */ + +#ifndef _Included_org_cef_callback_CefCommandLine_N +#define _Included_org_cef_callback_CefCommandLine_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_Reset + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_callback_CefCommandLine_1N_N_1Reset(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_GetProgram + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1GetProgram(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_SetProgram + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1SetProgram(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_HasSwitches + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1HasSwitches(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_HasSwitch + * Signature: (JLjava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1HasSwitch(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_GetSwitchValue + * Signature: (JLjava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1GetSwitchValue(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_GetSwitches + * Signature: (J)Ljava/util/Map; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1GetSwitches(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_AppendSwitch + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1AppendSwitch(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_AppendSwitchWithValue + * Signature: (JLjava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1AppendSwitchWithValue(JNIEnv*, + jobject, + jlong, + jstring, + jstring); + +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_HasArguments + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1HasArguments(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_GetArguments + * Signature: (J)Ljava/util/Vector; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1GetArguments(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefCommandLine_N + * Method: N_AppendArgument + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefCommandLine_1N_N_1AppendArgument(JNIEnv*, + jobject, + jlong, + jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefContextMenuParams_N.cpp b/lib/jcef/native/CefContextMenuParams_N.cpp new file mode 100644 index 0000000..0d1c2c0 --- /dev/null +++ b/lib/jcef/native/CefContextMenuParams_N.cpp @@ -0,0 +1,231 @@ +// 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 "CefContextMenuParams_N.h" + +#include "include/cef_context_menu_handler.h" + +#include "jni_util.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +} // namespace + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetXCoord(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return 0; + return menuParams->GetXCoord(); +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetYCoord(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return 0; + return menuParams->GetYCoord(); +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetTypeFlags(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return 0; + return (jint)menuParams->GetTypeFlags(); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetLinkUrl(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return nullptr; + return NewJNIString(env, menuParams->GetLinkUrl()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetUnfilteredLinkUrl( + JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return nullptr; + return NewJNIString(env, menuParams->GetUnfilteredLinkUrl()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetSourceUrl(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return nullptr; + return NewJNIString(env, menuParams->GetSourceUrl()); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1HasImageContents(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return JNI_FALSE; + return menuParams->HasImageContents() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetPageUrl(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return nullptr; + return NewJNIString(env, menuParams->GetPageUrl()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetFrameUrl(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return nullptr; + return NewJNIString(env, menuParams->GetFrameUrl()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetFrameCharset(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return nullptr; + return NewJNIString(env, menuParams->GetFrameCharset()); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetMediaType(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + + jobject result = + GetJNIEnumValue(env, "org/cef/callback/CefContextMenuParams$MediaType", + "CM_MEDIATYPE_NONE"); + if (!menuParams) + return result; + + switch (menuParams->GetMediaType()) { + JNI_CASE(env, "org/cef/callback/CefContextMenuParams$MediaType", + CM_MEDIATYPE_IMAGE, result); + JNI_CASE(env, "org/cef/callback/CefContextMenuParams$MediaType", + CM_MEDIATYPE_VIDEO, result); + JNI_CASE(env, "org/cef/callback/CefContextMenuParams$MediaType", + CM_MEDIATYPE_AUDIO, result); + JNI_CASE(env, "org/cef/callback/CefContextMenuParams$MediaType", + CM_MEDIATYPE_FILE, result); + JNI_CASE(env, "org/cef/callback/CefContextMenuParams$MediaType", + CM_MEDIATYPE_PLUGIN, result); + default: + JNI_CASE(env, "org/cef/callback/CefContextMenuParams$MediaType", + CM_MEDIATYPE_NONE, result); + } + return result; +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetMediaStateFlags( + JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return 0; + return (jint)menuParams->GetMediaStateFlags(); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetSelectionText(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return nullptr; + return NewJNIString(env, menuParams->GetSelectionText()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetMisspelledWord(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return nullptr; + return NewJNIString(env, menuParams->GetMisspelledWord()); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetDictionarySuggestions( + JNIEnv* env, + jobject obj, + jlong self, + jobject jsuggestions) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return false; + + std::vector suggestions; + bool result = menuParams->GetDictionarySuggestions(suggestions); + if (!result) + return JNI_FALSE; + + for (std::vector::size_type i = 0; i < suggestions.size(); ++i) { + AddJNIStringToVector(env, jsuggestions, suggestions.at(i)); + } + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1IsEditable(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return JNI_FALSE; + return menuParams->IsEditable() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1IsSpellCheckEnabled( + JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return JNI_FALSE; + return menuParams->IsSpellCheckEnabled() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetEditStateFlags(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuParams = GetSelf(self); + if (!menuParams) + return 0; + return (jint)menuParams->GetEditStateFlags(); +} diff --git a/lib/jcef/native/CefContextMenuParams_N.h b/lib/jcef/native/CefContextMenuParams_N.h new file mode 100644 index 0000000..6a96024 --- /dev/null +++ b/lib/jcef/native/CefContextMenuParams_N.h @@ -0,0 +1,195 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefContextMenuParams_N */ + +#ifndef _Included_org_cef_callback_CefContextMenuParams_N +#define _Included_org_cef_callback_CefContextMenuParams_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetXCoord + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetXCoord(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetYCoord + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetYCoord(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetTypeFlags + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetTypeFlags(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetLinkUrl + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetLinkUrl(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetUnfilteredLinkUrl + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetUnfilteredLinkUrl(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetSourceUrl + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetSourceUrl(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_HasImageContents + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1HasImageContents(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetPageUrl + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetPageUrl(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetFrameUrl + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetFrameUrl(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetFrameCharset + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetFrameCharset(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetMediaType + * Signature: (J)Lorg/cef/callback/CefContextMenuParams/MediaType; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetMediaType(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetMediaStateFlags + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetMediaStateFlags(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetSelectionText + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetSelectionText(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetMisspelledWord + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetMisspelledWord(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetDictionarySuggestions + * Signature: (JLjava/util/Vector;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetDictionarySuggestions( + JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_IsEditable + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1IsEditable(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_IsSpellCheckEnabled + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1IsSpellCheckEnabled(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefContextMenuParams_N + * Method: N_GetEditStateFlags + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefContextMenuParams_1N_N_1GetEditStateFlags(JNIEnv*, + jobject, + jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefCookieManager_N.cpp b/lib/jcef/native/CefCookieManager_N.cpp new file mode 100644 index 0000000..f029e29 --- /dev/null +++ b/lib/jcef/native/CefCookieManager_N.cpp @@ -0,0 +1,171 @@ +// 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 "CefCookieManager_N.h" + +#include "include/base/cef_callback.h" +#include "include/cef_cookie.h" +#include "include/cef_task.h" +#include "include/wrapper/cef_closure_task.h" + +#include "completion_callback.h" +#include "cookie_visitor.h" +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +const char kCefClassName[] = "CefCookieManager"; + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +CefCookie GetJNICookie(JNIEnv* env, jobject jcookie) { + CefCookie cookie; + + ScopedJNIClass cls(env, "org/cef/network/CefCookie"); + if (!cls) + return cookie; + + CefString name(&cookie.name); + CefString value(&cookie.value); + CefString domain(&cookie.domain); + CefString path(&cookie.path); + CefBaseTime creation, lastAccess, expires; + + GetJNIFieldString(env, cls, jcookie, "name", &name); + GetJNIFieldString(env, cls, jcookie, "value", &value); + GetJNIFieldString(env, cls, jcookie, "domain", &domain); + GetJNIFieldString(env, cls, jcookie, "path", &path); + GetJNIFieldBoolean(env, cls, jcookie, "secure", &cookie.secure); + GetJNIFieldBoolean(env, cls, jcookie, "httponly", &cookie.httponly); + GetJNIFieldDate(env, cls, jcookie, "creation", &creation); + cookie.creation = creation; + GetJNIFieldDate(env, cls, jcookie, "lastAccess", &lastAccess); + cookie.last_access = lastAccess; + GetJNIFieldBoolean(env, cls, jcookie, "hasExpires", &cookie.has_expires); + if (cookie.has_expires) { + GetJNIFieldDate(env, cls, jcookie, "expires", &expires); + cookie.expires = expires; + } + + return cookie; +} + +} // namespace + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1GetGlobalManager(JNIEnv* env, + jclass cls) { + // TODO(JCEF): Expose the callback object. + CefRefPtr manager = + CefCookieManager::GetGlobalManager(nullptr); + if (!manager) + return nullptr; + + ScopedJNIObjectLocal jManager(env, NewJNIObject(env, cls)); + if (!jManager) + return nullptr; + + SetCefForJNIObject(env, jManager, manager.get(), kCefClassName); + return jManager.Release(); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + SetCefForJNIObject(env, obj, nullptr, kCefClassName); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1VisitAllCookies(JNIEnv* env, + jobject obj, + jlong self, + jobject jvisitor) { + CefRefPtr manager = GetSelf(self); + if (!manager || !jvisitor) + return JNI_FALSE; + + CefRefPtr visitor = new CookieVisitor(env, jvisitor); + return manager->VisitAllCookies(visitor) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1VisitUrlCookies( + JNIEnv* env, + jobject obj, + jlong self, + jstring jurl, + jboolean jincludeHttpOnly, + jobject jvisitor) { + CefRefPtr manager = GetSelf(self); + if (!manager || !jvisitor) + return JNI_FALSE; + + CefRefPtr visitor = new CookieVisitor(env, jvisitor); + bool result = manager->VisitUrlCookies( + GetJNIString(env, jurl), (jincludeHttpOnly != JNI_FALSE), visitor); + return result ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1SetCookie(JNIEnv* env, + jobject obj, + jlong self, + jstring jurl, + jobject jcookie) { + CefRefPtr manager = GetSelf(self); + if (!manager) + return JNI_FALSE; + + // The method CefCookieManager::SetCookie must be called on the IO thread. + // We ignore its return value and return the result of the PostTask event to + // java instead. + // TODO(JCEF): Expose the callback object. + bool result = CefPostTask( + TID_IO, base::BindOnce(base::IgnoreResult(&CefCookieManager::SetCookie), + manager.get(), GetJNIString(env, jurl), + GetJNICookie(env, jcookie), + CefRefPtr())); + return result ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1DeleteCookies(JNIEnv* env, + jobject obj, + jlong self, + jstring jurl, + jstring jcookieName) { + CefRefPtr manager = GetSelf(self); + if (!manager) + return JNI_FALSE; + + // The method CefCookieManager::DeleteCookies must be called on the IO thread. + // We ignore its return value and return the result of the PostTask event to + // java instead. + // TODO(JCEF): Expose the callback object. + bool result = CefPostTask( + TID_IO, + base::BindOnce(base::IgnoreResult(&CefCookieManager::DeleteCookies), + manager.get(), GetJNIString(env, jurl), + GetJNIString(env, jcookieName), + CefRefPtr())); + return result ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1FlushStore(JNIEnv* env, + jobject obj, + jlong self, + jobject jhandler) { + CefRefPtr manager = GetSelf(self); + if (!manager) + return JNI_FALSE; + CefRefPtr callback = + new CompletionCallback(env, jhandler); + bool result = manager->FlushStore(callback); + return result ? JNI_TRUE : JNI_FALSE; +} diff --git a/lib/jcef/native/CefCookieManager_N.h b/lib/jcef/native/CefCookieManager_N.h new file mode 100644 index 0000000..0388ebb --- /dev/null +++ b/lib/jcef/native/CefCookieManager_N.h @@ -0,0 +1,88 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_network_CefCookieManager_N */ + +#ifndef _Included_org_cef_network_CefCookieManager_N +#define _Included_org_cef_network_CefCookieManager_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_network_CefCookieManager_N + * Method: N_GetGlobalManager + * Signature: ()Lorg/cef/network/CefCookieManager_N; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1GetGlobalManager(JNIEnv*, jclass); + +/* + * Class: org_cef_network_CefCookieManager_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1Dispose(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefCookieManager_N + * Method: N_VisitAllCookies + * Signature: (JLorg/cef/callback/CefCookieVisitor;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1VisitAllCookies(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_network_CefCookieManager_N + * Method: N_VisitUrlCookies + * Signature: (JLjava/lang/String;ZLorg/cef/callback/CefCookieVisitor;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1VisitUrlCookies(JNIEnv*, + jobject, + jlong, + jstring, + jboolean, + jobject); + +/* + * Class: org_cef_network_CefCookieManager_N + * Method: N_SetCookie + * Signature: (JLjava/lang/String;Lorg/cef/network/CefCookie;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1SetCookie(JNIEnv*, + jobject, + jlong, + jstring, + jobject); + +/* + * Class: org_cef_network_CefCookieManager_N + * Method: N_DeleteCookies + * Signature: (JLjava/lang/String;Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1DeleteCookies(JNIEnv*, + jobject, + jlong, + jstring, + jstring); + +/* + * Class: org_cef_network_CefCookieManager_N + * Method: N_FlushStore + * Signature: (JLorg/cef/callback/CefCompletionCallback;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefCookieManager_1N_N_1FlushStore(JNIEnv*, + jobject, + jlong, + jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefDownloadItemCallback_N.cpp b/lib/jcef/native/CefDownloadItemCallback_N.cpp new file mode 100644 index 0000000..3b89120 --- /dev/null +++ b/lib/jcef/native/CefDownloadItemCallback_N.cpp @@ -0,0 +1,63 @@ +// 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 "CefDownloadItemCallback_N.h" +#include "include/cef_download_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 DownloadHandler::OnDownloadUpdated. + SetCefForJNIObject(env, obj, nullptr, + "CefDownloadItemCallback"); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDownloadItemCallback_1N_N_1Cancel(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Cancel(); + ClearSelf(env, obj); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDownloadItemCallback_1N_N_1Pause(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Pause(); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDownloadItemCallback_1N_N_1Resume(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Resume(); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDownloadItemCallback_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + // Intentionally not executing any callback methods here. + ClearSelf(env, obj); +} diff --git a/lib/jcef/native/CefDownloadItemCallback_N.h b/lib/jcef/native/CefDownloadItemCallback_N.h new file mode 100644 index 0000000..9aa58e1 --- /dev/null +++ b/lib/jcef/native/CefDownloadItemCallback_N.h @@ -0,0 +1,53 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefDownloadItemCallback_N */ + +#ifndef _Included_org_cef_callback_CefDownloadItemCallback_N +#define _Included_org_cef_callback_CefDownloadItemCallback_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefDownloadItemCallback_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDownloadItemCallback_1N_N_1Dispose(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItemCallback_N + * Method: N_Cancel + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDownloadItemCallback_1N_N_1Cancel(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItemCallback_N + * Method: N_Pause + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDownloadItemCallback_1N_N_1Pause(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItemCallback_N + * Method: N_Resume + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDownloadItemCallback_1N_N_1Resume(JNIEnv*, + jobject, + jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefDownloadItem_N.cpp b/lib/jcef/native/CefDownloadItem_N.cpp new file mode 100644 index 0000000..5ab9b57 --- /dev/null +++ b/lib/jcef/native/CefDownloadItem_N.cpp @@ -0,0 +1,178 @@ +// 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 "CefDownloadItem_N.h" +#include "include/cef_download_item.h" +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +} // namespace + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1IsValid(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return JNI_FALSE; + return downloadItem->IsValid() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1IsInProgress(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return JNI_FALSE; + return downloadItem->IsInProgress() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1IsComplete(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return JNI_FALSE; + return downloadItem->IsComplete() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1IsCanceled(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return JNI_FALSE; + return downloadItem->IsCanceled() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jlong JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetCurrentSpeed(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return 0; + return downloadItem->GetCurrentSpeed(); +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetPercentComplete(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return 0; + return downloadItem->GetPercentComplete(); +} + +JNIEXPORT jlong JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetTotalBytes(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return 0; + return downloadItem->GetTotalBytes(); +} + +JNIEXPORT jlong JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetReceivedBytes(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return 0; + return downloadItem->GetReceivedBytes(); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetStartTime(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return nullptr; + ScopedJNIDate jdate(env, downloadItem->GetStartTime()); + return jdate.Release(); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetEndTime(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return nullptr; + ScopedJNIDate jdate(env, downloadItem->GetEndTime()); + return jdate.Release(); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetFullPath(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return nullptr; + return NewJNIString(env, downloadItem->GetFullPath()); +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetId(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return -1; + return downloadItem->GetId(); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetURL(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return nullptr; + return NewJNIString(env, downloadItem->GetURL()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetSuggestedFileName(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return nullptr; + return NewJNIString(env, downloadItem->GetSuggestedFileName()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetContentDisposition(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return nullptr; + return NewJNIString(env, downloadItem->GetContentDisposition()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetMimeType(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr downloadItem = GetSelf(self); + if (!downloadItem) + return nullptr; + return NewJNIString(env, downloadItem->GetMimeType()); +} diff --git a/lib/jcef/native/CefDownloadItem_N.h b/lib/jcef/native/CefDownloadItem_N.h new file mode 100644 index 0000000..dda01c6 --- /dev/null +++ b/lib/jcef/native/CefDownloadItem_N.h @@ -0,0 +1,161 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefDownloadItem_N */ + +#ifndef _Included_org_cef_callback_CefDownloadItem_N +#define _Included_org_cef_callback_CefDownloadItem_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_IsValid + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1IsValid(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_IsInProgress + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1IsInProgress(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_IsComplete + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1IsComplete(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_IsCanceled + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1IsCanceled(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetCurrentSpeed + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetCurrentSpeed(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetPercentComplete + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetPercentComplete(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetTotalBytes + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetTotalBytes(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetReceivedBytes + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetReceivedBytes(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetStartTime + * Signature: (J)Ljava/util/Date; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetStartTime(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetEndTime + * Signature: (J)Ljava/util/Date; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetEndTime(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetFullPath + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetFullPath(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetId + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetId(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetURL + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetURL(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetSuggestedFileName + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetSuggestedFileName(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetContentDisposition + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetContentDisposition(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDownloadItem_N + * Method: N_GetMimeType + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDownloadItem_1N_N_1GetMimeType(JNIEnv*, + jobject, + jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefDragData_N.cpp b/lib/jcef/native/CefDragData_N.cpp new file mode 100644 index 0000000..f913208 --- /dev/null +++ b/lib/jcef/native/CefDragData_N.cpp @@ -0,0 +1,298 @@ +// 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 "CefDragData_N.h" + +#include "include/cef_drag_handler.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" +#include "write_handler.h" + +namespace { + +const char kCefClassName[] = "CefDragData"; + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +} // namespace + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefDragData_1N_N_1Create(JNIEnv* env, jclass cls) { + CefRefPtr dragData = CefDragData::Create(); + ScopedJNIDragData jdragData(env, dragData); + return jdragData.Release(); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefDragData_1N_N_1Clone(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return nullptr; + + CefRefPtr cloneData = dragData->Clone(); + ScopedJNIDragData jcloneData(env, cloneData); + return jcloneData.Release(); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + SetCefForJNIObject(env, obj, nullptr, kCefClassName); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1IsReadOnly(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return JNI_TRUE; + return dragData->IsReadOnly() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1IsLink(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return JNI_FALSE; + return dragData->IsLink() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1IsFragment(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return JNI_FALSE; + return dragData->IsFragment() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1IsFile(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return JNI_FALSE; + return dragData->IsFile() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetLinkURL(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return nullptr; + return NewJNIString(env, dragData->GetLinkURL()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetLinkTitle(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return nullptr; + return NewJNIString(env, dragData->GetLinkTitle()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetLinkMetadata(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return nullptr; + return NewJNIString(env, dragData->GetLinkMetadata()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFragmentText(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return nullptr; + return NewJNIString(env, dragData->GetFragmentText()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFragmentHtml(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return nullptr; + return NewJNIString(env, dragData->GetFragmentHtml()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFragmentBaseURL(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return nullptr; + return NewJNIString(env, dragData->GetFragmentBaseURL()); +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFileContents(JNIEnv* env, + jobject obj, + jlong self, + jobject jstream) { + CefRefPtr dragData = GetSelf(self); + if (!dragData || !jstream) + return 0; + + CefRefPtr handler = new WriteHandler(env, jstream); + return (jint)dragData->GetFileContents( + CefStreamWriter::CreateForHandler(handler)); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFileName(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return nullptr; + return NewJNIString(env, dragData->GetFileName()); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFileNames(JNIEnv* env, + jobject obj, + jlong self, + jobject jfileNames) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return JNI_FALSE; + + std::vector fileNames; + if (!dragData->GetFileNames(fileNames)) + return JNI_FALSE; + + for (size_t i = 0; i < fileNames.size(); ++i) { + AddJNIStringToVector(env, jfileNames, fileNames.at(i)); + } + 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, + jlong self, + jstring jurl) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return; + dragData->SetLinkURL(GetJNIString(env, jurl)); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1SetLinkTitle(JNIEnv* env, + jobject obj, + jlong self, + jstring jtitle) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return; + dragData->SetLinkTitle(GetJNIString(env, jtitle)); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1SetLinkMetadata(JNIEnv* env, + jobject obj, + jlong self, + jstring jmetaData) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return; + dragData->SetLinkMetadata(GetJNIString(env, jmetaData)); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1SetFragmentText(JNIEnv* env, + jobject obj, + jlong self, + jstring jfragment) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return; + dragData->SetFragmentText(GetJNIString(env, jfragment)); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1SetFragmentHtml(JNIEnv* env, + jobject obj, + jlong self, + jstring jfragment) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return; + dragData->SetFragmentHtml(GetJNIString(env, jfragment)); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1SetFragmentBaseURL(JNIEnv* env, + jobject obj, + jlong self, + jstring jfragment) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return; + dragData->SetFragmentBaseURL(GetJNIString(env, jfragment)); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1ResetFileContents(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return; + dragData->ResetFileContents(); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1AddFile(JNIEnv* env, + jobject obj, + jlong self, + jstring jpath, + jstring jdisplayName) { + CefRefPtr dragData = GetSelf(self); + if (!dragData) + return; + dragData->AddFile(GetJNIString(env, jpath), GetJNIString(env, jdisplayName)); +} diff --git a/lib/jcef/native/CefDragData_N.h b/lib/jcef/native/CefDragData_N.h new file mode 100644 index 0000000..36ae14c --- /dev/null +++ b/lib/jcef/native/CefDragData_N.h @@ -0,0 +1,255 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefDragData_N */ + +#ifndef _Included_org_cef_callback_CefDragData_N +#define _Included_org_cef_callback_CefDragData_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_Create + * Signature: ()Lorg/cef/callback/CefDragData_N; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefDragData_1N_N_1Create(JNIEnv*, jclass); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_Clone + * Signature: (J)Lorg/cef/callback/CefDragData_N; + */ +JNIEXPORT jobject JNICALL Java_org_cef_callback_CefDragData_1N_N_1Clone(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_callback_CefDragData_1N_N_1Dispose(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_IsReadOnly + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1IsReadOnly(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_IsLink + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1IsLink(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_IsFragment + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1IsFragment(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_IsFile + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1IsFile(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_GetLinkURL + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetLinkURL(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_GetLinkTitle + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetLinkTitle(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_GetLinkMetadata + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetLinkMetadata(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_GetFragmentText + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFragmentText(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_GetFragmentHtml + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFragmentHtml(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_GetFragmentBaseURL + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFragmentBaseURL(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_GetFileContents + * Signature: (JLjava/io/OutputStream;)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFileContents(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_GetFileName + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFileName(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_GetFileNames + * Signature: (JLjava/util/Vector;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFileNames(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_GetFilePaths + * Signature: (JLjava/util/Vector;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefDragData_1N_N_1GetFilePaths(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_SetLinkURL + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1SetLinkURL(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_SetLinkTitle + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1SetLinkTitle(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_SetLinkMetadata + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1SetLinkMetadata(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_SetFragmentText + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1SetFragmentText(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_SetFragmentHtml + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1SetFragmentHtml(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_SetFragmentBaseURL + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1SetFragmentBaseURL(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_ResetFileContents + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefDragData_1N_N_1ResetFileContents(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_callback_CefDragData_N + * Method: N_AddFile + * Signature: (JLjava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_cef_callback_CefDragData_1N_N_1AddFile(JNIEnv*, + jobject, + jlong, + jstring, + jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefFileDialogCallback_N.cpp b/lib/jcef/native/CefFileDialogCallback_N.cpp new file mode 100644 index 0000000..73cd4fc --- /dev/null +++ b/lib/jcef/native/CefFileDialogCallback_N.cpp @@ -0,0 +1,49 @@ +// 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 "CefFileDialogCallback_N.h" +#include "include/cef_dialog_handler.h" +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +void ClearSelf(JNIEnv* env, jobject obj) { + // Clear the reference added in DialogHandler::OnFileDialog. + SetCefForJNIObject(env, obj, nullptr, + "CefFileDialogCallback"); +} + +} // namespace + +JNIEXPORT void JNICALL +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(filePaths); + + ClearSelf(env, obj); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefFileDialogCallback_1N_N_1Cancel(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Cancel(); + ClearSelf(env, obj); +} diff --git a/lib/jcef/native/CefFileDialogCallback_N.h b/lib/jcef/native/CefFileDialogCallback_N.h new file mode 100644 index 0000000..1da3ded --- /dev/null +++ b/lib/jcef/native/CefFileDialogCallback_N.h @@ -0,0 +1,34 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefFileDialogCallback_N */ + +#ifndef _Included_org_cef_callback_CefFileDialogCallback_N +#define _Included_org_cef_callback_CefFileDialogCallback_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefFileDialogCallback_N + * Method: N_Continue + * Signature: (JLjava/util/Vector;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefFileDialogCallback_1N_N_1Continue(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_callback_CefFileDialogCallback_N + * Method: N_Cancel + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefFileDialogCallback_1N_N_1Cancel(JNIEnv*, + jobject, + jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefFrame_N.cpp b/lib/jcef/native/CefFrame_N.cpp new file mode 100644 index 0000000..cab338e --- /dev/null +++ b/lib/jcef/native/CefFrame_N.cpp @@ -0,0 +1,177 @@ +// Copyright (c) 2017 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 "CefFrame_N.h" + +#include "include/cef_frame.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +void ClearSelf(JNIEnv* env, jobject obj) { + SetCefForJNIObject(env, obj, nullptr, "CefFrame"); +} + +} // namespace + +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + ClearSelf(env, obj); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_browser_CefFrame_1N_N_1GetIdentifier(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return nullptr; + return NewJNIString(env, frame->GetIdentifier()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_browser_CefFrame_1N_N_1GetURL(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return nullptr; + return NewJNIString(env, frame->GetURL()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_browser_CefFrame_1N_N_1GetName(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return nullptr; + return NewJNIString(env, frame->GetName()); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefFrame_1N_N_1IsMain(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return JNI_FALSE; + return frame->IsMain() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefFrame_1N_N_1IsValid(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return JNI_FALSE; + return frame->IsValid() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefFrame_1N_N_1IsFocused(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return JNI_FALSE; + return frame->IsFocused() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefFrame_1N_N_1GetParent(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return nullptr; + CefRefPtr parent = frame->GetParent(); + if (!parent) + return nullptr; + ScopedJNIFrame jparent(env, parent); + return jparent.Release(); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefFrame_1N_N_1ExecuteJavaScript(JNIEnv* env, + jobject obj, + jlong self, + jstring code, + jstring url, + jint line) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return; + frame->ExecuteJavaScript(GetJNIString(env, code), GetJNIString(env, url), + line); +} + +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Undo(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return; + + frame->Undo(); +} + +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Redo(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return; + + frame->Redo(); +} + +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Cut(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return; + + frame->Cut(); +} + +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Copy(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return; + + frame->Copy(); +} + +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Paste(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return; + + 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/lib/jcef/native/CefFrame_N.h b/lib/jcef/native/CefFrame_N.h new file mode 100644 index 0000000..a156818 --- /dev/null +++ b/lib/jcef/native/CefFrame_N.h @@ -0,0 +1,150 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_browser_CefFrame_N */ + +#ifndef _Included_org_cef_browser_CefFrame_N +#define _Included_org_cef_browser_CefFrame_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Dispose(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_GetIdentifier + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_browser_CefFrame_1N_N_1GetIdentifier(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_GetURL + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_cef_browser_CefFrame_1N_N_1GetURL(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_GetName + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_cef_browser_CefFrame_1N_N_1GetName(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_IsMain + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_org_cef_browser_CefFrame_1N_N_1IsMain(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_IsValid + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_org_cef_browser_CefFrame_1N_N_1IsValid(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_IsFocused + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefFrame_1N_N_1IsFocused(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_GetParent + * Signature: (J)Lorg/cef/browser/CefFrame; + */ +JNIEXPORT jobject JNICALL Java_org_cef_browser_CefFrame_1N_N_1GetParent(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_ExecuteJavaScript + * Signature: (JLjava/lang/String;Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefFrame_1N_N_1ExecuteJavaScript(JNIEnv*, + jobject, + jlong, + jstring, + jstring, + jint); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_Undo + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Undo(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_Redo + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Redo(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_Cut + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Cut(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_Copy + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Copy(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_Paste + * Signature: (J)V + */ +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 +#endif diff --git a/lib/jcef/native/CefJSDialogCallback_N.cpp b/lib/jcef/native/CefJSDialogCallback_N.cpp new file mode 100644 index 0000000..11c9183 --- /dev/null +++ b/lib/jcef/native/CefJSDialogCallback_N.cpp @@ -0,0 +1,36 @@ +// 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 "CefJSDialogCallback_N.h" +#include "include/cef_jsdialog_handler.h" +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +void ClearSelf(JNIEnv* env, jobject obj) { + // Clear the reference added in JSDialogHandler::OnJSDialog and + // JSDialogHandler::OnBeforeUnloadDialog. + SetCefForJNIObject(env, obj, nullptr, + "CefJSDialogCallback"); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefJSDialogCallback_1N_N_1Continue(JNIEnv* env, + jobject obj, + jlong self, + jboolean jsuccess, + jstring juser_input) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Continue((jsuccess != JNI_FALSE), GetJNIString(env, juser_input)); + ClearSelf(env, obj); +} diff --git a/lib/jcef/native/CefJSDialogCallback_N.h b/lib/jcef/native/CefJSDialogCallback_N.h new file mode 100644 index 0000000..94fdb6a --- /dev/null +++ b/lib/jcef/native/CefJSDialogCallback_N.h @@ -0,0 +1,25 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefJSDialogCallback_N */ + +#ifndef _Included_org_cef_callback_CefJSDialogCallback_N +#define _Included_org_cef_callback_CefJSDialogCallback_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefJSDialogCallback_N + * Method: N_Continue + * Signature: (JZLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefJSDialogCallback_1N_N_1Continue(JNIEnv*, + jobject, + jlong, + jboolean, + jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefMenuModel_N.cpp b/lib/jcef/native/CefMenuModel_N.cpp new file mode 100644 index 0000000..561366d --- /dev/null +++ b/lib/jcef/native/CefMenuModel_N.cpp @@ -0,0 +1,688 @@ +// 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 "CefMenuModel_N.h" + +#include "include/cef_menu_model.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +} // namespace + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1Clear(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->Clear() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetCount(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return 0; + return (jint)menuModel->GetCount(); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1AddSeparator(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->AddSeparator() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1AddItem(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id, + jstring jlabel) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->AddItem(jcommand_id, GetJNIString(env, jlabel)) ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1AddCheckItem(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id, + jstring jlabel) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->AddCheckItem(jcommand_id, GetJNIString(env, jlabel)) + ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1AddRadioItem(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id, + jstring jlabel, + jint jgroup_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->AddRadioItem(jcommand_id, GetJNIString(env, jlabel), + jgroup_id) + ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1AddSubMenu(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id, + jstring jlabel) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return nullptr; + CefRefPtr subMenu = + menuModel->AddSubMenu(jcommand_id, GetJNIString(env, jlabel)); + ScopedJNIMenuModel jmenuModel(env, subMenu); + return jmenuModel.Release(); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1InsertSeparatorAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->InsertSeparatorAt(jindex) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1InsertItemAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jint jcommand_id, + jstring jlabel) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->InsertItemAt(jindex, jcommand_id, GetJNIString(env, jlabel)) + ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1InsertCheckItemAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jint jcommand_id, + jstring jlabel) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->InsertCheckItemAt(jindex, jcommand_id, + GetJNIString(env, jlabel)) + ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1InsertRadioItemAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jint jcommand_id, + jstring jlabel, + jint jgroup_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->InsertRadioItemAt(jindex, jcommand_id, + GetJNIString(env, jlabel), jgroup_id) + ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1InsertSubMenuAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jint jcommand_id, + jstring jlabel) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return nullptr; + CefRefPtr subMenu = menuModel->InsertSubMenuAt( + jindex, jcommand_id, GetJNIString(env, jlabel)); + ScopedJNIMenuModel jmenuModel(env, subMenu); + return jmenuModel.Release(); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1Remove(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->Remove(jcommand_id) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1RemoveAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->RemoveAt(jindex) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetIndexOf(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return -1; + return menuModel->GetIndexOf(jcommand_id); +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetCommandIdAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return -1; + return menuModel->GetCommandIdAt(jindex); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetCommandIdAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetCommandIdAt(jindex, jcommand_id) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetLabel(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return nullptr; + return NewJNIString(env, menuModel->GetLabel(jcommand_id)); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetLabelAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return nullptr; + return NewJNIString(env, menuModel->GetLabelAt(jindex)); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetLabel(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id, + jstring jlabel) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetLabel(jcommand_id, GetJNIString(env, jlabel)) + ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetLabelAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jstring jlabel) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetLabelAt(jindex, GetJNIString(env, jlabel)) ? JNI_TRUE + : JNI_FALSE; +} + +jobject toJType(JNIEnv* env, CefMenuModel::MenuItemType type) { + jobject result = nullptr; + switch (type) { + JNI_CASE(env, "org/cef/callback/CefMenuModel$MenuItemType", + MENUITEMTYPE_COMMAND, result); + JNI_CASE(env, "org/cef/callback/CefMenuModel$MenuItemType", + MENUITEMTYPE_CHECK, result); + JNI_CASE(env, "org/cef/callback/CefMenuModel$MenuItemType", + MENUITEMTYPE_RADIO, result); + JNI_CASE(env, "org/cef/callback/CefMenuModel$MenuItemType", + MENUITEMTYPE_SEPARATOR, result); + JNI_CASE(env, "org/cef/callback/CefMenuModel$MenuItemType", + MENUITEMTYPE_SUBMENU, result); + default: + JNI_CASE(env, "org/cef/callback/CefMenuModel$MenuItemType", + MENUITEMTYPE_NONE, result); + } + return result; +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetType(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return toJType(env, MENUITEMTYPE_NONE); + return toJType(env, menuModel->GetType(jcommand_id)); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetTypeAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return toJType(env, MENUITEMTYPE_NONE); + return toJType(env, menuModel->GetTypeAt(jindex)); +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetGroupId(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return -1; + return menuModel->GetGroupId(jcommand_id); +} + +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetGroupIdAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return -1; + return menuModel->GetGroupIdAt(jindex); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetGroupId(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id, + jint jgroup_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetGroupId(jcommand_id, jgroup_id) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetGroupIdAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jint jgroup_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetGroupIdAt(jindex, jgroup_id) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetSubMenu(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return nullptr; + + CefRefPtr subMenu = menuModel->GetSubMenu(jcommand_id); + ScopedJNIMenuModel jmenuModel(env, subMenu); + return jmenuModel.Release(); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetSubMenuAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return nullptr; + + CefRefPtr subMenu = menuModel->GetSubMenuAt(jindex); + ScopedJNIMenuModel jmenuModel(env, subMenu); + return jmenuModel.Release(); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsVisible(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->IsVisible(jcommand_id) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsVisibleAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->IsVisibleAt(jindex) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetVisible(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id, + jboolean jvisible) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetVisible(jcommand_id, (jvisible != JNI_FALSE)) + ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetVisibleAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jboolean jvisible) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetVisibleAt(jindex, (jvisible != JNI_FALSE)) ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsEnabled(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->IsEnabled(jcommand_id) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsEnabledAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->IsEnabledAt(jindex) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetEnabled(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id, + jboolean jenabled) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetEnabled(jcommand_id, jenabled != JNI_FALSE) ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetEnabledAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jboolean jenabled) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetEnabledAt(jindex, jenabled != JNI_FALSE) ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsChecked(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->IsChecked(jcommand_id) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsCheckedAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->IsCheckedAt(jindex) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetChecked(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id, + jboolean jchecked) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetChecked(jcommand_id, (jchecked != JNI_FALSE)) + ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetCheckedAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jboolean jchecked) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetCheckedAt(jindex, (jchecked != JNI_FALSE)) ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1HasAccelerator(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->HasAccelerator(jcommand_id) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1HasAcceleratorAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->HasAcceleratorAt(jindex) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetAccelerator(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id, + jint jkey_code, + jboolean jshift_pressed, + jboolean jctrl_pressed, + jboolean jalt_pressed) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetAccelerator( + jcommand_id, jkey_code, (jshift_pressed != JNI_FALSE), + (jctrl_pressed != JNI_FALSE), (jalt_pressed != JNI_FALSE)) + ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetAcceleratorAt( + JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jint jkey_code, + jboolean jshift_pressed, + jboolean jctrl_pressed, + jboolean jalt_pressed) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->SetAcceleratorAt( + jindex, jkey_code, (jshift_pressed != JNI_FALSE), + (jctrl_pressed != JNI_FALSE), (jalt_pressed != JNI_FALSE)) + ? JNI_TRUE + : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1RemoveAccelerator(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->RemoveAccelerator(jcommand_id) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1RemoveAcceleratorAt(JNIEnv* env, + jobject obj, + jlong self, + jint jindex) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + return menuModel->RemoveAcceleratorAt(jindex) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetAccelerator(JNIEnv* env, + jobject obj, + jlong self, + jint jcommand_id, + jobject jkey_code, + jobject jshift_pressed, + jobject jctrl_pressed, + jobject jalt_pressed) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + int key_code = 0; + bool shift_pressed = false; + bool ctrl_pressed = false; + bool alt_pressed = false; + bool success = menuModel->GetAccelerator(jcommand_id, key_code, shift_pressed, + ctrl_pressed, alt_pressed); + if (!success) + return JNI_FALSE; + + SetJNIIntRef(env, jkey_code, key_code); + SetJNIBoolRef(env, jshift_pressed, shift_pressed); + SetJNIBoolRef(env, jctrl_pressed, ctrl_pressed); + SetJNIBoolRef(env, jalt_pressed, alt_pressed); + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetAcceleratorAt( + JNIEnv* env, + jobject obj, + jlong self, + jint jindex, + jobject jkey_code, + jobject jshift_pressed, + jobject jctrl_pressed, + jobject jalt_pressed) { + CefRefPtr menuModel = GetSelf(self); + if (!menuModel) + return JNI_FALSE; + int key_code = 0; + bool shift_pressed = false; + bool ctrl_pressed = false; + bool alt_pressed = false; + bool success = menuModel->GetAcceleratorAt(jindex, key_code, shift_pressed, + ctrl_pressed, alt_pressed); + if (!success) + return JNI_FALSE; + + SetJNIIntRef(env, jkey_code, key_code); + SetJNIBoolRef(env, jshift_pressed, shift_pressed); + SetJNIBoolRef(env, jctrl_pressed, ctrl_pressed); + SetJNIBoolRef(env, jalt_pressed, alt_pressed); + return JNI_TRUE; +} diff --git a/lib/jcef/native/CefMenuModel_N.h b/lib/jcef/native/CefMenuModel_N.h new file mode 100644 index 0000000..899cdbf --- /dev/null +++ b/lib/jcef/native/CefMenuModel_N.h @@ -0,0 +1,580 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefMenuModel_N */ + +#ifndef _Included_org_cef_callback_CefMenuModel_N +#define _Included_org_cef_callback_CefMenuModel_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_Clear + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1Clear(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetCount + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetCount(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_AddSeparator + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1AddSeparator(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_AddItem + * Signature: (JILjava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1AddItem(JNIEnv*, + jobject, + jlong, + jint, + jstring); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_AddCheckItem + * Signature: (JILjava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1AddCheckItem(JNIEnv*, + jobject, + jlong, + jint, + jstring); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_AddRadioItem + * Signature: (JILjava/lang/String;I)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1AddRadioItem(JNIEnv*, + jobject, + jlong, + jint, + jstring, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_AddSubMenu + * Signature: (JILjava/lang/String;)Lorg/cef/callback/CefMenuModel; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1AddSubMenu(JNIEnv*, + jobject, + jlong, + jint, + jstring); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_InsertSeparatorAt + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1InsertSeparatorAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_InsertItemAt + * Signature: (JIILjava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1InsertItemAt(JNIEnv*, + jobject, + jlong, + jint, + jint, + jstring); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_InsertCheckItemAt + * Signature: (JIILjava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1InsertCheckItemAt(JNIEnv*, + jobject, + jlong, + jint, + jint, + jstring); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_InsertRadioItemAt + * Signature: (JIILjava/lang/String;I)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1InsertRadioItemAt(JNIEnv*, + jobject, + jlong, + jint, + jint, + jstring, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_InsertSubMenuAt + * Signature: (JIILjava/lang/String;)Lorg/cef/callback/CefMenuModel; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1InsertSubMenuAt(JNIEnv*, + jobject, + jlong, + jint, + jint, + jstring); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_Remove + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1Remove(JNIEnv*, jobject, jlong, jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_RemoveAt + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1RemoveAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetIndexOf + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetIndexOf(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetCommandIdAt + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetCommandIdAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetCommandIdAt + * Signature: (JII)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetCommandIdAt(JNIEnv*, + jobject, + jlong, + jint, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetLabel + * Signature: (JI)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetLabel(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetLabelAt + * Signature: (JI)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetLabelAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetLabel + * Signature: (JILjava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetLabel(JNIEnv*, + jobject, + jlong, + jint, + jstring); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetLabelAt + * Signature: (JILjava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetLabelAt(JNIEnv*, + jobject, + jlong, + jint, + jstring); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetType + * Signature: (JI)Lorg/cef/callback/CefMenuModel/MenuItemType; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetType(JNIEnv*, jobject, jlong, jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetTypeAt + * Signature: (JI)Lorg/cef/callback/CefMenuModel/MenuItemType; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetTypeAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetGroupId + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetGroupId(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetGroupIdAt + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetGroupIdAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetGroupId + * Signature: (JII)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetGroupId(JNIEnv*, + jobject, + jlong, + jint, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetGroupIdAt + * Signature: (JII)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetGroupIdAt(JNIEnv*, + jobject, + jlong, + jint, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetSubMenu + * Signature: (JI)Lorg/cef/callback/CefMenuModel; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetSubMenu(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetSubMenuAt + * Signature: (JI)Lorg/cef/callback/CefMenuModel; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetSubMenuAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_IsVisible + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsVisible(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_IsVisibleAt + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsVisibleAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetVisible + * Signature: (JIZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetVisible(JNIEnv*, + jobject, + jlong, + jint, + jboolean); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetVisibleAt + * Signature: (JIZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetVisibleAt(JNIEnv*, + jobject, + jlong, + jint, + jboolean); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_IsEnabled + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsEnabled(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_IsEnabledAt + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsEnabledAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetEnabled + * Signature: (JIZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetEnabled(JNIEnv*, + jobject, + jlong, + jint, + jboolean); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetEnabledAt + * Signature: (JIZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetEnabledAt(JNIEnv*, + jobject, + jlong, + jint, + jboolean); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_IsChecked + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsChecked(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_IsCheckedAt + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1IsCheckedAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetChecked + * Signature: (JIZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetChecked(JNIEnv*, + jobject, + jlong, + jint, + jboolean); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetCheckedAt + * Signature: (JIZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetCheckedAt(JNIEnv*, + jobject, + jlong, + jint, + jboolean); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_HasAccelerator + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1HasAccelerator(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_HasAcceleratorAt + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1HasAcceleratorAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetAccelerator + * Signature: (JIIZZZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetAccelerator(JNIEnv*, + jobject, + jlong, + jint, + jint, + jboolean, + jboolean, + jboolean); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_SetAcceleratorAt + * Signature: (JIIZZZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1SetAcceleratorAt(JNIEnv*, + jobject, + jlong, + jint, + jint, + jboolean, + jboolean, + jboolean); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_RemoveAccelerator + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1RemoveAccelerator(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_RemoveAcceleratorAt + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1RemoveAcceleratorAt(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetAccelerator + * Signature: + * (JILorg/cef/misc/IntRef;Lorg/cef/misc/BoolRef;Lorg/cef/misc/BoolRef;Lorg/cef/misc/BoolRef;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetAccelerator(JNIEnv*, + jobject, + jlong, + jint, + jobject, + jobject, + jobject, + jobject); + +/* + * Class: org_cef_callback_CefMenuModel_N + * Method: N_GetAcceleratorAt + * Signature: + * (JILorg/cef/misc/IntRef;Lorg/cef/misc/BoolRef;Lorg/cef/misc/BoolRef;Lorg/cef/misc/BoolRef;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefMenuModel_1N_N_1GetAcceleratorAt(JNIEnv*, + jobject, + jlong, + jint, + jobject, + jobject, + jobject, + jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefMessageRouter_N.cpp b/lib/jcef/native/CefMessageRouter_N.cpp new file mode 100644 index 0000000..d8e3e3e --- /dev/null +++ b/lib/jcef/native/CefMessageRouter_N.cpp @@ -0,0 +1,137 @@ +// 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 "CefMessageRouter_N.h" + +#include "include/base/cef_callback.h" +#include "include/wrapper/cef_closure_task.h" +#include "include/wrapper/cef_message_router.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" +#include "message_router_handler.h" + +namespace { + +const char kCefClassName[] = "CefMessageRouter"; + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +CefRefPtr GetHandler(JNIEnv* env, + jobject jrouterHandler, + bool allow_create) { + ScopedJNIObject jrouterHandlerObj( + env, jrouterHandler, false /* should_delete */, + "CefMessageRouterHandler"); + return allow_create ? jrouterHandlerObj.GetOrCreateCefObject() + : jrouterHandlerObj.GetCefObject(); +} + +} // namespace + +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefMessageRouter_1N_N_1Create(JNIEnv* env, + jclass cls, + jobject jrouterConfig) { + CefMessageRouterConfig config = GetJNIMessageRouterConfig(env, jrouterConfig); + CefRefPtr msgRouter = + CefMessageRouterBrowserSide::Create(config); + ScopedJNIMessageRouter jmsgRouter(env, msgRouter); + + JNI_CALL_VOID_METHOD( + env, jmsgRouter, "setMessageRouterConfig", + "(Lorg/cef/browser/CefMessageRouter$CefMessageRouterConfig;)V", + jrouterConfig); + + return jmsgRouter.Release(); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefMessageRouter_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + SetCefForJNIObject(env, obj, nullptr, + kCefClassName); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefMessageRouter_1N_N_1AddHandler(JNIEnv* env, + jobject obj, + jlong self, + jobject jrouterHandler, + jboolean jfirst) { + CefRefPtr msgRouter = GetSelf(self); + if (!msgRouter) + return JNI_FALSE; + + CefRefPtr routerHandler = + GetHandler(env, jrouterHandler, true /* allow_create */); + + if (CefCurrentlyOn(TID_UI)) { + msgRouter->AddHandler(routerHandler.get(), (jfirst != JNI_FALSE)); + } else { + CefPostTask(TID_UI, base::BindOnce( + [](CefRefPtr msgRouter, + CefRefPtr routerHandler, + bool first) { + msgRouter->AddHandler(routerHandler.get(), first); + }, + msgRouter, routerHandler, (jfirst != JNI_FALSE))); + } + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefMessageRouter_1N_N_1RemoveHandler( + JNIEnv* env, + jobject obj, + jlong self, + jobject jrouterHandler) { + CefRefPtr msgRouter = GetSelf(self); + if (!msgRouter) + return JNI_FALSE; + + CefRefPtr routerHandler = + GetHandler(env, jrouterHandler, false /* allow_create */); + if (!routerHandler) + return JNI_FALSE; + + if (CefCurrentlyOn(TID_UI)) { + msgRouter->RemoveHandler(routerHandler.get()); + } else { + CefPostTask(TID_UI, base::BindOnce( + [](CefRefPtr msgRouter, + CefRefPtr routerHandler) { + msgRouter->RemoveHandler(routerHandler.get()); + }, + msgRouter, routerHandler)); + } + + // Remove JNI reference on jrouterhandler added by the ScopedJNIObject + SetCefForJNIObject(env, jrouterHandler, nullptr, + "CefMessageRouterHandler"); + + return JNI_TRUE; +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefMessageRouter_1N_N_1CancelPending( + JNIEnv* env, + jobject obj, + jlong self, + jobject jbrowser, + jobject jrouterHandler) { + CefRefPtr msgRouter = GetSelf(self); + if (!msgRouter) + return; + + // Browser and/or routerHandler may be null. + CefRefPtr browser = GetJNIBrowser(env, jbrowser); + CefRefPtr routerHandler = + GetHandler(env, jrouterHandler, false /* allow_create */); + + msgRouter->CancelPending(browser, routerHandler.get()); +} diff --git a/lib/jcef/native/CefMessageRouter_N.h b/lib/jcef/native/CefMessageRouter_N.h new file mode 100644 index 0000000..fe9d3a0 --- /dev/null +++ b/lib/jcef/native/CefMessageRouter_N.h @@ -0,0 +1,66 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_browser_CefMessageRouter_N */ + +#ifndef _Included_org_cef_browser_CefMessageRouter_N +#define _Included_org_cef_browser_CefMessageRouter_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_browser_CefMessageRouter_N + * Method: N_Create + * Signature: + * (Lorg/cef/browser/CefMessageRouter/CefMessageRouterConfig;)Lorg/cef/browser/CefMessageRouter_N; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefMessageRouter_1N_N_1Create(JNIEnv*, jclass, jobject); + +/* + * Class: org_cef_browser_CefMessageRouter_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefMessageRouter_1N_N_1Dispose(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_browser_CefMessageRouter_N + * Method: N_AddHandler + * Signature: (JLorg/cef/handler/CefMessageRouterHandler;Z)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefMessageRouter_1N_N_1AddHandler(JNIEnv*, + jobject, + jlong, + jobject, + jboolean); + +/* + * Class: org_cef_browser_CefMessageRouter_N + * Method: N_RemoveHandler + * Signature: (JLorg/cef/handler/CefMessageRouterHandler;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefMessageRouter_1N_N_1RemoveHandler(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_browser_CefMessageRouter_N + * Method: N_CancelPending + * Signature: + * (JLorg/cef/browser/CefBrowser;Lorg/cef/handler/CefMessageRouterHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefMessageRouter_1N_N_1CancelPending(JNIEnv*, + jobject, + jlong, + jobject, + jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefPostDataElement_N.cpp b/lib/jcef/native/CefPostDataElement_N.cpp new file mode 100644 index 0000000..414e7a5 --- /dev/null +++ b/lib/jcef/native/CefPostDataElement_N.cpp @@ -0,0 +1,145 @@ +// 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 "CefPostDataElement_N.h" + +#include "include/cef_request.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +const char kCefClassName[] = "CefPostDataElement"; + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +} // namespace + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1Create(JNIEnv* env, jclass cls) { + CefRefPtr dataElement = CefPostDataElement::Create(); + ScopedJNIPostDataElement jdataElement(env, dataElement); + return jdataElement.Release(); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + SetCefForJNIObject(env, obj, nullptr, kCefClassName); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1IsReadOnly(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dataElement = GetSelf(self); + if (!dataElement) + return JNI_FALSE; + return dataElement->IsReadOnly() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1SetToEmpty(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dataElement = GetSelf(self); + if (!dataElement) + return; + dataElement->SetToEmpty(); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1SetToFile(JNIEnv* env, + jobject obj, + jlong self, + jstring jfilename) { + CefRefPtr dataElement = GetSelf(self); + if (!dataElement) + return; + dataElement->SetToFile(GetJNIString(env, jfilename)); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1SetToBytes(JNIEnv* env, + jobject obj, + jlong self, + jint jsize, + jbyteArray jbytes) { + CefRefPtr dataElement = GetSelf(self); + if (!dataElement) + return; + + jbyte* jbyte = env->GetByteArrayElements(jbytes, nullptr); + if (!jbyte) + return; + dataElement->SetToBytes(jsize, jbyte); + env->ReleaseByteArrayElements(jbytes, jbyte, 0); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1GetType(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dataElement = GetSelf(self); + if (!dataElement) + return nullptr; + + CefPostDataElement::Type type = dataElement->GetType(); + jobject jtype = nullptr; + switch (type) { + JNI_CASE(env, "org/cef/network/CefPostDataElement$Type", PDE_TYPE_EMPTY, + jtype); + JNI_CASE(env, "org/cef/network/CefPostDataElement$Type", PDE_TYPE_BYTES, + 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; +} + +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1GetFile(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dataElement = GetSelf(self); + if (!dataElement) + return nullptr; + return NewJNIString(env, dataElement->GetFile()); +} + +JNIEXPORT jint JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1GetBytesCount(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr dataElement = GetSelf(self); + if (!dataElement) + return 0; + return (jint)dataElement->GetBytesCount(); +} + +JNIEXPORT jint JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1GetBytes(JNIEnv* env, + jobject obj, + jlong self, + jint jsize, + jbyteArray jbytes) { + CefRefPtr dataElement = GetSelf(self); + if (!dataElement) + return 0; + + jbyte* jbyte = env->GetByteArrayElements(jbytes, nullptr); + if (!jbyte) + return 0; + memset(jbyte, 0, jsize); + + size_t readLen = dataElement->GetBytes(jsize, jbyte); + env->ReleaseByteArrayElements(jbytes, jbyte, 0); + return (jint)readLen; +} diff --git a/lib/jcef/native/CefPostDataElement_N.h b/lib/jcef/native/CefPostDataElement_N.h new file mode 100644 index 0000000..a58109e --- /dev/null +++ b/lib/jcef/native/CefPostDataElement_N.h @@ -0,0 +1,110 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_network_CefPostDataElement_N */ + +#ifndef _Included_org_cef_network_CefPostDataElement_N +#define _Included_org_cef_network_CefPostDataElement_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_network_CefPostDataElement_N + * Method: N_Create + * Signature: ()Lorg/cef/network/CefPostDataElement_N; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1Create(JNIEnv*, jclass); + +/* + * Class: org_cef_network_CefPostDataElement_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1Dispose(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefPostDataElement_N + * Method: N_IsReadOnly + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1IsReadOnly(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefPostDataElement_N + * Method: N_SetToEmpty + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1SetToEmpty(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefPostDataElement_N + * Method: N_SetToFile + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1SetToFile(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_network_CefPostDataElement_N + * Method: N_SetToBytes + * Signature: (JI[B)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1SetToBytes(JNIEnv*, + jobject, + jlong, + jint, + jbyteArray); + +/* + * Class: org_cef_network_CefPostDataElement_N + * Method: N_GetType + * Signature: (J)Lorg/cef/network/CefPostDataElement/Type; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1GetType(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefPostDataElement_N + * Method: N_GetFile + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1GetFile(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefPostDataElement_N + * Method: N_GetBytesCount + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1GetBytesCount(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefPostDataElement_N + * Method: N_GetBytes + * Signature: (JI[B)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_network_CefPostDataElement_1N_N_1GetBytes(JNIEnv*, + jobject, + jlong, + jint, + jbyteArray); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefPostData_N.cpp b/lib/jcef/native/CefPostData_N.cpp new file mode 100644 index 0000000..cea7a22 --- /dev/null +++ b/lib/jcef/native/CefPostData_N.cpp @@ -0,0 +1,121 @@ +// 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 "CefPostData_N.h" + +#include "include/cef_request.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +const char kCefClassName[] = "CefPostData"; + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +} // namespace + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefPostData_1N_N_1Create(JNIEnv* env, jclass cls) { + CefRefPtr postData = CefPostData::Create(); + ScopedJNIPostData jpostData(env, postData); + return jpostData.Release(); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostData_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + SetCefForJNIObject(env, obj, nullptr, kCefClassName); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefPostData_1N_N_1IsReadOnly(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr postData = GetSelf(self); + if (!postData) + return JNI_FALSE; + return postData->IsReadOnly() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jint JNICALL +Java_org_cef_network_CefPostData_1N_N_1GetElementCount(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr postData = GetSelf(self); + if (!postData) + return 0; + return (jint)postData->GetElementCount(); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostData_1N_N_1GetElements(JNIEnv* env, + jobject obj, + jlong self, + jobject jelements) { + CefRefPtr postData = GetSelf(self); + if (!postData) + return; + CefPostData::ElementVector elements; + postData->GetElements(elements); + + CefPostData::ElementVector::const_iterator iter; + for (iter = elements.begin(); iter != elements.end(); ++iter) { + ScopedJNIPostDataElement jdataElement(env, *iter); + JNI_CALL_VOID_METHOD(env, jelements, "addElement", "(Ljava/lang/Object;)V", + jdataElement.get()); + } +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefPostData_1N_N_1RemoveElement(JNIEnv* env, + jobject obj, + jlong self, + jobject jelement) { + CefRefPtr postData = GetSelf(self); + if (!postData) + return JNI_FALSE; + + ScopedJNIPostDataElement dataElementObj(env); + dataElementObj.SetHandle(jelement, false /* should_delete */); + + CefRefPtr dataElement = dataElementObj.GetCefObject(); + if (!dataElement) + return JNI_FALSE; + + return postData->RemoveElement(dataElement) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefPostData_1N_N_1AddElement(JNIEnv* env, + jobject obj, + jlong self, + jobject jelement) { + CefRefPtr postData = GetSelf(self); + if (!postData) + return JNI_FALSE; + + ScopedJNIPostDataElement dataElementObj(env); + dataElementObj.SetHandle(jelement, false /* should_delete */); + + CefRefPtr dataElement = dataElementObj.GetCefObject(); + if (!dataElement) + return JNI_FALSE; + + return postData->AddElement(dataElement) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostData_1N_N_1RemoveElements(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr postData = GetSelf(self); + if (!postData) + return; + postData->RemoveElements(); +} diff --git a/lib/jcef/native/CefPostData_N.h b/lib/jcef/native/CefPostData_N.h new file mode 100644 index 0000000..f0bbd26 --- /dev/null +++ b/lib/jcef/native/CefPostData_N.h @@ -0,0 +1,87 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_network_CefPostData_N */ + +#ifndef _Included_org_cef_network_CefPostData_N +#define _Included_org_cef_network_CefPostData_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_network_CefPostData_N + * Method: N_Create + * Signature: ()Lorg/cef/network/CefPostData_N; + */ +JNIEXPORT jobject JNICALL Java_org_cef_network_CefPostData_1N_N_1Create(JNIEnv*, + jclass); + +/* + * Class: org_cef_network_CefPostData_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefPostData_1N_N_1Dispose(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefPostData_N + * Method: N_IsReadOnly + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefPostData_1N_N_1IsReadOnly(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefPostData_N + * Method: N_GetElementCount + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_network_CefPostData_1N_N_1GetElementCount(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefPostData_N + * Method: N_GetElements + * Signature: (JLjava/util/Vector;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostData_1N_N_1GetElements(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_network_CefPostData_N + * Method: N_RemoveElement + * Signature: (JLorg/cef/network/CefPostDataElement;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefPostData_1N_N_1RemoveElement(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_network_CefPostData_N + * Method: N_AddElement + * Signature: (JLorg/cef/network/CefPostDataElement;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefPostData_1N_N_1AddElement(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_network_CefPostData_N + * Method: N_RemoveElements + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefPostData_1N_N_1RemoveElements(JNIEnv*, jobject, jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefPrintDialogCallback_N.cpp b/lib/jcef/native/CefPrintDialogCallback_N.cpp new file mode 100644 index 0000000..eb50677 --- /dev/null +++ b/lib/jcef/native/CefPrintDialogCallback_N.cpp @@ -0,0 +1,52 @@ +// 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 "CefPrintDialogCallback_N.h" +#include "include/cef_print_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 PrintHandler::OnPrintDialog. + SetCefForJNIObject(env, obj, nullptr, + "CefPrintDialogCallback"); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefPrintDialogCallback_1N_N_1Continue( + JNIEnv* env, + jobject obj, + jlong self, + jobject jprintsettings) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + + CefRefPtr settings = GetCefFromJNIObject( + env, jprintsettings, "CefPrintSettings"); + if (settings) { + callback->Continue(settings); + } else { + callback->Cancel(); + } + ClearSelf(env, obj); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefPrintDialogCallback_1N_N_1Cancel(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Cancel(); + ClearSelf(env, obj); +} diff --git a/lib/jcef/native/CefPrintDialogCallback_N.h b/lib/jcef/native/CefPrintDialogCallback_N.h new file mode 100644 index 0000000..20d5243 --- /dev/null +++ b/lib/jcef/native/CefPrintDialogCallback_N.h @@ -0,0 +1,34 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefPrintDialogCallback_N */ + +#ifndef _Included_org_cef_callback_CefPrintDialogCallback_N +#define _Included_org_cef_callback_CefPrintDialogCallback_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefPrintDialogCallback_N + * Method: N_Continue + * Signature: (JLorg/cef/misc/CefPrintSettings;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefPrintDialogCallback_1N_N_1Continue(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_callback_CefPrintDialogCallback_N + * Method: N_Cancel + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefPrintDialogCallback_1N_N_1Cancel(JNIEnv*, + jobject, + jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefPrintJobCallback_N.cpp b/lib/jcef/native/CefPrintJobCallback_N.cpp new file mode 100644 index 0000000..e19c1fe --- /dev/null +++ b/lib/jcef/native/CefPrintJobCallback_N.cpp @@ -0,0 +1,33 @@ +// 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 "CefPrintJobCallback_N.h" +#include "jni_scoped_helpers.h" + +#include "include/cef_print_handler.h" + +namespace { + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +void ClearSelf(JNIEnv* env, jobject obj) { + // Clear the reference added in PrintJobHandler::OnPrintJob. + SetCefForJNIObject(env, obj, nullptr, + "CefPrintJobCallback"); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefPrintJobCallback_1N_N_1Continue(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Continue(); + ClearSelf(env, obj); +} diff --git a/lib/jcef/native/CefPrintJobCallback_N.h b/lib/jcef/native/CefPrintJobCallback_N.h new file mode 100644 index 0000000..dda0381 --- /dev/null +++ b/lib/jcef/native/CefPrintJobCallback_N.h @@ -0,0 +1,23 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefPrintJobCallback_N */ + +#ifndef _Included_org_cef_callback_CefPrintJobCallback_N +#define _Included_org_cef_callback_CefPrintJobCallback_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefPrintJobCallback_N + * Method: N_Continue + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefPrintJobCallback_1N_N_1Continue(JNIEnv*, + jobject, + jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefPrintSettings_N.cpp b/lib/jcef/native/CefPrintSettings_N.cpp new file mode 100644 index 0000000..b340c9b --- /dev/null +++ b/lib/jcef/native/CefPrintSettings_N.cpp @@ -0,0 +1,492 @@ +// 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 "CefPrintSettings_N.h" + +#include "include/cef_print_handler.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +const char kCefClassName[] = "CefPrintSettings"; + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +// Retrieve the CefPageRange equivalent of a org.cef.misc.CefPageRange +CefRange GetJNIPageRange(JNIEnv* env, jobject obj) { + CefRange range; + + ScopedJNIClass cls(env, "org/cef/misc/CefPageRange"); + if (!cls) + return range; + + int from, to; + if (GetJNIFieldInt(env, cls, obj, "from", &from) && + GetJNIFieldInt(env, cls, obj, "to", &to)) { + range.Set(from, to); + } + return range; +} + +// Create a new org.cef.misc.CefPageRange +jobject NewJNIPageRange(JNIEnv* env, const CefRange& range) { + ScopedJNIClass cls(env, "org/cef/misc/CefPageRange"); + if (!cls) + return nullptr; + + ScopedJNIObjectLocal obj(env, NewJNIObject(env, cls)); + if (!obj) + return nullptr; + + if (SetJNIFieldInt(env, cls, obj, "from", range.from) && + SetJNIFieldInt(env, cls, obj, "to", range.to)) { + return obj.Release(); + } + + return nullptr; +} + +} // namespace + +JNIEXPORT jobject JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1Create(JNIEnv* env, jclass cls) { + CefRefPtr settings = CefPrintSettings::Create(); + ScopedJNIPrintSettings jsettings(env, settings); + return jsettings.Release(); +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + SetCefForJNIObject(env, obj, nullptr, kCefClassName); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1IsValid(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return JNI_FALSE; + return settings->IsValid() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1IsReadOnly(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return JNI_FALSE; + return settings->IsReadOnly() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetOrientation(JNIEnv* env, + jobject obj, + jlong self, + jboolean jlandscape) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return; + settings->SetOrientation(jlandscape != JNI_FALSE); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1IsLandscape(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return JNI_FALSE; + return settings->IsLandscape() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetPrinterPrintableArea( + JNIEnv* env, + jobject obj, + jlong self, + jobject jphysical_size_device_units, + jobject jprintable_area_device_units, + jboolean jlandscape_needs_flip) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return; + + CefSize physical_size = GetJNISize(env, jphysical_size_device_units); + CefRect printable_area = GetJNIRect(env, jprintable_area_device_units); + bool needs_flip = jlandscape_needs_flip != JNI_FALSE; + settings->SetPrinterPrintableArea(physical_size, printable_area, needs_flip); +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetDeviceName(JNIEnv* env, + jobject obj, + jlong self, + jstring jname) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return; + settings->SetDeviceName(GetJNIString(env, jname)); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetDeviceName(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return nullptr; + return NewJNIString(env, settings->GetDeviceName()); +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetDPI(JNIEnv* env, + jobject obj, + jlong self, + jint jdpi) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return; + settings->SetDPI((int)jdpi); +} + +JNIEXPORT jint JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetDPI(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return 0; + return (jint)settings->GetDPI(); +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetPageRanges(JNIEnv* env, + jobject obj, + jlong self, + jobject jrangeVector) { + CefRefPtr settings = GetSelf(self); + if (!settings || !jrangeVector) + return; + + CefPrintSettings::PageRangeList rangeList; + jint jsize = 0; + JNI_CALL_METHOD(env, jrangeVector, "size", "()I", Int, jsize); + for (jint index = 0; index < jsize; index++) { + ScopedJNIObjectResult jresult(env); + JNI_CALL_METHOD(env, jrangeVector, "get", "(I)Ljava/lang/Object;", Object, + jresult, index); + if (!jresult) + continue; + rangeList.push_back(GetJNIPageRange(env, jresult)); + } + settings->SetPageRanges(rangeList); +} + +JNIEXPORT jint JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetPageRangesCount(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return 0; + return (jint)settings->GetPageRangesCount(); +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetPageRanges(JNIEnv* env, + jobject obj, + jlong self, + jobject jrangeVector) { + CefRefPtr settings = GetSelf(self); + if (!settings || !jrangeVector) + return; + + CefPrintSettings::PageRangeList rangeList; + settings->GetPageRanges(rangeList); + + CefPrintSettings::PageRangeList::size_type i = 0; + for (i = 0; i < rangeList.size(); ++i) { + ScopedJNIObjectLocal jrange(env, NewJNIPageRange(env, rangeList.at(i))); + JNI_CALL_VOID_METHOD(env, jrangeVector, "addElement", + "(Ljava/lang/Object;)V", jrange.get()); + } +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetSelectionOnly( + JNIEnv* env, + jobject obj, + jlong self, + jboolean jselection_only) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return; + settings->SetSelectionOnly(jselection_only != JNI_FALSE); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1IsSelectionOnly(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return JNI_FALSE; + return settings->IsSelectionOnly() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetCollate(JNIEnv* env, + jobject obj, + jlong self, + jboolean jcollate) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return; + settings->SetCollate(jcollate != JNI_FALSE); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1WillCollate(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return JNI_FALSE; + return settings->WillCollate() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetColorModel(JNIEnv* env, + jobject obj, + jlong self, + jobject jcolor_model) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return; + CefPrintSettings::ColorModel mode; + if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_GRAY")) { + mode = COLOR_MODEL_GRAY; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_COLOR")) { + mode = COLOR_MODEL_COLOR; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_CMYK")) { + mode = COLOR_MODEL_CMYK; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_CMY")) { + mode = COLOR_MODEL_CMY; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_KCMY")) { + mode = COLOR_MODEL_KCMY; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_CMY_K")) { + mode = COLOR_MODEL_CMY_K; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_BLACK")) { + mode = COLOR_MODEL_BLACK; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_GRAYSCALE")) { + mode = COLOR_MODEL_GRAYSCALE; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_RGB")) { + mode = COLOR_MODEL_RGB; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_RGB16")) { + mode = COLOR_MODEL_RGB16; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_RGBA")) { + mode = COLOR_MODEL_RGBA; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_COLORMODE_COLOR")) { + mode = COLOR_MODEL_COLORMODE_COLOR; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_COLORMODE_MONOCHROME")) { + mode = COLOR_MODEL_COLORMODE_MONOCHROME; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_HP_COLOR_COLOR")) { + mode = COLOR_MODEL_HP_COLOR_COLOR; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_HP_COLOR_BLACK")) { + mode = COLOR_MODEL_HP_COLOR_BLACK; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_PRINTOUTMODE_NORMAL")) { + mode = COLOR_MODEL_PRINTOUTMODE_NORMAL; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_PRINTOUTMODE_NORMAL_GRAY")) { + mode = COLOR_MODEL_PRINTOUTMODE_NORMAL_GRAY; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_PROCESSCOLORMODEL_CMYK")) { + mode = COLOR_MODEL_PROCESSCOLORMODEL_CMYK; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_PROCESSCOLORMODEL_GREYSCALE")) { + mode = COLOR_MODEL_PROCESSCOLORMODEL_GREYSCALE; + } else if (IsJNIEnumValue(env, jcolor_model, + "org/cef/misc/CefPrintSettings$ColorModel", + "COLOR_MODEL_PROCESSCOLORMODEL_RGB")) { + mode = COLOR_MODEL_PROCESSCOLORMODEL_RGB; + } else { + mode = COLOR_MODEL_UNKNOWN; + } + settings->SetColorModel(mode); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetColorModel(JNIEnv* env, + jobject obj, + jlong self) { + jobject result = GetJNIEnumValue( + env, "org/cef/misc/CefPrintSettings$ColorModel", "COLOR_MODEL_UNKNOWN"); + + CefRefPtr settings = GetSelf(self); + if (!settings) + return result; + + switch (settings->GetColorModel()) { + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", COLOR_MODEL_GRAY, + result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", COLOR_MODEL_COLOR, + result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", COLOR_MODEL_CMYK, + result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", COLOR_MODEL_CMY, + result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", COLOR_MODEL_KCMY, + result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", COLOR_MODEL_CMY_K, + result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", COLOR_MODEL_BLACK, + result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", + COLOR_MODEL_GRAYSCALE, result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", COLOR_MODEL_RGB, + result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", COLOR_MODEL_RGB16, + result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", COLOR_MODEL_RGBA, + result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", + COLOR_MODEL_COLORMODE_COLOR, result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", + COLOR_MODEL_COLORMODE_MONOCHROME, result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", + COLOR_MODEL_HP_COLOR_COLOR, result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", + COLOR_MODEL_HP_COLOR_BLACK, result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", + COLOR_MODEL_PRINTOUTMODE_NORMAL, result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", + COLOR_MODEL_PRINTOUTMODE_NORMAL_GRAY, result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", + COLOR_MODEL_PROCESSCOLORMODEL_CMYK, result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", + COLOR_MODEL_PROCESSCOLORMODEL_GREYSCALE, result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", + COLOR_MODEL_PROCESSCOLORMODEL_RGB, result); + default: + JNI_CASE(env, "org/cef/misc/CefPrintSettings$ColorModel", + COLOR_MODEL_UNKNOWN, result); + } + return result; +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetCopies(JNIEnv* env, + jobject obj, + jlong self, + jint jcopies) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return; + settings->SetCopies((int)jcopies); +} + +JNIEXPORT jint JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetCopies(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return 0; + return (jint)settings->GetCopies(); +} + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetDuplexMode(JNIEnv* env, + jobject obj, + jlong self, + jobject jduplex_mode) { + CefRefPtr settings = GetSelf(self); + if (!settings) + return; + CefPrintSettings::DuplexMode mode; + if (IsJNIEnumValue(env, jduplex_mode, + "org/cef/misc/CefPrintSettings$DuplexMode", + "DUPLEX_MODE_SIMPLEX")) { + mode = DUPLEX_MODE_SIMPLEX; + } else if (IsJNIEnumValue(env, jduplex_mode, + "org/cef/misc/CefPrintSettings$DuplexMode", + "DUPLEX_MODE_LONG_EDGE")) { + mode = DUPLEX_MODE_LONG_EDGE; + } else if (IsJNIEnumValue(env, jduplex_mode, + "org/cef/misc/CefPrintSettings$DuplexMode", + "DUPLEX_MODE_SHORT_EDGE")) { + mode = DUPLEX_MODE_SHORT_EDGE; + } else { + mode = DUPLEX_MODE_UNKNOWN; + } + settings->SetDuplexMode(mode); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetDuplexMode(JNIEnv* env, + jobject obj, + jlong self) { + jobject result = GetJNIEnumValue( + env, "org/cef/misc/CefPrintSettings$DuplexMode", "DUPLEX_MODE_UNKNOWN"); + + CefRefPtr settings = GetSelf(self); + if (!settings) + return result; + + switch (settings->GetDuplexMode()) { + JNI_CASE(env, "org/cef/misc/CefPrintSettings$DuplexMode", + DUPLEX_MODE_SIMPLEX, result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$DuplexMode", + DUPLEX_MODE_LONG_EDGE, result); + JNI_CASE(env, "org/cef/misc/CefPrintSettings$DuplexMode", + DUPLEX_MODE_SHORT_EDGE, result); + default: + JNI_CASE(env, "org/cef/misc/CefPrintSettings$DuplexMode", + DUPLEX_MODE_UNKNOWN, result); + } + return result; +} diff --git a/lib/jcef/native/CefPrintSettings_N.h b/lib/jcef/native/CefPrintSettings_N.h new file mode 100644 index 0000000..64c07be --- /dev/null +++ b/lib/jcef/native/CefPrintSettings_N.h @@ -0,0 +1,245 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_misc_CefPrintSettings_N */ + +#ifndef _Included_org_cef_misc_CefPrintSettings_N +#define _Included_org_cef_misc_CefPrintSettings_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_Create + * Signature: ()Lorg/cef/misc/CefPrintSettings_N; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1Create(JNIEnv*, jclass); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_misc_CefPrintSettings_1N_N_1Dispose(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_IsValid + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1IsValid(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_IsReadOnly + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1IsReadOnly(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_SetOrientation + * Signature: (JZ)V + */ +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetOrientation(JNIEnv*, + jobject, + jlong, + jboolean); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_IsLandscape + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1IsLandscape(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_SetPrinterPrintableArea + * Signature: (JLjava/awt/Dimension;Ljava/awt/Rectangle;Z)V + */ +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetPrinterPrintableArea(JNIEnv*, + jobject, + jlong, + jobject, + jobject, + jboolean); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_SetDeviceName + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetDeviceName(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_GetDeviceName + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetDeviceName(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_SetDPI + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_cef_misc_CefPrintSettings_1N_N_1SetDPI(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_GetDPI + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_cef_misc_CefPrintSettings_1N_N_1GetDPI(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_SetPageRanges + * Signature: (JLjava/util/Vector;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetPageRanges(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_GetPageRangesCount + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetPageRangesCount(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_GetPageRanges + * Signature: (JLjava/util/Vector;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetPageRanges(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_SetSelectionOnly + * Signature: (JZ)V + */ +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetSelectionOnly(JNIEnv*, + jobject, + jlong, + jboolean); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_IsSelectionOnly + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1IsSelectionOnly(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_SetCollate + * Signature: (JZ)V + */ +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetCollate(JNIEnv*, + jobject, + jlong, + jboolean); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_WillCollate + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1WillCollate(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_SetColorModel + * Signature: (JLorg/cef/misc/CefPrintSettings/ColorModel;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetColorModel(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_GetColorModel + * Signature: (J)Lorg/cef/misc/CefPrintSettings/ColorModel; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetColorModel(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_SetCopies + * Signature: (JI)V + */ +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetCopies(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_GetCopies + * Signature: (J)I + */ +JNIEXPORT jint JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetCopies(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_SetDuplexMode + * Signature: (JLorg/cef/misc/CefPrintSettings/DuplexMode;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1SetDuplexMode(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_misc_CefPrintSettings_N + * Method: N_GetDuplexMode + * Signature: (J)Lorg/cef/misc/CefPrintSettings/DuplexMode; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_misc_CefPrintSettings_1N_N_1GetDuplexMode(JNIEnv*, jobject, jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefQueryCallback_N.cpp b/lib/jcef/native/CefQueryCallback_N.cpp new file mode 100644 index 0000000..017ff1a --- /dev/null +++ b/lib/jcef/native/CefQueryCallback_N.cpp @@ -0,0 +1,48 @@ +// 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 "CefQueryCallback_N.h" +#include "include/wrapper/cef_message_router.h" +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +using CefQueryCallback = CefMessageRouterBrowserSide::Callback; + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +void ClearSelf(JNIEnv* env, jobject obj) { + // Clear the reference added in ClientHandler::OnQuery. + SetCefForJNIObject(env, obj, nullptr, "CefQueryCallback"); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefQueryCallback_1N_N_1Success(JNIEnv* env, + jobject obj, + jlong self, + jstring response) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Success(GetJNIString(env, response)); + ClearSelf(env, obj); +} + +JNIEXPORT void JNICALL +Java_org_cef_callback_CefQueryCallback_1N_N_1Failure(JNIEnv* env, + jobject obj, + jlong self, + jint error_code, + jstring error_message) { + CefRefPtr callback = GetSelf(self); + if (!callback) + return; + callback->Failure(error_code, GetJNIString(env, error_message)); + ClearSelf(env, obj); +} diff --git a/lib/jcef/native/CefQueryCallback_N.h b/lib/jcef/native/CefQueryCallback_N.h new file mode 100644 index 0000000..f6ba930 --- /dev/null +++ b/lib/jcef/native/CefQueryCallback_N.h @@ -0,0 +1,36 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefQueryCallback_N */ + +#ifndef _Included_org_cef_callback_CefQueryCallback_N +#define _Included_org_cef_callback_CefQueryCallback_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefQueryCallback_N + * Method: N_Success + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefQueryCallback_1N_N_1Success(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_callback_CefQueryCallback_N + * Method: N_Failure + * Signature: (JILjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_callback_CefQueryCallback_1N_N_1Failure(JNIEnv*, + jobject, + jlong, + jint, + jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefRegistration_N.cpp b/lib/jcef/native/CefRegistration_N.cpp new file mode 100644 index 0000000..dc23751 --- /dev/null +++ b/lib/jcef/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/lib/jcef/native/CefRegistration_N.h b/lib/jcef/native/CefRegistration_N.h new file mode 100644 index 0000000..9747b04 --- /dev/null +++ b/lib/jcef/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/lib/jcef/native/CefRequestContext_N.cpp b/lib/jcef/native/CefRequestContext_N.cpp new file mode 100644 index 0000000..db6b2dd --- /dev/null +++ b/lib/jcef/native/CefRequestContext_N.cpp @@ -0,0 +1,162 @@ +// 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 "CefRequestContext_N.h" +#include "include/cef_request_context.h" +#include "jni_util.h" +#include "request_context_handler.h" + +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1GetGlobalContext(JNIEnv* env, + jclass cls) { + CefRefPtr context = CefRequestContext::GetGlobalContext(); + if (!context.get()) + return nullptr; + + ScopedJNIObjectLocal jContext(env, NewJNIObject(env, cls)); + if (!jContext) + return nullptr; + + SetCefForJNIObject(env, jContext, context.get(), "CefRequestContext"); + return jContext.Release(); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1CreateContext(JNIEnv* env, + jclass cls, + jobject jhandler) { + CefRefPtr handler = nullptr; + if (jhandler != nullptr) { + handler = new RequestContextHandler(env, jhandler); + } + + // TODO(JCEF): Expose CefRequestContextSettings. + CefRequestContextSettings settings; + CefRefPtr context = + CefRequestContext::CreateContext(settings, handler); + if (!context.get()) + return nullptr; + + ScopedJNIObjectLocal jContext(env, NewJNIObject(env, cls)); + if (!jContext) + return nullptr; + + SetCefForJNIObject(env, jContext, context.get(), "CefRequestContext"); + return jContext.Release(); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1IsGlobal(JNIEnv* env, + jobject obj) { + CefRefPtr context = + GetCefFromJNIObject(env, obj, "CefRequestContext"); + if (!context.get()) + return JNI_FALSE; + 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, + jobject obj) { + SetCefForJNIObject(env, obj, nullptr, "CefRequestContext"); +} diff --git a/lib/jcef/native/CefRequestContext_N.h b/lib/jcef/native/CefRequestContext_N.h new file mode 100644 index 0000000..407cc77 --- /dev/null +++ b/lib/jcef/native/CefRequestContext_N.h @@ -0,0 +1,100 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_browser_CefRequestContext_N */ + +#ifndef _Included_org_cef_browser_CefRequestContext_N +#define _Included_org_cef_browser_CefRequestContext_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_browser_CefRequestContext_N + * Method: N_GetGlobalContext + * Signature: ()Lorg/cef/browser/CefRequestContext_N; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1GetGlobalContext(JNIEnv*, jclass); + +/* + * Class: org_cef_browser_CefRequestContext_N + * Method: N_CreateContext + * Signature: + * (Lorg/cef/handler/CefRequestContextHandler;)Lorg/cef/browser/CefRequestContext_N; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1CreateContext(JNIEnv*, + jclass, + jobject); + +/* + * Class: org_cef_browser_CefRequestContext_N + * Method: N_IsGlobal + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1IsGlobal(JNIEnv*, jobject); + +/* + * Class: org_cef_browser_CefRequestContext_N + * Method: N_HasPreference + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1HasPreference(JNIEnv*, + jobject, + jstring); + +/* + * Class: org_cef_browser_CefRequestContext_N + * Method: N_GetPreference + * Signature: (Ljava/lang/String;)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1GetPreference(JNIEnv*, + jobject, + jstring); + +/* + * Class: org_cef_browser_CefRequestContext_N + * Method: N_GetAllPreferences + * Signature: (Z)Ljava/util/Map; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1GetAllPreferences(JNIEnv*, + jobject, + jboolean); + +/* + * Class: org_cef_browser_CefRequestContext_N + * Method: N_CanSetPreference + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1CanSetPreference(JNIEnv*, + jobject, + jstring); + +/* + * Class: org_cef_browser_CefRequestContext_N + * Method: N_SetPreference + * Signature: (Ljava/lang/String;Ljava/lang/Object;Lorg/cef;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1SetPreference(JNIEnv*, + jobject, + jstring, + jobject); + +/* + * Class: org_cef_browser_CefRequestContext_N + * Method: N_CefRequestContext_DTOR + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefRequestContext_1N_N_1CefRequestContext_1DTOR(JNIEnv*, + jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefRequest_N.cpp b/lib/jcef/native/CefRequest_N.cpp new file mode 100644 index 0000000..626a76e --- /dev/null +++ b/lib/jcef/native/CefRequest_N.cpp @@ -0,0 +1,417 @@ +// 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 "CefRequest_N.h" +#include "include/cef_request.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +const char kCefClassName[] = "CefRequest"; + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +} // namespace + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefRequest_1N_N_1Create(JNIEnv* env, jclass cls) { + CefRefPtr request = CefRequest::Create(); + ScopedJNIRequest jrequest(env, request); + return jrequest.Release(); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + SetCefForJNIObject(env, obj, nullptr, kCefClassName); +} + +JNIEXPORT jlong JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetIdentifier(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr request = GetSelf(self); + if (!request) + return 0; + return (jlong)request->GetIdentifier(); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefRequest_1N_N_1IsReadOnly(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr request = GetSelf(self); + if (!request) + return JNI_FALSE; + return request->IsReadOnly() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetURL(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr request = GetSelf(self); + if (!request) + return nullptr; + return NewJNIString(env, request->GetURL()); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetURL(JNIEnv* env, + jobject obj, + jlong self, + jstring jurl) { + CefRefPtr request = GetSelf(self); + if (!request) + return; + request->SetURL(GetJNIString(env, jurl)); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetReferrer(JNIEnv* env, + jobject obj, + jlong self, + jstring jurl, + jobject jpolicy) { + CefRefPtr request = GetSelf(self); + if (!request) + return; + + cef_referrer_policy_t policy = REFERRER_POLICY_DEFAULT; + if (jpolicy != nullptr) { + if (IsJNIEnumValue(env, jpolicy, + "org/cef/network/CefRequest$ReferrerPolicy", + "REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_FROM_" + "SECURE_TO_INSECURE")) { + policy = + REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE; + } else if (IsJNIEnumValue(env, jpolicy, + "org/cef/network/CefRequest$ReferrerPolicy", + "REFERRER_POLICY_REDUCE_REFERRER_GRANULARITY_ON_" + "TRANSITION_CROSS_ORIGIN")) { + policy = + REFERRER_POLICY_REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN; + } else if (IsJNIEnumValue( + env, jpolicy, "org/cef/network/CefRequest$ReferrerPolicy", + "REFERRER_POLICY_ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN")) { + policy = REFERRER_POLICY_ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN; + } else if (IsJNIEnumValue(env, jpolicy, + "org/cef/network/CefRequest$ReferrerPolicy", + "REFERRER_POLICY_NEVER_CLEAR_REFERRER")) { + policy = REFERRER_POLICY_NEVER_CLEAR_REFERRER; + } else if (IsJNIEnumValue(env, jpolicy, + "org/cef/network/CefRequest$ReferrerPolicy", + "REFERRER_POLICY_ORIGIN")) { + policy = REFERRER_POLICY_ORIGIN; + } else if (IsJNIEnumValue(env, jpolicy, + "org/cef/network/CefRequest$ReferrerPolicy", + "REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_" + "CROSS_ORIGIN")) { + policy = REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN; + } else if (IsJNIEnumValue(env, jpolicy, + "org/cef/network/CefRequest$ReferrerPolicy", + "REFERRER_POLICY_ORIGIN_CLEAR_ON_TRANSITION_FROM_" + "SECURE_TO_INSECURE")) { + policy = + REFERRER_POLICY_ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE; + } else if (IsJNIEnumValue(env, jpolicy, + "org/cef/network/CefRequest$ReferrerPolicy", + "REFERRER_POLICY_NO_REFERRER")) { + policy = REFERRER_POLICY_NO_REFERRER; + } else if (IsJNIEnumValue(env, jpolicy, + "org/cef/network/CefRequest$ReferrerPolicy", + "REFERRER_POLICY_NUM_VALUES")) { + policy = REFERRER_POLICY_NUM_VALUES; + } + } + + request->SetReferrer(GetJNIString(env, jurl), policy); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetReferrerURL(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr request = GetSelf(self); + if (!request) + return nullptr; + + return NewJNIString(env, request->GetReferrerURL()); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetReferrerPolicy(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr request = GetSelf(self); + if (!request) + return nullptr; + + jobject result = nullptr; + CefRequest::ReferrerPolicy rp = request->GetReferrerPolicy(); + switch (rp) { + default: + // same as + // REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE + JNI_CASE(env, "org/cef/network/CefRequest$ReferrerPolicy", + REFERRER_POLICY_DEFAULT, result); + JNI_CASE( + env, "org/cef/network/CefRequest$ReferrerPolicy", + REFERRER_POLICY_REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ReferrerPolicy", + REFERRER_POLICY_ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, result); + JNI_CASE(env, "org/cef/network/CefRequest$ReferrerPolicy", + REFERRER_POLICY_NEVER_CLEAR_REFERRER, result); + JNI_CASE(env, "org/cef/network/CefRequest$ReferrerPolicy", + REFERRER_POLICY_ORIGIN, result); + JNI_CASE(env, "org/cef/network/CefRequest$ReferrerPolicy", + REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN, + result); + JNI_CASE( + env, "org/cef/network/CefRequest$ReferrerPolicy", + REFERRER_POLICY_ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ReferrerPolicy", + REFERRER_POLICY_NO_REFERRER, result); + // REFERRER_POLICY_LAST_VALUE equals REFERRER_POLICY_NO_REFERRER as of CEF + // 3683 + } + return result; +} + +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetMethod(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr request = GetSelf(self); + if (!request) + return nullptr; + return NewJNIString(env, request->GetMethod()); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetMethod(JNIEnv* env, + jobject obj, + jlong self, + jstring jmethod) { + CefRefPtr request = GetSelf(self); + if (!request) + return; + request->SetMethod(GetJNIString(env, jmethod)); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetPostData(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr request = GetSelf(self); + if (!request) + return nullptr; + CefRefPtr postData = request->GetPostData(); + if (!postData.get()) + return nullptr; + ScopedJNIPostData jpostData(env, postData); + return jpostData.Release(); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetPostData(JNIEnv* env, + jobject obj, + jlong self, + jobject jpostData) { + CefRefPtr request = GetSelf(self); + if (!request) + return; + ScopedJNIPostData postDataObj(env); + if (jpostData) { + postDataObj.SetHandle(jpostData, false /* should_delete */); + } + request->SetPostData(postDataObj.GetCefObject()); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetHeaderByName(JNIEnv* env, + jobject obj, + jlong self, + jstring jname) { + CefRefPtr request = GetSelf(self); + if (!request) + return nullptr; + return NewJNIString(env, request->GetHeaderByName(GetJNIString(env, jname))); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetHeaderByName(JNIEnv* env, + jobject obj, + jlong self, + jstring jname, + jstring jvalue, + jboolean joverride) { + CefRefPtr request = GetSelf(self); + if (!request) + return; + return request->SetHeaderByName(GetJNIString(env, jname), + GetJNIString(env, jvalue), + joverride != JNI_FALSE); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetHeaderMap(JNIEnv* env, + jobject obj, + jlong self, + jobject jheaderMap) { + CefRefPtr request = GetSelf(self); + if (!request) + return; + CefRequest::HeaderMap headerMap; + request->GetHeaderMap(headerMap); + SetJNIStringMultiMap(env, jheaderMap, headerMap); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetHeaderMap(JNIEnv* env, + jobject obj, + jlong self, + jobject jheaderMap) { + CefRefPtr request = GetSelf(self); + if (!request) + return; + CefRequest::HeaderMap headerMap; + GetJNIStringMultiMap(env, jheaderMap, headerMap); + request->SetHeaderMap(headerMap); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1Set(JNIEnv* env, + jobject obj, + jlong self, + jstring jurl, + jstring jmethod, + jobject jpostData, + jobject jheaderMap) { + CefRefPtr request = GetSelf(self); + if (!request) + return; + + CefRequest::HeaderMap headerMap; + GetJNIStringMultiMap(env, jheaderMap, headerMap); + request->SetHeaderMap(headerMap); + + ScopedJNIPostData postDataObj(env); + if (jpostData) { + postDataObj.SetHandle(jpostData, false /* should_delete */); + } + + request->Set(GetJNIString(env, jurl), GetJNIString(env, jmethod), + postDataObj.GetCefObject(), headerMap); +} + +JNIEXPORT jint JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetFlags(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr request = GetSelf(self); + if (!request) + return 0; + return request->GetFlags(); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetFlags(JNIEnv* env, + jobject obj, + jlong self, + jint jflags) { + CefRefPtr request = GetSelf(self); + if (!request) + return; + request->SetFlags((int)jflags); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetFirstPartyForCookies(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr request = GetSelf(self); + if (!request) + return nullptr; + return NewJNIString(env, request->GetFirstPartyForCookies()); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetFirstPartyForCookies(JNIEnv* env, + jobject obj, + jlong self, + jstring jcookie) { + CefRefPtr request = GetSelf(self); + if (!request) + return; + request->SetFirstPartyForCookies(GetJNIString(env, jcookie)); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetResourceType(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr request = GetSelf(self); + if (!request) + return nullptr; + + jobject result = nullptr; + CefRequest::ResourceType rt = request->GetResourceType(); + switch (rt) { + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_MAIN_FRAME, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_SUB_FRAME, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_STYLESHEET, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_SCRIPT, result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_IMAGE, result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_FONT_RESOURCE, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_SUB_RESOURCE, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_OBJECT, result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_MEDIA, result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_WORKER, result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_SHARED_WORKER, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_PREFETCH, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_FAVICON, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_XHR, result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_PING, result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_SERVICE_WORKER, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_CSP_REPORT, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", RT_PLUGIN_RESOURCE, + result); + JNI_CASE(env, "org/cef/network/CefRequest$ResourceType", + 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; +} + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetTransitionType(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr request = GetSelf(self); + if (!request) + return nullptr; + ScopedJNITransitionType type(env, request->GetTransitionType()); + return type.Release(); +} diff --git a/lib/jcef/native/CefRequest_N.h b/lib/jcef/native/CefRequest_N.h new file mode 100644 index 0000000..832b455 --- /dev/null +++ b/lib/jcef/native/CefRequest_N.h @@ -0,0 +1,250 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_network_CefRequest_N */ + +#ifndef _Included_org_cef_network_CefRequest_N +#define _Included_org_cef_network_CefRequest_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_network_CefRequest_N + * Method: N_Create + * Signature: ()Lorg/cef/network/CefRequest_N; + */ +JNIEXPORT jobject JNICALL Java_org_cef_network_CefRequest_1N_N_1Create(JNIEnv*, + jclass); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefRequest_1N_N_1Dispose(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetIdentifier + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetIdentifier(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_IsReadOnly + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefRequest_1N_N_1IsReadOnly(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetURL + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_cef_network_CefRequest_1N_N_1GetURL(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_SetURL + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefRequest_1N_N_1SetURL(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetMethod + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetMethod(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_SetMethod + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefRequest_1N_N_1SetMethod(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_SetReferrer + * Signature: (JLjava/lang/String;Lorg/cef/network/CefRequest/ReferrerPolicy;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetReferrer(JNIEnv*, + jobject, + jlong, + jstring, + jobject); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetReferrerURL + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetReferrerURL(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetReferrerPolicy + * Signature: (J)Lorg/cef/network/CefRequest/ReferrerPolicy; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetReferrerPolicy(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetPostData + * Signature: (J)Lorg/cef/network/CefPostData; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetPostData(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_SetPostData + * Signature: (JLorg/cef/network/CefPostData;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetPostData(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetHeaderByName + * Signature: (JLjava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetHeaderByName(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_SetHeaderByName + * Signature: (JLjava/lang/String;Ljava/lang/String;Z)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetHeaderByName(JNIEnv*, + jobject, + jlong, + jstring, + jstring, + jboolean); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetHeaderMap + * Signature: (JLjava/util/Map;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetHeaderMap(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_SetHeaderMap + * Signature: (JLjava/util/Map;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetHeaderMap(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_Set + * Signature: + * (JLjava/lang/String;Ljava/lang/String;Lorg/cef/network/CefPostData;Ljava/util/Map;)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefRequest_1N_N_1Set(JNIEnv*, + jobject, + jlong, + jstring, + jstring, + jobject, + jobject); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetFlags + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_cef_network_CefRequest_1N_N_1GetFlags(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_SetFlags + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefRequest_1N_N_1SetFlags(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetFirstPartyForCookies + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetFirstPartyForCookies(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_SetFirstPartyForCookies + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefRequest_1N_N_1SetFirstPartyForCookies(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetResourceType + * Signature: (J)Lorg/cef/network/CefRequest/ResourceType; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetResourceType(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefRequest_N + * Method: N_GetTransitionType + * Signature: (J)Lorg/cef/network/CefRequest/TransitionType; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefRequest_1N_N_1GetTransitionType(JNIEnv*, + jobject, + jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefResourceReadCallback_N.cpp b/lib/jcef/native/CefResourceReadCallback_N.cpp new file mode 100644 index 0000000..4eebcda --- /dev/null +++ b/lib/jcef/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/lib/jcef/native/CefResourceReadCallback_N.h b/lib/jcef/native/CefResourceReadCallback_N.h new file mode 100644 index 0000000..1a12bbf --- /dev/null +++ b/lib/jcef/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/lib/jcef/native/CefResourceSkipCallback_N.cpp b/lib/jcef/native/CefResourceSkipCallback_N.cpp new file mode 100644 index 0000000..9f2b20c --- /dev/null +++ b/lib/jcef/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/lib/jcef/native/CefResourceSkipCallback_N.h b/lib/jcef/native/CefResourceSkipCallback_N.h new file mode 100644 index 0000000..2de2e11 --- /dev/null +++ b/lib/jcef/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/lib/jcef/native/CefResponse_N.cpp b/lib/jcef/native/CefResponse_N.cpp new file mode 100644 index 0000000..de1b32a --- /dev/null +++ b/lib/jcef/native/CefResponse_N.cpp @@ -0,0 +1,185 @@ +// 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 "CefResponse_N.h" + +#include "include/cef_response.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" + +namespace { + +const char kCefClassName[] = "CefResponse"; + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +} // namespace + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefResponse_1N_N_1Create(JNIEnv* env, jclass cls) { + CefRefPtr response = CefResponse::Create(); + ScopedJNIResponse jresponse(env, response); + return jresponse.Release(); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + SetCefForJNIObject(env, obj, nullptr, kCefClassName); +} + +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefResponse_1N_N_1IsReadOnly(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr response = GetSelf(self); + if (!response) + return JNI_FALSE; + return response->IsReadOnly() ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefResponse_1N_N_1GetError(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr response = GetSelf(self); + if (!response) + return nullptr; + return NewJNIErrorCode(env, response->GetError()); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1SetError(JNIEnv* env, + jobject obj, + jlong self, + jobject jerrorCode) { + CefRefPtr response = GetSelf(self); + if (!response) + return; + + if (!jerrorCode) + return; + response->SetError(GetJNIErrorCode(env, jerrorCode)); +} + +JNIEXPORT jint JNICALL +Java_org_cef_network_CefResponse_1N_N_1GetStatus(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr response = GetSelf(self); + if (!response) + return 0; + return response->GetStatus(); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1SetStatus(JNIEnv* env, + jobject obj, + jlong self, + jint jstatus) { + CefRefPtr response = GetSelf(self); + if (!response) + return; + return response->SetStatus(jstatus); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefResponse_1N_N_1GetStatusText(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr response = GetSelf(self); + if (!response) + return nullptr; + return NewJNIString(env, response->GetStatusText()); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1SetStatusText(JNIEnv* env, + jobject obj, + jlong self, + jstring jstatus) { + CefRefPtr response = GetSelf(self); + if (!response) + return; + response->SetStatusText(GetJNIString(env, jstatus)); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefResponse_1N_N_1GetMimeType(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr response = GetSelf(self); + if (!response) + return nullptr; + return NewJNIString(env, response->GetMimeType()); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1SetMimeType(JNIEnv* env, + jobject obj, + jlong self, + jstring jmimeType) { + CefRefPtr response = GetSelf(self); + if (!response) + return; + response->SetMimeType(GetJNIString(env, jmimeType)); +} + +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefResponse_1N_N_1GetHeaderByName(JNIEnv* env, + jobject obj, + jlong self, + jstring jname) { + CefRefPtr response = GetSelf(self); + if (!response) + return nullptr; + return NewJNIString(env, response->GetHeaderByName(GetJNIString(env, jname))); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1SetHeaderByName(JNIEnv* env, + jobject obj, + jlong self, + jstring jname, + jstring jvalue, + jboolean joverride) { + CefRefPtr response = GetSelf(self); + if (!response) + return; + return response->SetHeaderByName(GetJNIString(env, jname), + GetJNIString(env, jvalue), + joverride != JNI_FALSE); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1GetHeaderMap(JNIEnv* env, + jobject obj, + jlong self, + jobject jheaderMap) { + CefRefPtr response = GetSelf(self); + if (!response) + return; + + CefResponse::HeaderMap headerMap; + response->GetHeaderMap(headerMap); + SetJNIStringMultiMap(env, jheaderMap, headerMap); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1SetHeaderMap(JNIEnv* env, + jobject obj, + jlong self, + jobject jheaderMap) { + CefRefPtr response = GetSelf(self); + if (!response) + return; + + CefResponse::HeaderMap headerMap; + GetJNIStringMultiMap(env, jheaderMap, headerMap); + response->SetHeaderMap(headerMap); +} diff --git a/lib/jcef/native/CefResponse_N.h b/lib/jcef/native/CefResponse_N.h new file mode 100644 index 0000000..9fd93c0 --- /dev/null +++ b/lib/jcef/native/CefResponse_N.h @@ -0,0 +1,159 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_network_CefResponse_N */ + +#ifndef _Included_org_cef_network_CefResponse_N +#define _Included_org_cef_network_CefResponse_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_network_CefResponse_N + * Method: N_Create + * Signature: ()Lorg/cef/network/CefResponse_N; + */ +JNIEXPORT jobject JNICALL Java_org_cef_network_CefResponse_1N_N_1Create(JNIEnv*, + jclass); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefResponse_1N_N_1Dispose(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_IsReadOnly + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_network_CefResponse_1N_N_1IsReadOnly(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_GetError + * Signature: (J)Lorg/cef/handler/CefLoadHandler/ErrorCode; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefResponse_1N_N_1GetError(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_SetError + * Signature: (JLorg/cef/handler/CefLoadHandler/ErrorCode;)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefResponse_1N_N_1SetError(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_GetStatus + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_cef_network_CefResponse_1N_N_1GetStatus(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_SetStatus + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefResponse_1N_N_1SetStatus(JNIEnv*, + jobject, + jlong, + jint); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_GetStatusText + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefResponse_1N_N_1GetStatusText(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_SetStatusText + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1SetStatusText(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_GetMimeType + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefResponse_1N_N_1GetMimeType(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_SetMimeType + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1SetMimeType(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_GetHeaderByName + * Signature: (JLjava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_cef_network_CefResponse_1N_N_1GetHeaderByName(JNIEnv*, + jobject, + jlong, + jstring); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_SetHeaderByName + * Signature: (JLjava/lang/String;Ljava/lang/String;Z)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1SetHeaderByName(JNIEnv*, + jobject, + jlong, + jstring, + jstring, + jboolean); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_GetHeaderMap + * Signature: (JLjava/util/Map;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1GetHeaderMap(JNIEnv*, + jobject, + jlong, + jobject); + +/* + * Class: org_cef_network_CefResponse_N + * Method: N_SetHeaderMap + * Signature: (JLjava/util/Map;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_network_CefResponse_1N_N_1SetHeaderMap(JNIEnv*, + jobject, + jlong, + jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefSchemeRegistrar_N.cpp b/lib/jcef/native/CefSchemeRegistrar_N.cpp new file mode 100644 index 0000000..25b6380 --- /dev/null +++ b/lib/jcef/native/CefSchemeRegistrar_N.cpp @@ -0,0 +1,71 @@ +// 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 "CefSchemeRegistrar_N.h" + +#include + +#include "include/cef_scheme.h" + +#include "client_app.h" +#include "jni_util.h" +#include "util.h" + +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefSchemeRegistrar_1N_N_1AddCustomScheme( + JNIEnv* env, + jobject obj, + jstring jSchemeName, + jboolean jIsStandard, + jboolean jIsLocal, + jboolean jIsDisplayIsolated, + jboolean jIsSecure, + jboolean jIsCorsEnabled, + jboolean jIsCspBypassing, + jboolean jIsFetchEnabled) { + CefRawPtr registrar = + GetCefFromJNIObject(env, obj, "CefSchemeRegistrar"); + if (!registrar) + return JNI_FALSE; + CefString schemeName = GetJNIString(env, jSchemeName); + + int options = 0; + if (jIsStandard != JNI_FALSE) + options |= CEF_SCHEME_OPTION_STANDARD; + if (jIsLocal != JNI_FALSE) + options |= CEF_SCHEME_OPTION_LOCAL; + if (jIsDisplayIsolated != JNI_FALSE) + options |= CEF_SCHEME_OPTION_DISPLAY_ISOLATED; + if (jIsSecure != JNI_FALSE) + options |= CEF_SCHEME_OPTION_SECURE; + if (jIsCorsEnabled != JNI_FALSE) + options |= CEF_SCHEME_OPTION_CORS_ENABLED; + if (jIsCspBypassing != JNI_FALSE) + options |= CEF_SCHEME_OPTION_CSP_BYPASSING; + if (jIsFetchEnabled != JNI_FALSE) + options |= CEF_SCHEME_OPTION_FETCH_ENABLED; + + bool result = registrar->AddCustomScheme(schemeName, options); + if (!result) + return JNI_FALSE; + + // The registered scheme has to be forwarded to all other processes which will + // be created by the browser process (e.g. the render-process). Otherwise + // things like JS "localStorage" get/set will end up in a crashed + // render process. + std::string tmpName = util::GetTempFileName("scheme", false); + + std::ofstream fStream(tmpName.c_str(), + std::ofstream::out | std::ofstream::app); + + if (fStream.is_open()) { + // 1) Write the scheme name and the params to the file. + fStream << schemeName.ToString().c_str() << "," << options; + fStream.close(); + + // 2) Register file to be deleted in CefShutdown() + ClientApp::registerTempFile(tmpName); + } + return JNI_TRUE; +} diff --git a/lib/jcef/native/CefSchemeRegistrar_N.h b/lib/jcef/native/CefSchemeRegistrar_N.h new file mode 100644 index 0000000..cee96c0 --- /dev/null +++ b/lib/jcef/native/CefSchemeRegistrar_N.h @@ -0,0 +1,30 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_callback_CefSchemeRegistrar_N */ + +#ifndef _Included_org_cef_callback_CefSchemeRegistrar_N +#define _Included_org_cef_callback_CefSchemeRegistrar_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_callback_CefSchemeRegistrar_N + * Method: N_AddCustomScheme + * Signature: (Ljava/lang/String;ZZZZZZZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_cef_callback_CefSchemeRegistrar_1N_N_1AddCustomScheme(JNIEnv*, + jobject, + jstring, + jboolean, + jboolean, + jboolean, + jboolean, + jboolean, + jboolean, + jboolean); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/CefURLRequest_N.cpp b/lib/jcef/native/CefURLRequest_N.cpp new file mode 100644 index 0000000..d453fbc --- /dev/null +++ b/lib/jcef/native/CefURLRequest_N.cpp @@ -0,0 +1,205 @@ +// 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 "CefURLRequest_N.h" + +#include "include/cef_request.h" +#include "include/cef_task.h" +#include "include/cef_urlrequest.h" + +#include "critical_wait.h" +#include "jni_scoped_helpers.h" +#include "jni_util.h" +#include "url_request_client.h" + +namespace { +class URLRequest : public CefTask { + public: + URLRequest(CefThreadId threadId, + CefRefPtr request, + CefRefPtr client) + : threadId_(threadId), + request_(request), + client_(client), + waitCond_(&lock_) {} + + bool Create() { + if (!urlRequest_) + Dispatch(REQ_CREATE); + return (urlRequest_.get() != nullptr); + } + + CefURLRequest::Status GetRequestStatus() { + if (!urlRequest_) + return UR_UNKNOWN; + Dispatch(REQ_STATUS); + return status_; + } + + CefURLRequest::ErrorCode GetRequestError() { + if (!urlRequest_) + return ERR_FAILED; + Dispatch(REQ_ERROR); + return error_; + } + + CefRefPtr GetResponse() { + if (!urlRequest_) + return nullptr; + Dispatch(REQ_RESPONSE); + return response_; + } + + void Cancel() { + if (!urlRequest_) + return; + Dispatch(REQ_CANCEL); + } + + private: + enum URLRequestMode { + REQ_CREATE, + REQ_STATUS, + REQ_ERROR, + REQ_RESPONSE, + REQ_CANCEL, + }; + + CefThreadId threadId_; + CefRefPtr request_; + CefRefPtr client_; + + // sync method calls + CriticalLock lock_; + CriticalWait waitCond_; + URLRequestMode mode_; + + // result values + CefRefPtr urlRequest_; + CefURLRequest::Status status_; + CefURLRequest::ErrorCode error_; + CefRefPtr response_; + + void Dispatch(URLRequestMode mode) { + mode_ = mode; + if (CefCurrentlyOn(threadId_)) { + Execute(); + } else { + lock_.Lock(); + CefPostTask(threadId_, this); + waitCond_.Wait(); + lock_.Unlock(); + } + } + + virtual void Execute() override { + lock_.Lock(); + switch (mode_) { + case REQ_CREATE: + // TODO(JCEF): Add the ability to specify a CefRequestContext. + urlRequest_ = CefURLRequest::Create(request_, client_.get(), nullptr); + break; + case REQ_STATUS: + status_ = urlRequest_->GetRequestStatus(); + break; + case REQ_ERROR: + error_ = urlRequest_->GetRequestError(); + break; + case REQ_RESPONSE: + response_ = urlRequest_->GetResponse(); + break; + case REQ_CANCEL: + urlRequest_->Cancel(); + break; + } + waitCond_.WakeUp(); + lock_.Unlock(); + } + + IMPLEMENT_REFCOUNTING(URLRequest); +}; + +const char kCefClassName[] = "CefURLRequest"; + +CefRefPtr GetSelf(jlong self) { + return reinterpret_cast(self); +} + +} // namespace + +JNIEXPORT void JNICALL +Java_org_cef_network_CefURLRequest_1N_N_1Create(JNIEnv* env, + jobject obj, + jobject jrequest, + jobject jRequestClient) { + ScopedJNIRequest requestObj(env); + requestObj.SetHandle(jrequest, false /* should_delete */); + CefRefPtr request = requestObj.GetCefObject(); + if (!request) + return; + + CefRefPtr client = + URLRequestClient::Create(env, jRequestClient, obj); + + CefRefPtr urlRequest = new URLRequest(TID_UI, request, client); + if (!urlRequest->Create()) + return; + SetCefForJNIObject(env, obj, urlRequest.get(), kCefClassName); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefURLRequest_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + SetCefForJNIObject(env, obj, nullptr, kCefClassName); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefURLRequest_1N_N_1GetRequestStatus(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr urlRequest = GetSelf(self); + if (!urlRequest) + return nullptr; + + ScopedJNIURLRequestStatus status(env, urlRequest->GetRequestStatus()); + return status.Release(); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefURLRequest_1N_N_1GetRequestError(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr urlRequest = GetSelf(self); + cef_errorcode_t err = ERR_FAILED; + if (urlRequest) + err = urlRequest->GetRequestError(); + return NewJNIErrorCode(env, err); +} + +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefURLRequest_1N_N_1GetResponse(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr urlRequest = GetSelf(self); + if (!urlRequest) + return nullptr; + + CefRefPtr response = urlRequest->GetResponse(); + if (!response) + return nullptr; + + ScopedJNIResponse jresponse(env, response); + return jresponse.Release(); +} + +JNIEXPORT void JNICALL +Java_org_cef_network_CefURLRequest_1N_N_1Cancel(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr urlRequest = GetSelf(self); + if (!urlRequest) + return; + urlRequest->Cancel(); +} diff --git a/lib/jcef/native/CefURLRequest_N.h b/lib/jcef/native/CefURLRequest_N.h new file mode 100644 index 0000000..cb43cbc --- /dev/null +++ b/lib/jcef/native/CefURLRequest_N.h @@ -0,0 +1,70 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_network_CefURLRequest_N */ + +#ifndef _Included_org_cef_network_CefURLRequest_N +#define _Included_org_cef_network_CefURLRequest_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_network_CefURLRequest_N + * Method: N_Create + * Signature: + * (Lorg/cef/network/CefRequest;Lorg/cef/callback/CefURLRequestClient;)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefURLRequest_1N_N_1Create(JNIEnv*, + jobject, + jobject, + jobject); + +/* + * Class: org_cef_network_CefURLRequest_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefURLRequest_1N_N_1Dispose(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefURLRequest_N + * Method: N_GetRequestStatus + * Signature: (J)Lorg/cef/network/CefURLRequest/Status; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefURLRequest_1N_N_1GetRequestStatus(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefURLRequest_N + * Method: N_GetRequestError + * Signature: (J)Lorg/cef/handler/CefLoadHandler/ErrorCode; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefURLRequest_1N_N_1GetRequestError(JNIEnv*, + jobject, + jlong); + +/* + * Class: org_cef_network_CefURLRequest_N + * Method: N_GetResponse + * Signature: (J)Lorg/cef/network/CefResponse; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_network_CefURLRequest_1N_N_1GetResponse(JNIEnv*, jobject, jlong); + +/* + * Class: org_cef_network_CefURLRequest_N + * Method: N_Cancel + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_network_CefURLRequest_1N_N_1Cancel(JNIEnv*, + jobject, + jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/jcef/native/browser_process_handler.cpp b/lib/jcef/native/browser_process_handler.cpp new file mode 100644 index 0000000..ad583e8 --- /dev/null +++ b/lib/jcef/native/browser_process_handler.cpp @@ -0,0 +1,112 @@ +// 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 "browser_process_handler.h" + +#include "client_handler.h" +#include "context.h" +#include "jni_scoped_helpers.h" +#include "jni_util.h" +#include "print_handler.h" +#include "util.h" + +#include "include/cef_base.h" + +// instantiate static values +std::set BrowserProcessHandler::router_cfg_; +base::Lock BrowserProcessHandler::router_cfg_lock_; + +BrowserProcessHandler::BrowserProcessHandler(JNIEnv* env, jobject app_handler) + : handle_(env, app_handler) {} + +BrowserProcessHandler::~BrowserProcessHandler() { + base::AutoLock lock_scope(router_cfg_lock_); + router_cfg_.clear(); +} + +void BrowserProcessHandler::OnContextInitialized() { + Context::GetInstance()->OnContextInitialized(); + + if (!handle_) + return; + + ScopedJNIEnv env; + if (!env) + return; + + JNI_CALL_VOID_METHOD(env, handle_, "onContextInitialized", "()V"); +} + +void BrowserProcessHandler::OnScheduleMessagePumpWork(int64_t delay_ms) { + if (!handle_) + return; + + ScopedJNIEnv env; + if (!env) + return; + + JNI_CALL_VOID_METHOD(env, handle_, "onScheduleMessagePumpWork", "(J)V", + 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; + static std::set::iterator iter; + + base::AutoLock lock_scope(router_cfg_lock_); + if (router_cfg_.empty()) + return nullptr; + + // Configuration pased to CefHelperApp::OnBrowserCreated. + auto router_configs = CefListValue::Create(); + for (iter = router_cfg_.begin(); iter != router_cfg_.end(); ++iter) { + CefRefPtr dict = CefDictionaryValue::Create(); + dict->SetString("js_query_function", iter->js_query_function); + dict->SetString("js_cancel_function", iter->js_cancel_function); + router_configs->SetDictionary(idx, dict); + idx++; + } + + return router_configs; +} + +// static +void BrowserProcessHandler::AddMessageRouterConfig( + const CefMessageRouterConfig& cfg) { + base::AutoLock lock_scope(router_cfg_lock_); + router_cfg_.insert(cfg); +} + +// static +void BrowserProcessHandler::RemoveMessageRouterConfig( + const CefMessageRouterConfig& cfg) { + base::AutoLock lock_scope(router_cfg_lock_); + router_cfg_.erase(cfg); +} diff --git a/lib/jcef/native/browser_process_handler.h b/lib/jcef/native/browser_process_handler.h new file mode 100644 index 0000000..8bbf29e --- /dev/null +++ b/lib/jcef/native/browser_process_handler.h @@ -0,0 +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. + +#ifndef JCEF_NATIVE_BROWSER_PROCESS_HANDLER_H_ +#define JCEF_NATIVE_BROWSER_PROCESS_HANDLER_H_ +#pragma once + +#include + +#include + +#include "include/base/cef_lock.h" +#include "include/cef_browser_process_handler.h" +#include "include/wrapper/cef_message_router.h" + +#include "jni_scoped_helpers.h" + +// comparator to check if configuration values are the same +struct cmpCfg { + bool operator()(const CefMessageRouterConfig& lValue, + const CefMessageRouterConfig& rValue) const { + std::less comp; + return comp(lValue.js_query_function.ToString(), + rValue.js_query_function.ToString()); + } +}; + +// BrowserProcessHandler implementation. +class BrowserProcessHandler : public CefBrowserProcessHandler { + public: + BrowserProcessHandler(JNIEnv* env, jobject app_handler); + virtual ~BrowserProcessHandler(); + + void OnContextInitialized() 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); + static void RemoveMessageRouterConfig(const CefMessageRouterConfig& cfg); + + protected: + ScopedJNIObjectGlobal handle_; + static std::set router_cfg_; + static base::Lock router_cfg_lock_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(BrowserProcessHandler); +}; + +#endif // JCEF_NATIVE_BROWSER_PROCESS_HANDLER_H_ diff --git a/lib/jcef/native/client_app.cpp b/lib/jcef/native/client_app.cpp new file mode 100644 index 0000000..5cb2489 --- /dev/null +++ b/lib/jcef/native/client_app.cpp @@ -0,0 +1,133 @@ +// 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 "client_app.h" +#include "jni_util.h" +#include "util.h" +#if defined(OS_MACOSX) +#include "util_mac.h" +#endif + +namespace { + +std::set& GetTempFilesSet() { + static std::set tempFiles; + return tempFiles; +} + +} // namespace + +ClientApp::ClientApp(const std::string& cache_path, + JNIEnv* env, + const jobject app_handler) + : cache_path_(cache_path), + handle_(env, app_handler), + process_handler_(new BrowserProcessHandler(env, app_handler)) {} + +void ClientApp::OnBeforeCommandLineProcessing( + const CefString& process_type, + CefRefPtr command_line) { + // If the java code has registered an AppHandler, we'll forward + // the commandline processing to it before we append the essential + // switches "locale_pak" and "use-core-animation". + if (handle_ && process_type.empty()) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIString jprocessType(env, process_type); + ScopedJNIObject jcommandLine( + env, command_line, "org/cef/callback/CefCommandLine_N", + "CefCommandLine"); + jcommandLine.SetTemporary(); + + JNI_CALL_VOID_METHOD( + env, handle_, "onBeforeCommandLineProcessing", + "(Ljava/lang/String;Lorg/cef/callback/CefCommandLine;)V", + jprocessType.get(), jcommandLine.get()); + } + + if (process_type.empty()) { +#if defined(OS_MACOSX) + // If windowed rendering is used, we need the browser window as CALayer + // due Java7 is CALayer based instead of NSLayer based. + command_line->AppendSwitch("use-core-animation"); + + // Skip keychain prompt on startup. + command_line->AppendSwitch("use-mock-keychain"); +#endif // defined(OS_MACOSX) + + if (cache_path_.empty() && + !command_line->HasSwitch("disable-gpu-shader-disk-cache")) { + // Don't create a "GPUCache" directory when cache_path is unspecified. + command_line->AppendSwitch("disable-gpu-shader-disk-cache"); + } + } +} + +void ClientApp::OnRegisterCustomSchemes( + CefRawPtr registrar) { + if (!handle_) + return; + + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIObject> jregistrar( + env, registrar, "org/cef/callback/CefSchemeRegistrar_N", + "CefSchemeRegistrar"); + jregistrar.SetTemporary(); + + JNI_CALL_VOID_METHOD(env, handle_, "onRegisterCustomSchemes", + "(Lorg/cef/callback/CefSchemeRegistrar;)V", + jregistrar.get()); +} + +CefRefPtr ClientApp::GetBrowserProcessHandler() { + return process_handler_.get(); +} + +#if defined(OS_MACOSX) +bool ClientApp::HandleTerminate() { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIClass jcls(env, "org/cef/CefApp"); + if (!jcls) { + return false; + } + + jmethodID methodId = + env->GetStaticMethodID(jcls, "getInstance", "()Lorg/cef/CefApp;"); + if (!methodId) { + return false; + } + + ScopedJNIObjectLocal jcefApp(env, + env->CallStaticObjectMethod(jcls, methodId)); + if (!jcefApp) { + return false; + } + + JNI_CALL_VOID_METHOD(env, jcefApp, "handleBeforeTerminate", "()V"); + return true; +} +#endif // defined(OS_MACOSX) + +// static +void ClientApp::registerTempFile(const std::string& tmpFile) { + GetTempFilesSet().insert(tmpFile); +} + +// static +void ClientApp::eraseTempFiles() { + std::set& tempFiles = GetTempFilesSet(); + std::set::iterator iter; + for (iter = tempFiles.begin(); iter != tempFiles.end(); ++iter) { + remove((*iter).c_str()); + } + tempFiles.clear(); +} diff --git a/lib/jcef/native/client_app.h b/lib/jcef/native/client_app.h new file mode 100644 index 0000000..a04407f --- /dev/null +++ b/lib/jcef/native/client_app.h @@ -0,0 +1,49 @@ +// 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 JCEF_NATIVE_CLIENT_APP_H_ +#define JCEF_NATIVE_CLIENT_APP_H_ +#pragma once + +#include + +#include "include/cef_app.h" + +#include "browser_process_handler.h" +#include "jni_scoped_helpers.h" + +// ClientApp implementation. +class ClientApp : public CefApp { + public: + ClientApp(const std::string& cache_path, + JNIEnv* env, + const jobject app_handler); + + // CefApp methods: + void OnBeforeCommandLineProcessing( + const CefString& process_type, + CefRefPtr command_line) override; + void OnRegisterCustomSchemes( + CefRawPtr registrar) override; + CefRefPtr GetBrowserProcessHandler() override; + +#if defined(OS_MACOSX) + // Used to continue termination handling in Java. + bool HandleTerminate(); +#endif + + // Used to manage the lifespan of temporary files. + static void registerTempFile(const std::string& tmpFile); + static void eraseTempFiles(); + + protected: + const std::string cache_path_; + ScopedJNIObjectGlobal handle_; + CefRefPtr process_handler_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(ClientApp); +}; + +#endif // JCEF_NATIVE_CLIENT_APP_H_ diff --git a/lib/jcef/native/client_handler.cpp b/lib/jcef/native/client_handler.cpp new file mode 100644 index 0000000..9b5567f --- /dev/null +++ b/lib/jcef/native/client_handler.cpp @@ -0,0 +1,307 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "client_handler.h" + +#include +#include +#include +#include +#include +#include + +#include "browser_process_handler.h" +#include "context_menu_handler.h" +#include "dialog_handler.h" +#include "display_handler.h" +#include "download_handler.h" +#include "drag_handler.h" +#include "focus_handler.h" +#include "jsdialog_handler.h" +#include "keyboard_handler.h" +#include "life_span_handler.h" +#include "load_handler.h" +#include "message_router_handler.h" +#include "print_handler.h" +#include "render_handler.h" +#include "request_handler.h" + +#include "include/cef_browser.h" +#include "include/cef_frame.h" +#include "include/cef_parser.h" +#include "include/cef_path_util.h" +#include "include/cef_process_util.h" +#include "include/cef_trace.h" +#include "include/wrapper/cef_stream_resource_handler.h" +#include "jni_util.h" +#include "util.h" + +namespace { + +CefRefPtr GetMessageRouter(JNIEnv* env, + jobject jmessageRouter) { + ScopedJNIMessageRouter messageRouter(env); + messageRouter.SetHandle(jmessageRouter, false /* should_delete */); + return messageRouter.GetCefObject(); +} + +CefMessageRouterConfig GetMessageRouterConfig(JNIEnv* env, + jobject jmessageRouter) { + ScopedJNIObjectResult jrouterConfig(env); + JNI_CALL_METHOD(env, jmessageRouter, "getMessageRouterConfig", + "()Lorg/cef/browser/CefMessageRouter$CefMessageRouterConfig;", + Object, jrouterConfig); + return GetJNIMessageRouterConfig(env, jrouterConfig); +} + +} // namespace + +ClientHandler::ClientHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +template +CefRefPtr ClientHandler::GetHandler(const char* class_name) { + std::string methodName, className, methodSig; + + std::stringstream ss; + ss << "get" << class_name; + methodName = ss.str(); + + ss.str(std::string()); + ss << "Cef" << class_name; + className = ss.str(); + + ss.str(std::string()); + ss << "()Lorg/cef/handler/" << className << ";"; + methodSig = ss.str(); + + ScopedJNIEnv env; + if (!env) + return nullptr; + + CefRefPtr result = nullptr; + ScopedJNIObjectResult jresult(env); + JNI_CALL_METHOD(env, handle_, methodName.c_str(), methodSig.c_str(), Object, + jresult); + if (jresult) { + ScopedJNIObject jhandler(env, jresult.Release(), + true /* should_delete */, className.c_str()); + result = jhandler.GetOrCreateCefObject(); + } + + return result; +} + +CefRefPtr ClientHandler::GetContextMenuHandler() { + return GetHandler("ContextMenuHandler"); +} + +CefRefPtr ClientHandler::GetDialogHandler() { + return GetHandler("DialogHandler"); +} + +CefRefPtr ClientHandler::GetDisplayHandler() { + return GetHandler("DisplayHandler"); +} + +CefRefPtr ClientHandler::GetDownloadHandler() { + return GetHandler("DownloadHandler"); +} + +CefRefPtr ClientHandler::GetDragHandler() { + return GetHandler("DragHandler"); +} + +CefRefPtr ClientHandler::GetFocusHandler() { + return GetHandler("FocusHandler"); +} + +CefRefPtr ClientHandler::GetJSDialogHandler() { + return GetHandler("JSDialogHandler"); +} + +CefRefPtr ClientHandler::GetKeyboardHandler() { + return GetHandler("KeyboardHandler"); +} + +CefRefPtr ClientHandler::GetLifeSpanHandler() { + return GetHandler("LifeSpanHandler"); +} + +CefRefPtr ClientHandler::GetLoadHandler() { + return GetHandler("LoadHandler"); +} + +CefRefPtr ClientHandler::GetPrintHandler() { + return GetHandler("PrintHandler"); +} + +CefRefPtr ClientHandler::GetRenderHandler() { + return GetHandler("RenderHandler"); +} + +CefRefPtr ClientHandler::GetRequestHandler() { + return GetHandler("RequestHandler"); +} + +bool ClientHandler::OnProcessMessageReceived( + CefRefPtr browser, + CefRefPtr frame, + CefProcessId source_process, + CefRefPtr message) { + bool handled = false; + + // Iterate on a copy of |message_routers_| to avoid re-entrancy of + // |message_router_lock_| if the client CefMessageRouterHandler impl + // calls CefClientHandler.addMessageRouter/removeMessageRouter. + MessageRouterSet message_routers; + { + base::AutoLock lock_scope(message_router_lock_); + message_routers = message_routers_; + } + + for (auto& router : message_routers) { + handled = router->OnProcessMessageReceived(browser, frame, source_process, + message); + if (handled) + break; + } + return handled; +} + +CefRefPtr ClientHandler::GetWindowHandler() { + return GetHandler("WindowHandler"); +} + +void ClientHandler::AddMessageRouter(JNIEnv* env, jobject jmessageRouter) { + CefRefPtr router = GetMessageRouter(env, jmessageRouter); + if (!router) + return; + + CefMessageRouterConfig config = GetMessageRouterConfig(env, jmessageRouter); + + // 1) Add CefMessageRouterBrowserSide into the list. + { + base::AutoLock lock_scope(message_router_lock_); + message_routers_.insert(router); + } + + // 2) Update CefApp for new render-processes. + BrowserProcessHandler::AddMessageRouterConfig(config); + + // 3) Update running render-processes. + BrowserSet allBrowsers = GetAllBrowsers(env); + if (allBrowsers.empty()) + return; + + CefRefPtr message = + CefProcessMessage::Create("AddMessageRouter"); + CefRefPtr args = message->GetArgumentList(); + args->SetString(0, config.js_query_function); + args->SetString(1, config.js_cancel_function); + + BrowserSet::const_iterator it = allBrowsers.begin(); + for (; it != allBrowsers.end(); ++it) { + (*it)->GetMainFrame()->SendProcessMessage(PID_RENDERER, message); + } +} + +void ClientHandler::RemoveMessageRouter(JNIEnv* env, jobject jmessageRouter) { + CefRefPtr router = GetMessageRouter(env, jmessageRouter); + if (!router) + return; + + CefMessageRouterConfig config = GetMessageRouterConfig(env, jmessageRouter); + + // 1) Remove CefMessageRouterBrowserSide from the list. + { + base::AutoLock lock_scope(message_router_lock_); + message_routers_.erase(router); + } + + // 2) Update CefApp. + BrowserProcessHandler::RemoveMessageRouterConfig(config); + + // 3) Update running render-processes. + BrowserSet allBrowsers = GetAllBrowsers(env); + if (allBrowsers.empty()) + return; + + CefRefPtr message = + CefProcessMessage::Create("RemoveMessageRouter"); + CefRefPtr args = message->GetArgumentList(); + args->SetString(0, config.js_query_function); + args->SetString(1, config.js_cancel_function); + + BrowserSet::const_iterator it = allBrowsers.begin(); + for (; it != allBrowsers.end(); ++it) { + (*it)->GetMainFrame()->SendProcessMessage(PID_RENDERER, message); + } +} + +void ClientHandler::OnAfterCreated() {} + +void ClientHandler::OnBeforeClose(CefRefPtr browser) { + REQUIRE_UI_THREAD(); + + base::AutoLock lock_scope(message_router_lock_); + for (auto& router : message_routers_) { + router->OnBeforeClose(browser); + } +} + +void ClientHandler::OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame) { + REQUIRE_UI_THREAD(); + + base::AutoLock lock_scope(message_router_lock_); + for (auto& router : message_routers_) { + router->OnBeforeBrowse(browser, frame); + } +} + +void ClientHandler::OnRenderProcessTerminated(CefRefPtr browser) { + REQUIRE_UI_THREAD(); + + base::AutoLock lock_scope(message_router_lock_); + for (auto& router : message_routers_) { + router->OnRenderProcessTerminated(browser); + } +} + +jobject ClientHandler::getBrowser(JNIEnv* env, CefRefPtr browser) { + jobject jbrowser = nullptr; + JNI_CALL_METHOD(env, handle_, "getBrowser", "(I)Lorg/cef/browser/CefBrowser;", + Object, jbrowser, browser->GetIdentifier()); + return jbrowser; +} + +ClientHandler::BrowserSet ClientHandler::GetAllBrowsers(JNIEnv* env) { + BrowserSet result; + + jobject jbrowsers = nullptr; + JNI_CALL_METHOD(env, handle_, "getAllBrowser", "()[Ljava/lang/Object;", + Object, jbrowsers); + if (!jbrowsers) + return result; + + jobjectArray jbrowserArray = (jobjectArray)jbrowsers; + jint length = env->GetArrayLength(jbrowserArray); + for (int i = 0; i < length; ++i) { + jobject jbrowser = env->GetObjectArrayElement(jbrowserArray, i); + if (!jbrowser) + continue; + + ScopedJNIBrowser sbrowser(env); + sbrowser.SetHandle(jbrowser, true /* should_delete */); + CefRefPtr browser = sbrowser.GetCefObject(); + if (!browser) + continue; + + result.insert(browser); + } + env->DeleteLocalRef(jbrowserArray); + + return result; +} diff --git a/lib/jcef/native/client_handler.h b/lib/jcef/native/client_handler.h new file mode 100644 index 0000000..db28582 --- /dev/null +++ b/lib/jcef/native/client_handler.h @@ -0,0 +1,83 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef JCEF_NATIVE_CLIENT_HANDLER_H_ +#define JCEF_NATIVE_CLIENT_HANDLER_H_ +#pragma once + +#include + +#include + +#include "include/base/cef_lock.h" +#include "include/cef_base.h" +#include "include/cef_client.h" + +#include "jni_scoped_helpers.h" +#include "message_router_handler.h" +#include "window_handler.h" + +// ClientHandler implementation. +class ClientHandler : public CefClient { + public: + ClientHandler(JNIEnv* env, jobject handler); + + // CefClient methods + CefRefPtr GetContextMenuHandler() override; + CefRefPtr GetDialogHandler() override; + CefRefPtr GetDisplayHandler() override; + CefRefPtr GetDownloadHandler() override; + CefRefPtr GetDragHandler() override; + CefRefPtr GetFocusHandler() override; + CefRefPtr GetJSDialogHandler() override; + CefRefPtr GetKeyboardHandler() override; + CefRefPtr GetLifeSpanHandler() override; + CefRefPtr GetLoadHandler() override; + CefRefPtr GetPrintHandler() override; + CefRefPtr GetRenderHandler() override; + CefRefPtr GetRequestHandler() override; + + bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, + CefProcessId source_process, + CefRefPtr message) override; + + // Additional handler for windowed rendering mode + CefRefPtr GetWindowHandler(); + + // Methods to deal with message router bindings + void AddMessageRouter(JNIEnv* env, jobject jmessageRouter); + void RemoveMessageRouter(JNIEnv* env, jobject jmessageRouter); + + // Methods to set and remove a browser ref. + void OnAfterCreated(); + void OnBeforeClose(CefRefPtr browser); + void OnBeforeBrowse(CefRefPtr browser, CefRefPtr frame); + void OnRenderProcessTerminated(CefRefPtr browser); + + jobject getBrowser(JNIEnv* env, CefRefPtr browser); + + protected: + typedef std::set> BrowserSet; + BrowserSet GetAllBrowsers(JNIEnv* env); + + template + CefRefPtr GetHandler(const char* class_name); + + ScopedJNIObjectGlobal handle_; + + // The child browser window. + std::map browserMap_; + + using MessageRouterSet = std::set>; + MessageRouterSet message_routers_; + + // Protects access to |message_routers_|. + base::Lock message_router_lock_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(ClientHandler); +}; + +#endif // JCEF_NATIVE_CLIENT_HANDLER_H_ diff --git a/lib/jcef/native/compatibility.manifest b/lib/jcef/native/compatibility.manifest new file mode 100644 index 0000000..10d10da --- /dev/null +++ b/lib/jcef/native/compatibility.manifest @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/lib/jcef/native/completion_callback.cpp b/lib/jcef/native/completion_callback.cpp new file mode 100644 index 0000000..ab61c4e --- /dev/null +++ b/lib/jcef/native/completion_callback.cpp @@ -0,0 +1,19 @@ +// 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 "completion_callback.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" +#include "util.h" + +CompletionCallback::CompletionCallback(JNIEnv* env, jobject jhandler) + : handle_(env, jhandler) {} + +void CompletionCallback::OnComplete() { + ScopedJNIEnv env; + if (!env) + return; + JNI_CALL_VOID_METHOD(env, handle_, "onComplete", "()V"); +} diff --git a/lib/jcef/native/completion_callback.h b/lib/jcef/native/completion_callback.h new file mode 100644 index 0000000..6866ab2 --- /dev/null +++ b/lib/jcef/native/completion_callback.h @@ -0,0 +1,30 @@ +// 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 JCEF_NATIVE_COMPLETION_CALLBACK_H_ +#define JCEF_NATIVE_COMPLETION_CALLBACK_H_ +#pragma once + +#include + +#include "include/cef_callback.h" + +#include "jni_scoped_helpers.h" + +// CompletionCallback implementation. +class CompletionCallback : public CefCompletionCallback { + public: + CompletionCallback(JNIEnv* env, jobject jhandler); + + // CompletionCallback methods + virtual void OnComplete() override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(CompletionCallback); +}; + +#endif // JCEF_NATIVE_COMPLETION_CALLBACK_H_ diff --git a/lib/jcef/native/context.cpp b/lib/jcef/native/context.cpp new file mode 100644 index 0000000..2fa324f --- /dev/null +++ b/lib/jcef/native/context.cpp @@ -0,0 +1,299 @@ +// Copyright (c) 2016 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 "context.h" + +#include "include/cef_app.h" + +#include "client_app.h" +#include "jni_util.h" + +#if defined(OS_MACOSX) +#include "util_mac.h" +#endif + +namespace { + +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; + + ScopedJNIClass cls(env, "org/cef/CefSettings"); + if (!cls) + return settings; + + if (GetJNIFieldString(env, cls, obj, "browser_subprocess_path", &tmp) && + !tmp.empty()) { + CefString(&settings.browser_subprocess_path) = tmp; + tmp.clear(); + } + GetJNIFieldBoolean(env, cls, obj, "windowless_rendering_enabled", + &settings.windowless_rendering_enabled); + GetJNIFieldBoolean(env, cls, obj, "command_line_args_disabled", + &settings.command_line_args_disabled); + if (GetJNIFieldString(env, cls, obj, "cache_path", &tmp) && !tmp.empty()) { + 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()) { + CefString(&settings.user_agent) = tmp; + tmp.clear(); + } + if (GetJNIFieldString(env, cls, obj, "user_agent_product", &tmp) && + !tmp.empty()) { + CefString(&settings.user_agent_product) = tmp; + tmp.clear(); + } + if (GetJNIFieldString(env, cls, obj, "locale", &tmp) && !tmp.empty()) { + CefString(&settings.locale) = tmp; + tmp.clear(); + } + if (GetJNIFieldString(env, cls, obj, "log_file", &tmp) && !tmp.empty()) { + CefString(&settings.log_file) = tmp; + tmp.clear(); + } + jobject obj_sev = nullptr; + if (GetJNIFieldObject(env, cls, obj, "log_severity", &obj_sev, + "Lorg/cef/CefSettings$LogSeverity;")) { + ScopedJNIObjectLocal severity(env, obj_sev); + if (IsJNIEnumValue(env, severity, "org/cef/CefSettings$LogSeverity", + "LOGSEVERITY_VERBOSE")) { + settings.log_severity = LOGSEVERITY_VERBOSE; + } else if (IsJNIEnumValue(env, severity, "org/cef/CefSettings$LogSeverity", + "LOGSEVERITY_INFO")) { + settings.log_severity = LOGSEVERITY_INFO; + } else if (IsJNIEnumValue(env, severity, "org/cef/CefSettings$LogSeverity", + "LOGSEVERITY_WARNING")) { + settings.log_severity = LOGSEVERITY_WARNING; + } else if (IsJNIEnumValue(env, severity, "org/cef/CefSettings$LogSeverity", + "LOGSEVERITY_ERROR")) { + settings.log_severity = LOGSEVERITY_ERROR; + } else if (IsJNIEnumValue(env, severity, "org/cef/CefSettings$LogSeverity", + "LOGSEVERITY_DISABLE")) { + settings.log_severity = LOGSEVERITY_DISABLE; + } else { + settings.log_severity = LOGSEVERITY_DEFAULT; + } + } + if (GetJNIFieldString(env, cls, obj, "javascript_flags", &tmp) && + !tmp.empty()) { + CefString(&settings.javascript_flags) = tmp; + tmp.clear(); + } + if (GetJNIFieldString(env, cls, obj, "resources_dir_path", &tmp) && + !tmp.empty()) { + CefString(&settings.resources_dir_path) = tmp; + tmp.clear(); + } + if (GetJNIFieldString(env, cls, obj, "locales_dir_path", &tmp) && + !tmp.empty()) { + CefString(&settings.locales_dir_path) = tmp; + tmp.clear(); + } + 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; + if (GetJNIFieldObject(env, cls, obj, "background_color", &obj_col, + "Lorg/cef/CefSettings$ColorType;")) { + ScopedJNIObjectLocal color_type(env, obj_col); + jlong jcolor = 0; + JNI_CALL_METHOD(env, color_type, "getColor", "()J", Long, jcolor); + settings.background_color = (cef_color_t)jcolor; + } + if (GetJNIFieldString(env, cls, obj, "cookieable_schemes_list", &tmp) && + !tmp.empty()) { + CefString(&settings.cookieable_schemes_list) = tmp; + tmp.clear(); + } + GetJNIFieldBoolean(env, cls, obj, "cookieable_schemes_exclude_defaults", + &settings.cookieable_schemes_exclude_defaults); + + return settings; +} + +} // namespace + +// static +void Context::Create() { + new Context(); +} + +// static +void Context::Destroy() { + DCHECK(g_context); + if (g_context) + delete g_context; +} + +// static +Context* Context::GetInstance() { + return g_context; +} + +bool Context::PreInitialize(JNIEnv* env, jobject c) { + DCHECK(thread_checker_.CalledOnValidThread()); + + JavaVM* jvm; + jint rs = env->GetJavaVM(&jvm); + DCHECK_EQ(rs, JNI_OK); + if (rs != JNI_OK) + return JNI_FALSE; + SetJVM(jvm); + + ScopedJNIClass javaClass(env, env->GetObjectClass(c)); + ScopedJNIObjectResult javaClassLoader(env); + JNI_CALL_METHOD(env, javaClass, "getClassLoader", "()Ljava/lang/ClassLoader;", + Object, javaClassLoader); + ASSERT(javaClassLoader); + if (!javaClassLoader) + return false; + SetJavaClassLoader(env, javaClassLoader); + + return true; +} + +bool Context::Initialize(JNIEnv* env, + jobject c, + jobject appHandler, + jobject jsettings) { + DCHECK(thread_checker_.CalledOnValidThread()); + +#if defined(OS_WIN) + CefMainArgs main_args(::GetModuleHandle(nullptr)); +#else + CefMainArgs main_args(0, nullptr); +#endif + + CefSettings settings = GetJNISettings(env, jsettings); + + // Sandbox is not supported because: + // - Use of a separate sub-process executable on Windows. + // - Use of a temporary file to communicate custom schemes to the + // renderer process. + settings.no_sandbox = true; + +#if defined(OS_WIN) || defined(OS_LINUX) + // Use external message pump with OSR. + external_message_pump_ = !!settings.windowless_rendering_enabled; + if (!external_message_pump_) { + // Windowed rendering on Windows requires multi-threaded message loop, + // otherwise something eats the messages required by Java and the Java + // window becomes unresponsive. + // + // Actually the same appears to be true for Linux, which is why we also + // need multithreaded message loops there. Note that however, on Linux + // it is more difficult to get this to work: it is necessary for the first + // call to Xlib to be a call to XInitThreads! Since Java itself calls + // Xlib when it initializes the first window, an application must make + // sure to invoke this method before any other Xlib functions are called + // - including by the Java runtime itself, which makes this feat a little + // tricky. The CefApp class exposes a static method for this purpose, + // initXlibForMultithreading(), but the host application must load the + // jcef native lib by itself in order to use it, and it must invoke it + // VERY early, ideally at the beginning of the main method. + // Another neat trick to get this done is to create a special native lib + // just for this purpose like described in this StackOverflow thread: + // https://stackoverflow.com/questions/24559368 + settings.multi_threaded_message_loop = true; + } +#endif + + // Use CefAppHandler.onScheduleMessagePumpWork to schedule calls to + // DoMessageLoopWork. + settings.external_message_pump = external_message_pump_; + + CefRefPtr client_app( + new ClientApp(CefString(&settings.cache_path), env, appHandler)); + bool res = false; + +#if defined(OS_MACOSX) + res = util_mac::CefInitializeOnMainThread(main_args, settings, + client_app.get()); +#else + res = CefInitialize(main_args, settings, client_app.get(), nullptr); +#endif + + return res; +} + +void Context::OnContextInitialized() { + REQUIRE_UI_THREAD(); + temp_window_.reset(new TempWindow()); +} + +void Context::DoMessageLoopWork() { + DCHECK(thread_checker_.CalledOnValidThread()); + +#if defined(OS_MACOSX) + util_mac::CefDoMessageLoopWorkOnMainThread(); +#else + CefDoMessageLoopWork(); +#endif +} + +void Context::Shutdown() { + DCHECK(thread_checker_.CalledOnValidThread()); + + // Clear scheme handler factories on shutdown to avoid refcount DCHECK. + CefClearSchemeHandlerFactories(); + + ClientApp::eraseTempFiles(); +#if defined(OS_MACOSX) + util_mac::CefShutdownOnMainThread(); +#else + // Pump CefDoMessageLoopWork a few times before shutting down. + if (external_message_pump_) { + for (int i = 0; i < 10; ++i) + CefDoMessageLoopWork(); + } + + temp_window_.reset(nullptr); + + CefShutdown(); +#endif +} + +Context::Context() : external_message_pump_(true) { + DCHECK(!g_context); + g_context = this; + +#if defined(OS_MACOSX) + // On macOS we create this object very early to allow LibraryLoader + // assignment. However, we still want the PreInitialize() call to determine + // thread ownership. + thread_checker_.DetachFromThread(); +#endif +} + +Context::~Context() { + DCHECK(thread_checker_.CalledOnValidThread()); + g_context = nullptr; + +#if defined(OS_MACOSX) + cef_unload_library(); +#endif +} diff --git a/lib/jcef/native/context.h b/lib/jcef/native/context.h new file mode 100644 index 0000000..e6c0245 --- /dev/null +++ b/lib/jcef/native/context.h @@ -0,0 +1,49 @@ +// Copyright (c) 2016 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_CONTEXT_H_ +#define JCEF_NATIVE_CONTEXT_H_ +#pragma once + +#include + +#include "include/base/cef_macros.h" +#include "include/base/cef_thread_checker.h" + +#include "temp_window.h" + +#if defined(OS_MACOSX) +#include "include/wrapper/cef_library_loader.h" +#endif + +class Context { + public: + static void Create(); + static void Destroy(); + + // Returns the singleton instance of this object. + static Context* GetInstance(); + + bool PreInitialize(JNIEnv* env, jobject c); + bool Initialize(JNIEnv* env, + jobject c, + jobject appHandler, + jobject jsettings); + void OnContextInitialized(); + void DoMessageLoopWork(); + void Shutdown(); + + private: + Context(); + ~Context(); + + bool external_message_pump_; + base::ThreadChecker thread_checker_; + + std::unique_ptr temp_window_; + + DISALLOW_COPY_AND_ASSIGN(Context); +}; + +#endif // JCEF_NATIVE_CONTEXT_H_ diff --git a/lib/jcef/native/context_menu_handler.cpp b/lib/jcef/native/context_menu_handler.cpp new file mode 100644 index 0000000..912b546 --- /dev/null +++ b/lib/jcef/native/context_menu_handler.cpp @@ -0,0 +1,94 @@ +// 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 "context_menu_handler.h" + +#include "jni_util.h" + +namespace { + +// JNI CefContextMenuParams object. +class ScopedJNIContextMenuParams + : public ScopedJNIObject { + public: + ScopedJNIContextMenuParams(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject( + env, + obj, + "org/cef/callback/CefContextMenuParams_N", + "CefContextMenuParams") {} +}; + +} // namespace + +ContextMenuHandler::ContextMenuHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +void ContextMenuHandler::OnBeforeContextMenu( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr params, + CefRefPtr model) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIContextMenuParams jparams(env, params); + jparams.SetTemporary(); + ScopedJNIMenuModel jmodel(env, model); + jmodel.SetTemporary(); + + JNI_CALL_VOID_METHOD(env, handle_, "onBeforeContextMenu", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/" + "CefFrame;Lorg/cef/callback/CefContextMenuParams;" + "Lorg/cef/callback/CefMenuModel;)V", + jbrowser.get(), jframe.get(), jparams.get(), + jmodel.get()); +} + +bool ContextMenuHandler::OnContextMenuCommand( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr params, + int command_id, + EventFlags event_flags) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIContextMenuParams jparams(env, params); + jparams.SetTemporary(); + jboolean result = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "onContextMenuCommand", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/" + "cef/callback/" + "CefContextMenuParams;II)Z", + Boolean, result, jbrowser.get(), jframe.get(), jparams.get(), + (jint)command_id, (jint)event_flags); + + return (result != JNI_FALSE); +} + +void ContextMenuHandler::OnContextMenuDismissed(CefRefPtr browser, + CefRefPtr frame) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + + JNI_CALL_VOID_METHOD( + env, handle_, "onContextMenuDismissed", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;)V", + jbrowser.get(), jframe.get()); +} diff --git a/lib/jcef/native/context_menu_handler.h b/lib/jcef/native/context_menu_handler.h new file mode 100644 index 0000000..218604f --- /dev/null +++ b/lib/jcef/native/context_menu_handler.h @@ -0,0 +1,39 @@ +// 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 JCEF_NATIVE_CONTEXT_MENU_HANDLER_H_ +#define JCEF_NATIVE_CONTEXT_MENU_HANDLER_H_ +#pragma once + +#include +#include "include/cef_context_menu_handler.h" + +#include "jni_scoped_helpers.h" + +// ContextMenuHandler implementation. +class ContextMenuHandler : public CefContextMenuHandler { + public: + ContextMenuHandler(JNIEnv* env, jobject handler); + + // CefContextMenuHandler methods + void OnBeforeContextMenu(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr params, + CefRefPtr model) override; + bool OnContextMenuCommand(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr params, + int command_id, + EventFlags event_flags) override; + void OnContextMenuDismissed(CefRefPtr browser, + CefRefPtr frame) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(ContextMenuHandler); +}; + +#endif // JCEF_NATIVE_CONTEXT_MENU_HANDLER_H_ diff --git a/lib/jcef/native/cookie_access_filter.cpp b/lib/jcef/native/cookie_access_filter.cpp new file mode 100644 index 0000000..4930509 --- /dev/null +++ b/lib/jcef/native/cookie_access_filter.cpp @@ -0,0 +1,65 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "cookie_access_filter.h" + +#include "jni_util.h" +#include "util.h" + +CookieAccessFilter::CookieAccessFilter(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +bool CookieAccessFilter::CanSendCookie(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + const CefCookie& cookie) { + ScopedJNIEnv env; + if (!env) + return true; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNICookie jcookie(env, cookie); + jboolean result = JNI_TRUE; + + JNI_CALL_METHOD(env, handle_, "canSendCookie", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/" + "cef/network/CefRequest;Lorg/cef/network/CefCookie;)Z", + Boolean, result, jbrowser.get(), jframe.get(), jrequest.get(), + jcookie.get()); + + return (result != JNI_FALSE); +} + +bool CookieAccessFilter::CanSaveCookie(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr response, + const CefCookie& cookie) { + ScopedJNIEnv env; + if (!env) + return true; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNIResponse jresponse(env, response); + jresponse.SetTemporary(); + ScopedJNICookie jcookie(env, cookie); + jboolean result = JNI_TRUE; + + JNI_CALL_METHOD( + env, handle_, "canSaveCookie", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/cef/network/" + "CefRequest;Lorg/cef/network/CefResponse;Lorg/cef/network/CefCookie;)Z", + Boolean, result, jbrowser.get(), jframe.get(), jrequest.get(), + jresponse.get(), jcookie.get()); + + return (result != JNI_FALSE); +} diff --git a/lib/jcef/native/cookie_access_filter.h b/lib/jcef/native/cookie_access_filter.h new file mode 100644 index 0000000..42c8b6c --- /dev/null +++ b/lib/jcef/native/cookie_access_filter.h @@ -0,0 +1,37 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef JCEF_NATIVE_COOKIE_ACCESS_FILTER_H_ +#define JCEF_NATIVE_COOKIE_ACCESS_FILTER_H_ +#pragma once + +#include +#include "include/cef_resource_request_handler.h" + +#include "jni_scoped_helpers.h" + +// CookieAccessFilter implementation. +class CookieAccessFilter : public CefCookieAccessFilter { + public: + CookieAccessFilter(JNIEnv* env, jobject handler); + + // CefCookieAccessFilter methods: + bool CanSendCookie(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + const CefCookie& cookie) override; + bool CanSaveCookie(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr response, + const CefCookie& cookie) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(CookieAccessFilter); +}; + +#endif // JCEF_NATIVE_COOKIE_ACCESS_FILTER_H_ diff --git a/lib/jcef/native/cookie_visitor.cpp b/lib/jcef/native/cookie_visitor.cpp new file mode 100644 index 0000000..f62575f --- /dev/null +++ b/lib/jcef/native/cookie_visitor.cpp @@ -0,0 +1,33 @@ +// 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 "cookie_visitor.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" +#include "util.h" + +CookieVisitor::CookieVisitor(JNIEnv* env, jobject jvisitor) + : handle_(env, jvisitor) {} + +bool CookieVisitor::Visit(const CefCookie& cookie, + int count, + int total, + bool& deleteCookie) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNICookie jcookie(env, cookie); + ScopedJNIBoolRef jdeleteCookie(env, deleteCookie); + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "visit", + "(Lorg/cef/network/CefCookie;IILorg/cef/misc/BoolRef;)Z", + Boolean, jresult, jcookie.get(), (jint)count, (jint)total, + jdeleteCookie.get()); + + deleteCookie = jdeleteCookie; + return (jresult != JNI_FALSE); +} diff --git a/lib/jcef/native/cookie_visitor.h b/lib/jcef/native/cookie_visitor.h new file mode 100644 index 0000000..7351642 --- /dev/null +++ b/lib/jcef/native/cookie_visitor.h @@ -0,0 +1,33 @@ +// 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 JCEF_NATIVE_COOKIE_VISITOR_H_ +#define JCEF_NATIVE_COOKIE_VISITOR_H_ +#pragma once + +#include + +#include "include/cef_cookie.h" + +#include "jni_scoped_helpers.h" + +// CookieVisitor implementation. +class CookieVisitor : public CefCookieVisitor { + public: + CookieVisitor(JNIEnv* env, jobject jvisitor); + + // CookieVisitor methods + virtual bool Visit(const CefCookie& cookie, + int count, + int total, + bool& deleteCookie) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(CookieVisitor); +}; + +#endif // JCEF_NATIVE_COOKIE_VISITOR_H_ diff --git a/lib/jcef/native/critical_wait.h b/lib/jcef/native/critical_wait.h new file mode 100644 index 0000000..a6408e3 --- /dev/null +++ b/lib/jcef/native/critical_wait.h @@ -0,0 +1,50 @@ +// 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 JCEF_NATIVE_CRITICAL_WAIT_H_ +#define JCEF_NATIVE_CRITICAL_WAIT_H_ +#pragma once + +#include "include/cef_task.h" + +#if defined(OS_WIN) +#include +#define WAIT_MUTEX HANDLE +#define WAIT_COND HANDLE +#else +#include +#define WAIT_MUTEX pthread_mutex_t +#define WAIT_COND pthread_cond_t +#endif + +class CriticalLock { + public: + CriticalLock(); + ~CriticalLock(); + + void Lock(); + void Unlock(); + + private: + friend class CriticalWait; + WAIT_MUTEX lock_; +}; + +class CriticalWait { + public: + explicit CriticalWait(CriticalLock* lock); + ~CriticalWait(); + + void Wait(); + bool Wait(unsigned int maxWaitMs); + void WakeUp(); + + CriticalLock* lock() { return lock_; } + + private: + WAIT_COND cond_; + CriticalLock* lock_; +}; + +#endif // JCEF_NATIVE_CRITICAL_WAIT_H_ diff --git a/lib/jcef/native/critical_wait_posix.cpp b/lib/jcef/native/critical_wait_posix.cpp new file mode 100644 index 0000000..45ec5b2 --- /dev/null +++ b/lib/jcef/native/critical_wait_posix.cpp @@ -0,0 +1,57 @@ +// 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 "critical_wait.h" + +#include + +// CriticalLock + +CriticalLock::CriticalLock() { + pthread_mutex_init(&lock_, nullptr); +} + +CriticalLock::~CriticalLock() { + pthread_mutex_destroy(&lock_); +} + +void CriticalLock::Lock() { + pthread_mutex_lock(&lock_); +} + +void CriticalLock::Unlock() { + pthread_mutex_unlock(&lock_); +} + +// CriticalWait + +CriticalWait::CriticalWait(CriticalLock* lock) : lock_(lock) { + pthread_cond_init(&cond_, nullptr); +} + +CriticalWait::~CriticalWait() { + pthread_cond_destroy(&cond_); +} + +void CriticalWait::Wait() { + pthread_cond_wait(&cond_, &lock_->lock_); +} + +bool CriticalWait::Wait(unsigned int maxWaitMs) { + int sec = (int)(maxWaitMs / 1000); + int nsec = (maxWaitMs - sec * 1000) * 1000000; // convert to nsec + struct timeval tv; + struct timespec ts; + + gettimeofday(&tv, nullptr); + ts.tv_sec = tv.tv_sec + sec; + ts.tv_nsec = nsec; + + int res = pthread_cond_timedwait(&cond_, &lock_->lock_, &ts); + return res == 0; +} + +void CriticalWait::WakeUp() { + pthread_cond_signal(&cond_); +} diff --git a/lib/jcef/native/critical_wait_win.cpp b/lib/jcef/native/critical_wait_win.cpp new file mode 100644 index 0000000..9da3cab --- /dev/null +++ b/lib/jcef/native/critical_wait_win.cpp @@ -0,0 +1,50 @@ +// 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 "critical_wait.h" + +// CriticalLock + +CriticalLock::CriticalLock() { + lock_ = CreateMutex(nullptr, FALSE, nullptr); +} + +CriticalLock::~CriticalLock() { + CloseHandle(lock_); +} + +void CriticalLock::Lock() { + WaitForSingleObject(lock_, INFINITE); +} + +void CriticalLock::Unlock() { + ReleaseMutex(lock_); +} + +// CriticalWait + +CriticalWait::CriticalWait(CriticalLock* lock) : lock_(lock) { + cond_ = CreateEvent(nullptr, FALSE, FALSE, nullptr); +} + +CriticalWait::~CriticalWait() { + CloseHandle(cond_); +} + +void CriticalWait::Wait() { + lock_->Unlock(); + WaitForSingleObject(cond_, INFINITE); + lock_->Lock(); +} + +bool CriticalWait::Wait(unsigned int maxWaitMs) { + lock_->Unlock(); + DWORD result = WaitForSingleObject(cond_, (DWORD)maxWaitMs); + lock_->Lock(); + return result != WAIT_FAILED; +} + +void CriticalWait::WakeUp() { + SetEvent(cond_); +} diff --git a/lib/jcef/native/devtools_message_observer.cpp b/lib/jcef/native/devtools_message_observer.cpp new file mode 100644 index 0000000..84a47fb --- /dev/null +++ b/lib/jcef/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/lib/jcef/native/devtools_message_observer.h b/lib/jcef/native/devtools_message_observer.h new file mode 100644 index 0000000..19e34bb --- /dev/null +++ b/lib/jcef/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/lib/jcef/native/dialog_handler.cpp b/lib/jcef/native/dialog_handler.cpp new file mode 100644 index 0000000..eb26e56 --- /dev/null +++ b/lib/jcef/native/dialog_handler.cpp @@ -0,0 +1,86 @@ +// 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 "dialog_handler.h" + +#include "client_handler.h" +#include "jni_util.h" +#include "util.h" + +namespace { + +// JNI CefFileDialogCallback object. +class ScopedJNIFileDialogCallback + : public ScopedJNIObject { + public: + ScopedJNIFileDialogCallback(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject( + env, + obj, + "org/cef/callback/CefFileDialogCallback_N", + "CefFileDialogCallback") {} +}; + +} // namespace + +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, + const std::vector& accept_extensions, + const std::vector& accept_descriptions, + CefRefPtr callback) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIString jtitle(env, title); + 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); + switch (mode) { + default: + JNI_CASE(env, "org/cef/handler/CefDialogHandler$FileDialogMode", + 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); + } + + jboolean jreturn = JNI_FALSE; + + JNI_CALL_METHOD( + env, handle_, "onFileDialog", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/handler/" + "CefDialogHandler$FileDialogMode;Ljava/lang/String;Ljava/lang/" + "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(), jacceptExtensions.get(), + jacceptDescriptions.get(), jcallback.get()); + + if (jreturn == JNI_FALSE) { + // If the Java method returns "false" the callback won't be used and + // the reference can therefore be removed. + jcallback.SetTemporary(); + } + + return (jreturn != JNI_FALSE); +} diff --git a/lib/jcef/native/dialog_handler.h b/lib/jcef/native/dialog_handler.h new file mode 100644 index 0000000..0a5411e --- /dev/null +++ b/lib/jcef/native/dialog_handler.h @@ -0,0 +1,36 @@ +// 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 JCEF_NATIVE_DIALOG_HANDLER_H_ +#define JCEF_NATIVE_DIALOG_HANDLER_H_ +#pragma once + +#include +#include "include/cef_dialog_handler.h" + +#include "jni_scoped_helpers.h" + +// DialogHandler implementation. +class DialogHandler : public CefDialogHandler { + public: + DialogHandler(JNIEnv* env, jobject handler); + + // CefDialogHandler methods + virtual bool 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) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(DialogHandler); +}; + +#endif // JCEF_NATIVE_DIALOG_HANDLER_H_ diff --git a/lib/jcef/native/display_handler.cpp b/lib/jcef/native/display_handler.cpp new file mode 100644 index 0000000..d2fcca8 --- /dev/null +++ b/lib/jcef/native/display_handler.cpp @@ -0,0 +1,214 @@ +// 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 "display_handler.h" + +#include "jni_util.h" + +namespace { + +int GetCursorId(cef_cursor_type_t type) { + ScopedJNIEnv env; + if (!env) + return 0; + + const char* cursorClassName = "java/awt/Cursor"; + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + CROSSHAIR_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + DEFAULT_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + E_RESIZE_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + HAND_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + MOVE_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + N_RESIZE_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + NE_RESIZE_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + NW_RESIZE_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + S_RESIZE_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + SE_RESIZE_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + SW_RESIZE_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + TEXT_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + W_RESIZE_CURSOR, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), + WAIT_CURSOR, 0); + + switch (type) { + case CT_CROSS: + return JNI_STATIC(CROSSHAIR_CURSOR); + case CT_HAND: + return JNI_STATIC(HAND_CURSOR); + case CT_IBEAM: + return JNI_STATIC(TEXT_CURSOR); + case CT_WAIT: + return JNI_STATIC(WAIT_CURSOR); + case CT_EASTRESIZE: + return JNI_STATIC(E_RESIZE_CURSOR); + case CT_NORTHRESIZE: + return JNI_STATIC(N_RESIZE_CURSOR); + case CT_NORTHEASTRESIZE: + return JNI_STATIC(NE_RESIZE_CURSOR); + case CT_NORTHWESTRESIZE: + return JNI_STATIC(NW_RESIZE_CURSOR); + case CT_SOUTHRESIZE: + return JNI_STATIC(S_RESIZE_CURSOR); + case CT_SOUTHEASTRESIZE: + return JNI_STATIC(SE_RESIZE_CURSOR); + case CT_SOUTHWESTRESIZE: + return JNI_STATIC(SW_RESIZE_CURSOR); + case CT_WESTRESIZE: + return JNI_STATIC(W_RESIZE_CURSOR); + case CT_MOVE: + return JNI_STATIC(MOVE_CURSOR); + default: + return JNI_STATIC(DEFAULT_CURSOR); + } +} + +} // namespace + +DisplayHandler::DisplayHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +void DisplayHandler::OnAddressChange(CefRefPtr browser, + CefRefPtr frame, + const CefString& url) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIString jurl(env, url); + + JNI_CALL_VOID_METHOD(env, handle_, "onAddressChange", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/" + "CefFrame;Ljava/lang/String;)V", + jbrowser.get(), jframe.get(), jurl.get()); +} + +void DisplayHandler::OnTitleChange(CefRefPtr browser, + const CefString& title) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIString jtitle(env, title); + + JNI_CALL_VOID_METHOD(env, handle_, "onTitleChange", + "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;)V", + 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) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIString jtext(env, text); + jboolean jreturn = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "onTooltip", + "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;)Z", Boolean, + jreturn, jbrowser.get(), jtext.get()); + + return (jreturn != JNI_FALSE); +} + +void DisplayHandler::OnStatusMessage(CefRefPtr browser, + const CefString& value) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIString jvalue(env, value); + + JNI_CALL_VOID_METHOD(env, handle_, "onStatusMessage", + "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;)V", + jbrowser.get(), jvalue.get()); +} + +bool DisplayHandler::OnConsoleMessage(CefRefPtr browser, + cef_log_severity_t level, + const CefString& message, + const CefString& source, + int line) { + ScopedJNIEnv env; + if (!env) + return false; + + jobject jlevel = nullptr; + switch (level) { + JNI_CASE(env, "org/cef/CefSettings$LogSeverity", LOGSEVERITY_VERBOSE, + jlevel); + JNI_CASE(env, "org/cef/CefSettings$LogSeverity", LOGSEVERITY_INFO, jlevel); + JNI_CASE(env, "org/cef/CefSettings$LogSeverity", LOGSEVERITY_WARNING, + jlevel); + JNI_CASE(env, "org/cef/CefSettings$LogSeverity", LOGSEVERITY_ERROR, jlevel); + JNI_CASE(env, "org/cef/CefSettings$LogSeverity", LOGSEVERITY_FATAL, jlevel); + JNI_CASE(env, "org/cef/CefSettings$LogSeverity", LOGSEVERITY_DISABLE, + jlevel); + case LOGSEVERITY_DEFAULT: + break; + } + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIString jmessage(env, message); + ScopedJNIString jsource(env, source); + jboolean jreturn = JNI_FALSE; + + JNI_CALL_METHOD( + env, handle_, "onConsoleMessage", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/CefSettings$LogSeverity;" + "Ljava/lang/String;Ljava/lang/String;I)Z", + Boolean, jreturn, jbrowser.get(), jlevel, jmessage.get(), jsource.get(), + line); + + return (jreturn != JNI_FALSE); +} + +// TODO(JCEF): Expose all parameters. +bool DisplayHandler::OnCursorChange(CefRefPtr browser, + CefCursorHandle cursor, + cef_cursor_type_t type, + const CefCursorInfo& custom_cursor_info) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + const int cursorId = GetCursorId(type); + jboolean jreturn = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "onCursorChange", + "(Lorg/cef/browser/CefBrowser;I)Z", Boolean, jreturn, + jbrowser.get(), cursorId); + + return (jreturn != JNI_FALSE); +} diff --git a/lib/jcef/native/display_handler.h b/lib/jcef/native/display_handler.h new file mode 100644 index 0000000..30615fd --- /dev/null +++ b/lib/jcef/native/display_handler.h @@ -0,0 +1,48 @@ +// 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 JCEF_NATIVE_DISPLAY_HANDLER_H_ +#define JCEF_NATIVE_DISPLAY_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_display_handler.h" + +#include "jni_scoped_helpers.h" + +// DisplayHandler implementation. +class DisplayHandler : public CefDisplayHandler { + public: + DisplayHandler(JNIEnv* env, jobject handler); + + // CefDisplayHandler methods: + void OnAddressChange(CefRefPtr browser, + CefRefPtr frame, + 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; + bool OnConsoleMessage(CefRefPtr browser, + cef_log_severity_t level, + const CefString& message, + const CefString& source, + int line) override; + bool OnCursorChange(CefRefPtr browser, + CefCursorHandle cursor, + cef_cursor_type_t type, + const CefCursorInfo& custom_cursor_info) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(DisplayHandler); +}; + +#endif // JCEF_NATIVE_DISPLAY_HANDLER_H_ diff --git a/lib/jcef/native/download_handler.cpp b/lib/jcef/native/download_handler.cpp new file mode 100644 index 0000000..e0b3775 --- /dev/null +++ b/lib/jcef/native/download_handler.cpp @@ -0,0 +1,97 @@ +// 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 "download_handler.h" + +#include "jni_util.h" + +namespace { + +// JNI CefDownloadItem object. +class ScopedJNIDownloadItem : public ScopedJNIObject { + public: + ScopedJNIDownloadItem(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/callback/CefDownloadItem_N", + "CefDownloadItem") {} +}; + +// JNI CefBeforeDownloadCallback object. +class ScopedJNIBeforeDownloadCallback + : public ScopedJNIObject { + public: + ScopedJNIBeforeDownloadCallback(JNIEnv* env, + CefRefPtr obj) + : ScopedJNIObject( + env, + obj, + "org/cef/callback/CefBeforeDownloadCallback_N", + "CefBeforeDownloadCallback") {} +}; + +// JNI CefDownloadItemCallback object. +class ScopedJNIDownloadItemCallback + : public ScopedJNIObject { + public: + ScopedJNIDownloadItemCallback(JNIEnv* env, + CefRefPtr obj) + : ScopedJNIObject( + env, + obj, + "org/cef/callback/CefDownloadItemCallback_N", + "CefDownloadItemCallback") {} +}; + +} // namespace + +DownloadHandler::DownloadHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +bool DownloadHandler::OnBeforeDownload( + CefRefPtr browser, + CefRefPtr download_item, + const CefString& suggested_name, + CefRefPtr callback) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIDownloadItem jdownloadItem(env, download_item); + jdownloadItem.SetTemporary(); + ScopedJNIString jsuggestedName(env, suggested_name); + ScopedJNIBeforeDownloadCallback jcallback(env, callback); + + 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;)Z", + jbrowser.get(), jdownloadItem.get(), jsuggestedName.get(), + jcallback.get()); + + return jresult; +} + +void DownloadHandler::OnDownloadUpdated( + CefRefPtr browser, + CefRefPtr download_item, + CefRefPtr callback) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIDownloadItem jdownloadItem(env, download_item); + jdownloadItem.SetTemporary(); + ScopedJNIDownloadItemCallback jcallback(env, callback); + + JNI_CALL_VOID_METHOD( + env, handle_, "onDownloadUpdated", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/callback/CefDownloadItem;" + "Lorg/cef/callback/CefDownloadItemCallback;)V", + jbrowser.get(), jdownloadItem.get(), jcallback.get()); +} diff --git a/lib/jcef/native/download_handler.h b/lib/jcef/native/download_handler.h new file mode 100644 index 0000000..adbaacb --- /dev/null +++ b/lib/jcef/native/download_handler.h @@ -0,0 +1,38 @@ +// 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 JCEF_NATIVE_DOWNLOAD_HANDLER_H_ +#define JCEF_NATIVE_DOWNLOAD_HANDLER_H_ +#pragma once + +#include +#include "include/cef_download_handler.h" + +#include "jni_scoped_helpers.h" + +// DownloadHandler implementation. +class DownloadHandler : public CefDownloadHandler { + public: + DownloadHandler(JNIEnv* env, jobject handler); + + // CefDownloadHandler methods + virtual bool OnBeforeDownload( + CefRefPtr browser, + CefRefPtr download_item, + const CefString& suggested_name, + CefRefPtr callback) override; + + virtual void OnDownloadUpdated( + CefRefPtr browser, + CefRefPtr download_item, + CefRefPtr callback) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(DownloadHandler); +}; + +#endif // JCEF_NATIVE_DOWNLOAD_HANDLER_H_ diff --git a/lib/jcef/native/drag_handler.cpp b/lib/jcef/native/drag_handler.cpp new file mode 100644 index 0000000..72318c3 --- /dev/null +++ b/lib/jcef/native/drag_handler.cpp @@ -0,0 +1,30 @@ +// 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 "drag_handler.h" + +#include "jni_util.h" + +DragHandler::DragHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +bool DragHandler::OnDragEnter(CefRefPtr browser, + CefRefPtr dragData, + CefDragHandler::DragOperationsMask mask) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIDragData jdragData(env, dragData); + jdragData.SetTemporary(); + jboolean result = JNI_FALSE; + + JNI_CALL_METHOD( + env, handle_, "onDragEnter", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/callback/CefDragData;I)Z", Boolean, + result, jbrowser.get(), jdragData.get(), (jint)mask); + + return (result != JNI_FALSE); +} diff --git a/lib/jcef/native/drag_handler.h b/lib/jcef/native/drag_handler.h new file mode 100644 index 0000000..440a1c0 --- /dev/null +++ b/lib/jcef/native/drag_handler.h @@ -0,0 +1,32 @@ +// 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 JCEF_NATIVE_DRAG_HANDLER_H_ +#define JCEF_NATIVE_DRAG_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_drag_handler.h" + +#include "jni_scoped_helpers.h" + +// DragHandler implementation. +class DragHandler : public CefDragHandler { + public: + DragHandler(JNIEnv* env, jobject handler); + + // CefDragHandler methods + bool OnDragEnter(CefRefPtr browser, + CefRefPtr dragData, + CefDragHandler::DragOperationsMask mask) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(DragHandler); +}; + +#endif // JCEF_NATIVE_DRAG_HANDLER_H_ diff --git a/lib/jcef/native/focus_handler.cpp b/lib/jcef/native/focus_handler.cpp new file mode 100644 index 0000000..d62375c --- /dev/null +++ b/lib/jcef/native/focus_handler.cpp @@ -0,0 +1,59 @@ +// 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 "focus_handler.h" + +#include "include/base/cef_callback.h" +#include "include/wrapper/cef_closure_task.h" + +#include "client_handler.h" +#include "jni_util.h" + +FocusHandler::FocusHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +void FocusHandler::OnTakeFocus(CefRefPtr browser, bool next) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + JNI_CALL_VOID_METHOD(env, handle_, "onTakeFocus", + "(Lorg/cef/browser/CefBrowser;Z)V", jbrowser.get(), + (jboolean)next); +} + +bool FocusHandler::OnSetFocus(CefRefPtr browser, + FocusSource source) { + ScopedJNIEnv env; + if (!env) + return false; + + jboolean jreturn = JNI_FALSE; + ScopedJNIObjectResult jsource(env); + switch (source) { + JNI_CASE(env, "org/cef/handler/CefFocusHandler$FocusSource", + FOCUS_SOURCE_NAVIGATION, jsource); + default: + JNI_CASE(env, "org/cef/handler/CefFocusHandler$FocusSource", + FOCUS_SOURCE_SYSTEM, jsource); + } + + ScopedJNIBrowser jbrowser(env, browser); + JNI_CALL_METHOD(env, handle_, "onSetFocus", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/handler/" + "CefFocusHandler$FocusSource;)Z", + Boolean, jreturn, jbrowser.get(), jsource.get()); + return (jreturn != JNI_FALSE); +} + +void FocusHandler::OnGotFocus(CefRefPtr browser) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + JNI_CALL_VOID_METHOD(env, handle_, "onGotFocus", + "(Lorg/cef/browser/CefBrowser;)V", jbrowser.get()); +} diff --git a/lib/jcef/native/focus_handler.h b/lib/jcef/native/focus_handler.h new file mode 100644 index 0000000..d70a4ac --- /dev/null +++ b/lib/jcef/native/focus_handler.h @@ -0,0 +1,33 @@ +// 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 JCEF_NATIVE_FOCUS_HANDLER_H_ +#define JCEF_NATIVE_FOCUS_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_focus_handler.h" + +#include "jni_scoped_helpers.h" + +// FocusHandler implementation. +class FocusHandler : public CefFocusHandler { + public: + FocusHandler(JNIEnv* env, jobject handler); + + // CefFocusHandler methods + virtual void OnTakeFocus(CefRefPtr browser, bool next) override; + virtual bool OnSetFocus(CefRefPtr browser, + FocusSource source) override; + virtual void OnGotFocus(CefRefPtr browser) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(FocusHandler); +}; + +#endif // JCEF_NATIVE_FOCUS_HANDLER_H_ diff --git a/lib/jcef/native/int_callback.cpp b/lib/jcef/native/int_callback.cpp new file mode 100644 index 0000000..a45471a --- /dev/null +++ b/lib/jcef/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/lib/jcef/native/int_callback.h b/lib/jcef/native/int_callback.h new file mode 100644 index 0000000..6437479 --- /dev/null +++ b/lib/jcef/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/lib/jcef/native/jcef.dll.manifest b/lib/jcef/native/jcef.dll.manifest new file mode 100644 index 0000000..d068c13 --- /dev/null +++ b/lib/jcef/native/jcef.dll.manifest @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/lib/jcef/native/jcef_dll.rc b/lib/jcef/native/jcef_dll.rc new file mode 100644 index 0000000..a9a23e5 --- /dev/null +++ b/lib/jcef/native/jcef_dll.rc @@ -0,0 +1,107 @@ +// Microsoft Visual C++ generated resource script. +// + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#include "jcef_version.h" +#include "include/cef_version.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#include ""include/version.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION CEF_VERSION_MAJOR,CEF_VERSION_MINOR,CEF_VERSION_PATCH,JCEF_COMMIT_NUMBER + PRODUCTVERSION CEF_VERSION_MAJOR,CEF_VERSION_MINOR,CEF_VERSION_PATCH,JCEF_COMMIT_NUMBER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Java Chromium Embedded Framework (JCEF) Dynamic Link Library" + VALUE "FileVersion", JCEF_VERSION + VALUE "InternalName", "jcef" + VALUE "LegalCopyright", "Copyright (C) " MAKE_STRING(JCEF_COPYRIGHT_YEAR) " The Chromium Embedded Framework Authors" + VALUE "OriginalFilename", "jcef.dll" + VALUE "ProductName", "Java Chromium Embedded Framework (JCEF) Dynamic Link Library" + VALUE "ProductVersion", JCEF_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/lib/jcef/native/jcef_helper.cpp b/lib/jcef/native/jcef_helper.cpp new file mode 100644 index 0000000..6877da7 --- /dev/null +++ b/lib/jcef/native/jcef_helper.cpp @@ -0,0 +1,217 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include + +#include "include/cef_app.h" +#include "include/wrapper/cef_message_router.h" +#include "util.h" + +#if defined(OS_MACOSX) +// When generating projects with CMake the CEF_USE_SANDBOX value will be defined +// automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable +// use of the sandbox. +#if defined(CEF_USE_SANDBOX) +#include "include/cef_sandbox_mac.h" +#endif + +#include "include/wrapper/cef_library_loader.h" +#endif // defined(OS_MACOSX) + +#if defined(OS_WIN) +#include +#endif + +namespace { + +// comparator to check if configuration values are the same +struct cmpCfg { + bool operator()(const CefMessageRouterConfig& lValue, + const CefMessageRouterConfig& rValue) const { + std::less comp; + return comp(lValue.js_query_function.ToString(), + rValue.js_query_function.ToString()); + } +}; + +class CefHelperApp : public CefApp, public CefRenderProcessHandler { + public: + CefHelperApp() {} + + void OnRegisterCustomSchemes( + CefRawPtr registrar) override { + std::fstream fStream; + std::string fName = util::GetTempFileName("scheme", true); + char schemeName[512] = ""; + int options; + + fStream.open(fName.c_str(), std::fstream::in); + while (fStream.is_open() && !fStream.eof()) { + fStream.getline(schemeName, 512, ','); + if (strlen(schemeName) == 0) + break; + + fStream >> options; + + registrar->AddCustomScheme(schemeName, options); + } + fStream.close(); + } + + virtual CefRefPtr GetRenderProcessHandler() + override { + return this; + } + + void OnBrowserCreated(CefRefPtr browser, + CefRefPtr extra_info) override { + if (!extra_info) { + return; + } + auto router_configs = extra_info->GetList("router_configs"); + if (router_configs) { + // Configuration from BrowserProcessHandler::GetMessageRouterConfigs. + for (size_t idx = 0; idx < router_configs->GetSize(); idx++) { + CefRefPtr dict = + router_configs->GetDictionary((int)idx); + // Create the renderer-side router for query handling. + CefMessageRouterConfig config; + config.js_query_function = dict->GetString("js_query_function"); + config.js_cancel_function = dict->GetString("js_cancel_function"); + + CefRefPtr router = + CefMessageRouterRendererSide::Create(config); + message_router_.insert(std::make_pair(config, router)); + } + } + } + + void OnContextCreated(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) override { + std::map, + cmpCfg>::iterator iter; + for (iter = message_router_.begin(); iter != message_router_.end(); + iter++) { + iter->second->OnContextCreated(browser, frame, context); + } + } + + void OnContextReleased(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) override { + std::map, + cmpCfg>::iterator iter; + for (iter = message_router_.begin(); iter != message_router_.end(); + iter++) { + iter->second->OnContextReleased(browser, frame, context); + } + } + + bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, + CefProcessId source_process, + CefRefPtr message) override { + if (message->GetName() == "AddMessageRouter") { + CefRefPtr args = message->GetArgumentList(); + CefMessageRouterConfig config; + config.js_query_function = args->GetString(0); + config.js_cancel_function = args->GetString(1); + + // only add a new message router if it wasn't already created + if (message_router_.find(config) != message_router_.end()) { + return true; + } + + CefRefPtr router = + CefMessageRouterRendererSide::Create(config); + message_router_.insert(std::make_pair(config, router)); + return true; + + } else if (message->GetName() == "RemoveMessageRouter") { + CefRefPtr args = message->GetArgumentList(); + CefMessageRouterConfig config; + config.js_query_function = args->GetString(0); + config.js_cancel_function = args->GetString(1); + + message_router_.erase(config); + return true; + } + + bool handled = false; + std::map, + cmpCfg>::iterator iter; + for (iter = message_router_.begin(); iter != message_router_.end(); + iter++) { + handled = iter->second->OnProcessMessageReceived(browser, frame, + source_process, message); + if (handled) + break; + } + return handled; + } + + private: + std::map, + cmpCfg> + message_router_; + + IMPLEMENT_REFCOUNTING(CefHelperApp); +}; + +} // namespace + +#if defined(OS_WIN) +int CALLBACK WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + CefMainArgs main_args(hInstance); +#else // !defined(OS_WIN) +int main(int argc, char* argv[]) { +#if defined(OS_MACOSX) +#if defined(CEF_USE_SANDBOX) + // Initialize the macOS sandbox for this helper process. + CefScopedSandboxContext sandbox_context; + if (!sandbox_context.Initialize(argc, argv)) + return 1; +#endif // defined(CEF_USE_SANDBOX) + + // Check for the path on the command-line. + std::string framework_path; + const std::string switchPrefix = "--framework-dir-path="; + for (int i = 0; i < argc; ++i) { + std::string arg = argv[i]; + if (arg.find(switchPrefix) == 0) { + framework_path = arg.substr(switchPrefix.length()); + break; + } + } + + // Load the CEF framework library at runtime instead of linking directly + // as required by the macOS sandbox implementation. + CefScopedLibraryLoader library_loader; + if (!framework_path.empty()) { + framework_path += "/Chromium Embedded Framework"; + if (!cef_load_library(framework_path.c_str())) + return 1; + } else if (!library_loader.LoadInHelper()) { + return 1; + } +#endif // defined(OS_MACOSX) + + CefMainArgs main_args(argc, argv); +#endif // !defined(OS_WIN) + + CefRefPtr app = new CefHelperApp(); + const int result = CefExecuteProcess(main_args, app.get(), nullptr); + +#if defined(OS_MACOSX) + if (!framework_path.empty()) + cef_unload_library(); +#endif + + return result; +} diff --git a/lib/jcef/native/jcef_helper.exe.manifest b/lib/jcef/native/jcef_helper.exe.manifest new file mode 100644 index 0000000..d068c13 --- /dev/null +++ b/lib/jcef/native/jcef_helper.exe.manifest @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/lib/jcef/native/jcef_helper.rc b/lib/jcef/native/jcef_helper.rc new file mode 100644 index 0000000..6f6c0f9 --- /dev/null +++ b/lib/jcef/native/jcef_helper.rc @@ -0,0 +1,107 @@ +// Microsoft Visual C++ generated resource script. +// + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#include "jcef_version.h" +#include "include/cef_version.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#include ""include/version.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION CEF_VERSION_MAJOR,CEF_VERSION_MINOR,CEF_VERSION_PATCH,JCEF_COMMIT_NUMBER + PRODUCTVERSION CEF_VERSION_MAJOR,CEF_VERSION_MINOR,CEF_VERSION_PATCH,JCEF_COMMIT_NUMBER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Java Chromium Embedded Framework (JCEF) Helper" + VALUE "FileVersion", JCEF_VERSION + VALUE "InternalName", "jcef_helper" + VALUE "LegalCopyright", "Copyright (C) " MAKE_STRING(JCEF_COPYRIGHT_YEAR) " The Chromium Embedded Framework Authors" + VALUE "OriginalFilename", "jcef_helper.exe" + VALUE "ProductName", "Java Chromium Embedded Framework (JCEF) Helper" + VALUE "ProductVersion", JCEF_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/lib/jcef/native/jni_scoped_helpers.cpp b/lib/jcef/native/jni_scoped_helpers.cpp new file mode 100644 index 0000000..f661364 --- /dev/null +++ b/lib/jcef/native/jni_scoped_helpers.cpp @@ -0,0 +1,500 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include +#include + +#include "jni_scoped_helpers.h" + +#include "client_handler.h" +#include "jni_util.h" + +namespace { + +// Retrieves the JNIEnv for the current thread. Attaches the VM to the current +// thread if necessary. Sets |mustDetach| to true if DetachJNIEnv must be +// called. +jint GetJNIEnv(JNIEnv** env, bool* mustDetach) { + *env = nullptr; + *mustDetach = false; + + JavaVM* jvm = GetJVM(); + if (!jvm) + return JNI_ERR; + + jint result = jvm->GetEnv((void**)env, JNI_VERSION_1_6); + if (result == JNI_EDETACHED) { + result = jvm->AttachCurrentThreadAsDaemon((void**)env, nullptr); + if (result == JNI_OK) { + *mustDetach = true; + } + } + + return result; +} + +// Detaches the current thread from the VM. Should only be called if +// |mustDetach| was set to true by GetJNIEnv. +void DetachJNIEnv() { + JavaVM* jvm = GetJVM(); + if (jvm) { + jvm->DetachCurrentThread(); + } +} + +// Using a simple cache to store global refs to loaded classes, since we +// need to load the same classes over and over, which should neither change +// on the JVM side nor be GCed... +std::map classCache_; +std::mutex classCacheMutex_; +// ...except if there's a change in the classloader to use by JCEF, in which +// case the cache can be invalidated +jobject classCacheClassLoader_; + +// Returns a class with the given fully qualified |class_name| (with '/' as +// separator). +jclass FindClass(JNIEnv* env, const char* class_name) { + std::string classNameSeparatedByDots(class_name); + std::replace(classNameSeparatedByDots.begin(), classNameSeparatedByDots.end(), + '/', '.'); + + jobject classLoader = GetJavaClassLoader(); + ASSERT(classLoader); + + // std::map is not thread-safe with regard to concurrent reading and writing + std::lock_guard guard(classCacheMutex_); + + if (classLoader != classCacheClassLoader_) { + for (std::pair& entry : classCache_) { + env->DeleteGlobalRef(entry.second); + } + classCache_.clear(); + classCacheClassLoader_ = classLoader; + } + + std::map::iterator it = + classCache_.find(classNameSeparatedByDots); + if (it != classCache_.end()) { + return static_cast(env->NewLocalRef(it->second)); + } + + ScopedJNIString classNameJString(env, classNameSeparatedByDots); + jobject result = nullptr; + + JNI_CALL_METHOD(env, classLoader, "loadClass", + "(Ljava/lang/String;)Ljava/lang/Class;", Object, result, + classNameJString.get()); + + // Make a global reference out of the local reference to allow for caching. + // This produces a non-garbage-collectable class, since this global ref is + // never released! However, for the classes that are requested by JCEF via + // this mechanism, that should be acceptable, because they aren't candidates + // to be GCed anyway. + classCache_[classNameSeparatedByDots] = env->NewGlobalRef(result); + + return static_cast(result); +} + +jobject NewJNIBoolRef(JNIEnv* env, bool initValue) { + ScopedJNIObjectLocal jboolRef(env, "org/cef/misc/BoolRef"); + if (!jboolRef) + return nullptr; + SetJNIBoolRef(env, jboolRef, initValue); + return jboolRef.Release(); +} + +jobject NewJNIIntRef(JNIEnv* env, int initValue) { + ScopedJNIObjectLocal jintRef(env, "org/cef/misc/IntRef"); + if (!jintRef) + return nullptr; + SetJNIIntRef(env, jintRef, 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) + return nullptr; + SetJNIStringRef(env, jstringRef, initValue); + return jstringRef.Release(); +} + +jobject NewJNIDate(JNIEnv* env, const CefBaseTime& time) { + ScopedJNIObjectLocal jdate(env, "java/util/Date"); + if (!jdate) + return nullptr; + 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(); +} + +jobject NewJNICookie(JNIEnv* env, const CefCookie& cookie) { + ScopedJNIString name(env, CefString(&cookie.name)); + ScopedJNIString value(env, CefString(&cookie.value)); + ScopedJNIString domain(env, CefString(&cookie.domain)); + ScopedJNIString path(env, CefString(&cookie.path)); + const bool hasExpires = (cookie.has_expires != 0); + ScopedJNIObjectLocal expires( + env, hasExpires ? NewJNIDate(env, cookie.expires) : nullptr); + ScopedJNIDate creation(env, cookie.creation); + ScopedJNIDate last_access(env, cookie.last_access); + + return NewJNIObject(env, "org/cef/network/CefCookie", + "(Ljava/lang/String;Ljava/lang/String;" + "Ljava/lang/String;Ljava/lang/String;" + "ZZLjava/util/Date;Ljava/util/Date;" + "ZLjava/util/Date;)V", + name.get(), value.get(), domain.get(), path.get(), + (cookie.secure != 0 ? JNI_TRUE : JNI_FALSE), + (cookie.httponly != 0 ? JNI_TRUE : JNI_FALSE), + creation.get(), last_access.get(), + (hasExpires ? JNI_TRUE : JNI_FALSE), expires.get()); +} + +jobject NewJNITransitionType(JNIEnv* env, + CefRequest::TransitionType transitionType) { + ScopedJNIObjectResult result(env); + switch (transitionType & TT_SOURCE_MASK) { + default: + JNI_CASE(env, "org/cef/network/CefRequest$TransitionType", TT_LINK, + result); + JNI_CASE(env, "org/cef/network/CefRequest$TransitionType", TT_EXPLICIT, + result); + JNI_CASE(env, "org/cef/network/CefRequest$TransitionType", + TT_AUTO_SUBFRAME, result); + JNI_CASE(env, "org/cef/network/CefRequest$TransitionType", + TT_MANUAL_SUBFRAME, result); + JNI_CASE(env, "org/cef/network/CefRequest$TransitionType", TT_FORM_SUBMIT, + result); + JNI_CASE(env, "org/cef/network/CefRequest$TransitionType", TT_RELOAD, + result); + } + + if (result) { + const int qualifiers = (transitionType & TT_QUALIFIER_MASK); + JNI_CALL_VOID_METHOD(env, result, "addQualifiers", "(I)V", qualifiers); + } + + return result.Release(); +} + +jobject NewJNIURLRequestStatus( + JNIEnv* env, + CefResourceRequestHandler::URLRequestStatus status) { + ScopedJNIObjectResult result(env); + switch (status) { + default: + JNI_CASE(env, "org/cef/network/CefURLRequest$Status", UR_UNKNOWN, result); + JNI_CASE(env, "org/cef/network/CefURLRequest$Status", UR_SUCCESS, result); + JNI_CASE(env, "org/cef/network/CefURLRequest$Status", UR_IO_PENDING, + result); + JNI_CASE(env, "org/cef/network/CefURLRequest$Status", UR_CANCELED, + result); + JNI_CASE(env, "org/cef/network/CefURLRequest$Status", UR_FAILED, result); + } + return result.Release(); +} + +jobject GetJNIBrowser(JNIEnv* env, CefRefPtr browser) { + if (!browser) + return nullptr; + CefRefPtr client = + (ClientHandler*)browser->GetHost()->GetClient().get(); + return client->getBrowser(env, browser); +} + +} // namespace + +// static +const int ScopedJNIEnv::kDefaultLocalCapacity = 1024; + +ScopedJNIEnv::ScopedJNIEnv(jint local_capacity) + : ScopedJNIEnv(nullptr, local_capacity) {} + +ScopedJNIEnv::ScopedJNIEnv(JNIEnv* env, jint local_capacity) + : jenv_(env), local_capacity_(local_capacity) { + if (!jenv_) { + if (GetJNIEnv(&jenv_, &should_detach_) != JNI_OK || !jenv_) { + NOTREACHED() << "Failed to retrieve JNIEnv"; + return; + } + } + if (local_capacity_ > 0) { + if (jenv_->EnsureLocalCapacity(local_capacity_) != JNI_OK || + jenv_->PushLocalFrame(local_capacity_) != JNI_OK) { + LOG(WARNING) << "Failed to create local frame with capacity " + << local_capacity_; + local_capacity_ = 0; + } + } +} + +ScopedJNIEnv::~ScopedJNIEnv() { + if (!jenv_) + return; + if (local_capacity_ > 0) { + if (export_result_) { + *export_result_ = jenv_->PopLocalFrame(*export_result_); + } else { + jenv_->PopLocalFrame(nullptr); + } + } + if (should_detach_) { + DetachJNIEnv(); + } +} + +ScopedJNIObjectGlobal::ScopedJNIObjectGlobal(JNIEnv* env, jobject handle) + : jhandle_(nullptr) { + if (handle) { + jhandle_ = env->NewGlobalRef(handle); + DCHECK(jhandle_); + } +} + +ScopedJNIObjectGlobal::~ScopedJNIObjectGlobal() { + if (jhandle_) { + ScopedJNIEnv env; + if (env) + env->DeleteGlobalRef(jhandle_); + } +} + +jobject ScopedJNIObjectGlobal::get() const { + return jhandle_; +} + +ScopedJNIObjectGlobal::operator jobject() const { + return jhandle_; +} + +ScopedJNIObjectLocal::ScopedJNIObjectLocal(JNIEnv* env, jobject handle) + : ScopedJNIBase(env) { + jhandle_ = handle; +} + +ScopedJNIObjectLocal::ScopedJNIObjectLocal(JNIEnv* env, const char* class_name) + : ScopedJNIObjectLocal(env, NewJNIObject(env, class_name)) {} + +ScopedJNIObjectResult::ScopedJNIObjectResult(JNIEnv* env) + : ScopedJNIBase(env) {} + +ScopedJNIClass::ScopedJNIClass(JNIEnv* env, const char* class_name) + : ScopedJNIClass(env, FindClass(env, class_name)) {} + +ScopedJNIClass::ScopedJNIClass(JNIEnv* env, const jclass& cls) + : ScopedJNIBase(env) { + jhandle_ = cls; +} + +ScopedJNIString::ScopedJNIString(JNIEnv* env, const std::string& str) + : ScopedJNIBase(env) { + jhandle_ = NewJNIString(env, str); + DCHECK(jhandle_); +} + +ScopedJNIDate::ScopedJNIDate(JNIEnv* env, const CefBaseTime& time) + : ScopedJNIBase(env) { + jhandle_ = NewJNIDate(env, time); + DCHECK(jhandle_); +} + +ScopedJNICookie::ScopedJNICookie(JNIEnv* env, const CefCookie& cookie) + : ScopedJNIBase(env) { + jhandle_ = NewJNICookie(env, cookie); + DCHECK(jhandle_); +} + +ScopedJNITransitionType::ScopedJNITransitionType( + JNIEnv* env, + CefRequest::TransitionType transitionType) + : ScopedJNIBase(env) { + jhandle_ = NewJNITransitionType(env, transitionType); + DCHECK(jhandle_); +} + +ScopedJNIURLRequestStatus::ScopedJNIURLRequestStatus( + JNIEnv* env, + CefResourceRequestHandler::URLRequestStatus status) + : ScopedJNIBase(env) { + jhandle_ = NewJNIURLRequestStatus(env, status); + DCHECK(jhandle_); +} + +ScopedJNIStringResult::ScopedJNIStringResult(JNIEnv* env) + : ScopedJNIBase(env) {} + +ScopedJNIStringResult::ScopedJNIStringResult(JNIEnv* env, const jstring& str) + : ScopedJNIStringResult(env) { + jhandle_ = str; +} + +CefString ScopedJNIStringResult::GetCefString() const { + if (!jhandle_) + return CefString(); + return GetJNIString(env_, jhandle_); +} + +ScopedJNIBrowser::ScopedJNIBrowser(JNIEnv* env, CefRefPtr obj) + : ScopedJNIBase(env) { + if (obj) { + // Will return nullptr for browsers that represent native popup windows. + jhandle_ = GetJNIBrowser(env_, obj); + } else { + jhandle_ = nullptr; + } +} + +void ScopedJNIBrowser::SetHandle(jobject handle, bool should_delete) { + DCHECK(!jhandle_); + DCHECK(handle); + jhandle_ = handle; + delete_ref_ = should_delete; +} + +CefRefPtr ScopedJNIBrowser::GetCefObject() const { + if (!jhandle_) + return nullptr; + return GetJNIBrowser(env_, jhandle_); +} + +ScopedJNIAuthCallback::ScopedJNIAuthCallback(JNIEnv* env, + CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/callback/CefAuthCallback_N", + "CefAuthCallback") {} + +ScopedJNIDragData::ScopedJNIDragData(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/callback/CefDragData_N", + "CefDragData") {} + +ScopedJNIFrame::ScopedJNIFrame(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/browser/CefFrame_N", + "CefFrame") {} + +ScopedJNIMenuModel::ScopedJNIMenuModel(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/callback/CefMenuModel_N", + "CefMenuModel") {} + +ScopedJNIMessageRouter::ScopedJNIMessageRouter(JNIEnv* env, + CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/browser/CefMessageRouter_N", + "CefMessageRouter") {} + +ScopedJNIPostData::ScopedJNIPostData(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/network/CefPostData_N", + "CefPostData") {} + +ScopedJNIPostDataElement::ScopedJNIPostDataElement( + JNIEnv* env, + CefRefPtr obj) + : ScopedJNIObject( + env, + obj, + "org/cef/network/CefPostDataElement_N", + "CefPostDataElement") {} + +ScopedJNIPrintSettings::ScopedJNIPrintSettings(JNIEnv* env, + CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/misc/CefPrintSettings_N", + "CefPrintSettings") {} + +ScopedJNIRequest::ScopedJNIRequest(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/network/CefRequest_N", + "CefRequest") {} + +ScopedJNIResponse::ScopedJNIResponse(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/network/CefResponse_N", + "CefResponse") {} + +ScopedJNICallback::ScopedJNICallback(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject(env, + 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); + DCHECK(jhandle_); +} + +ScopedJNIBoolRef::operator bool() const { + return GetJNIBoolRef(env_, jhandle_); +} + +ScopedJNIIntRef::ScopedJNIIntRef(JNIEnv* env, int value) + : ScopedJNIBase(env) { + jhandle_ = NewJNIIntRef(env, value); + DCHECK(jhandle_); +} + +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); + DCHECK(jhandle_); +} + +ScopedJNIStringRef::operator CefString() const { + return GetJNIStringRef(env_, jhandle_); +} diff --git a/lib/jcef/native/jni_scoped_helpers.h b/lib/jcef/native/jni_scoped_helpers.h new file mode 100644 index 0000000..3e73e45 --- /dev/null +++ b/lib/jcef/native/jni_scoped_helpers.h @@ -0,0 +1,982 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef JCEF_NATIVE_JNI_SCOPED_HELPERS_H_ +#define JCEF_NATIVE_JNI_SCOPED_HELPERS_H_ + +#include + +#include + +#include "include/cef_auth_callback.h" +#include "include/cef_browser.h" +#include "include/cef_drag_data.h" +#include "include/cef_frame.h" +#include "include/cef_menu_model.h" +#include "include/cef_print_settings.h" +#include "include/cef_request.h" +#include "include/cef_resource_request_handler.h" +#include "include/cef_response.h" +#include "include/wrapper/cef_message_router.h" + +// +// -------- +// OVERVIEW +// -------- +// +// JCEF uses JNI bindings to support two-way communication between Java objects +// and native C++ objects. The life span of the binding may differ depending +// on the intended usage, and the Java and/or C++ objects may still exist after +// the binding has been terminated. Consequently, care must be taken to follow +// the intended usage for each object type. +// +// Some common usage patterns are: +// +// - Objects created from C++ code with life span terminated after execution +// of a single Java method callback (see `EXAMPLE 1` below). +// - Objects created from Java code with life span terminated via execution of +// the Java dispose() or finalize() method (see `EXAMPLE 2` below). +// - C++ objects that wrap Java objects for the purpose of executing Java +// method callbacks with life span terminated on deletion of the C++ object +// (see `EXAMPLE 3` below). +// +// The Java object representing a binding is often associated with the C++ +// object via the CefNative Java interface. When a C++ object is created the +// native code increments the C++ reference count and calls the setNativeRef +// method on the JNI handle. The C++ pointer address is passed to JNI using the +// `jlong` type and stored in the Java object using a `long N_CefHandle` member. +// This `long` value can be passed into future JNI function calls from Java code +// or retrieved from C++ code by calling the getNativeRef method on the JNI +// handle. When the binding is terminated (via a call to dispose()/finalize() or +// from C++ code) the setNativeRef method is called with a value of 0 and the +// C++ reference count is decremented, possibly triggering deletion of the C++ +// object. +// +// A C++ object that executes callbacks on a Java object will hold a global +// reference to that Java object's JNI handle. This will keep the Java object +// alive until after all of the associated C++ objects have been deleted. In +// most cases these Java objects will not extend CefNative and a new C++ object +// will be created on each callback. +// +// CefClient is a special case where the C++ object wraps a JNI handle and the +// Java object extends CefNative to avoid creation of a new C++ object on +// each callback. Care is taken with CefClient to explicitly release the C++ +// references on shutdown (via remove*Handler methods) and thereby avoid a +// reference loop between the C++ object and JNI handle. +// +// Below are examples of the common usage patterns for JCEF bindings. +// +// +// --------- +// EXAMPLE 1 +// --------- +// +// An object implemented in native code that is only ever created from native +// code and then passed to a Java callback. +// +// In this example CefSomeObject is implemented in native code and exposed to +// Java via an equivalent interface. The native object is associated with the +// Java object via CefNative, with life span controlled by the native caller. +// Because the Java object is scoped to the native method there's no need to +// support destruction via dispose() or finalize() from the Java side. +// +// For a complete example see CefContextMenuHandler.onBeforeContextMenu and +// CefMenuModel. +// +// Java client usage: +// +// // Extending a CefSomeHandler interface that has an onCallback method. +// class MyHandler extends CefSomeHandler { +// // Client callback that will executed from native code. +// @Override +// public void onCallback(CefSomeObject someObject) { +// // |someObject| is backed by a native CEF object and only valid for the +// // scope of this method. +// int something = someObject.getSomething(); +// } +// } +// +// Java implementation of org.cef.handler.CefSomeObject: +// +// // Only instantiated via CefSomeObject_N. +// public interface CefSomeObject { +// // Public interface methods... +// public abstract int getSomething(); +// } +// +// Java implementation of org.cef.handler.CefSomeObject_N: +// +// // Created from SomeHandler::OnCallback in native code. +// class CefSomeObject_N extends CefNativeAdapter implements CefSomeObject { +// CefSomeObject_N() {} +// +// // CefSomeObject implementation: +// @Override +// public int getSomething() { +// try { +// // Pass the native handle as a parameter for faster lookup. +// return N_GetSomething(getNativeRef(null)); +// } catch (UnsatisfiedLinkError ule) { +// ule.printStackTrace(); +// return -1; +// } +// } +// +// // This becomes a native JNI binding. +// private final native int N_GetSomething(long self); +// } +// +// C++ implementation of CefSomeObject_N.cpp: +// +// CefRefPtr GetSelf(jlong self) { +// return reinterpret_cast(self); +// } +// +// // Native implementation of N_GetSomething(). +// JNIEXPORT jint JNICALL +// Java_org_cef_handler_CefSomeObject_1N_N_1GetSomething(JNIEnv* env, +// jobject obj, +// jlong self) { +// CefRefPtr object = GetSelf(self); +// if (!object) +// return -1; +// return object->GetSomething(); +// } +// +// C++ implementation of the SomeHandler::OnCallback method: +// +// // Helper for creating a CefSomeObject JNI handle. +// class ScopedJNISomeObject : public ScopedJNIObject { +// public: +// ScopedJNISomeObject(JNIEnv* env, CefRefPtr obj) +// : ScopedJNIObject(env, +// obj, +// "org/cef/handler/CefSomeObject_N", +// "CefSomeObject") {} +// }; +// +// void SomeHandler::OnCallback() { +// // Create the JNI instance of CefSomeObject. +// ScopedJNISomeObject jsomeObject(env, model); +// // Disassociate from the Java object when |jsomeObject| is destroyed. +// jsomeObject.SetTemporary(); +// +// // Pass the CefSomeObject instance to CefSomeHandler.onCallback. +// JNI_CALL_VOID_METHOD(env, handle_, "onCallback", +// "(Lorg/cef/handler/CefSomeObject;)V", +// jsomeObject.get()); +// } +// +// +// --------- +// EXAMPLE 2 +// --------- +// +// An object implemented in native code that can be created and accessed from +// Java code. +// +// In this example CefSomeObject is implemented in native code and exposed to +// Java via an equivalent interface. The native object is associated with the +// Java object via CefNative, with life span controlled by the Java object. +// +// For a complete example see CefDragData. +// +// Java client usage: +// +// // Create and use a CefSomeObject which is backed by a native CEF object. +// CefSomeObject someObject = CefSomeObject.create(); +// int something = someObject.getSomething(); +// +// // Explicitly release the native CEF object when done. If we don't do this +// // the object may eventually be released via finalize() if/when garbage +// // collection is triggered. +// someObject.dispose(); +// +// Java implementation of org.cef.handler.CefSomeObject: +// +// public abstract class CefSomeObject { +// // Public interface methods... +// public abstract int getSomething(); +// +// // This constructor can't be called directly. Use create() instead. +// CefSomeObject() {} +// +// // Cleanup in case the user forgets to call dispose(). +// @Override +// protected void finalize() throws Throwable { +// dispose(); +// super.finalize(); +// } +// +// // Implemented in CefSomeObject_N to terminate the native binding. +// public abstract void dispose(); +// +// public static final CefSomeObject create() { +// return CefSomeObject_N.createNative(); +// } +// } +// +// Java implementation of org.cef.handler.CefSomeObject_N: +// +// class CefSomeObject_N extends CefSomeObject implements CefNative { +// // CefNative implementation: +// // Used internally to store a pointer to the CEF object. +// private long N_CefHandle = 0; +// +// @Override +// public void setNativeRef(String identifer, long nativeRef) { +// N_CefHandle = nativeRef; +// } +// +// @Override +// public long getNativeRef(String identifer) { +// return N_CefHandle; +// } +// +// CefSomeObject_N() { +// super(); +// } +// +// // CefSomeObject implementation: +// @Override +// public void dispose() { +// try { +// N_Dispose(); +// } catch (UnsatisfiedLinkError ule) { +// ule.printStackTrace(); +// } +// } +// +// public static CefDragData createNative() { +// try { +// return CefSomeObject_N.N_Create(); +// } catch (UnsatisfiedLinkError ule) { +// ule.printStackTrace(); +// return null; +// } +// } +// +// @Override +// public int getSomething() { +// try { +// // Pass the native handle as a parameter for faster lookup. +// return N_GetSomething(N_CefHandle); +// } catch (UnsatisfiedLinkError ule) { +// ule.printStackTrace(); +// return -1; +// } +// } +// +// // These become native JNI bindings. +// private final native static CefSomeObject_N N_Create(); +// private final native void N_Dispose(); +// private final native int N_GetSomething(long self); +// } +// +// C++ implementation of CefSomeObject_N.cpp: +// +// const char kCefClassName[] = "CefSomeObject"; +// +// CefRefPtr GetSelf(JNIEnv* env, jlong self) { +// return reinterpret_cast(self); +// } +// +// // Helper for creating a CefSomeObject JNI handle. +// class ScopedJNISomeObject : public ScopedJNIObject { +// public: +// ScopedJNISomeObject(JNIEnv* env, CefRefPtr obj) +// : ScopedJNIObject(env, +// obj, +// "org/cef/handler/CefSomeObject_N", +// kCefClassName) {} +// }; +// +// JNIEXPORT void JNICALL +// Java_org_cef_handler_CefSomeObject_1N_N_1Dispose(JNIEnv* env, +// jobject obj) { +// // Terminate the binding and release the native object reference that +// // was taken by ScopedJNISomeObject. The native object may be destroyed. +// SetCefForJNIObject(env, obj, nullptr, kCefClassName); +// } +// +// JNIEXPORT jobject JNICALL +// Java_org_cef_handler_CefSomeObject_1N_N_1Create(JNIEnv* env, jclass cls) { +// CefRefPtr object = CefSomeObject::Create(); +// +// // Create and return a new JNI handle that holds a reference to |object|. +// ScopedJNISomeObject jobject(env, object); +// return jobject.Release(); +// } +// +// JNIEXPORT jint JNICALL +// Java_org_cef_handler_CefSomeObject_1N_N_1GetSomething(JNIEnv* env, +// jobject obj, +// jlong self) { +// CefRefPtr object = GetSelf(env, self); +// if (!object) +// return -1; +// return object->GetSomething(); +// } +// +// +// --------- +// EXAMPLE 3 +// --------- +// +// A native interface that delegates callbacks to a Java interface. The native +// object is not associated with the Java object so multiple calls to +// getSomeHandler will create a new native object. +// +// In this example the CefSomeHandler interface exists in both native code and +// Java code. The client returns an instance of CefSomeHandler from the +// CefSourceHandler.getSomeHandler Java method. Native code then calls the +// CefSomeHandler.doSomething method at a later time. +// +// For a complete example see CefDisplayHandler. +// +// Java client usage: +// +// // Client implementation of CefSomeHandler. +// class MySomeHandler extends CefSomeHandlerAdapter { +// MySomeHandler() {} +// +// @Override +// public void doSomething() { /* Do something here... */ } +// } +// +// // Client implementation of an interface that returns a CefSomeHandler. +// class MySourceHandler extends CefSourceHandlerAdapter { +// @Override +// public CefSomeHandler getSomeHandler() { return new MySomeHandler(); } +// } +// +// // Somehow install the MySourceHandler and trigger a call to +// // getSomeHandler() from native code. +// CefContext.somehowInstallAndExecuteSourceHandler(new MySourceHandler()); +// +// Java implementation of org.cef.handler.CefSomeHandler: +// +// public interface CefSomeHandler { +// public void DoSomething(); +// } +// +// Java implementation of org.cef.handler.CefSomeHandlerAdapter: +// +// public abstract class CefSomeHandlerAdapter implements CefSomeHandler { +// @Override +// public void doSomething() {} +// } +// +// C++ implementation of some_handler.h/cpp: +// +// class SomeHandler : public CefSomeHandler { +// public: +// SomeHandler(JNIEnv* env, jobject handler); +// +// // CefSomeHandler methods: +// void DoSomething() override; +// +// private: +// // Manages a global JNI reference to the Java object. +// ScopedJNIObjectGlobal handle_; +// }; +// +// SomeHandler::SomeHandler(JNIEnv* env, jobject handler) +// : handle_(env, handler) {} +// +// void SomeHandler::DoSomething() { +// ScopedJNIEnv env; +// if (!env) +// return; +// JNI_CALL_VOID_METHOD(env, handle_, "doSomething", "()V"); +// } +// +// C++ implementation of the SourceHandler::GetSomeHandler method: +// +// CefRefPtr SourceHandler::GetSomeHandler() { +// ScopedJNIEnv env; +// if (!env) +// return nullptr; +// +// ScopedJNIObjectResult jresult(env); +// +// // Call CefSourceHandler.getSomeHandler() in Java code to get a +// // CefSomeHandler object. +// JNI_CALL_METHOD(env, handle_, "getSomeHandler", +// "()Lorg/cef/handler/CefSomeHandler;", Object, jresult); +// +// // Create and return a new SomeHandler C++ object that wraps the Java +// // object. +// return new SomeHandler(env, jresult); +// } +// + +// Type specialization helpers for SetCefForJNIObject. +struct SetCefForJNIObjectHelper { + static inline void AddRef(CefBaseScoped* obj) {} + static inline void Release(CefBaseScoped* obj) {} + + template + static inline T* Get(CefRawPtr obj) { + return obj; + } + + static inline void AddRef(CefBaseRefCounted* obj) { obj->AddRef(); } + static inline void Release(CefBaseRefCounted* obj) { obj->Release(); } + + template + static inline T* Get(CefRefPtr obj) { + return obj.get(); + } + + // For ref-counted implementations that don't derive from CefBaseRefCounted. + template + static inline void AddRef(base::RefCountedThreadSafe* obj) { + obj->AddRef(); + } + template + static inline void Release(base::RefCountedThreadSafe* obj) { + obj->Release(); + } +}; + +// Forward declarations required by the below template types. +jobject NewJNIObject(JNIEnv* env, const char* class_name); +template +bool SetCefForJNIObject(JNIEnv* env, jobject obj, T* base, const char* varName); +template +T* GetCefFromJNIObject(JNIEnv* env, jobject obj, const char* varName); + +class ScopedJNIEnv { + public: + static const int kDefaultLocalCapacity; + + // Retrieve the JNIEnv for the current thread or attach the VM to the current + // thread if necessary. + // If |local_capacity| > 0 a local frame will be created with the specified + // maximum number of local references. Otherwise, no local frame will be + // created. + ScopedJNIEnv(jint local_capacity = kDefaultLocalCapacity); + + // Like above, but using an already known JNIEnv. + ScopedJNIEnv(JNIEnv* env, jint local_capacity = kDefaultLocalCapacity); + + ~ScopedJNIEnv(); + + // If a local frame was created, export |result| to the previous local + // reference frame on destruction. + void set_export_result(jobject* result) { export_result_ = result; } + + // Explicit return. + JNIEnv* get() const { return jenv_; } + + // Implicit cast works in most cases. + operator JNIEnv*() const { return jenv_; } + + // Pointer override for forwarding calls to the JNIEnv. + JNIEnv* operator->() const { + DCHECK(jenv_); + return jenv_; + } + + private: + JNIEnv* jenv_; + jint local_capacity_; + bool should_detach_ = false; + jobject* export_result_ = nullptr; +}; + +// Used by the native counterpart of JCEF objects to hold a global JNI handle. +class ScopedJNIObjectGlobal { + public: + // Creates a global reference to |handle|. + ScopedJNIObjectGlobal(JNIEnv* env, jobject handle); + ~ScopedJNIObjectGlobal(); + + // Explicit return. + jobject get() const; + + // Implicit cast works in most cases. + operator jobject() const; + + protected: + jobject jhandle_; +}; + +// Base class for scoped JNI types. Most derived classes will populate +// |jhandle_| in the constructor. +template +class ScopedJNIBase { + public: + ScopedJNIBase(JNIEnv* env, bool should_delete = true) + : env_(env), jhandle_(nullptr), delete_ref_(should_delete) { + DCHECK(env_); + } + + virtual ~ScopedJNIBase() { + if (jhandle_ && delete_ref_) { + env_->DeleteLocalRef(jhandle_); + } + } + + // Explicit return for use with JNI_CALL_METHOD. + T get() const { return jhandle_; } + + // Implicit cast works in most cases. + operator T() const { return jhandle_; } + + // Returns and disassociates from the underlying handle. + T Release() { + T temp = jhandle_; + jhandle_ = nullptr; + return temp; + } + + protected: + JNIEnv* const env_; + T jhandle_; + bool delete_ref_; +}; + +// Manages a local handle to a JNI object. Use ScopedJNIObject instead if +// the Java class implements CefNative. +class ScopedJNIObjectLocal : public ScopedJNIBase { + public: + // A local reference to |handle| should already exist. + ScopedJNIObjectLocal(JNIEnv* env, jobject handle); + + // Create a new instance of the specified |class_name|. + ScopedJNIObjectLocal(JNIEnv* env, const char* class_name); +}; + +// Used for later assignment of a handle whose lifespan will then be managed. +// This will usually be a JNI object result parameter from JNI_CALL_METHOD. +class ScopedJNIObjectResult : public ScopedJNIBase { + public: + explicit ScopedJNIObjectResult(JNIEnv* env); + + jobject& operator=(const jobject& obj) { + DCHECK(!jhandle_); + jhandle_ = obj; + return jhandle_; + } +}; + +// Used for JNI objects that implement CefNative. +template > +class ScopedJNIObject : public ScopedJNIBase { + public: + // Attach to an existing JNI object handle. |should_delete| should be false + // if the handle is a parameter to or return value from a JNI function that + // this scoped object resides within. + ScopedJNIObject(JNIEnv* env, + jobject handle, + bool should_delete, + const char* cef_class_name) + : ScopedJNIBase(env, should_delete), + cef_class_name_(cef_class_name), + temporary_(false), + created_handle_(false) { + DCHECK(handle); + jhandle_ = handle; + } + + // Create a new JNI object handle that attaches to an existing CEF object. A + // reference will be taken to |obj| and associated with the JNI handle via the + // CefNative Java interface. The reference will later be invalidated using one + // of the following approaches, depending on the object's intended usage: + // 1. Via a JNI Dispose callback that is executed from the Java object's + // dispose() method. This is the preferred approach for long-lived objects + // as it gives the Java application explicit control over the CEF object's + // life span. + // 2. Via execution of a JNI callback that represents completion of a single + // use Cef*Callback object. + // 3. Via this object's destructor if SetTemporary() was called. This approach + // can be used to create Java objects that are only valid for the duration + // of a JNI method call. + // 4. Via a JNI Dispose callback that is executed from the Java object's + // finalize() method. This is the catch-all case if none of the above + // conditions trigger and should be used with caution because the + // finalize() method is not guaranteed to be called in a timely manner. + ScopedJNIObject(JNIEnv* env, + PtrT obj, + const char* jni_class_name, + const char* cef_class_name) + : ScopedJNIBase(env), + object_(obj), + cef_class_name_(cef_class_name), + temporary_(false), + created_handle_(false) { + if (obj) { + jhandle_ = NewJNIObject(env_, jni_class_name); + if (jhandle_) { + created_handle_ = true; + SetCefForJNIObject(env_, jhandle_, SetCefForJNIObjectHelper::Get(obj), + cef_class_name); + } + } + } + + virtual ~ScopedJNIObject() { + if (temporary_ && created_handle_) { + // Invalidate the Java object. + SetCefForJNIObject(env_, jhandle_, nullptr, cef_class_name_); + } + } + + // Attach to the specified |handle|. |should_delete| should be false if the + // handle is a parameter to or return value from a JNI callback function. + void SetHandle(jobject handle, bool should_delete) { + DCHECK(!jhandle_); + DCHECK(handle); + jhandle_ = handle; + delete_ref_ = should_delete; + } + + // Invalidate the Java object on destruction. + void SetTemporary() { + DCHECK(created_handle_); + temporary_ = true; + } + + // Get an existing native CEF object. + PtrT GetCefObject() { + if (object_) + return object_; + if (jhandle_) + object_ = GetCefFromJNIObject(env_, jhandle_, cef_class_name_); + return object_; + } + + // Get an existing or create a new native CEF object. + PtrT GetOrCreateCefObject() { + PtrT object = GetCefObject(); + if (!object && jhandle_) { + object = new T(env_, jhandle_); + SetCefForJNIObject(env_, jhandle_, SetCefForJNIObjectHelper::Get(object), + cef_class_name_); + object_ = object; + } + return object; + } + + protected: + PtrT object_; + const char* const cef_class_name_; + bool temporary_; + bool created_handle_; +}; + +// JNI class. Finding |class_name| may fail. +class ScopedJNIClass : public ScopedJNIBase { + public: + ScopedJNIClass(JNIEnv* env, const char* class_name); + ScopedJNIClass(JNIEnv* env, const jclass& cls); +}; + +// JNI string. +class ScopedJNIString : public ScopedJNIBase { + public: + ScopedJNIString(JNIEnv* env, const std::string& str); +}; + +// JNI date. +class ScopedJNIDate : public ScopedJNIBase { + public: + ScopedJNIDate(JNIEnv* env, const CefBaseTime& time); +}; + +// JNI cookie. +class ScopedJNICookie : public ScopedJNIBase { + public: + ScopedJNICookie(JNIEnv* env, const CefCookie& cookie); +}; + +// JNI TransitionType. +class ScopedJNITransitionType : public ScopedJNIBase { + public: + ScopedJNITransitionType(JNIEnv* env, + CefRequest::TransitionType transitionType); +}; + +// JNI URLRequestStatus. +class ScopedJNIURLRequestStatus : public ScopedJNIBase { + public: + ScopedJNIURLRequestStatus(JNIEnv* env, + CefResourceRequestHandler::URLRequestStatus status); +}; + +// Used for assignment of a handle whose lifespan will then be managed. +class ScopedJNIStringResult : public ScopedJNIBase { + public: + explicit ScopedJNIStringResult(JNIEnv* env); + ScopedJNIStringResult(JNIEnv* env, const jstring& str); + + jstring& operator=(const jstring& str) { + DCHECK(!jhandle_); + jhandle_ = str; + return jhandle_; + } + + jobject& operator=(const jobject& obj) { + return (jobject&)operator=((jstring)obj); + } + + // Get the associated CEF string. + CefString GetCefString() const; +}; + +// JNI CefBrowser object. This is a special case where the CefBrowser object +// must always already exist. +class ScopedJNIBrowser : public ScopedJNIBase { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIBrowser(JNIEnv* env, CefRefPtr obj = nullptr); + + // Attach to the specified |handle|. + void SetHandle(jobject handle, bool should_delete); + + // Get the associated CEF object. + CefRefPtr GetCefObject() const; +}; + +// JNI CefAuthCallback object. +class ScopedJNIAuthCallback : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIAuthCallback(JNIEnv* env, CefRefPtr obj = nullptr); +}; + +// JNI CefDragData object. +class ScopedJNIDragData : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIDragData(JNIEnv* env, CefRefPtr obj = nullptr); +}; + +// JNI CefFrame object. +class ScopedJNIFrame : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIFrame(JNIEnv* env, CefRefPtr obj = nullptr); +}; + +// JNI CefMenuModel object. +class ScopedJNIMenuModel : public ScopedJNIObject { + public: + // |obj| must be non-nullptr. + ScopedJNIMenuModel(JNIEnv* env, CefRefPtr obj); +}; + +// JNI CefMessageRouter object. +using CefMessageRouter = CefMessageRouterBrowserSide; +class ScopedJNIMessageRouter : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIMessageRouter(JNIEnv* env, + CefRefPtr obj = nullptr); +}; + +// JNI CefPostData object. +class ScopedJNIPostData : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIPostData(JNIEnv* env, CefRefPtr obj = nullptr); +}; + +// JNI CefPostDataElement object. +class ScopedJNIPostDataElement : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIPostDataElement(JNIEnv* env, + CefRefPtr obj = nullptr); +}; + +// JNI CefPrintSettings object. +class ScopedJNIPrintSettings : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIPrintSettings(JNIEnv* env, + CefRefPtr obj = nullptr); +}; + +// JNI CefRequest object. +class ScopedJNIRequest : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIRequest(JNIEnv* env, CefRefPtr obj = nullptr); +}; + +// JNI CefResponse object. +class ScopedJNIResponse : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + ScopedJNIResponse(JNIEnv* env, CefRefPtr obj = nullptr); +}; + +// JNI CefCallback object. +class ScopedJNICallback : public ScopedJNIObject { + public: + // If |obj| is nullptr the SetHandle method should be used. + 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: + ScopedJNIBoolRef(JNIEnv* env, bool value); + + // Implicit retrieval of the underlying value. + operator bool() const; +}; + +// JNI IntRef object. +class ScopedJNIIntRef : public ScopedJNIBase { + public: + ScopedJNIIntRef(JNIEnv* env, int value); + + // Implicit retrieval of the underlying value. + 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: + ScopedJNIStringRef(JNIEnv* env, const CefString& value); + + // Implicit retrieval of the underlying value. + operator CefString() const; +}; + +// Helper macros to call a method on the java side. +#define JNI_CALL_METHOD(env, obj, method, sig, type, storeIn, ...) \ + { \ + if (env && obj) { \ + ScopedJNIClass _cls(env, env->GetObjectClass(obj)); \ + jmethodID _methodId = env->GetMethodID(_cls, method, sig); \ + if (_methodId != nullptr) { \ + storeIn = env->Call##type##Method(obj, _methodId, ##__VA_ARGS__); \ + } \ + if (env->ExceptionOccurred()) { \ + env->ExceptionDescribe(); \ + env->ExceptionClear(); \ + } \ + } \ + } + +#define JNI_CALL_VOID_METHOD_EX(env, obj, method, sig, ...) \ + { \ + if (env && obj) { \ + ScopedJNIClass _cls(env, env->GetObjectClass(obj)); \ + jmethodID _methodId = env->GetMethodID(_cls, method, sig); \ + if (_methodId != nullptr) { \ + env->CallVoidMethod(obj, _methodId, ##__VA_ARGS__); \ + } \ + } \ + } + +#define JNI_CALL_VOID_METHOD(env, obj, method, sig, ...) \ + { \ + if (env && obj) { \ + ScopedJNIClass _cls(env, env->GetObjectClass(obj)); \ + jmethodID _methodId = env->GetMethodID(_cls, method, sig); \ + if (_methodId != nullptr) { \ + env->CallVoidMethod(obj, _methodId, ##__VA_ARGS__); \ + } \ + if (env->ExceptionOccurred()) { \ + env->ExceptionDescribe(); \ + env->ExceptionClear(); \ + } \ + } \ + } + +#define JNI_CALL_BOOLEAN_METHOD(out, env, obj, method, sig, ...) \ + { \ + if (env && obj) { \ + ScopedJNIClass _cls(env, env->GetObjectClass(obj)); \ + jmethodID _methodId = env->GetMethodID(_cls, method, sig); \ + if (_methodId != nullptr) { \ + out = env->CallBooleanMethod(obj, _methodId, ##__VA_ARGS__); \ + } \ + if (env->ExceptionOccurred()) { \ + env->ExceptionDescribe(); \ + env->ExceptionClear(); \ + } \ + } \ + } + +// Set the CEF base object for an existing JNI object. A reference will be +// added to the base object. If a previous base object existed a reference +// will be removed from that object. +template +bool SetCefForJNIObject(JNIEnv* env, + jobject obj, + T* base, + const char* varName) { + if (!obj) + return false; + + ScopedJNIString identifer(env, varName); + jlong previousValue = 0; + JNI_CALL_METHOD(env, obj, "getNativeRef", "(Ljava/lang/String;)J", Long, + previousValue, identifer.get()); + if (previousValue != 0) { + // Remove a reference from the previous base object. + SetCefForJNIObjectHelper::Release(reinterpret_cast(previousValue)); + } + + JNI_CALL_VOID_METHOD(env, obj, "setNativeRef", "(Ljava/lang/String;J)V", + identifer.get(), (jlong)base); + if (base) { + // Add a reference to the new base object. + SetCefForJNIObjectHelper::AddRef(base); + } + return true; +} + +// Retrieve the CEF base object from an existing JNI object. +template +T* GetCefFromJNIObject(JNIEnv* env, jobject obj, const char* varName) { + if (!obj) + return nullptr; + + ScopedJNIString identifer(env, varName); + jlong previousValue = 0; + JNI_CALL_METHOD(env, obj, "getNativeRef", "(Ljava/lang/String;)J", Long, + previousValue, identifer.get()); + if (previousValue != 0) + return reinterpret_cast(previousValue); + return nullptr; +} + +#endif // JCEF_NATIVE_JNI_SCOPED_HELPERS_H_ diff --git a/lib/jcef/native/jni_util.cpp b/lib/jcef/native/jni_util.cpp new file mode 100644 index 0000000..0b2fcfd --- /dev/null +++ b/lib/jcef/native/jni_util.cpp @@ -0,0 +1,1327 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "jni_util.h" + +#include +#include + +#include "jni_scoped_helpers.h" + +#include "include/cef_base.h" + +namespace { + +JavaVM* g_jvm = nullptr; + +jobject g_javaClassLoader = nullptr; + +} // namespace + +void SetJVM(JavaVM* jvm) { + ASSERT(!g_jvm); + g_jvm = jvm; +} + +JavaVM* GetJVM() { + return g_jvm; +} + +void SetJavaClassLoader(JNIEnv* env, jobject javaClassLoader) { + ASSERT(!g_javaClassLoader); + g_javaClassLoader = env->NewGlobalRef(javaClassLoader); +} + +jobject GetJavaClassLoader() { + return g_javaClassLoader; +} + +jobject NewJNIObject(JNIEnv* env, jclass cls) { + jmethodID initID = env->GetMethodID(cls, "", "()V"); + if (initID == 0) { + env->ExceptionClear(); + return nullptr; + } + + jobject obj = env->NewObject(cls, initID); + if (obj == nullptr) { + env->ExceptionClear(); + return nullptr; + } + + return obj; +} + +jobject NewJNIObject(JNIEnv* env, const char* class_name) { + ScopedJNIClass cls(env, class_name); + if (!cls) + return nullptr; + + return NewJNIObject(env, cls); +} + +jobject NewJNIObject(JNIEnv* env, + const char* class_name, + const char* sig, + ...) { + ScopedJNIClass cls(env, class_name); + if (!cls) + return nullptr; + + jmethodID initID = env->GetMethodID(cls, "", sig); + if (initID == 0) { + env->ExceptionClear(); + return nullptr; + } + + va_list ap; + va_start(ap, sig); + + jobject obj = env->NewObjectV(cls, initID, ap); + if (obj == nullptr) { + env->ExceptionClear(); + return nullptr; + } + + return obj; +} + +bool GetJNIBoolRef(JNIEnv* env, jobject jboolRef) { + jboolean boolRefRes = JNI_FALSE; + JNI_CALL_METHOD(env, jboolRef, "get", "()Z", Boolean, boolRefRes); + return (boolRefRes != JNI_FALSE); +} + +int GetJNIIntRef(JNIEnv* env, jobject jintRef) { + jint intRefRes = -1; + JNI_CALL_METHOD(env, jintRef, "get", "()I", Int, intRefRes); + 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); + return str.GetCefString(); +} + +void SetJNIBoolRef(JNIEnv* env, jobject jboolRef, bool boolValue) { + JNI_CALL_VOID_METHOD(env, jboolRef, "set", "(Z)V", + (boolValue ? JNI_TRUE : JNI_FALSE)); +} + +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) { + JNI_CALL_VOID_METHOD(env, jstringRef, "set", "(Ljava/lang/String;)V", + NewJNIString(env, stringValue)); +} + +jstring NewJNIString(JNIEnv* env, const std::string& str) { + return env->NewStringUTF(str.c_str()); +} + +CefString GetJNIString(JNIEnv* env, jstring jstr) { + CefString cef_str; + const char* chr = nullptr; + if (jstr) + chr = env->GetStringUTFChars(jstr, nullptr); + if (chr) + cef_str = chr; + if (jstr) + env->ReleaseStringUTFChars(jstr, chr); + return cef_str; +} + +jobjectArray NewJNIStringArray(JNIEnv* env, + const std::vector& vals) { + if (vals.empty()) + return nullptr; + + ScopedJNIClass cls(env, "java/lang/String"); + if (!cls) + return nullptr; + + const jsize size = static_cast(vals.size()); + jobjectArray arr = env->NewObjectArray(size, cls, nullptr); + + for (jsize i = 0; i < size; i++) { + ScopedJNIString str(env, vals[i]); + env->SetObjectArrayElement(arr, i, str); + } + + return arr; +} + +void GetJNIStringArray(JNIEnv* env, + jobjectArray jarray, + std::vector& vals) { + jsize argc = env->GetArrayLength(jarray); + for (jsize i = 0; i < argc; ++i) { + ScopedJNIStringResult str(env, + (jstring)env->GetObjectArrayElement(jarray, i)); + vals.push_back(str.GetCefString()); + } +} + +jobject NewJNIStringVector(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) { + AddJNIStringToVector(env, jvector, *iter); + } + return jvector.Release(); +} + +void AddJNIStringToVector(JNIEnv* env, jobject jvector, const CefString& str) { + ScopedJNIString argument(env, str); + JNI_CALL_VOID_METHOD(env, jvector, "addElement", "(Ljava/lang/Object;)V", + argument.get()); +} + +void GetJNIStringVector(JNIEnv* env, + jobject jvector, + std::vector& vals) { + if (!jvector) + return; + + jint jsize = 0; + JNI_CALL_METHOD(env, jvector, "size", "()I", Int, jsize); + + for (jint index = 0; index < jsize; index++) { + ScopedJNIStringResult jstr(env); + JNI_CALL_METHOD(env, jvector, "get", "(I)Ljava/lang/Object;", Object, jstr, + index); + vals.push_back(jstr.GetCefString()); + } +} + +jobject NewJNIStringMap(JNIEnv* env, + const std::map& vals) { + ScopedJNIObjectLocal jmap(env, "java/util/HashMap"); + if (!jmap) + return nullptr; + + for (auto iter = vals.begin(); iter != vals.end(); ++iter) { + ScopedJNIString jkey(env, iter->first); + ScopedJNIString jvalue(env, iter->second); + ScopedJNIObjectResult jresult(env); + JNI_CALL_METHOD(env, jmap, "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + Object, jresult, jkey.get(), jvalue.get()); + } + return jmap.Release(); +} + +void GetJNIStringMultiMap(JNIEnv* env, + jobject jheaderMap, + std::multimap& vals) { + if (!jheaderMap) + return; + + // public abstract java.util.Set> entrySet(); + ScopedJNIObjectResult jentrySet(env); + JNI_CALL_METHOD(env, jheaderMap, "entrySet", "()Ljava/util/Set;", Object, + jentrySet); + if (!jentrySet) + return; + + // public abstract java.lang.Object[] toArray(); + ScopedJNIObjectResult jentrySetValues(env); + JNI_CALL_METHOD(env, jentrySet, "toArray", "()[Ljava/lang/Object;", Object, + jentrySetValues); + if (!jentrySetValues) + return; + + jint length = env->GetArrayLength((jobjectArray)jentrySetValues.get()); + for (jint i = 0; i < length; i++) { + ScopedJNIObjectLocal jmapEntry( + env, + env->GetObjectArrayElement((jobjectArray)jentrySetValues.get(), i)); + if (!jmapEntry) + return; + ScopedJNIStringResult jkey(env); + ScopedJNIStringResult jvalue(env); + JNI_CALL_METHOD(env, jmapEntry, "getKey", "()Ljava/lang/Object;", Object, + jkey); + JNI_CALL_METHOD(env, jmapEntry, "getValue", "()Ljava/lang/Object;", Object, + jvalue); + vals.insert(std::make_pair(jkey.GetCefString(), jvalue.GetCefString())); + } +} + +void SetJNIStringMultiMap(JNIEnv* env, + jobject jheaderMap, + const std::multimap& vals) { + for (auto it = vals.begin(); it != vals.end(); ++it) { + ScopedJNIString jkey(env, it->first); + ScopedJNIString jvalue(env, it->second); + ScopedJNIObjectResult jresult(env); + JNI_CALL_METHOD(env, jheaderMap, "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + Object, jresult, jkey.get(), jvalue.get()); + } +} + +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; + + if (jConfig == nullptr) + return config; + ScopedJNIClass cls(env, + "org/cef/browser/CefMessageRouter$CefMessageRouterConfig"); + if (cls == nullptr) + return config; + + GetJNIFieldString(env, cls, jConfig, "jsQueryFunction", + &config.js_query_function); + GetJNIFieldString(env, cls, jConfig, "jsCancelFunction", + &config.js_cancel_function); + 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) { + default: + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_NONE, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_IO_PENDING, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_FAILED, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_ABORTED, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INVALID_ARGUMENT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INVALID_HANDLE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_FILE_NOT_FOUND, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_TIMED_OUT, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_FILE_TOO_BIG, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_UNEXPECTED, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_ACCESS_DENIED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_NOT_IMPLEMENTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INSUFFICIENT_RESOURCES, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_OUT_OF_MEMORY, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_UPLOAD_FILE_CHANGED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SOCKET_NOT_CONNECTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_FILE_EXISTS, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_FILE_PATH_TOO_LONG, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_FILE_NO_SPACE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_FILE_VIRUS_INFECTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_BLOCKED_BY_CLIENT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_NETWORK_CHANGED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$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_UPLOAD_STREAM_REWIND_NOT_SUPPORTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CONTEXT_SHUT_DOWN, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_BLOCKED_BY_RESPONSE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CLEARTEXT_NOT_PERMITTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CONNECTION_CLOSED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CONNECTION_RESET, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CONNECTION_REFUSED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CONNECTION_ABORTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CONNECTION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_NAME_NOT_RESOLVED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INTERNET_DISCONNECTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_PROTOCOL_ERROR, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_ADDRESS_INVALID, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_ADDRESS_UNREACHABLE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_CLIENT_AUTH_CERT_NEEDED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_TUNNEL_CONNECTION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_NO_SSL_VERSIONS_ENABLED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_VERSION_OR_CIPHER_MISMATCH, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_RENEGOTIATION_REQUESTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PROXY_AUTH_UNSUPPORTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_BAD_SSL_CLIENT_AUTH_CERT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CONNECTION_TIMED_OUT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SOCKS_CONNECTION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SOCKS_CONNECTION_HOST_UNREACHABLE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_ALPN_NEGOTIATION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_NO_RENEGOTIATION, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_DECOMPRESSION_FAILURE_ALERT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_BAD_RECORD_MAC_ALERT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PROXY_AUTH_REQUESTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PROXY_CONNECTION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PRECONNECT_MAX_SOCKET_LIMIT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PROXY_CERTIFICATE_INVALID, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_NAME_RESOLUTION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_NETWORK_ACCESS_DENIED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_TEMPORARILY_THROTTLED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_MSG_TOO_BIG, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_WS_PROTOCOL_ERROR, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_ADDRESS_IN_USE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_HANDSHAKE_NOT_COMPLETED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_BAD_PEER_PUBLIC_KEY, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_DECRYPT_ERROR_ALERT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_WS_THROTTLE_QUEUE_TOO_LARGE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_SERVER_CERT_CHANGED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_UNRECOGNIZED_NAME_ALERT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SOCKET_SET_RECEIVE_BUFFER_SIZE_ERROR, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SOCKET_SET_SEND_BUFFER_SIZE_ERROR, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_ICANN_NAME_COLLISION, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_SERVER_CERT_BAD_FORMAT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CT_STH_PARSING_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CT_STH_INCOMPLETE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CT_CONSISTENCY_PROOF_PARSING_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_OBSOLETE_CIPHER, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_WS_UPGRADE, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_READ_IF_READY_NOT_IMPLEMENTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_NO_BUFFER_SPACE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_CLIENT_AUTH_NO_COMMON_ALGORITHMS, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_EARLY_DATA_REJECTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_WRONG_VERSION_ON_EARLY_DATA, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_TLS13_DOWNGRADE_DETECTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SSL_KEY_USAGE_INCOMPATIBLE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INVALID_ECH_CONFIG_LIST, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_ECH_NOT_NEGOTIATED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_ECH_FALLBACK_CERTIFICATE_INVALID, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_COMMON_NAME_INVALID, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_DATE_INVALID, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_AUTHORITY_INVALID, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_CONTAINS_ERRORS, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_NO_REVOCATION_MECHANISM, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_UNABLE_TO_CHECK_REVOCATION, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_REVOKED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_INVALID, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_WEAK_SIGNATURE_ALGORITHM, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_NON_UNIQUE_NAME, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_WEAK_KEY, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_NAME_CONSTRAINT_VIOLATION, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$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_KNOWN_INTERCEPTION_BLOCKED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_CERT_END, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_INVALID_URL, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_DISALLOWED_URL_SCHEME, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_UNKNOWN_URL_SCHEME, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INVALID_REDIRECT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_TOO_MANY_REDIRECTS, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_UNSAFE_REDIRECT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_UNSAFE_PORT, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INVALID_RESPONSE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INVALID_CHUNKED_ENCODING, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_METHOD_NOT_SUPPORTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_UNEXPECTED_PROXY_AUTH, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_EMPTY_RESPONSE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_RESPONSE_HEADERS_TOO_BIG, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PAC_SCRIPT_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_REQUEST_RANGE_NOT_SATISFIABLE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_MALFORMED_IDENTITY, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CONTENT_DECODING_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_NETWORK_IO_SUSPENDED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SYN_REPLY_NOT_RECEIVED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_ENCODING_CONVERSION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_NO_SUPPORTED_PROXIES, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_HTTP2_PROTOCOL_ERROR, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INVALID_AUTH_CREDENTIALS, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_UNSUPPORTED_AUTH_SCHEME, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_ENCODING_DETECTION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_MISSING_AUTH_CREDENTIALS, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_MISCONFIGURED_AUTH_ENVIRONMENT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_RESPONSE_BODY_TOO_BIG_TO_DRAIN, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INCOMPLETE_HTTP2_HEADERS, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PAC_NOT_IN_DHCP, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_HTTP2_SERVER_REFUSED_STREAM, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_HTTP2_PING_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CONTENT_LENGTH_MISMATCH, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INCOMPLETE_CHUNKED_ENCODING, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_QUIC_PROTOCOL_ERROR, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_RESPONSE_HEADERS_TRUNCATED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_QUIC_HANDSHAKE_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_HTTP2_INADEQUATE_TRANSPORT_SECURITY, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_HTTP2_FLOW_CONTROL_ERROR, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_HTTP2_FRAME_SIZE_ERROR, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_HTTP2_COMPRESSION_ERROR, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PROXY_AUTH_REQUESTED_WITH_NO_CONNECTION, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_HTTP_1_1_REQUIRED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PROXY_HTTP_1_1_REQUIRED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PAC_SCRIPT_TERMINATED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INVALID_HTTP_RESPONSE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$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_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_HTTP_RESPONSE_CODE_FAILURE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_QUIC_CERT_ROOT_NOT_KNOWN, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_QUIC_GOAWAY_REQUEST_CAN_BE_RETRIED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_CACHE_MISS, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_READ_FAILURE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_WRITE_FAILURE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_OPERATION_NOT_SUPPORTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_OPEN_FAILURE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_CREATE_FAILURE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_CACHE_RACE, + jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_CHECKSUM_READ_FAILURE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_CHECKSUM_MISMATCH, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_LOCK_TIMEOUT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_AUTH_FAILURE_AFTER_READ, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_ENTRY_NOT_SUITABLE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_DOOM_FAILURE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CACHE_OPEN_OR_CREATE_FAILURE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INSECURE_RESPONSE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_NO_PRIVATE_KEY_FOR_CERT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_ADD_USER_CERT_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INVALID_SIGNED_EXCHANGE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_INVALID_WEB_BUNDLE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_TRUST_TOKEN_OPERATION_FAILED, jerrorCode); + 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_PKCS12_IMPORT_BAD_PASSWORD, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PKCS12_IMPORT_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_IMPORT_CA_CERT_NOT_CA, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_IMPORT_CERT_ALREADY_EXISTS, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_IMPORT_CA_CERT_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_IMPORT_SERVER_CERT_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PKCS12_IMPORT_INVALID_MAC, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PKCS12_IMPORT_INVALID_FILE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PKCS12_IMPORT_UNSUPPORTED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_KEY_GENERATION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_PRIVATE_KEY_EXPORT_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_SELF_SIGNED_CERT_GENERATION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_CERT_DATABASE_CHANGED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_DNS_MALFORMED_RESPONSE, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_DNS_SERVER_REQUIRES_TCP, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_DNS_SERVER_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_DNS_TIMED_OUT, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_DNS_CACHE_MISS, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_DNS_SEARCH_EMPTY, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_DNS_SORT_ERROR, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_DNS_SECURE_RESOLVER_HOSTNAME_RESOLUTION_FAILED, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_DNS_NAME_HTTPS_ONLY, jerrorCode); + JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", + ERR_DNS_REQUEST_CANCELLED, jerrorCode); + } + 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; + + if (jerrorCode) { + jint jcode = 0; + JNI_CALL_METHOD(env, jerrorCode, "getCode", "()I", Int, jcode); + errorCode = static_cast(jcode); + } + + return errorCode; +} + +bool GetJNIFieldObject(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + jobject* value, + const char* object_type) { + jfieldID field = env->GetFieldID(cls, field_name, object_type); + if (field) { + *value = env->GetObjectField(obj, field); + return *value != nullptr; + } + env->ExceptionClear(); + return false; +} + +bool GetJNIFieldString(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + CefString* value) { + jobject fieldobj = nullptr; + if (GetJNIFieldObject(env, cls, obj, field_name, &fieldobj, + "Ljava/lang/String;")) { + ScopedJNIStringResult str(env, (jstring)fieldobj); + *value = str.GetCefString(); + return true; + } + return false; +} + +bool GetJNIFieldDate(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + 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); + CefTime cef_time; + cef_time.SetDoubleT((double)(timestamp / 1000)); + cef_time_to_basetime(&cef_time, value); + return true; + } + return false; +} + +bool GetJNIFieldBoolean(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + int* value) { + jfieldID field = env->GetFieldID(cls, field_name, "Z"); + if (field) { + *value = env->GetBooleanField(obj, field) != JNI_FALSE ? 1 : 0; + return true; + } + env->ExceptionClear(); + return false; +} + +bool GetJNIFieldDouble(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + double* value) { + jfieldID field = env->GetFieldID(cls, field_name, "D"); + if (field) { + *value = env->GetDoubleField(obj, field); + return true; + } + env->ExceptionClear(); + return false; +} + +bool GetJNIFieldInt(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + int* value) { + jfieldID field = env->GetFieldID(cls, field_name, "I"); + if (field) { + *value = env->GetIntField(obj, field); + return true; + } + env->ExceptionClear(); + return false; +} + +bool GetJNIFieldLong(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + jlong* value) { + jfieldID field = env->GetFieldID(cls, field_name, "J"); + if (field) { + *value = env->GetLongField(obj, field); + return true; + } + env->ExceptionClear(); + return false; +} + +bool SetJNIFieldInt(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + int value) { + jfieldID field = env->GetFieldID(cls, field_name, "I"); + if (field) { + env->SetIntField(obj, field, value); + return true; + } + env->ExceptionClear(); + return false; +} + +bool SetJNIFieldDouble(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + double value) { + jfieldID field = env->GetFieldID(cls, field_name, "D"); + if (field) { + env->SetDoubleField(obj, field, value); + return true; + } + env->ExceptionClear(); + return false; +} + +bool SetJNIFieldBoolean(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + int value) { + jfieldID field = env->GetFieldID(cls, field_name, "Z"); + if (field) { + env->SetBooleanField(obj, field, value == 0 ? 0 : 1); + return true; + } + env->ExceptionClear(); + return false; +} + +bool GetJNIFieldStaticInt(JNIEnv* env, + jclass cls, + const char* field_name, + int* value) { + jfieldID field = env->GetStaticFieldID(cls, field_name, "I"); + if (field) { + *value = env->GetStaticIntField(cls, field); + return true; + } + env->ExceptionClear(); + return false; +} + +bool CallJNIMethodI_V(JNIEnv* env, + jclass cls, + jobject obj, + const char* method_name, + int* value) { + jmethodID methodID = env->GetMethodID(cls, method_name, "()I"); + if (methodID) { + *value = env->CallIntMethod(obj, methodID); + return true; + } + env->ExceptionClear(); + return false; +} + +bool CallJNIMethodC_V(JNIEnv* env, + jclass cls, + jobject obj, + const char* method_name, + char16_t* value) { + jmethodID methodID = env->GetMethodID(cls, method_name, "()C"); + if (methodID) { + *value = env->CallCharMethod(obj, methodID); + return true; + } + env->ExceptionClear(); + return false; +} + +CefSize GetJNISize(JNIEnv* env, jobject obj) { + CefSize size; + + ScopedJNIClass cls(env, "java/awt/Dimension"); + if (!cls) + return size; + + int width, height; + if (GetJNIFieldInt(env, cls, obj, "width", &width) && + GetJNIFieldInt(env, cls, obj, "height", &height)) { + size.Set(width, height); + } + return size; +} + +CefRect GetJNIRect(JNIEnv* env, jobject obj) { + CefRect rect; + + ScopedJNIClass cls(env, "java/awt/Rectangle"); + if (!cls) + return rect; + + int x, y, width, height; + if (GetJNIFieldInt(env, cls, obj, "x", &x) && + GetJNIFieldInt(env, cls, obj, "y", &y) && + GetJNIFieldInt(env, cls, obj, "width", &width) && + GetJNIFieldInt(env, cls, obj, "height", &height)) { + rect.Set(x, y, width, height); + return rect; + } + + return rect; +} + +bool GetJNIPoint(JNIEnv* env, jobject obj, int* x, int* y) { + ScopedJNIClass cls(env, "java/awt/Point"); + if (!cls) + return false; + + if (GetJNIFieldInt(env, cls, obj, "x", x) && + GetJNIFieldInt(env, cls, obj, "y", y)) { + return true; + } + + return false; +} + +CefRefPtr GetJNIBrowser(JNIEnv* env, jobject jbrowser) { + return GetCefFromJNIObject(env, jbrowser, "CefBrowser"); +} + +jobject GetJNIEnumValue(JNIEnv* env, + const char* class_name, + const char* enum_valname) { + ScopedJNIClass cls(env, class_name); + if (!cls) + return nullptr; + + std::string tmp; + tmp.append("L").append(class_name).append(";"); + + jfieldID fieldId = env->GetStaticFieldID(cls, enum_valname, tmp.c_str()); + if (!fieldId) + return nullptr; + + return env->GetStaticObjectField(cls, fieldId); +} + +bool IsJNIEnumValue(JNIEnv* env, + jobject jenum, + const char* class_name, + const char* enum_valname) { + if (!jenum) + return false; + + ScopedJNIObjectLocal compareTo( + env, GetJNIEnumValue(env, class_name, enum_valname)); + if (compareTo) { + jboolean isEqual = JNI_FALSE; + JNI_CALL_METHOD(env, jenum, "equals", "(Ljava/lang/Object;)Z", Boolean, + isEqual, compareTo.get()); + return (isEqual != JNI_FALSE); + } + return false; +} diff --git a/lib/jcef/native/jni_util.h b/lib/jcef/native/jni_util.h new file mode 100644 index 0000000..6028427 --- /dev/null +++ b/lib/jcef/native/jni_util.h @@ -0,0 +1,250 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef JCEF_NATIVE_JNI_UTIL_H_ +#define JCEF_NATIVE_JNI_UTIL_H_ + +#include +#include +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_frame.h" +#include "include/wrapper/cef_message_router.h" +#include "util.h" + +// Set the global JVM reference. +void SetJVM(JavaVM* jvm); +JavaVM* GetJVM(); + +// Sets the java class loader to use for creating java objects in native code. +// We have to use a class loader instead of the JNIEnv::FindClass method +// because JNIEnv::FindClass always uses the system class loader if called +// from a non-Java thread, which will not work if the embedding Java code +// uses a custom class loader for JCEF classes (e.g. in JavaWebStart). +void SetJavaClassLoader(JNIEnv* env, jobject javaClassLoader); +jobject GetJavaClassLoader(); + +#if defined(OS_WIN) +HWND GetHwndOfCanvas(jobject canvas, JNIEnv* env); +#elif defined(OS_LINUX) +unsigned long GetDrawableOfCanvas(jobject canvas, JNIEnv* env); +#endif + +// Create a new JNI object and call the default constructor. +jobject NewJNIObject(JNIEnv* env, jclass cls); +jobject NewJNIObject(JNIEnv* env, const char* class_name); +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); + +// Create a new String value. +jstring NewJNIString(JNIEnv* env, const std::string& str); + +// Retrieve a String value. +CefString GetJNIString(JNIEnv* env, jstring jstr); + +// Create a new array of String values. +jobjectArray NewJNIStringArray(JNIEnv* env, const std::vector& vals); + +// Retrieve the String values from an array. +void GetJNIStringArray(JNIEnv* env, + jobjectArray jarray, + std::vector& vals); + +// Create a new vector of String values. +jobject NewJNIStringVector(JNIEnv* env, const std::vector& vals); + +// Add a String value to the Vector. +void AddJNIStringToVector(JNIEnv* env, jobject jvector, const CefString& str); + +// Retrieve the String values from a Vector. +void GetJNIStringVector(JNIEnv* env, + jobject jvector, + std::vector& vals); + +// Create a new Map of String values. +jobject NewJNIStringMap(JNIEnv* env, + const std::map& vals); + +// |jheaderMap| is expected to be a Map. +void GetJNIStringMultiMap(JNIEnv* env, + jobject jheaderMap, + std::multimap& vals); + +// |jheaderMap| is expected to be a Map. +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, + const char* field_name, + jobject* value, + const char* object_type); + +bool GetJNIFieldString(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + CefString* value); + +bool GetJNIFieldDate(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + CefBaseTime* value); + +bool GetJNIFieldBoolean(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + int* value); + +// Retrieve the int value stored in the |field_name| field of |cls|. +bool GetJNIFieldInt(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + int* value); + +bool GetJNIFieldDouble(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + double* value); + +// Retrieve the long value stored in the |field_name| field of |cls|. +bool GetJNIFieldLong(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + jlong* value); + +// Set the int value stored in the |field_name| field of |cls|. +bool SetJNIFieldInt(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + int value); +bool SetJNIFieldDouble(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + double value); +bool SetJNIFieldBoolean(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + int value); + +// Retrieve the static int value stored in the |field_name| field of |cls|. +bool GetJNIFieldStaticInt(JNIEnv* env, + jclass cls, + const char* field_name, + int* value); + +// Call a JNI method that returns an int and accepts no arguments. +bool CallJNIMethodI_V(JNIEnv* env, + jclass cls, + jobject obj, + const char* method_name, + int* value); + +// Call a JNI method that returns a char and accepts no arguments. +bool CallJNIMethodC_V(JNIEnv* env, + jclass cls, + jobject obj, + const char* method_name, + char16_t* value); + +// Rertieve the CefSize equivalent of a java.awt.Dimension. +CefSize GetJNISize(JNIEnv* env, jobject obj); + +// Retrieve the CefRect equivalent of a java.awt.Rectangle. +CefRect GetJNIRect(JNIEnv* env, jobject obj); + +// Retrieve the value of a java.awt.Point. +bool GetJNIPoint(JNIEnv* env, jobject obj, int* x, int* y); + +// Get the existing CEF browser counterpart. +CefRefPtr GetJNIBrowser(JNIEnv* env, jobject jbrowser); + +jobject GetJNIEnumValue(JNIEnv* env, + const char* class_name, + const char* enum_valname); + +bool IsJNIEnumValue(JNIEnv* env, + jobject jenum, + const char* class_name, + const char* enum_valname); + +// Helper macro for handling jni enum values in a switch statement +#define JNI_CASE(env, cls, type, result) \ + case type: \ + result = GetJNIEnumValue(env, cls, #type); \ + break; + +// Helper macros for defining and retrieving static ints. +#define JNI_STATIC(name) _static_##name + +#define JNI_STATIC_DEFINE_INT(env, cls, name) \ + JNI_STATIC_DEFINE_INT_RV(env, cls, name, ); + +#define JNI_STATIC_DEFINE_INT_RV(env, cls, name, rv) \ + static int JNI_STATIC(name) = -1; \ + if (JNI_STATIC(name) == -1 && \ + !GetJNIFieldStaticInt(env, cls, #name, &JNI_STATIC(name))) \ + return rv; + +#define JNI_GET_BROWSER_OR_RETURN(env, jbrowser, ...) \ + GetJNIBrowser(env, jbrowser); \ + if (!browser.get()) \ + return __VA_ARGS__; + +#endif // JCEF_NATIVE_JNI_UTIL_H_ diff --git a/lib/jcef/native/jni_util_linux.cpp b/lib/jcef/native/jni_util_linux.cpp new file mode 100644 index 0000000..acd28e1 --- /dev/null +++ b/lib/jcef/native/jni_util_linux.cpp @@ -0,0 +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. + +#include "jni_util.h" + +#include +#include +#include + +unsigned long GetDrawableOfCanvas(jobject canvas, JNIEnv* env) { + JAWT awt; + JAWT_DrawingSurface* ds; + JAWT_DrawingSurfaceInfo* dsi; + JAWT_X11DrawingSurfaceInfo* dsi_x11; + jint lock; + + // Get the AWT. + awt.version = JAWT_VERSION_1_4; + JAWT_GetAWT(env, &awt); + + // Get the drawing surface. + ds = awt.GetDrawingSurface(env, canvas); + assert(ds != nullptr); + + // Lock the drawing surface. + // May fail during shutdown. + lock = ds->Lock(ds); + if (lock & JAWT_LOCK_ERROR) { + return 0; + } + + // Get the drawing surface info. + dsi = ds->GetDrawingSurfaceInfo(ds); + if (dsi == nullptr) { + // Unlock the drawing surface + ds->Unlock(ds); + return 0; + } + + // Get the platform-specific drawing info. + dsi_x11 = (JAWT_X11DrawingSurfaceInfo*)dsi->platformInfo; + Drawable result = dsi_x11->drawable; + + // Free the drawing surface info + ds->FreeDrawingSurfaceInfo(dsi); + // Unlock the drawing surface + ds->Unlock(ds); + // Free the drawing surface + awt.FreeDrawingSurface(ds); + + return result; +} diff --git a/lib/jcef/native/jni_util_win.cpp b/lib/jcef/native/jni_util_win.cpp new file mode 100644 index 0000000..a1fa572 --- /dev/null +++ b/lib/jcef/native/jni_util_win.cpp @@ -0,0 +1,55 @@ +// 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 "jni_util.h" + +#include +#include +#include + +HWND GetHwndOfCanvas(jobject canvas, JNIEnv* env) { + JAWT awt; + JAWT_DrawingSurface* ds; + JAWT_DrawingSurfaceInfo* dsi; + JAWT_Win32DrawingSurfaceInfo* dsi_win; + jboolean bGetAwt; + jint lock; + + // Get the AWT. + awt.version = JAWT_VERSION_1_4; + bGetAwt = JAWT_GetAWT(env, &awt); + assert(bGetAwt != JNI_FALSE); + + // Get the drawing surface. + ds = awt.GetDrawingSurface(env, canvas); + assert(ds != nullptr); + + // Lock the drawing surface. + // May fail during shutdown. + lock = ds->Lock(ds); + if (lock & JAWT_LOCK_ERROR) { + return 0; + } + + // Get the drawing surface info. + dsi = ds->GetDrawingSurfaceInfo(ds); + if (dsi == nullptr) { + // Unlock the drawing surface + ds->Unlock(ds); + return 0; + } + + // Get the platform-specific drawing info. + dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo; + HWND result = dsi_win->hwnd; + + // Free the drawing surface info + ds->FreeDrawingSurfaceInfo(dsi); + // Unlock the drawing surface + ds->Unlock(ds); + // Free the drawing surface + awt.FreeDrawingSurface(ds); + + return result; +} diff --git a/lib/jcef/native/jsdialog_handler.cpp b/lib/jcef/native/jsdialog_handler.cpp new file mode 100644 index 0000000..594e0da --- /dev/null +++ b/lib/jcef/native/jsdialog_handler.cpp @@ -0,0 +1,131 @@ +// 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 "jsdialog_handler.h" + +#include "client_handler.h" +#include "jni_util.h" +#include "util.h" + +namespace { + +// JNI CefJSDialogCallback object. +class ScopedJNIJSDialogCallback : public ScopedJNIObject { + public: + ScopedJNIJSDialogCallback(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject( + env, + obj, + "org/cef/callback/CefJSDialogCallback_N", + "CefJSDialogCallback") {} +}; + +} // namespace + +JSDialogHandler::JSDialogHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +bool JSDialogHandler::OnJSDialog(CefRefPtr browser, + const CefString& origin_url, + CefJSDialogHandler::JSDialogType dialog_type, + const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIString joriginUrl(env, origin_url); + ScopedJNIString jmessageText(env, message_text); + ScopedJNIString jdefaultPromptText(env, default_prompt_text); + ScopedJNIJSDialogCallback jcallback(env, callback); + ScopedJNIBoolRef jsuppressMessage(env, suppress_message); + + ScopedJNIObjectResult jdialogType(env); + switch (dialog_type) { + default: + JNI_CASE(env, "org/cef/handler/CefJSDialogHandler$JSDialogType", + JSDIALOGTYPE_ALERT, jdialogType); + JNI_CASE(env, "org/cef/handler/CefJSDialogHandler$JSDialogType", + JSDIALOGTYPE_CONFIRM, jdialogType); + JNI_CASE(env, "org/cef/handler/CefJSDialogHandler$JSDialogType", + JSDIALOGTYPE_PROMPT, jdialogType); + } + + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD( + env, handle_, "onJSDialog", + "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;" + "Lorg/cef/handler/CefJSDialogHandler$JSDialogType;Ljava/lang/String;" + "Ljava/lang/String;Lorg/cef/callback/CefJSDialogCallback;Lorg/cef/misc/" + "BoolRef;)Z", + Boolean, jresult, jbrowser.get(), joriginUrl.get(), jdialogType.get(), + jmessageText.get(), jdefaultPromptText.get(), jcallback.get(), + jsuppressMessage.get()); + + suppress_message = jsuppressMessage; + + 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 JSDialogHandler::OnBeforeUnloadDialog( + CefRefPtr browser, + const CefString& message_text, + bool is_reload, + CefRefPtr callback) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIString jmessageText(env, message_text); + ScopedJNIJSDialogCallback jcallback(env, callback); + + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "onBeforeUnloadDialog", + "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;ZLorg/cef/" + "callback/CefJSDialogCallback;)Z", + Boolean, jresult, jbrowser.get(), jmessageText.get(), + (is_reload ? JNI_TRUE : JNI_FALSE), 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); +} + +void JSDialogHandler::OnResetDialogState(CefRefPtr browser) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + + JNI_CALL_VOID_METHOD(env, handle_, "onResetDialogState", + "(Lorg/cef/browser/CefBrowser;)V", jbrowser.get()); +} + +void JSDialogHandler::OnDialogClosed(CefRefPtr browser) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + + JNI_CALL_VOID_METHOD(env, handle_, "onDialogClosed", + "(Lorg/cef/browser/CefBrowser;)V", jbrowser.get()); +} diff --git a/lib/jcef/native/jsdialog_handler.h b/lib/jcef/native/jsdialog_handler.h new file mode 100644 index 0000000..0e86b54 --- /dev/null +++ b/lib/jcef/native/jsdialog_handler.h @@ -0,0 +1,44 @@ +// 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 JCEF_NATIVE_JSDIALOG_HANDLER_H_ +#define JCEF_NATIVE_JSDIALOG_HANDLER_H_ +#pragma once + +#include +#include "include/cef_jsdialog_handler.h" + +#include "jni_scoped_helpers.h" + +// JSDialogHandler implementation. +class JSDialogHandler : public CefJSDialogHandler { + public: + JSDialogHandler(JNIEnv* env, jobject handler); + + // CefJSDialogHandler methods + virtual bool OnJSDialog(CefRefPtr browser, + const CefString& origin_url, + JSDialogType dialog_type, + const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) override; + + virtual bool OnBeforeUnloadDialog( + CefRefPtr browser, + const CefString& message_text, + bool is_reload, + CefRefPtr callback) override; + + virtual void OnResetDialogState(CefRefPtr browser) override; + virtual void OnDialogClosed(CefRefPtr browser) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(JSDialogHandler); +}; + +#endif // JCEF_NATIVE_JSDIALOG_HANDLER_H_ diff --git a/lib/jcef/native/keyboard_handler.cpp b/lib/jcef/native/keyboard_handler.cpp new file mode 100644 index 0000000..88bb640 --- /dev/null +++ b/lib/jcef/native/keyboard_handler.cpp @@ -0,0 +1,88 @@ +// 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 "keyboard_handler.h" + +#include "client_handler.h" +#include "jni_util.h" +#include "util.h" + +namespace { + +jobject NewJNIKeyEvent(JNIEnv* env, const CefKeyEvent& event) { + ScopedJNIObjectResult jkeyEventType(env); + switch (event.type) { + default: + JNI_CASE(env, "org/cef/handler/CefKeyboardHandler$CefKeyEvent$EventType", + KEYEVENT_RAWKEYDOWN, jkeyEventType); + JNI_CASE(env, "org/cef/handler/CefKeyboardHandler$CefKeyEvent$EventType", + KEYEVENT_KEYDOWN, jkeyEventType); + JNI_CASE(env, "org/cef/handler/CefKeyboardHandler$CefKeyEvent$EventType", + KEYEVENT_KEYUP, jkeyEventType); + JNI_CASE(env, "org/cef/handler/CefKeyboardHandler$CefKeyEvent$EventType", + KEYEVENT_CHAR, jkeyEventType); + } + + return NewJNIObject( + env, "org/cef/handler/CefKeyboardHandler$CefKeyEvent", + "(Lorg/cef/handler/CefKeyboardHandler$CefKeyEvent$EventType;IIIZCCZ)V", + jkeyEventType.get(), event.modifiers, event.windows_key_code, + event.native_key_code, (event.is_system_key != 0 ? JNI_TRUE : JNI_FALSE), + event.character, event.unmodified_character, + (event.focus_on_editable_field != 0 ? JNI_TRUE : JNI_FALSE)); +} + +} // namespace + +KeyboardHandler::KeyboardHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +bool KeyboardHandler::OnPreKeyEvent(CefRefPtr browser, + const CefKeyEvent& event, + CefEventHandle os_event, + bool* is_keyboard_shortcut) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIObjectLocal jevent(env, NewJNIKeyEvent(env, event)); + if (!jevent) + return false; + + ScopedJNIBoolRef jboolRef(env, *is_keyboard_shortcut); + if (!jboolRef) + return false; + + jboolean jresult = JNI_FALSE; + ScopedJNIBrowser jbrowser(env, browser); + JNI_CALL_METHOD(env, handle_, "onPreKeyEvent", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/handler/" + "CefKeyboardHandler$CefKeyEvent;Lorg/cef/misc/BoolRef;)Z", + Boolean, jresult, jbrowser.get(), jevent.get(), + jboolRef.get()); + + *is_keyboard_shortcut = jboolRef; + return (jresult != JNI_FALSE); +} + +bool KeyboardHandler::OnKeyEvent(CefRefPtr browser, + const CefKeyEvent& event, + CefEventHandle os_event) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIObjectLocal jevent(env, NewJNIKeyEvent(env, event)); + if (!jevent) + return false; + + jboolean jresult = JNI_FALSE; + ScopedJNIBrowser jbrowser(env, browser); + JNI_CALL_METHOD(env, handle_, "onKeyEvent", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/handler/" + "CefKeyboardHandler$CefKeyEvent;)Z", + Boolean, jresult, jbrowser.get(), jevent.get()); + + return (jresult != JNI_FALSE); +} diff --git a/lib/jcef/native/keyboard_handler.h b/lib/jcef/native/keyboard_handler.h new file mode 100644 index 0000000..1d8ef86 --- /dev/null +++ b/lib/jcef/native/keyboard_handler.h @@ -0,0 +1,37 @@ +// 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 JCEF_NATIVE_KEYBOARD_HANDLER_H_ +#define JCEF_NATIVE_KEYBOARD_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_keyboard_handler.h" + +#include "jni_scoped_helpers.h" + +// KeyboardHandler implementation. +class KeyboardHandler : public CefKeyboardHandler { + public: + KeyboardHandler(JNIEnv* env, jobject handler); + + // CefKeyboardHandler methods + virtual bool OnPreKeyEvent(CefRefPtr browser, + const CefKeyEvent& event, + CefEventHandle os_event, + bool* is_keyboard_shortcut) override; + + virtual bool OnKeyEvent(CefRefPtr browser, + const CefKeyEvent& event, + CefEventHandle os_event) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(KeyboardHandler); +}; + +#endif // JCEF_NATIVE_KEYBOARD_HANDLER_H_ diff --git a/lib/jcef/native/life_span_handler.cpp b/lib/jcef/native/life_span_handler.cpp new file mode 100644 index 0000000..aaa8c25 --- /dev/null +++ b/lib/jcef/native/life_span_handler.cpp @@ -0,0 +1,131 @@ +// 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 "life_span_handler.h" + +#include "client_handler.h" +#include "jni_util.h" +#include "util.h" + +LifeSpanHandler::LifeSpanHandler(JNIEnv* env, jobject handler) + : handle_(env, 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, + bool user_gesture, + const CefPopupFeatures& popupFeatures, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings, + CefRefPtr& extra_info, + bool* no_javascript_access) { + if (browser->GetHost()->IsWindowRenderingDisabled()) { + // Cancel popups in off-screen rendering mode. + return true; + } + + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIString jtargetUrl(env, target_url); + ScopedJNIString jtargetFrameName(env, target_frame_name); + jboolean jreturn = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "onBeforePopup", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/" + "CefFrame;Ljava/lang/String;Ljava/lang/String;)Z", + Boolean, jreturn, jbrowser.get(), jframe.get(), + jtargetUrl.get(), jtargetFrameName.get()); + + return (jreturn != JNI_FALSE); +} + +void LifeSpanHandler::OnAfterCreated(CefRefPtr browser) { + ScopedJNIEnv env; + if (!env || jbrowsers_.empty()) + return; + + util::AddCefBrowser(browser); + + jobject jbrowser = jbrowsers_.front(); + jbrowsers_.pop_front(); + + CefRefPtr client = + (ClientHandler*)browser->GetHost()->GetClient().get(); + client->OnAfterCreated(); + + // Add a reference to |browser| that will be released in + // LifeSpanHandler::OnBeforeClose. + if (SetCefForJNIObject(env, jbrowser, browser.get(), "CefBrowser")) { + JNI_CALL_VOID_METHOD(env, handle_, "onAfterCreated", + "(Lorg/cef/browser/CefBrowser;)V", jbrowser); + } + + // Release the global ref added in CefBrowser_N::create. + env->DeleteGlobalRef(jbrowser); +} + +bool LifeSpanHandler::DoClose(CefRefPtr browser) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + jboolean jreturn = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "doClose", "(Lorg/cef/browser/CefBrowser;)Z", + Boolean, jreturn, jbrowser.get()); + + return (jreturn != JNI_FALSE); +} + +void LifeSpanHandler::OnBeforeClose(CefRefPtr browser) { + REQUIRE_UI_THREAD(); + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + + JNI_CALL_VOID_METHOD(env, handle_, "onBeforeClose", + "(Lorg/cef/browser/CefBrowser;)V", jbrowser.get()); + + // Clear the browser pointer member of the Java object. This will + // release the browser reference that was added in + // LifeSpanHandler::OnAfterCreated. + SetCefForJNIObject(env, jbrowser, nullptr, "CefBrowser"); + + CefRefPtr client = + (ClientHandler*)browser->GetHost()->GetClient().get(); + client->OnBeforeClose(browser); +} + +void LifeSpanHandler::OnAfterParentChanged(CefRefPtr browser) { + REQUIRE_UI_THREAD(); + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + + JNI_CALL_VOID_METHOD(env, handle_, "onAfterParentChanged", + "(Lorg/cef/browser/CefBrowser;)V", jbrowser.get()); +} + +void LifeSpanHandler::registerJBrowser(jobject browser) { + jbrowsers_.push_back(browser); +} + +void LifeSpanHandler::unregisterJBrowser(jobject browser) { + jbrowsers_.remove(browser); +} diff --git a/lib/jcef/native/life_span_handler.h b/lib/jcef/native/life_span_handler.h new file mode 100644 index 0000000..97ef6e5 --- /dev/null +++ b/lib/jcef/native/life_span_handler.h @@ -0,0 +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. + +#ifndef JCEF_NATIVE_LIFE_SPAN_HANDLER_H_ +#define JCEF_NATIVE_LIFE_SPAN_HANDLER_H_ +#pragma once + +#include + +#include + +#include "include/cef_life_span_handler.h" + +#include "jni_scoped_helpers.h" + +// LifeSpanHandler implementation. +class LifeSpanHandler : public CefLifeSpanHandler { + public: + LifeSpanHandler(JNIEnv* env, jobject handler); + + // CefLifeSpanHandler methods: + virtual bool OnBeforePopup(CefRefPtr browser, + CefRefPtr frame, + int popup_id, + const CefString& target_url, + const CefString& target_frame_name, + WindowOpenDisposition target_disposition, + bool user_gesture, + const CefPopupFeatures& popupFeatures, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings, + CefRefPtr& extra_info, + bool* no_javascript_access) override; + virtual void OnAfterCreated(CefRefPtr browser) override; + virtual bool DoClose(CefRefPtr browser) override; + virtual void OnBeforeClose(CefRefPtr browser) override; + + void OnAfterParentChanged(CefRefPtr browser); + + void registerJBrowser(jobject browser); + void unregisterJBrowser(jobject browser); + + protected: + ScopedJNIObjectGlobal handle_; + std::list jbrowsers_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(LifeSpanHandler); +}; + +#endif // JCEF_NATIVE_LIFE_SPAN_HANDLER_H_ diff --git a/lib/jcef/native/load_handler.cpp b/lib/jcef/native/load_handler.cpp new file mode 100644 index 0000000..eeff0ee --- /dev/null +++ b/lib/jcef/native/load_handler.cpp @@ -0,0 +1,89 @@ +// 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 "load_handler.h" + +#include "client_handler.h" +#include "jni_util.h" +#include "util.h" + +LoadHandler::LoadHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +void LoadHandler::OnLoadingStateChange(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + + JNI_CALL_VOID_METHOD(env, handle_, "onLoadingStateChange", + "(Lorg/cef/browser/CefBrowser;ZZZ)V", jbrowser.get(), + (isLoading ? JNI_TRUE : JNI_FALSE), + (canGoBack ? JNI_TRUE : JNI_FALSE), + (canGoForward ? JNI_TRUE : JNI_FALSE)); +} + +// TODO(jcef): Expose the |transition_type| argument. +void LoadHandler::OnLoadStart(CefRefPtr browser, + CefRefPtr frame, + TransitionType transition_type) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNITransitionType jtransitionType(env, transition_type); + + JNI_CALL_VOID_METHOD(env, handle_, "onLoadStart", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/" + "CefFrame;Lorg/cef/network/CefRequest$TransitionType;)V", + jbrowser.get(), jframe.get(), jtransitionType.get()); +} + +void LoadHandler::OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + + JNI_CALL_VOID_METHOD( + env, handle_, "onLoadEnd", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;I)V", + jbrowser.get(), jframe.get(), httpStatusCode); +} + +void LoadHandler::OnLoadError(CefRefPtr browser, + CefRefPtr frame, + ErrorCode errorCode, + const CefString& errorText, + const CefString& failedUrl) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIObjectLocal jErrorCode(env, NewJNIErrorCode(env, errorCode)); + ScopedJNIString jerrorText(env, errorText); + ScopedJNIString jfailedUrl(env, failedUrl); + + JNI_CALL_VOID_METHOD( + env, handle_, "onLoadError", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/cef/handler/" + "CefLoadHandler$ErrorCode;Ljava/lang/String;Ljava/lang/String;)V", + jbrowser.get(), jframe.get(), jErrorCode.get(), jerrorText.get(), + jfailedUrl.get()); +} diff --git a/lib/jcef/native/load_handler.h b/lib/jcef/native/load_handler.h new file mode 100644 index 0000000..f46205d --- /dev/null +++ b/lib/jcef/native/load_handler.h @@ -0,0 +1,44 @@ +// 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 JCEF_NATIVE_LOAD_HANDLER_H_ +#define JCEF_NATIVE_LOAD_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_load_handler.h" + +#include "jni_scoped_helpers.h" + +// LoadHandler implementation. +class LoadHandler : public CefLoadHandler { + public: + LoadHandler(JNIEnv* env, jobject handler); + + // CefLoadHandler methods + void OnLoadingStateChange(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) override; + void OnLoadStart(CefRefPtr browser, + CefRefPtr frame, + TransitionType transition_type) override; + void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) override; + void OnLoadError(CefRefPtr browser, + CefRefPtr frame, + ErrorCode errorCode, + const CefString& errorText, + const CefString& failedUrl) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(LoadHandler); +}; + +#endif // JCEF_NATIVE_LOAD_HANDLER_H_ diff --git a/lib/jcef/native/message_router_handler.cpp b/lib/jcef/native/message_router_handler.cpp new file mode 100644 index 0000000..793ccf7 --- /dev/null +++ b/lib/jcef/native/message_router_handler.cpp @@ -0,0 +1,79 @@ +// 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 "message_router_handler.h" + +#include "jni_util.h" + +namespace { + +using CefQueryCallback = CefMessageRouterBrowserSide::Callback; + +// JNI CefQueryCallback object. +class ScopedJNIQueryCallback : public ScopedJNIObject { + public: + ScopedJNIQueryCallback(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/callback/CefQueryCallback_N", + "CefQueryCallback") {} +}; + +} // namespace + +MessageRouterHandler::MessageRouterHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +bool MessageRouterHandler::OnQuery( + CefRefPtr browser, + CefRefPtr frame, + int64_t query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIString jrequest(env, request); + ScopedJNIQueryCallback jcallback(env, callback); + + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "onQuery", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/" + "CefFrame;JLjava/lang/String;ZLorg/cef/" + "callback/CefQueryCallback;)Z", + Boolean, jresult, jbrowser.get(), jframe.get(), + (jlong)query_id, jrequest.get(), + persistent ? JNI_TRUE : JNI_FALSE, 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; +} + +void MessageRouterHandler::OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64_t query_id) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + + JNI_CALL_VOID_METHOD( + env, handle_, "onQueryCanceled", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;J)V", + jbrowser.get(), jframe.get(), (jlong)query_id); +} diff --git a/lib/jcef/native/message_router_handler.h b/lib/jcef/native/message_router_handler.h new file mode 100644 index 0000000..90b4ae7 --- /dev/null +++ b/lib/jcef/native/message_router_handler.h @@ -0,0 +1,39 @@ +// 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 JCEF_NATIVE_MESSAGE_ROUTER_HANDLER_H_ +#define JCEF_NATIVE_MESSAGE_ROUTER_HANDLER_H_ +#pragma once + +#include + +#include "include/wrapper/cef_message_router.h" + +#include "jni_scoped_helpers.h" + +// MessageRouterHandler implementation. +class MessageRouterHandler : public CefMessageRouterBrowserSide::Handler, + public CefBaseRefCounted { + public: + MessageRouterHandler(JNIEnv* env, jobject handler); + + // CefMessageRouterHandler methods + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64_t query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) override; + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64_t query_id) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(MessageRouterHandler); +}; + +#endif // JCEF_NATIVE_MESSAGE_ROUTER_HANDLER_H_ diff --git a/lib/jcef/native/pdf_print_callback.cpp b/lib/jcef/native/pdf_print_callback.cpp new file mode 100644 index 0000000..26d507c --- /dev/null +++ b/lib/jcef/native/pdf_print_callback.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2017 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 "pdf_print_callback.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" +#include "util.h" + +PdfPrintCallback::PdfPrintCallback(JNIEnv* env, jobject jcallback) + : handle_(env, jcallback) {} + +void PdfPrintCallback::OnPdfPrintFinished(const CefString& path, bool ok) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIString jpath(env, path); + JNI_CALL_VOID_METHOD(env, handle_, "onPdfPrintFinished", + "(Ljava/lang/String;Z)V", jpath.get(), (jboolean)ok); +} diff --git a/lib/jcef/native/pdf_print_callback.h b/lib/jcef/native/pdf_print_callback.h new file mode 100644 index 0000000..2acc9a4 --- /dev/null +++ b/lib/jcef/native/pdf_print_callback.h @@ -0,0 +1,30 @@ +// Copyright (c) 2017 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_PDF_PRINT_CALLBACK_H_ +#define JCEF_NATIVE_PDF_PRINT_CALLBACK_H_ +#pragma once + +#include + +#include "include/cef_browser.h" + +#include "jni_scoped_helpers.h" + +// PdfPrintCallback implementation. +class PdfPrintCallback : public CefPdfPrintCallback { + public: + PdfPrintCallback(JNIEnv* env, jobject jcallback); + + // PdfPrintCallback methods + virtual void OnPdfPrintFinished(const CefString& path, bool ok) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(PdfPrintCallback); +}; + +#endif // JCEF_NATIVE_PDF_PRINT_CALLBACK_H_ diff --git a/lib/jcef/native/print_handler.cpp b/lib/jcef/native/print_handler.cpp new file mode 100644 index 0000000..ab39c62 --- /dev/null +++ b/lib/jcef/native/print_handler.cpp @@ -0,0 +1,154 @@ +// 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 "print_handler.h" + +#include "jni_util.h" +#include "util.h" + +namespace { + +// JNI CefPrintDialogCallback object. +class ScopedJNIPrintDialogCallback + : public ScopedJNIObject { + public: + ScopedJNIPrintDialogCallback(JNIEnv* env, + CefRefPtr obj) + : ScopedJNIObject( + env, + obj, + "org/cef/callback/CefPrintDialogCallback_N", + "CefPrintDialogCallback") {} +}; + +// JNI CefPrintJobCallback object. +class ScopedJNIPrintJobCallback : public ScopedJNIObject { + public: + ScopedJNIPrintJobCallback(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject( + env, + obj, + "org/cef/callback/CefPrintJobCallback_N", + "CefPrintJobCallback") {} +}; + +} // namespace + +PrintHandler::PrintHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +void PrintHandler::OnPrintStart(CefRefPtr browser) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + + JNI_CALL_VOID_METHOD(env, handle_, "onPrintStart", + "(Lorg/cef/browser/CefBrowser;)V", jbrowser.get()); +} + +void PrintHandler::OnPrintSettings(CefRefPtr browser, + CefRefPtr settings, + bool get_defaults) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIPrintSettings jsettings(env, settings); + jsettings.SetTemporary(); + + JNI_CALL_VOID_METHOD( + env, handle_, "onPrintSettings", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/misc/CefPrintSettings;Z)V", + jbrowser.get(), jsettings.get(), get_defaults ? JNI_TRUE : JNI_FALSE); +} + +bool PrintHandler::OnPrintDialog(CefRefPtr browser, + bool has_selection, + CefRefPtr callback) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIPrintDialogCallback jcallback(env, callback); + + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "onPrintDialog", + "(Lorg/cef/browser/CefBrowser;ZLorg/cef/callback/" + "CefPrintDialogCallback;)Z", + Boolean, jresult, jbrowser.get(), + (has_selection ? JNI_TRUE : JNI_FALSE), 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 PrintHandler::OnPrintJob(CefRefPtr browser, + const CefString& document_name, + const CefString& pdf_file_path, + CefRefPtr callback) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIString jdocumentName(env, document_name); + ScopedJNIString jpdfFilePath(env, pdf_file_path); + ScopedJNIPrintJobCallback jcallback(env, callback); + + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD( + env, handle_, "onPrintJob", + "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;Ljava/lang/String;" + "Lorg/cef/callback/CefPrintJobCallback;)Z", + Boolean, jresult, jbrowser.get(), jdocumentName.get(), jpdfFilePath.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(); + } + + return (jresult != JNI_FALSE); +} + +void PrintHandler::OnPrintReset(CefRefPtr browser) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + + JNI_CALL_VOID_METHOD(env, handle_, "onPrintReset", + "(Lorg/cef/browser/CefBrowser;)V", jbrowser.get()); +} + +CefSize PrintHandler::GetPdfPaperSize(CefRefPtr browser, + int device_units_per_inch) { + ScopedJNIEnv env; + if (!env) + return CefSize(0, 0); + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIObjectResult jresult(env); + + JNI_CALL_METHOD(env, handle_, "getPdfPaperSize", + "(Lorg/cef/browser/CefBrowser;I)Ljava/awt/Dimension;", Object, + jresult, jbrowser.get(), (jint)device_units_per_inch); + if (!jresult) + return CefSize(0, 0); + + return GetJNISize(env, jresult); +} diff --git a/lib/jcef/native/print_handler.h b/lib/jcef/native/print_handler.h new file mode 100644 index 0000000..2491d2d --- /dev/null +++ b/lib/jcef/native/print_handler.h @@ -0,0 +1,49 @@ +// 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 JCEF_NATIVE_PRINT_HANDLER_H_ +#define JCEF_NATIVE_PRINT_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_print_handler.h" + +#include "jni_scoped_helpers.h" + +// PrintHandler implementation. +class PrintHandler : public CefPrintHandler { + public: + PrintHandler(JNIEnv* env, jobject handler); + + // CefPrintHandler methods + virtual void OnPrintStart(CefRefPtr browser) override; + + virtual void OnPrintSettings(CefRefPtr browser, + CefRefPtr settings, + bool get_defaults) override; + + virtual bool OnPrintDialog( + CefRefPtr browser, + bool has_selection, + CefRefPtr callback) override; + + virtual bool OnPrintJob(CefRefPtr browser, + const CefString& document_name, + const CefString& pdf_file_path, + CefRefPtr callback) override; + + virtual void OnPrintReset(CefRefPtr browser) override; + + virtual CefSize GetPdfPaperSize(CefRefPtr browser, + int device_units_per_inch) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(PrintHandler); +}; + +#endif // CEF_TESTS_CEFCLIENT_CONTEXT_MENU_HANDLER_H_ diff --git a/lib/jcef/native/render_handler.cpp b/lib/jcef/native/render_handler.cpp new file mode 100644 index 0000000..dee7428 --- /dev/null +++ b/lib/jcef/native/render_handler.cpp @@ -0,0 +1,347 @@ +// 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 "render_handler.h" + +#include "client_handler.h" +#include "jni_util.h" + +namespace { + +// Create a new java.awt.Rectangle. +jobject NewJNIRect(JNIEnv* env, const CefRect& rect) { + ScopedJNIClass cls(env, "java/awt/Rectangle"); + if (!cls) + return nullptr; + + ScopedJNIObjectLocal obj(env, NewJNIObject(env, cls)); + if (!obj) + return nullptr; + + if (SetJNIFieldInt(env, cls, obj, "x", rect.x) && + SetJNIFieldInt(env, cls, obj, "y", rect.y) && + SetJNIFieldInt(env, cls, obj, "width", rect.width) && + SetJNIFieldInt(env, cls, obj, "height", rect.height)) { + return obj.Release(); + } + + return nullptr; +} + +jobject NewJNIScreenInfo(JNIEnv* env, CefScreenInfo& screenInfo) { + ScopedJNIClass cls(env, "org/cef/handler/CefScreenInfo"); + if (!cls) { + return nullptr; + } + + ScopedJNIObjectLocal obj(env, NewJNIObject(env, cls)); + if (!obj) { + return nullptr; + } + + if (SetJNIFieldDouble(env, cls, obj, "device_scale_factor", + (double)screenInfo.device_scale_factor) && + SetJNIFieldInt(env, cls, obj, "depth", screenInfo.depth) && + SetJNIFieldInt(env, cls, obj, "depth_per_component", + screenInfo.depth_per_component) && + SetJNIFieldBoolean(env, cls, obj, "is_monochrome", + screenInfo.is_monochrome) && + SetJNIFieldInt(env, cls, obj, "x", screenInfo.rect.x) && + SetJNIFieldInt(env, cls, obj, "y", screenInfo.rect.y) && + SetJNIFieldInt(env, cls, obj, "width", screenInfo.rect.width) && + SetJNIFieldInt(env, cls, obj, "height", screenInfo.rect.height) && + SetJNIFieldInt(env, cls, obj, "available_x", + screenInfo.available_rect.x) && + SetJNIFieldInt(env, cls, obj, "available_y", + screenInfo.available_rect.y) && + SetJNIFieldInt(env, cls, obj, "available_width", + screenInfo.available_rect.width) && + SetJNIFieldInt(env, cls, obj, "available_height", + screenInfo.available_rect.height)) { + return obj.Release(); + } + + return nullptr; +} + +bool GetJNIScreenInfo(JNIEnv* env, jobject jScreenInfo, CefScreenInfo& dest) { + ScopedJNIClass cls(env, "org/cef/handler/CefScreenInfo"); + if (!cls) { + return false; + } + + ScopedJNIObjectLocal obj(env, jScreenInfo); + if (!obj) { + return false; + } + double tmp; + if (!GetJNIFieldDouble(env, cls, obj, "device_scale_factor", &tmp)) { + return false; + } + dest.device_scale_factor = (float)tmp; + + if (GetJNIFieldInt(env, cls, obj, "depth", &(dest.depth)) && + GetJNIFieldInt(env, cls, obj, "depth_per_component", + &(dest.depth_per_component)) && + GetJNIFieldBoolean(env, cls, obj, "is_monochrome", + &(dest.is_monochrome)) && + GetJNIFieldInt(env, cls, obj, "x", &(dest.rect.x)) && + GetJNIFieldInt(env, cls, obj, "y", &(dest.rect.y)) && + GetJNIFieldInt(env, cls, obj, "width", &(dest.rect.width)) && + GetJNIFieldInt(env, cls, obj, "height", &(dest.rect.height)) && + GetJNIFieldInt(env, cls, obj, "available_x", &(dest.available_rect.x)) && + GetJNIFieldInt(env, cls, obj, "available_y", &(dest.available_rect.y)) && + GetJNIFieldInt(env, cls, obj, "available_width", + &(dest.available_rect.width)) && + GetJNIFieldInt(env, cls, obj, "available_height", + &(dest.available_rect.height)) + + ) { + return true; + } else { + return false; + } +} + +// create a new array of java.awt.Rectangle. +jobjectArray NewJNIRectArray(JNIEnv* env, const std::vector& vals) { + if (vals.empty()) + return nullptr; + + ScopedJNIClass cls(env, "java/awt/Rectangle"); + if (!cls) + return nullptr; + + const jsize size = static_cast(vals.size()); + jobjectArray arr = env->NewObjectArray(size, cls, nullptr); + + for (jsize i = 0; i < size; i++) { + ScopedJNIObjectLocal rect_obj(env, NewJNIRect(env, vals[i])); + env->SetObjectArrayElement(arr, i, rect_obj); + } + + return arr; +} + +// Create a new java.awt.Point. +jobject NewJNIPoint(JNIEnv* env, int x, int y) { + ScopedJNIClass cls(env, "java/awt/Point"); + if (!cls) + return nullptr; + + ScopedJNIObjectLocal obj(env, NewJNIObject(env, cls)); + if (!obj) + return nullptr; + + if (SetJNIFieldInt(env, cls, obj, "x", x) && + SetJNIFieldInt(env, cls, obj, "y", y)) { + return obj.Release(); + } + + return nullptr; +} + +} // namespace + +RenderHandler::RenderHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +bool RenderHandler::GetRootScreenRect(CefRefPtr browser, + CefRect& rect) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + bool result = GetViewRect(jbrowser, rect); + return result; +} + +void RenderHandler::GetViewRect(CefRefPtr browser, CefRect& rect) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + if (!GetViewRect(jbrowser, rect)) { + rect = CefRect(0, 0, 1, 1); + } +} + +/// +// Called to allow the client to fill in the CefScreenInfo object with +// appropriate values. Return true if the |screen_info| structure has been +// modified. +// +// If the screen info rectangle is left empty the rectangle from GetViewRect +// will be used. If the rectangle is still empty or invalid popups may not be +// drawn correctly. +/// +/*--cef()--*/ +bool RenderHandler::GetScreenInfo(CefRefPtr browser, + CefScreenInfo& screen_info) { + ScopedJNIEnv env; + if (!env) { + return false; + } + + ScopedJNIObjectLocal jScreenInfo(env, NewJNIScreenInfo(env, screen_info)); + if (!jScreenInfo) { + return false; + } + ScopedJNIBrowser jbrowser(env, browser); + jboolean jresult = 0; + + JNI_CALL_BOOLEAN_METHOD( + jresult, env, jbrowser.get(), "getScreenInfo", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/handler/CefScreenInfo;)Z", + jbrowser.get(), jScreenInfo.get()); + + if (jresult) { + if (GetJNIScreenInfo(env, jScreenInfo.get(), screen_info)) { + return true; + } + } + + return false; +} + +bool RenderHandler::GetScreenPoint(CefRefPtr browser, + int viewX, + int viewY, + int& screenX, + int& screenY) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + return GetScreenPoint(jbrowser, viewX, viewY, screenX, screenY); +} + +void RenderHandler::OnPopupShow(CefRefPtr browser, bool show) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + JNI_CALL_VOID_METHOD(env, handle_, "onPopupShow", + "(Lorg/cef/browser/CefBrowser;Z)V", jbrowser.get(), + (jboolean)show); +} + +void RenderHandler::OnPopupSize(CefRefPtr browser, + const CefRect& rect) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIObjectLocal jrect(env, NewJNIRect(env, rect)); + if (!jrect) + return; + + ScopedJNIBrowser jbrowser(env, browser); + JNI_CALL_VOID_METHOD(env, handle_, "onPopupSize", + "(Lorg/cef/browser/CefBrowser;Ljava/awt/Rectangle;)V", + jbrowser.get(), jrect.get()); +} + +void RenderHandler::OnPaint(CefRefPtr browser, + PaintElementType type, + const RectList& dirtyRects, + const void* buffer, + int width, + int height) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + jboolean jtype = type == PET_VIEW ? JNI_FALSE : JNI_TRUE; + ScopedJNIObjectLocal jrectArray(env, NewJNIRectArray(env, dirtyRects)); + ScopedJNIObjectLocal jdirectBuffer( + env, + env->NewDirectByteBuffer(const_cast(buffer), width * height * 4)); + JNI_CALL_VOID_METHOD(env, handle_, "onPaint", + "(Lorg/cef/browser/CefBrowser;Z[Ljava/awt/" + "Rectangle;Ljava/nio/ByteBuffer;II)V", + jbrowser.get(), jtype, jrectArray.get(), + jdirectBuffer.get(), width, height); +} + +bool RenderHandler::StartDragging(CefRefPtr browser, + CefRefPtr drag_data, + DragOperationsMask allowed_ops, + int x, + int y) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIDragData jdragdata(env, drag_data); + jdragdata.SetTemporary(); + jboolean jresult = JNI_FALSE; + JNI_CALL_METHOD( + env, handle_, "startDragging", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/callback/CefDragData;III)Z", + Boolean, jresult, jbrowser.get(), jdragdata.get(), (jint)allowed_ops, + (jint)x, (jint)y); + + return (jresult != JNI_FALSE); +} + +void RenderHandler::UpdateDragCursor(CefRefPtr browser, + DragOperation operation) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + JNI_CALL_VOID_METHOD(env, handle_, "updateDragCursor", + "(Lorg/cef/browser/CefBrowser;I)V", jbrowser.get(), + (jint)operation); +} + +bool RenderHandler::GetViewRect(jobject browser, CefRect& rect) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIObjectResult jreturn(env); + JNI_CALL_METHOD(env, handle_, "getViewRect", + "(Lorg/cef/browser/CefBrowser;)Ljava/awt/Rectangle;", Object, + jreturn, browser); + if (jreturn) { + rect = GetJNIRect(env, jreturn); + return true; + } + return false; +} + +bool RenderHandler::GetScreenPoint(jobject browser, + int viewX, + int viewY, + int& screenX, + int& screenY) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIObjectLocal jpoint(env, NewJNIPoint(env, viewX, viewY)); + if (!jpoint) + return false; + + ScopedJNIObjectResult jreturn(env); + JNI_CALL_METHOD( + env, handle_, "getScreenPoint", + "(Lorg/cef/browser/CefBrowser;Ljava/awt/Point;)Ljava/awt/Point;", Object, + jreturn, browser, jpoint.get()); + + if (jreturn) { + GetJNIPoint(env, jreturn, &screenX, &screenY); + return true; + } + return false; +} diff --git a/lib/jcef/native/render_handler.h b/lib/jcef/native/render_handler.h new file mode 100644 index 0000000..27379d6 --- /dev/null +++ b/lib/jcef/native/render_handler.h @@ -0,0 +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. + +#ifndef JCEF_NATIVE_RENDER_HANDLER_H_ +#define JCEF_NATIVE_RENDER_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_render_handler.h" + +#include "jni_scoped_helpers.h" + +// RenderHandler implementation. +class RenderHandler : public CefRenderHandler { + public: + RenderHandler(JNIEnv* env, jobject handler); + + // CefRenderHandler methods + virtual bool GetRootScreenRect(CefRefPtr browser, + CefRect& rect) override; + virtual void GetViewRect(CefRefPtr browser, + CefRect& rect) override; + + virtual bool GetScreenInfo(CefRefPtr browser, + CefScreenInfo& screen_info) override; + + virtual bool GetScreenPoint(CefRefPtr browser, + int viewX, + int viewY, + int& screenX, + int& screenY) override; + virtual void OnPopupShow(CefRefPtr browser, bool show) override; + virtual void OnPopupSize(CefRefPtr browser, + const CefRect& rect) override; + virtual void OnPaint(CefRefPtr browser, + PaintElementType type, + const RectList& dirtyRects, + const void* buffer, + int width, + int height) override; + virtual bool StartDragging(CefRefPtr browser, + CefRefPtr drag_data, + DragOperationsMask allowed_ops, + int x, + int y) override; + virtual void UpdateDragCursor(CefRefPtr browser, + DragOperation operation) override; + + bool GetViewRect(jobject browser, CefRect& rect); + bool GetScreenPoint(jobject browser, + int viewX, + int viewY, + int& screenX, + int& screenY); + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(RenderHandler); +}; + +#endif // JCEF_NATIVE_RENDER_HANDLER_H_ diff --git a/lib/jcef/native/request_context_handler.cpp b/lib/jcef/native/request_context_handler.cpp new file mode 100644 index 0000000..f94bf1e --- /dev/null +++ b/lib/jcef/native/request_context_handler.cpp @@ -0,0 +1,50 @@ +// 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 "request_context_handler.h" + +#include "jni_util.h" +#include "resource_request_handler.h" +#include "util.h" + +RequestContextHandler::RequestContextHandler(JNIEnv* env, jobject jhandler) + : handle_(env, jhandler) {} + +CefRefPtr +RequestContextHandler::GetResourceRequestHandler( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool is_navigation, + bool is_download, + const CefString& request_initiator, + bool& disable_default_handling) { + ScopedJNIEnv env; + if (!env) + return nullptr; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNIString jrequestInitiator(env, request_initiator); + ScopedJNIBoolRef jdisableDefaultHandling(env, disable_default_handling); + ScopedJNIObjectResult jresult(env); + + JNI_CALL_METHOD(env, handle_, "getResourceRequestHandler", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/" + "cef/network/CefRequest;ZZLjava/lang/String;Lorg/cef/misc/" + "BoolRef;)Lorg/cef/handler/CefResourceRequestHandler;", + Object, jresult, jbrowser.get(), jframe.get(), jrequest.get(), + is_navigation ? JNI_TRUE : JNI_FALSE, + is_download ? JNI_TRUE : JNI_FALSE, jrequestInitiator.get(), + jdisableDefaultHandling.get()); + + disable_default_handling = jdisableDefaultHandling; + + if (jresult) + return new ResourceRequestHandler(env, jresult); + return nullptr; +} diff --git a/lib/jcef/native/request_context_handler.h b/lib/jcef/native/request_context_handler.h new file mode 100644 index 0000000..fd70041 --- /dev/null +++ b/lib/jcef/native/request_context_handler.h @@ -0,0 +1,36 @@ +// 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 JCEF_NATIVE_STRING_VISITOR_H_ +#define JCEF_NATIVE_STRING_VISITOR_H_ +#pragma once + +#include +#include "include/cef_request_context_handler.h" + +#include "jni_scoped_helpers.h" + +// RequestContextHandler implementation. +class RequestContextHandler : public CefRequestContextHandler { + public: + RequestContextHandler(JNIEnv* env, jobject jhandler); + + // RequestContextHandler methods + CefRefPtr GetResourceRequestHandler( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool is_navigation, + bool is_download, + const CefString& request_initiator, + bool& disable_default_handling) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(RequestContextHandler); +}; + +#endif // JCEF_NATIVE_STRING_VISITOR_H_ diff --git a/lib/jcef/native/request_handler.cpp b/lib/jcef/native/request_handler.cpp new file mode 100644 index 0000000..2443445 --- /dev/null +++ b/lib/jcef/native/request_handler.cpp @@ -0,0 +1,218 @@ +// 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 "request_handler.h" + +#include "client_handler.h" +#include "jni_util.h" +#include "resource_handler.h" +#include "resource_request_handler.h" +#include "util.h" + +RequestHandler::RequestHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +bool RequestHandler::OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool user_gesture, + bool is_redirect) { + // Forward request to ClientHandler to make the message_router_ happy. + CefRefPtr client = + (ClientHandler*)browser->GetHost()->GetClient().get(); + client->OnBeforeBrowse(browser, frame); + + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "onBeforeBrowse", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/" + "cef/network/CefRequest;ZZ)Z", + Boolean, jresult, jbrowser.get(), jframe.get(), + jrequest.get(), (user_gesture ? JNI_TRUE : JNI_FALSE), + (is_redirect ? JNI_TRUE : JNI_FALSE)); + + return (jresult != JNI_FALSE); +} + +bool RequestHandler::OnOpenURLFromTab(CefRefPtr browser, + CefRefPtr frame, + const CefString& target_url, + WindowOpenDisposition target_disposition, + bool user_gesture) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIString jtargetUrl(env, target_url); + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "onOpenURLFromTab", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;" + "Ljava/lang/String;Z)Z", + Boolean, jresult, jbrowser.get(), jframe.get(), + jtargetUrl.get(), (user_gesture ? JNI_TRUE : JNI_FALSE)); + + return (jresult != JNI_FALSE); +} + +CefRefPtr RequestHandler::GetResourceRequestHandler( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool is_navigation, + bool is_download, + const CefString& request_initiator, + bool& disable_default_handling) { + ScopedJNIEnv env; + if (!env) + return nullptr; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNIString jrequestInitiator(env, request_initiator); + ScopedJNIBoolRef jdisableDefaultHandling(env, disable_default_handling); + ScopedJNIObjectResult jresult(env); + + JNI_CALL_METHOD(env, handle_, "getResourceRequestHandler", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/" + "cef/network/CefRequest;ZZLjava/lang/String;Lorg/cef/misc/" + "BoolRef;)Lorg/cef/handler/CefResourceRequestHandler;", + Object, jresult, jbrowser.get(), jframe.get(), jrequest.get(), + is_navigation ? JNI_TRUE : JNI_FALSE, + is_download ? JNI_TRUE : JNI_FALSE, jrequestInitiator.get(), + jdisableDefaultHandling.get()); + + disable_default_handling = jdisableDefaultHandling; + + if (jresult) + return new ResourceRequestHandler(env, jresult); + return nullptr; +} + +bool RequestHandler::GetAuthCredentials(CefRefPtr browser, + const CefString& origin_url, + bool isProxy, + const CefString& host, + int port, + const CefString& realm, + const CefString& scheme, + CefRefPtr callback) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIString joriginUrl(env, origin_url); + ScopedJNIString jhost(env, host); + ScopedJNIString jrealm(env, realm); + ScopedJNIString jscheme(env, scheme); + ScopedJNIAuthCallback jcallback(env, callback); + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD( + env, handle_, "getAuthCredentials", + "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;ZLjava/lang/String;" + "ILjava/lang/String;Ljava/lang/String;" + "Lorg/cef/callback/CefAuthCallback;)Z", + Boolean, jresult, jbrowser.get(), joriginUrl.get(), + (isProxy ? JNI_TRUE : JNI_FALSE), jhost.get(), port, jrealm.get(), + jscheme.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(); + } + + return (jresult != JNI_FALSE); +} + +bool RequestHandler::OnCertificateError(CefRefPtr browser, + cef_errorcode_t cert_error, + const CefString& request_url, + CefRefPtr ssl_info, + CefRefPtr callback) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIObjectLocal jcertError(env, NewJNIErrorCode(env, cert_error)); + ScopedJNIString jrequestUrl(env, request_url); + ScopedJNICallback jcallback(env, callback); + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD( + env, handle_, "onCertificateError", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/handler/CefLoadHandler$ErrorCode;" + "Ljava/lang/String;Lorg/cef/callback/CefCallback;)Z", + Boolean, jresult, jbrowser.get(), jcertError.get(), jrequestUrl.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(); + } + + return (jresult != JNI_FALSE); +} + +void RequestHandler::OnRenderProcessTerminated(CefRefPtr browser, + 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(); + client->OnRenderProcessTerminated(browser); + + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + + ScopedJNIObjectResult jstatus(env); + switch (status) { + JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", + TS_ABNORMAL_TERMINATION, jstatus); + JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", + TS_PROCESS_WAS_KILLED, jstatus); + JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", + 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); + } + + 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/lib/jcef/native/request_handler.h b/lib/jcef/native/request_handler.h new file mode 100644 index 0000000..9ee8356 --- /dev/null +++ b/lib/jcef/native/request_handler.h @@ -0,0 +1,64 @@ +// 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 JCEF_NATIVE_REQUEST_HANDLER_H_ +#define JCEF_NATIVE_REQUEST_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_request_handler.h" + +#include "jni_scoped_helpers.h" + +// RequestHandler implementation. +class RequestHandler : public CefRequestHandler { + public: + RequestHandler(JNIEnv* env, jobject handler); + + // CefRequestHandler methods: + bool OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool user_gesture, + bool is_redirect) override; + bool OnOpenURLFromTab(CefRefPtr browser, + CefRefPtr frame, + const CefString& target_url, + WindowOpenDisposition target_disposition, + bool user_gesture) override; + CefRefPtr GetResourceRequestHandler( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool is_navigation, + bool is_download, + const CefString& request_initiator, + bool& disable_default_handling) override; + bool GetAuthCredentials(CefRefPtr browser, + const CefString& origin_url, + bool isProxy, + const CefString& host, + int port, + const CefString& realm, + const CefString& scheme, + 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, + int error_code, + const CefString& error_string) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(RequestHandler); +}; + +#endif // JCEF_NATIVE_REQUEST_HANDLER_H_ diff --git a/lib/jcef/native/resource_handler.cpp b/lib/jcef/native/resource_handler.cpp new file mode 100644 index 0000000..a894301 --- /dev/null +++ b/lib/jcef/native/resource_handler.cpp @@ -0,0 +1,204 @@ +// 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 "resource_handler.h" + +#include "jni_util.h" +#include "util.h" + +ResourceHandler::ResourceHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +bool ResourceHandler::ProcessRequest(CefRefPtr request, + CefRefPtr callback) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNICallback jcallback(env, callback); + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD( + env, handle_, "processRequest", + "(Lorg/cef/network/CefRequest;Lorg/cef/callback/CefCallback;)Z", Boolean, + jresult, jrequest.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(); + } + + 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_t& response_length, + CefString& redirectUrl) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIResponse jresponse(env, response); + jresponse.SetTemporary(); + ScopedJNIIntRef jresponseLength(env, (int)response_length); + ScopedJNIStringRef jredirectUrl(env, redirectUrl); + + JNI_CALL_VOID_METHOD(env, handle_, "getResponseHeaders", + "(Lorg/cef/network/CefResponse;Lorg/cef/misc/" + "IntRef;Lorg/cef/misc/StringRef;)V", + jresponse.get(), jresponseLength.get(), + jredirectUrl.get()); + + response_length = jresponseLength; + redirectUrl = jredirectUrl; +} + +bool ResourceHandler::ReadResponse(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); + ScopedJNICallback jcallback(env, callback); + jboolean jresult = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "readResponse", + "([BILorg/cef/misc/IntRef;Lorg/cef/callback/CefCallback;)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(); + } + + 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::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) + return; + JNI_CALL_VOID_METHOD(env, handle_, "cancel", "()V"); +} diff --git a/lib/jcef/native/resource_handler.h b/lib/jcef/native/resource_handler.h new file mode 100644 index 0000000..bb9c0e1 --- /dev/null +++ b/lib/jcef/native/resource_handler.h @@ -0,0 +1,49 @@ +// 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 JCEF_NATIVE_RESOURCE_HANDLER_H_ +#define JCEF_NATIVE_RESOURCE_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_resource_handler.h" + +#include "jni_scoped_helpers.h" + +// ResourceHandler implementation. +class ResourceHandler : public CefResourceHandler { + public: + ResourceHandler(JNIEnv* env, jobject handler); + + // CefResourceHandler methods: + bool ProcessRequest(CefRefPtr request, + CefRefPtr callback) override; + bool Open(CefRefPtr request, + bool& handle_request, + CefRefPtr callback) override; + void GetResponseHeaders(CefRefPtr response, + 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: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(ResourceHandler); +}; + +#endif // JCEF_NATIVE_RESOURCE_HANDLER_H_ diff --git a/lib/jcef/native/resource_request_handler.cpp b/lib/jcef/native/resource_request_handler.cpp new file mode 100644 index 0000000..c234c17 --- /dev/null +++ b/lib/jcef/native/resource_request_handler.cpp @@ -0,0 +1,202 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "resource_request_handler.h" + +#include "cookie_access_filter.h" +#include "jni_util.h" +#include "resource_handler.h" +#include "util.h" + +ResourceRequestHandler::ResourceRequestHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +CefRefPtr ResourceRequestHandler::GetCookieAccessFilter( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) { + ScopedJNIEnv env; + if (!env) + return nullptr; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNIObjectResult jresult(env); + + JNI_CALL_METHOD(env, handle_, "getCookieAccessFilter", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/" + "cef/network/CefRequest;)" + "Lorg/cef/handler/CefCookieAccessFilter;", + Object, jresult, jbrowser.get(), jframe.get(), + jrequest.get()); + + if (jresult) + return new CookieAccessFilter(env, jresult); + return nullptr; +} + +// TODO(JCEF): Expose the |callback| parameter. +ResourceRequestHandler::ReturnValue +ResourceRequestHandler::OnBeforeResourceLoad(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr callback) { + ScopedJNIEnv env; + if (!env) + return RV_CONTINUE; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + jboolean result = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "onBeforeResourceLoad", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/" + "cef/network/CefRequest;)Z", + Boolean, result, jbrowser.get(), jframe.get(), + jrequest.get()); + + return (result != JNI_FALSE) ? RV_CANCEL : RV_CONTINUE; +} + +CefRefPtr ResourceRequestHandler::GetResourceHandler( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) { + ScopedJNIEnv env; + if (!env) + return nullptr; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNIObjectResult jresult(env); + + JNI_CALL_METHOD(env, handle_, "getResourceHandler", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/" + "cef/network/CefRequest;)" + "Lorg/cef/handler/CefResourceHandler;", + Object, jresult, jbrowser.get(), jframe.get(), + jrequest.get()); + + if (jresult) + return new ResourceHandler(env, jresult); + return nullptr; +} + +void ResourceRequestHandler::OnResourceRedirect(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr response, + CefString& new_url) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNIResponse jresponse(env, response); + jresponse.SetTemporary(); + ScopedJNIStringRef jnewUrl(env, new_url); + + JNI_CALL_VOID_METHOD( + env, handle_, "onResourceRedirect", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/cef/network/" + "CefRequest;Lorg/cef/network/CefResponse;Lorg/cef/misc/" + "StringRef;)V", + jbrowser.get(), jframe.get(), jrequest.get(), jresponse.get(), + jnewUrl.get()); + + new_url = jnewUrl; +} + +bool ResourceRequestHandler::OnResourceResponse( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr response) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNIResponse jresponse(env, response); + jresponse.SetTemporary(); + jboolean result = JNI_FALSE; + + JNI_CALL_METHOD(env, handle_, "onResourceResponse", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;" + "Lorg/cef/network/CefRequest;Lorg/cef/network/CefResponse;)Z", + Boolean, result, jbrowser.get(), jframe.get(), jrequest.get(), + jresponse.get()); + + return (result != JNI_FALSE); +} + +void ResourceRequestHandler::OnResourceLoadComplete( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr response, + CefResourceRequestHandler::URLRequestStatus status, + int64_t received_content_length) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNIResponse jresponse(env, response); + jresponse.SetTemporary(); + ScopedJNIURLRequestStatus jstatus(env, status); + + JNI_CALL_VOID_METHOD( + env, handle_, "onResourceLoadComplete", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;" + "Lorg/cef/network/CefRequest;Lorg/cef/network/CefResponse;" + "Lorg/cef/network/CefURLRequest$Status;J)V", + jbrowser.get(), jframe.get(), jrequest.get(), jresponse.get(), + jstatus.get(), (jlong)received_content_length); +} + +void ResourceRequestHandler::OnProtocolExecution(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool& allow_os_execution) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNIBoolRef jallowOsExecution(env, allow_os_execution); + + JNI_CALL_VOID_METHOD( + env, handle_, "onProtocolExecution", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/cef/network/" + "CefRequest;Lorg/cef/misc/BoolRef;)V", + jbrowser.get(), jframe.get(), jrequest.get(), jallowOsExecution.get()); + + allow_os_execution = jallowOsExecution; +} diff --git a/lib/jcef/native/resource_request_handler.h b/lib/jcef/native/resource_request_handler.h new file mode 100644 index 0000000..54b24eb --- /dev/null +++ b/lib/jcef/native/resource_request_handler.h @@ -0,0 +1,59 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef JCEF_NATIVE_RESOURCE_REQUEST_HANDLER_H_ +#define JCEF_NATIVE_RESOURCE_REQUEST_HANDLER_H_ +#pragma once + +#include +#include "include/cef_resource_request_handler.h" + +#include "jni_scoped_helpers.h" + +// ResourceRequestHandler implementation. +class ResourceRequestHandler : public CefResourceRequestHandler { + public: + ResourceRequestHandler(JNIEnv* env, jobject handler); + + // CefResourceRequestHandler methods: + CefRefPtr GetCookieAccessFilter( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) override; + ReturnValue OnBeforeResourceLoad(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr callback) override; + CefRefPtr GetResourceHandler( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) override; + void OnResourceRedirect(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr response, + CefString& new_url) override; + bool OnResourceResponse(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr response) override; + void OnResourceLoadComplete(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr response, + URLRequestStatus status, + int64_t received_content_length) override; + void OnProtocolExecution(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool& allow_os_execution) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(ResourceRequestHandler); +}; + +#endif // JCEF_NATIVE_RESOURCE_REQUEST_HANDLER_H_ diff --git a/lib/jcef/native/resources/jcef-Info.plist b/lib/jcef/native/resources/jcef-Info.plist new file mode 100644 index 0000000..089b876 --- /dev/null +++ b/lib/jcef/native/resources/jcef-Info.plist @@ -0,0 +1,35 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${EXECUTABLE_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + org.jcef.jcef.helper${BUNDLE_ID_SUFFIX} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + LSEnvironment + + MallocNanoZone + 0 + + LSFileQuarantineEnabled + + LSMinimumSystemVersion + 10.11.0 + LSUIElement + 1 + NSSupportsAutomaticGraphicsSwitching + + + diff --git a/lib/jcef/native/run_file_dialog_callback.cpp b/lib/jcef/native/run_file_dialog_callback.cpp new file mode 100644 index 0000000..e7f946f --- /dev/null +++ b/lib/jcef/native/run_file_dialog_callback.cpp @@ -0,0 +1,23 @@ +// 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 "run_file_dialog_callback.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" +#include "util.h" + +RunFileDialogCallback::RunFileDialogCallback(JNIEnv* env, jobject jcallback) + : handle_(env, jcallback) {} + +void RunFileDialogCallback::OnFileDialogDismissed( + const std::vector& file_paths) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIObjectLocal jfilePaths(env, NewJNIStringVector(env, file_paths)); + JNI_CALL_VOID_METHOD(env, handle_, "onFileDialogDismissed", + "(Ljava/util/Vector;)V", jfilePaths.get()); +} diff --git a/lib/jcef/native/run_file_dialog_callback.h b/lib/jcef/native/run_file_dialog_callback.h new file mode 100644 index 0000000..3f76b12 --- /dev/null +++ b/lib/jcef/native/run_file_dialog_callback.h @@ -0,0 +1,31 @@ +// 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 JCEF_NATIVE_RUN_FILE_DIALOG_CALLBACK_H_ +#define JCEF_NATIVE_RUN_FILE_DIALOG_CALLBACK_H_ +#pragma once + +#include + +#include "include/cef_browser.h" + +#include "jni_scoped_helpers.h" + +// RunFileDialogCallback implementation. +class RunFileDialogCallback : public CefRunFileDialogCallback { + public: + RunFileDialogCallback(JNIEnv* env, jobject jcallback); + + // RunFileDialogCallback methods + virtual void OnFileDialogDismissed( + const std::vector& file_paths) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(RunFileDialogCallback); +}; + +#endif // JCEF_NATIVE_RUN_FILE_DIALOG_CALLBACK_H_ diff --git a/lib/jcef/native/scheme_handler_factory.cpp b/lib/jcef/native/scheme_handler_factory.cpp new file mode 100644 index 0000000..d96a4b8 --- /dev/null +++ b/lib/jcef/native/scheme_handler_factory.cpp @@ -0,0 +1,40 @@ +// 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 "scheme_handler_factory.h" + +#include "jni_util.h" +#include "resource_handler.h" + +SchemeHandlerFactory::SchemeHandlerFactory(JNIEnv* env, jobject jfactory) + : handle_(env, jfactory) {} + +CefRefPtr SchemeHandlerFactory::Create( + CefRefPtr browser, + CefRefPtr frame, + const CefString& scheme_name, + CefRefPtr request) { + ScopedJNIEnv env; + if (!env) + return nullptr; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIFrame jframe(env, frame); + jframe.SetTemporary(); + ScopedJNIString jschemeName(env, scheme_name); + ScopedJNIRequest jrequest(env, request); + jrequest.SetTemporary(); + ScopedJNIObjectResult jresult(env); + + JNI_CALL_METHOD(env, handle_, "create", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/" + "CefFrame;Ljava/lang/String;Lorg/cef/" + "network/CefRequest;)Lorg/cef/handler/CefResourceHandler;", + Object, jresult, jbrowser.get(), jframe.get(), + jschemeName.get(), jrequest.get()); + + if (jresult) + return new ResourceHandler(env, jresult); + return nullptr; +} diff --git a/lib/jcef/native/scheme_handler_factory.h b/lib/jcef/native/scheme_handler_factory.h new file mode 100644 index 0000000..66dd522 --- /dev/null +++ b/lib/jcef/native/scheme_handler_factory.h @@ -0,0 +1,33 @@ +// 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 JCEF_NATIVE_SCHEME_HANDLER_FACTORY_H_ +#define JCEF_NATIVE_SCHEME_HANDLER_FACTORY_H_ +#pragma once + +#include + +#include "include/cef_scheme.h" + +#include "jni_scoped_helpers.h" + +// StringVisitor implementation. +class SchemeHandlerFactory : public CefSchemeHandlerFactory { + public: + SchemeHandlerFactory(JNIEnv* env, jobject jfactory); + + // CefSchemeHandlerFactory methods + CefRefPtr Create(CefRefPtr browser, + CefRefPtr frame, + const CefString& scheme_name, + CefRefPtr request) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(SchemeHandlerFactory); +}; + +#endif // JCEF_NATIVE_SCHEME_HANDLER_FACTORY_H_ diff --git a/lib/jcef/native/string_visitor.cpp b/lib/jcef/native/string_visitor.cpp new file mode 100644 index 0000000..7f6c787 --- /dev/null +++ b/lib/jcef/native/string_visitor.cpp @@ -0,0 +1,22 @@ +// 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 "string_visitor.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" +#include "util.h" + +StringVisitor::StringVisitor(JNIEnv* env, jobject jvisitor) + : handle_(env, jvisitor) {} + +void StringVisitor::Visit(const CefString& string) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIString jstring(env, string); + JNI_CALL_VOID_METHOD(env, handle_, "visit", "(Ljava/lang/String;)V", + jstring.get()); +} diff --git a/lib/jcef/native/string_visitor.h b/lib/jcef/native/string_visitor.h new file mode 100644 index 0000000..6b410ee --- /dev/null +++ b/lib/jcef/native/string_visitor.h @@ -0,0 +1,30 @@ +// 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 JCEF_NATIVE_STRING_VISITOR_H_ +#define JCEF_NATIVE_STRING_VISITOR_H_ +#pragma once + +#include + +#include "include/cef_string_visitor.h" + +#include "jni_scoped_helpers.h" + +// StringVisitor implementation. +class StringVisitor : public CefStringVisitor { + public: + StringVisitor(JNIEnv* env, jobject jvisitor); + + // StringVisitor methods + virtual void Visit(const CefString& string) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(StringVisitor); +}; + +#endif // JCEF_NATIVE_STRING_VISITOR_H_ diff --git a/lib/jcef/native/temp_window.h b/lib/jcef/native/temp_window.h new file mode 100644 index 0000000..be71166 --- /dev/null +++ b/lib/jcef/native/temp_window.h @@ -0,0 +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. + +#ifndef JCEF_NATIVE_TEMP_WINDOW_H_ +#define JCEF_NATIVE_TEMP_WINDOW_H_ +#pragma once + +#if defined(OS_WIN) +#include "temp_window_win.h" +#elif defined(OS_LINUX) +#include "temp_window_x11.h" +#elif defined(OS_MACOSX) +#include "temp_window_mac.h" +#endif + +#if defined(OS_WIN) +typedef TempWindowWin TempWindow; +#elif defined(OS_LINUX) +typedef TempWindowX11 TempWindow; +#elif defined(OS_MACOSX) +typedef TempWindowMac TempWindow; +#endif + +#endif // JCEF_NATIVE_TEMP_WINDOW_H_ diff --git a/lib/jcef/native/temp_window_mac.h b/lib/jcef/native/temp_window_mac.h new file mode 100644 index 0000000..769845c --- /dev/null +++ b/lib/jcef/native/temp_window_mac.h @@ -0,0 +1,40 @@ +// 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. + +#ifndef JCEF_NATIVE_TEMP_WINDOW_MAC_H_ +#define JCEF_NATIVE_TEMP_WINDOW_MAC_H_ +#pragma once + +#include "include/cef_base.h" + +#ifdef __OBJC__ +@class NSWindow; +#else +class NSWindow; +#endif + +// Represents a singleton hidden window that acts as a temporary parent for +// popup browsers. +class TempWindowMac { + public: + // Returns the singleton window handle. + static CefWindowHandle GetWindowHandle(); + + static NSWindow* GetWindow(); + + private: + // A single instance will be created/owned by Context. + friend class Context; + // Allow deletion via std::unique_ptr only. + friend std::default_delete; + + TempWindowMac(); + ~TempWindowMac(); + + NSWindow* window_; + + DISALLOW_COPY_AND_ASSIGN(TempWindowMac); +}; + +#endif // JCEF_NATIVE_TEMP_WINDOW_MAC_H_ diff --git a/lib/jcef/native/temp_window_mac.mm b/lib/jcef/native/temp_window_mac.mm new file mode 100644 index 0000000..32794cc --- /dev/null +++ b/lib/jcef/native/temp_window_mac.mm @@ -0,0 +1,47 @@ +// 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. + +#include "temp_window_mac.h" + +#include + +#include "include/base/cef_logging.h" +#include "include/cef_app.h" + +namespace { + +TempWindowMac* g_temp_window = nullptr; + +} // namespace + +TempWindowMac::TempWindowMac() : window_(nil) { + DCHECK(!g_temp_window); + g_temp_window = this; + + // Create a borderless non-visible 1x1 window. + window_ = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) + styleMask:NSWindowStyleMaskBorderless + backing:NSBackingStoreBuffered + defer:NO]; + CHECK(window_); +} + +TempWindowMac::~TempWindowMac() { + g_temp_window = nullptr; + DCHECK(window_); + + [window_ close]; +} + +// static +CefWindowHandle TempWindowMac::GetWindowHandle() { + DCHECK(g_temp_window); + return [g_temp_window->window_ contentView]; +} + +// static +NSWindow* TempWindowMac::GetWindow() { + DCHECK(g_temp_window); + return g_temp_window->window_; +} diff --git a/lib/jcef/native/temp_window_win.cc b/lib/jcef/native/temp_window_win.cc new file mode 100644 index 0000000..321d181 --- /dev/null +++ b/lib/jcef/native/temp_window_win.cc @@ -0,0 +1,54 @@ +// 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. + +#include "temp_window_win.h" + +#include + +#include "include/base/cef_logging.h" + +namespace { + +const wchar_t kWndClass[] = L"Client_TempWindow"; + +// Create the temp window. +HWND CreateTempWindow() { + HINSTANCE hInstance = ::GetModuleHandle(nullptr); + + WNDCLASSEX wc = {0}; + wc.cbSize = sizeof(wc); + wc.lpfnWndProc = DefWindowProc; + wc.hInstance = hInstance; + wc.lpszClassName = kWndClass; + RegisterClassEx(&wc); + + // Create a 1x1 pixel hidden window. + return CreateWindow(kWndClass, 0, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 0, 0, + 1, 1, nullptr, nullptr, hInstance, nullptr); +} + +TempWindowWin* g_temp_window = nullptr; + +} // namespace + +TempWindowWin::TempWindowWin() : hwnd_(nullptr) { + DCHECK(!g_temp_window); + g_temp_window = this; + + hwnd_ = CreateTempWindow(); + CHECK(hwnd_); +} + +TempWindowWin::~TempWindowWin() { + g_temp_window = nullptr; + DCHECK(hwnd_); + DestroyWindow(hwnd_); +} + +// static +CefWindowHandle TempWindowWin::GetWindowHandle() { + if (!g_temp_window) + return kNullWindowHandle; + return g_temp_window->hwnd_; +} diff --git a/lib/jcef/native/temp_window_win.h b/lib/jcef/native/temp_window_win.h new file mode 100644 index 0000000..bd1bd7a --- /dev/null +++ b/lib/jcef/native/temp_window_win.h @@ -0,0 +1,32 @@ +// 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. + +#ifndef JCEF_NATIVE_TEMP_WINDOW_WIN_H_ +#define JCEF_NATIVE_TEMP_WINDOW_WIN_H_ +#pragma once + +#include "include/cef_base.h" + +// Represents a singleton hidden window that acts as a temporary parent for +// popup browsers. +class TempWindowWin { + public: + // Returns the singleton window handle. + static CefWindowHandle GetWindowHandle(); + + private: + // A single instance will be created/owned by Context. + friend class Context; + // Allow deletion via std::unique_ptr only. + friend std::default_delete; + + TempWindowWin(); + ~TempWindowWin(); + + CefWindowHandle hwnd_; + + DISALLOW_COPY_AND_ASSIGN(TempWindowWin); +}; + +#endif // JCEF_NATIVE_TEMP_WINDOW_WIN_H_ diff --git a/lib/jcef/native/temp_window_x11.cc b/lib/jcef/native/temp_window_x11.cc new file mode 100644 index 0000000..1f3601e --- /dev/null +++ b/lib/jcef/native/temp_window_x11.cc @@ -0,0 +1,72 @@ +// 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. + +#include "temp_window_x11.h" + +#include + +#include "include/base/cef_logging.h" +#include "include/cef_app.h" +#include "util.h" + +namespace { + +::Display* g_xdisplay = nullptr; +TempWindowX11* g_temp_window = nullptr; + +// Create the temp window. +::Window CreateTempWindow() { + ::Window parent_xwindow = DefaultRootWindow(g_xdisplay); + + XSetWindowAttributes swa; + memset(&swa, 0, sizeof(swa)); + swa.background_pixmap = None; + swa.override_redirect = false; + return XCreateWindow(g_xdisplay, parent_xwindow, 0, 0, 1, 1, // size (1x1px) + 0, // border width + CopyFromParent, // depth + InputOutput, + CopyFromParent, // visual + CWBackPixmap | CWOverrideRedirect, &swa); +} + +// Close the temp window. +void CloseTempWindow(::Window xwindow) { + XDestroyWindow(g_xdisplay, xwindow); +} + +} // namespace + +TempWindowX11::TempWindowX11() : xwindow_(kNullWindowHandle) { + REQUIRE_UI_THREAD(); + + g_xdisplay = cef_get_xdisplay(); + CHECK(g_xdisplay); + + DCHECK(!g_temp_window); + g_temp_window = this; + + xwindow_ = CreateTempWindow(); + CHECK(xwindow_); +} + +TempWindowX11::~TempWindowX11() { + g_temp_window = nullptr; + DCHECK(xwindow_); + + CloseTempWindow(xwindow_); +} + +// static +CefWindowHandle TempWindowX11::GetWindowHandle() { + if (!g_temp_window) + return kNullWindowHandle; + return g_temp_window->xwindow_; +} + +// static +void* TempWindowX11::GetDisplay() { + CHECK(g_xdisplay); + return g_xdisplay; +} diff --git a/lib/jcef/native/temp_window_x11.h b/lib/jcef/native/temp_window_x11.h new file mode 100644 index 0000000..32e6e42 --- /dev/null +++ b/lib/jcef/native/temp_window_x11.h @@ -0,0 +1,34 @@ +// 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. + +#ifndef JCEF_NATIVE_TEMP_WINDOW_X11_H_ +#define JCEF_NATIVE_TEMP_WINDOW_X11_H_ +#pragma once + +#include "include/cef_base.h" + +// Represents a singleton hidden window that acts as a temporary parent for +// popup browsers. +class TempWindowX11 { + public: + // Returns the singleton window handle. + static CefWindowHandle GetWindowHandle(); + + static void* GetDisplay(); + + private: + // A single instance will be created/owned by Context. + friend class Context; + // Allow deletion via std::unique_ptr only. + friend std::default_delete; + + TempWindowX11(); + ~TempWindowX11(); + + CefWindowHandle xwindow_; + + DISALLOW_COPY_AND_ASSIGN(TempWindowX11); +}; + +#endif // JCEF_NATIVE_TEMP_WINDOW_X11_H_ diff --git a/lib/jcef/native/url_request_client.cpp b/lib/jcef/native/url_request_client.cpp new file mode 100644 index 0000000..2acc9ca --- /dev/null +++ b/lib/jcef/native/url_request_client.cpp @@ -0,0 +1,127 @@ +// 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 "url_request_client.h" + +#include "jni_util.h" +#include "util.h" + +namespace { + +const char kCefClassName[] = "CefURLRequestClient"; + +} // namespace + +URLRequestClient::URLRequestClient(JNIEnv* env, + jobject jURLRequestClient, + jobject jURLRequest) + : client_handle_(env, jURLRequestClient), + request_handle_(env, jURLRequest) {} + +CefRefPtr URLRequestClient::Create(JNIEnv* env, + jobject jURLRequestClient, + jobject jURLRequest) { + CefRefPtr client = GetCefFromJNIObject( + env, jURLRequestClient, kCefClassName); + if (!client) { + client = new URLRequestClient(env, jURLRequestClient, jURLRequest); + SetCefForJNIObject(env, jURLRequestClient, client.get(), kCefClassName); + } + return client; +} + +URLRequestClient::~URLRequestClient() { + ScopedJNIEnv env; + if (!env) + return; + + SetCefForJNIObject(env, client_handle_, nullptr, + kCefClassName); +} + +// TODO(jcef): Solve jurlReques instead of using nullptr +void URLRequestClient::OnRequestComplete(CefRefPtr request) { + ScopedJNIEnv env; + if (!env) + return; + + JNI_CALL_VOID_METHOD(env, client_handle_, "onRequestComplete", + "(Lorg/cef/network/CefURLRequest;)V", + request_handle_.get()); +} + +void URLRequestClient::OnUploadProgress(CefRefPtr request, + int64_t current, + int64_t total) { + ScopedJNIEnv env; + if (!env) + return; + + JNI_CALL_VOID_METHOD(env, client_handle_, "onUploadProgress", + "(Lorg/cef/network/CefURLRequest;II)V", + request_handle_.get(), (jint)current, (jint)total); +} + +void URLRequestClient::OnDownloadProgress(CefRefPtr request, + int64_t current, + int64_t total) { + ScopedJNIEnv env; + if (!env) + return; + + JNI_CALL_VOID_METHOD(env, client_handle_, "onDownloadProgress", + "(Lorg/cef/network/CefURLRequest;II)V", + request_handle_.get(), (jint)current, (jint)total); +} + +void URLRequestClient::OnDownloadData(CefRefPtr request, + const void* data, + size_t data_length) { + ScopedJNIEnv env; + if (!env) + return; + + jbyteArray jbyteArray = env->NewByteArray((jsize)data_length); + env->SetByteArrayRegion(jbyteArray, 0, (jsize)data_length, + (const jbyte*)data); + + JNI_CALL_VOID_METHOD(env, client_handle_, "onDownloadData", + "(Lorg/cef/network/CefURLRequest;[BI)V", + request_handle_.get(), jbyteArray, (jint)data_length); + + env->DeleteLocalRef(jbyteArray); +} + +bool URLRequestClient::GetAuthCredentials(bool isProxy, + const CefString& host, + int port, + const CefString& realm, + const CefString& scheme, + CefRefPtr callback) { + jboolean jresult = JNI_FALSE; + + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIString jhost(env, host); + ScopedJNIString jrealm(env, realm); + ScopedJNIString jscheme(env, scheme); + ScopedJNIAuthCallback jcallback(env, callback); + + JNI_CALL_METHOD(env, client_handle_, "getAuthCredentials", + "(ZLjava/lang/String;ILjava/lang/String;Ljava/lang/" + "String;Lorg/cef/callback/CefAuthCallback;)Z", + Boolean, jresult, (isProxy ? JNI_TRUE : JNI_FALSE), + jhost.get(), port, jrealm.get(), jscheme.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(); + } + + return (jresult != JNI_FALSE); +} diff --git a/lib/jcef/native/url_request_client.h b/lib/jcef/native/url_request_client.h new file mode 100644 index 0000000..5b9dfc1 --- /dev/null +++ b/lib/jcef/native/url_request_client.h @@ -0,0 +1,58 @@ +// 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 JCEF_NATIVE_URL_REQUEST_CLIENT_H_ +#define JCEF_NATIVE_URL_REQUEST_CLIENT_H_ +#pragma once + +#include +#include +#include + +#include "include/cef_urlrequest.h" + +#include "jni_scoped_helpers.h" + +// CefURLRequestClient implementation. +class URLRequestClient : public CefURLRequestClient { + private: + URLRequestClient(JNIEnv* env, jobject jURLRequestClient, jobject jURLRequest); + + public: + static CefRefPtr Create(JNIEnv* env, + jobject jRequestClient, + jobject jURLRequest); + virtual ~URLRequestClient(); + + // CefURLRequestClient methods + virtual void OnRequestComplete(CefRefPtr request) override; + + virtual void OnUploadProgress(CefRefPtr request, + int64_t current, + int64_t total) override; + + virtual void OnDownloadProgress(CefRefPtr request, + int64_t current, + int64_t total) override; + + virtual void OnDownloadData(CefRefPtr request, + const void* data, + size_t data_length) override; + + virtual bool GetAuthCredentials(bool isProxy, + const CefString& host, + int port, + const CefString& realm, + const CefString& scheme, + CefRefPtr callback) override; + + protected: + ScopedJNIObjectGlobal client_handle_; + ScopedJNIObjectGlobal request_handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(URLRequestClient); +}; + +#endif // JCEF_NATIVE_URL_REQUEST_CLIENT_H_ diff --git a/lib/jcef/native/util.h b/lib/jcef/native/util.h new file mode 100644 index 0000000..eba0745 --- /dev/null +++ b/lib/jcef/native/util.h @@ -0,0 +1,134 @@ +// Copyright (c) 2011 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_UTIL_H_ +#define JCEF_NATIVE_UTIL_H_ +#pragma once + +#include + +#ifdef USING_JAVA + +#include + +#include "include/base/cef_callback_forward.h" +#include "include/cef_browser.h" +#include "include/cef_task.h" + +#if defined(OS_LINUX) +#include "critical_wait.h" +#endif + +#endif // USING_JAVA + +#if defined(OS_WIN) + +#include // NOLINT(build/include_order) + +#ifndef NDEBUG +#define ASSERT(condition) \ + if (!(condition)) { \ + DebugBreak(); \ + } +#else +#define ASSERT(condition) ((void)0) +#endif + +#else // !OS_WIN + +#include // NOLINT(build/include_order) + +#ifndef NDEBUG +#define ASSERT(condition) \ + if (!(condition)) { \ + assert(false); \ + } +#else +#define ASSERT(condition) ((void)0) +#endif + +#endif // !OS_WIN + +#if defined(OS_MACOSX) + +// due a missing export definition within Java 7u40 (and prior) +// for Mac OS X, we have to redefine JNIEXPORT. +// Otherwise the JNI function names wouldn't be exported to libjcef +#ifdef JNIEXPORT +#undef JNIEXPORT +#define JNIEXPORT __attribute__((visibility("default"))) +#endif // JNIEXPORT + +#endif // OS_MACOSX + +#define REQUIRE_UI_THREAD() ASSERT(CefCurrentlyOn(TID_UI)); +#define REQUIRE_IO_THREAD() ASSERT(CefCurrentlyOn(TID_IO)); +#define REQUIRE_FILE_THREAD() ASSERT(CefCurrentlyOn(TID_FILE)); + +// Used to silence warnings about unused variables. +#if !defined(UNUSED) +#define UNUSED(x) ((void)(x)) +#endif + +namespace util { + +// Get the process-id of the current process. +int GetPid(); + +// Get the process-id of the parent process (that process that launched the +// current process). +int GetParentPid(); + +// Returns the absolute path for a temporary file whose name is unique to the +// process. |identifer| is attached to the filename. +std::string GetTempFileName(const std::string& identifer, bool useParentId); + +#ifdef USING_JAVA + +// Called by LifeSpanHandler::OnAfterCreated() to do some platform dependent +// tasks for the browser reference like registering mouse events. +void AddCefBrowser(CefRefPtr browser); + +// Called by CefBrowser.close(true) to destroy the native browser window. +void DestroyCefBrowser(CefRefPtr browser); + +#if defined(OS_MACOSX) + +// Set the parent of |browserHandle|. If the parent is nullptr the browser will +// be parented to the TempWindow. +void SetParent(CefWindowHandle browserHandle, + jlong parentHandle, + base::OnceClosure callback); + +#else // !defined(OS_MACOSX) + +// Return the window handle for the specified canvas. +CefWindowHandle GetWindowHandle(JNIEnv* env, jobject canvas); + +// Set the parent of |browserHandle|. If the parent is nullptr the browser will +// be parented to the TempWindow. +void SetParent(CefWindowHandle browserHandle, + CefWindowHandle parentHandle, + base::OnceClosure callback); + +#if defined(OS_LINUX) +void SetParentSync(CefWindowHandle browserHandle, + CefWindowHandle parentHandle, + CriticalWait* waitCond, + base::OnceClosure callback); +#endif + +// Set the window bounds for |browserHandle|. +void SetWindowBounds(CefWindowHandle browserHandle, const CefRect& contentRect); + +// Set the window size for |browserHandle|. +void SetWindowSize(CefWindowHandle browserHandle, int width, int height); + +#endif // !defined(OS_MACOSX) + +#endif // USING_JAVA + +} // namespace util + +#endif // JCEF_NATIVE_UTIL_H_ diff --git a/lib/jcef/native/util_linux.cpp b/lib/jcef/native/util_linux.cpp new file mode 100644 index 0000000..e04e9f8 --- /dev/null +++ b/lib/jcef/native/util_linux.cpp @@ -0,0 +1,96 @@ +// 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. + +#include "util.h" + +#include +#undef Success + +#include "include/base/cef_callback.h" + +#include "jni_util.h" +#include "temp_window.h" + +namespace util { + +namespace { + +void X_XMoveResizeWindow(unsigned long browserHandle, + int x, + int y, + unsigned int width, + 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) { + ::Display* xdisplay = (::Display*)TempWindow::GetDisplay(); + XSync(xdisplay, discard); +} + +} // namespace + +// This function is called by LifeSpanHandler::OnAfterCreated(). +void AddCefBrowser(CefRefPtr browser) { + // TODO(jcef): Implement this function stub to do some platform dependent + // tasks for the browser reference like registering mouse events. + + UNUSED(browser); +} + +// This function is called by LifeSpanHandler::DoClose(). +void DestroyCefBrowser(CefRefPtr browser) { + browser->GetHost()->CloseBrowser(true); +} + +CefWindowHandle GetWindowHandle(JNIEnv* env, jobject canvas) { + return GetDrawableOfCanvas(canvas, env); +} + +void SetParent(CefWindowHandle browserHandle, + CefWindowHandle parentHandle, + base::OnceClosure callback) { + SetParentSync(browserHandle, parentHandle, nullptr, std::move(callback)); +} + +void SetParentSync(CefWindowHandle browserHandle, + CefWindowHandle parentHandle, + CriticalWait* waitCond, + base::OnceClosure callback) { + if (waitCond) { + waitCond->lock()->Lock(); + } + if (parentHandle == kNullWindowHandle) + parentHandle = TempWindow::GetWindowHandle(); + if (parentHandle != kNullWindowHandle && browserHandle != kNullWindowHandle) + X_XReparentWindow(browserHandle, parentHandle); + + if (waitCond) { + X_XSync(false); + waitCond->WakeUp(); + waitCond->lock()->Unlock(); + } + std::move(callback).Run(); +} + +void SetWindowBounds(CefWindowHandle browserHandle, + const CefRect& contentRect) { + X_XMoveResizeWindow(browserHandle, contentRect.x, contentRect.y, + contentRect.width, contentRect.height); +} + +void SetWindowSize(CefWindowHandle browserHandle, int width, int height) { + X_XMoveResizeWindow(browserHandle, 0, 0, width, height); +} + +} // namespace util diff --git a/lib/jcef/native/util_mac.h b/lib/jcef/native/util_mac.h new file mode 100644 index 0000000..6af234f --- /dev/null +++ b/lib/jcef/native/util_mac.h @@ -0,0 +1,51 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef JCEF_NATIVE_UTIL_MAC_H_ +#define JCEF_NATIVE_UTIL_MAC_H_ + +#include +#include + +#include "include/cef_app.h" +#include "include/cef_base.h" + +#include "client_app.h" + +#ifdef __OBJC__ +@class NSView; +@class NSWindow; +#else +struct NSView; +class NSWindow; +#endif // __OBJC__ + +namespace util_mac { + +// Converts a relative path to an absolute path. +std::string GetAbsPath(const std::string& path); + +// Returns true if |ptr| is an NSView instance. +bool IsNSView(void* ptr); + +CefWindowHandle CreateBrowserContentView(NSWindow* window, CefRect& orig); +void TranslateRect(CefWindowHandle view, CefRect& orig); + +bool CefInitializeOnMainThread(const CefMainArgs& args, + const CefSettings& settings, + CefRefPtr application); + +void CefShutdownOnMainThread(); + +void CefDoMessageLoopWorkOnMainThread(); + +void SetVisibility(CefWindowHandle handle, bool isVisible); + +void UpdateView(CefWindowHandle handle, + CefRect contentRect, + CefRect browserRect); + +} // namespace util_mac + +#endif // JCEF_NATIVE_UTIL_MAC_H_ diff --git a/lib/jcef/native/util_mac.mm b/lib/jcef/native/util_mac.mm new file mode 100644 index 0000000..55eac97 --- /dev/null +++ b/lib/jcef/native/util_mac.mm @@ -0,0 +1,578 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#import "util_mac.h" +#import "util.h" + +#import +#import +#import +#include + +#include "include/base/cef_callback.h" +#include "include/cef_app.h" +#include "include/cef_application_mac.h" +#include "include/cef_browser.h" +#include "include/cef_path_util.h" + +#include "client_app.h" +#include "client_handler.h" +#include "critical_wait.h" +#include "jni_util.h" +#include "render_handler.h" +#include "temp_window.h" +#include "window_handler.h" + +namespace { + +static std::set g_browsers_; +static CriticalLock g_browsers_lock_; +id g_mouse_monitor_ = nil; +static CefRefPtr g_client_app_ = nullptr; +bool g_handling_send_event = false; + +} // namespace + +// Used for passing data to/from ClientHandler initialize:. +@interface InitializeParams : NSObject { + @public + CefMainArgs args_; + CefSettings settings_; + CefRefPtr application_; + bool result_; +} +@end +@implementation InitializeParams +@end + +// Used for passing data to/from ClientHandler setVisiblity:. +@interface SetVisibilityParams : NSObject { + @public + CefWindowHandle handle_; + bool isVisible_; +} +@end +@implementation SetVisibilityParams +@end + +// Obj-C Wrapper Class to be called by "performSelectorOnMainThread". +@interface CefHandler : NSObject { +} + ++ (void)initialize:(InitializeParams*)params; ++ (void)shutdown; ++ (void)doMessageLoopWork; ++ (void)setVisibility:(SetVisibilityParams*)params; + +@end // interface CefHandler + +// Java provides an NSApplicationAWT implementation that we can't access or +// override directly. Therefore add the necessary CefAppProtocol +// functionality to NSApplication using categories and swizzling. +@interface NSApplication (JCEFApplication) + +- (BOOL)isHandlingSendEvent; +- (void)setHandlingSendEvent:(BOOL)handlingSendEvent; +- (void)_swizzled_sendEvent:(NSEvent*)event; +- (void)_swizzled_terminate:(id)sender; + +@end + +@implementation NSApplication (JCEFApplication) + +// This selector is called very early during the application initialization. ++ (void)load { + // Swap NSApplication::sendEvent with _swizzled_sendEvent. + Method original = class_getInstanceMethod(self, @selector(sendEvent)); + Method swizzled = + class_getInstanceMethod(self, @selector(_swizzled_sendEvent)); + method_exchangeImplementations(original, swizzled); + + Method originalTerm = class_getInstanceMethod(self, @selector(terminate:)); + Method swizzledTerm = + class_getInstanceMethod(self, @selector(_swizzled_terminate:)); + method_exchangeImplementations(originalTerm, swizzledTerm); + + g_mouse_monitor_ = [NSEvent + addLocalMonitorForEventsMatchingMask:(NSEventMaskLeftMouseDown | + NSEventMaskLeftMouseUp | + NSEventMaskLeftMouseDragged | + NSEventMaskRightMouseDown | + NSEventMaskRightMouseUp | + NSEventMaskRightMouseDragged | + NSEventMaskOtherMouseDown | + NSEventMaskOtherMouseUp | + NSEventMaskOtherMouseDragged | + NSEventMaskScrollWheel | + NSEventMaskMouseMoved | + NSEventMaskMouseEntered | + NSEventMaskMouseExited) + handler:^(NSEvent* evt) { + // Get corresponding CefWindowHandle of + // Java-Canvas + NSView* browser = nullptr; + NSPoint absPos = [evt locationInWindow]; + NSWindow* evtWin = [evt window]; + g_browsers_lock_.Lock(); + std::set browsers = + g_browsers_; + g_browsers_lock_.Unlock(); + + std::set::iterator it; + for (it = browsers.begin(); + it != browsers.end(); ++it) { + NSView* wh = + CAST_CEF_WINDOW_HANDLE_TO_NSVIEW( + *it); + NSPoint relPos = [wh convertPoint:absPos + fromView:nil]; + if (evtWin == [wh window] && + [wh mouse:relPos + inRect:[wh frame]]) { + browser = wh; + break; + } + } + + if (!browser) + return evt; + + // Forward mouse event to browsers parent + // (JCEF UI) + switch ([evt type]) { + case NSEventTypeLeftMouseDown: + case NSEventTypeOtherMouseDown: + case NSEventTypeRightMouseDown: + [[browser superview] mouseDown:evt]; + return evt; + + case NSEventTypeLeftMouseUp: + case NSEventTypeOtherMouseUp: + case NSEventTypeRightMouseUp: + [[browser superview] mouseUp:evt]; + return evt; + + case NSEventTypeLeftMouseDragged: + case NSEventTypeOtherMouseDragged: + case NSEventTypeRightMouseDragged: + [[browser superview] mouseDragged:evt]; + return evt; + + case NSEventTypeMouseMoved: + [[browser superview] mouseMoved:evt]; + return evt; + + case NSEventTypeMouseEntered: + [[browser superview] mouseEntered:evt]; + return evt; + + case NSEventTypeMouseExited: + [[browser superview] mouseExited:evt]; + return evt; + + case NSEventTypeScrollWheel: + [[browser superview] scrollWheel:evt]; + return evt; + + default: + return evt; + } + }]; +} + +- (BOOL)isHandlingSendEvent { + return g_handling_send_event; +} + +- (void)setHandlingSendEvent:(BOOL)handlingSendEvent { + g_handling_send_event = handlingSendEvent; +} + +- (void)_swizzled_sendEvent:(NSEvent*)event { + CefScopedSendingEvent sendingEventScoper; + // Calls NSApplication::sendEvent due to the swizzling. + [self _swizzled_sendEvent:event]; +} + +// This method will be called via Cmd+Q. +- (void)_swizzled_terminate:(id)sender { + bool continueTerminate = true; + + if (g_client_app_.get()) { + // Call CefApp.handleBeforeTerminate() in Java. Will result in a call + // to CefShutdownOnMainThread() via CefApp.shutdown(). + continueTerminate = !g_client_app_->HandleTerminate(); + } + + if (continueTerminate) + [[CefHandler class] shutdown]; +} + +@end + +@implementation CefHandler + +// |params| will be released by the caller. ++ (void)initialize:(InitializeParams*)params { + g_client_app_ = params->application_; + params->result_ = CefInitialize(params->args_, params->settings_, + g_client_app_.get(), nullptr); +} + ++ (void)shutdown { + // Pump CefDoMessageLoopWork a few times before shutting down. + for (int i = 0; i < 10; ++i) + CefDoMessageLoopWork(); + + CefShutdown(); + g_client_app_ = nullptr; + + [NSEvent removeMonitor:g_mouse_monitor_]; +} + ++ (void)doMessageLoopWork { + CefDoMessageLoopWork(); +} + ++ (void)setVisibility:(SetVisibilityParams*)params { + if (g_client_app_) { + NSView* wh = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(params->handle_); + bool isHidden = [wh isHidden]; + if (isHidden == params->isVisible_) { + [wh setHidden:!params->isVisible_]; + [wh needsDisplay]; + [[wh superview] display]; + } + } + [params release]; +} + +@end // implementation CefHandler + +// Instead of adding CefBrowser as child of the windows main view, a content +// view (CefBrowserContentView) is set between the main view and the +// CefBrowser. Why? +// +// The CefBrowserContentView defines the viewable part of the browser view. +// In most cases the content view has the same size as the browser view, +// but for example if you add CefBrowser to a JScrollPane, you only want to +// see the portion of the browser window you're scrolled to. In this case +// the sizes of the content view and the browser view differ. +// +// With other words the CefBrowserContentView clips the CefBrowser to its +// displayable content. +// +// +- - - - - - - - - - - - - - - - - - - - -+ +// |/ / CefBrowser/ / / / / / /| +// +-------------------------+ / / / <--- invisible part of CefBrowser +// | | CefBrowserContentView | / / / | +// /| |/ / / +// |/ | | / / /| +// | <------------------ visible part of CefBrowser +// | | | / / / | +// /| |/ / / +// |/ | | / / /| +// | | / / / +// | +-------------------------+ / / / | +// / / / / / / / / / / +// |/ / / / / / / / / / /| +// / / / / / / / / / / +// | / / / / / / / / / / | +// +- - - - - - - - - - - - - - - - - - - - -+ +@interface CefBrowserContentView : NSView { + CefRefPtr cefBrowser; +} + +@property(readonly) BOOL isLiveResizing; + +- (void)addCefBrowser:(CefRefPtr)browser; +- (void)destroyCefBrowser; +- (void)updateView:(NSDictionary*)dict; +@end // interface CefBrowserContentView + +@implementation CefBrowserContentView + +@synthesize isLiveResizing; + +- (id)initWithFrame:(NSRect)frameRect { + self = [super initWithFrame:frameRect]; + cefBrowser = nullptr; + return self; +} + +- (void)dealloc { + if (cefBrowser) { + util::DestroyCefBrowser(cefBrowser); + } + [[NSNotificationCenter defaultCenter] removeObserver:self]; + cefBrowser = nullptr; + [super dealloc]; +} + +- (void)setFrame:(NSRect)frameRect { + // Instead of using the passed frame, get the visible rect from java because + // the passed frame rect doesn't contain the clipped view part. Otherwise + // we'll overlay some parts of the Java UI. + if (cefBrowser.get()) { + CefRefPtr clientHandler = + (ClientHandler*)(cefBrowser->GetHost()->GetClient().get()); + + CefRefPtr windowHandler = clientHandler->GetWindowHandler(); + if (windowHandler.get() != nullptr) { + CefRect rect; + windowHandler->GetRect(cefBrowser, rect); + util_mac::TranslateRect(self, rect); + frameRect = (NSRect){{rect.x, rect.y}, {rect.width, rect.height}}; + } + } + [super setFrame:frameRect]; +} + +- (void)addCefBrowser:(CefRefPtr)browser { + cefBrowser = browser; + // Register for the start and end events of "liveResize" to avoid + // Java paint updates while someone is resizing the main window (e.g. by + // pulling with the mouse cursor) + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(windowWillStartLiveResize:) + name:NSWindowWillStartLiveResizeNotification + object:[self window]]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(windowDidEndLiveResize:) + name:NSWindowDidEndLiveResizeNotification + object:[self window]]; +} + +- (void)destroyCefBrowser { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + cefBrowser = nullptr; + [self removeFromSuperview]; + // Also remove all subviews so the CEF objects are released. + for (NSView* view in [self subviews]) { + [view removeFromSuperview]; + } +} + +- (void)windowWillStartLiveResize:(NSNotification*)notification { + isLiveResizing = YES; +} + +- (void)windowDidEndLiveResize:(NSNotification*)notification { + isLiveResizing = NO; + [self setFrame:[self frame]]; +} + +- (void)updateView:(NSDictionary*)dict { + NSRect contentRect = NSRectFromString([dict valueForKey:@"content"]); + NSRect browserRect = NSRectFromString([dict valueForKey:@"browser"]); + + NSArray* childs = [self subviews]; + for (NSView* child in childs) { + [child setFrame:browserRect]; + [child setNeedsDisplay:YES]; + } + [super setFrame:contentRect]; + [self setNeedsDisplay:YES]; +} + +@end // implementation CefBrowserContentView + +namespace util_mac { + +std::string GetAbsPath(const std::string& path) { + char full_path[PATH_MAX]; + if (realpath(path.c_str(), full_path) == nullptr) + return std::string(); + return full_path; +} + +bool IsNSView(void* ptr) { + id obj = (id)ptr; + bool result = [obj isKindOfClass:[NSView class]]; + if (!result) + NSLog(@"Expected NSView, found %@", NSStringFromClass([obj class])); + return result; +} + +CefWindowHandle CreateBrowserContentView(NSWindow* window, CefRect& orig) { + NSView* mainView = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW([window contentView]); + TranslateRect(mainView, orig); + NSRect frame = {{orig.x, orig.y}, {orig.width, orig.height}}; + + CefBrowserContentView* contentView = + [[CefBrowserContentView alloc] initWithFrame:frame]; + + // Make the content view for the window have a layer. This will make all + // sub-views have layers. This is necessary to ensure correct layer + // ordering of all child views and their layers. + [contentView setWantsLayer:YES]; + + [mainView addSubview:contentView]; + [contentView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [contentView setNeedsDisplay:YES]; + + [contentView release]; + + // Override origin before "orig" is returned because the new origin is + // relative to the created CefBrowserContentView object + orig.x = 0; + orig.y = 0; + return contentView; +} + +// translate java's window origin to Obj-C's window origin +void TranslateRect(CefWindowHandle view, CefRect& orig) { + NSRect bounds = + [[[CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(view) window] contentView] bounds]; + orig.y = bounds.size.height - orig.height - orig.y; +} + +bool CefInitializeOnMainThread(const CefMainArgs& args, + const CefSettings& settings, + CefRefPtr application) { + InitializeParams* params = [[InitializeParams alloc] init]; + params->args_ = args; + params->settings_ = settings; + params->application_ = application; + params->result_ = false; + + // Block until done. + [[CefHandler class] performSelectorOnMainThread:@selector(initialize:) + withObject:params + waitUntilDone:YES]; + int result = params->result_; + [params release]; + return result; +} + +void CefShutdownOnMainThread() { + // Block until done. + [[CefHandler class] performSelectorOnMainThread:@selector(shutdown) + withObject:nil + waitUntilDone:YES]; +} + +void CefDoMessageLoopWorkOnMainThread() { + [[CefHandler class] + performSelector:@selector(doMessageLoopWork) + onThread:[NSThread mainThread] + withObject:nil + waitUntilDone:NO + modes:@[ NSDefaultRunLoopMode, NSEventTrackingRunLoopMode ]]; +} + +void SetVisibility(CefWindowHandle handle, bool isVisible) { + SetVisibilityParams* params = [[SetVisibilityParams alloc] init]; + params->handle_ = handle; + params->isVisible_ = isVisible; + [[CefHandler class] performSelectorOnMainThread:@selector(setVisibility:) + withObject:params + waitUntilDone:NO]; +} + +void UpdateView(CefWindowHandle handle, + CefRect contentRect, + CefRect browserRect) { + util_mac::TranslateRect(handle, contentRect); + CefBrowserContentView* browser = + (CefBrowserContentView*)[CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(handle) + superview]; + browserRect.y = contentRect.height - browserRect.height - browserRect.y; + + // Only update the view if nobody is currently resizing the main window. + // Otherwise the CefBrowser part may start flickering because there's a + // significant delay between the native window resize event and the java + // resize event + if (![browser isLiveResizing]) { + NSString* contentStr = [[NSString alloc] + initWithFormat:@"{{%d,%d},{%d,%d}", contentRect.x, contentRect.y, + contentRect.width, contentRect.height]; + NSString* browserStr = [[NSString alloc] + initWithFormat:@"{{%d,%d},{%d,%d}", browserRect.x, browserRect.y, + browserRect.width, browserRect.height]; + NSDictionary* dict = [[NSDictionary alloc] + initWithObjectsAndKeys:contentStr, @"content", browserStr, @"browser", + nil]; + [browser performSelectorOnMainThread:@selector(updateView:) + withObject:dict + waitUntilDone:NO]; + } +} + +} // namespace util_mac + +namespace util { + +void AddCefBrowser(CefRefPtr browser) { + if (!browser.get()) + return; + CefWindowHandle handle = browser->GetHost()->GetWindowHandle(); + g_browsers_lock_.Lock(); + g_browsers_.insert(handle); + g_browsers_lock_.Unlock(); + CefBrowserContentView* browserImpl = + (CefBrowserContentView*)[CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(handle) + superview]; + [browserImpl addCefBrowser:browser]; +} + +void DestroyCefBrowser(CefRefPtr browser) { + if (!browser.get()) + return; + NSView* handle = + CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(browser->GetHost()->GetWindowHandle()); + g_browsers_lock_.Lock(); + bool browser_exists = g_browsers_.erase(handle) > 0; + g_browsers_lock_.Unlock(); + if (!browser_exists) + return; + + // There are some cases where the superview of CefBrowser isn't + // a CefBrowserContentView. For example if another CefBrowser window was + // created by calling "window.open()" in JavaScript. + NSView* superView = [handle superview]; + if ([superView isKindOfClass:[CefBrowserContentView class]]) { + CefBrowserContentView* browserView = + (CefBrowserContentView*)[handle superview]; + [browserView destroyCefBrowser]; + } +} + +void SetParent(CefWindowHandle handle, + jlong parentHandle, + base::OnceClosure callback) { + base::RepeatingClosure* pCallback = new base::RepeatingClosure( + base::BindRepeating([](base::OnceClosure& cb) { std::move(cb).Run(); }, + OwnedRef(std::move(callback)))); + dispatch_async(dispatch_get_main_queue(), ^{ + g_browsers_lock_.Lock(); + bool browser_exists = g_browsers_.count(handle) > 0; + g_browsers_lock_.Unlock(); + if (!browser_exists) + return; + + CefBrowserContentView* browser_view = + (CefBrowserContentView*)[CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(handle) + superview]; + [browser_view retain]; + [browser_view removeFromSuperview]; + + NSView* contentView; + if (parentHandle) { + NSWindow* window = (NSWindow*)parentHandle; + contentView = [window contentView]; + } else { + contentView = + CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(TempWindow::GetWindowHandle()); + } + [contentView addSubview:browser_view]; + [browser_view release]; + pCallback->Run(); + delete pCallback; + }); +} + +} // namespace util diff --git a/lib/jcef/native/util_posix.cpp b/lib/jcef/native/util_posix.cpp new file mode 100644 index 0000000..0b5ead1 --- /dev/null +++ b/lib/jcef/native/util_posix.cpp @@ -0,0 +1,33 @@ +// 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 "util.h" + +#include +#include + +#include "include/cef_path_util.h" + +namespace util { + +int GetPid() { + return getpid(); +} + +int GetParentPid() { + return getppid(); +} + +std::string GetTempFileName(const std::string& identifer, bool useParentId) { + std::stringstream tmpName; + CefString tmpPath; + if (!CefGetPath(PK_DIR_TEMP, tmpPath)) + tmpPath = "/tmp/"; + tmpName << tmpPath.ToString().c_str(); + tmpName << "jcef-p" << (useParentId ? util::GetParentPid() : util::GetPid()); + tmpName << (identifer.empty() ? "" : "_") << identifer.c_str() << ".tmp"; + return tmpName.str(); +} + +} // namespace util diff --git a/lib/jcef/native/util_win.cpp b/lib/jcef/native/util_win.cpp new file mode 100644 index 0000000..cd60ef7 --- /dev/null +++ b/lib/jcef/native/util_win.cpp @@ -0,0 +1,338 @@ +// 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 "util.h" + +#include + +#include +#include +#include +#include +#include +#include + +#ifdef USING_JAVA +#include "client_handler.h" +#include "jni_util.h" +#include "temp_window.h" +#endif + +#include "include/base/cef_callback.h" +#include "include/cef_path_util.h" + +#define XBUTTON1_HI (XBUTTON1 << 16) +#undef MOUSE_MOVED + +namespace util { + +int GetPid() { + return (int)GetCurrentProcessId(); +} + +int GetParentPid() { + DWORD pid = GetCurrentProcessId(); + int ppid = 0; + HANDLE hProcess; + PROCESSENTRY32 pe32; + + hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcess == INVALID_HANDLE_VALUE) + return ppid; + + pe32.dwSize = sizeof(PROCESSENTRY32); + if (!Process32First(hProcess, &pe32)) { + CloseHandle(hProcess); + return ppid; + } + + do { + if (pe32.th32ProcessID == pid) { + ppid = (int)pe32.th32ParentProcessID; + break; + } + } while (Process32Next(hProcess, &pe32)); + + CloseHandle(hProcess); + return ppid; +} + +std::string GetTempFileName(const std::string& identifer, bool useParentId) { + std::stringstream tmpName; + CefString tmpPath; + if (!CefGetPath(PK_DIR_TEMP, tmpPath)) { + TCHAR lpPathBuffer[MAX_PATH]; + GetTempPath(MAX_PATH, lpPathBuffer); + tmpPath.FromWString(lpPathBuffer); + } + tmpName << tmpPath.ToString().c_str() << "\\"; + tmpName << "jcef-p" << (useParentId ? util::GetParentPid() : util::GetPid()); + tmpName << (identifer.empty() ? "" : "_") << identifer.c_str() << ".tmp"; + return tmpName.str(); +} + +#ifdef USING_JAVA + +static int getModifiers(BOOLEAN forceShift) { + ScopedJNIEnv env; + if (!env) + return 0; + + int modifiers = 0; + + const char* inputEventClassName = "java/awt/event/InputEvent"; + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, inputEventClassName), + ALT_DOWN_MASK, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, inputEventClassName), + CTRL_DOWN_MASK, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, inputEventClassName), + SHIFT_DOWN_MASK, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, inputEventClassName), + BUTTON1_DOWN_MASK, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, inputEventClassName), + BUTTON2_DOWN_MASK, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, inputEventClassName), + BUTTON3_DOWN_MASK, 0); + + if ((GetKeyState(VK_MENU) & 0x8000) != 0) + modifiers |= JNI_STATIC(ALT_DOWN_MASK); + if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) + modifiers |= JNI_STATIC(CTRL_DOWN_MASK); + if (forceShift || (GetKeyState(VK_SHIFT) & 0x8000) != 0) + modifiers |= JNI_STATIC(SHIFT_DOWN_MASK); + if ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0) + modifiers |= JNI_STATIC(BUTTON1_DOWN_MASK); + if ((GetAsyncKeyState(VK_MBUTTON) & 0x8000) != 0) + modifiers |= JNI_STATIC(BUTTON2_DOWN_MASK); + if ((GetAsyncKeyState(VK_RBUTTON) & 0x8000) != 0) + modifiers |= JNI_STATIC(BUTTON3_DOWN_MASK); + + return modifiers; +} + +static int getMouseButton(WPARAM wParam) { + ScopedJNIEnv env; + if (!env) + return 0; + + const char* mouseEventClassName = "java/awt/event/MouseEvent"; + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, mouseEventClassName), + BUTTON1, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, mouseEventClassName), + BUTTON2, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, mouseEventClassName), + BUTTON3, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, mouseEventClassName), + NOBUTTON, 0); + + switch (wParam) { + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + return JNI_STATIC(BUTTON1); + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MBUTTONDBLCLK: + return JNI_STATIC(BUTTON2); + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_RBUTTONDBLCLK: + return JNI_STATIC(BUTTON3); + default: + return JNI_STATIC(NOBUTTON); + } +} + +static int getMouseEvent(WPARAM wParam) { + ScopedJNIEnv env; + if (!env) + return 0; + + const char* mouseEventClassName = "java/awt/event/MouseEvent"; + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, mouseEventClassName), + MOUSE_MOVED, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, mouseEventClassName), + MOUSE_PRESSED, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, mouseEventClassName), + MOUSE_RELEASED, 0); + JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, mouseEventClassName), + MOUSE_WHEEL, 0); + + switch (wParam) { + case WM_MOUSEMOVE: + return JNI_STATIC(MOUSE_MOVED); + + // Handle a double click like a single click. + case WM_LBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: + // FALL THRU + + // Handle button down and up events. + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + return JNI_STATIC(MOUSE_PRESSED); + + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + return JNI_STATIC(MOUSE_RELEASED); + + // Handle horizontal mouse wheel event. + // The vertical mouse wheel is already recognized in Java. + // case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: + return JNI_STATIC(MOUSE_WHEEL); + default: + return 0; + } +} + +static std::map> g_browsers_; +static HANDLE g_browsers_lock_ = CreateMutex(NULL, FALSE, NULL); +static HHOOK g_mouse_monitor_ = NULL; +static HHOOK g_proc_monitor_ = NULL; +static int g_mouse_monitor_refs_ = 0; +static BOOLEAN g_once_ = TRUE; + +LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) { + if (nCode != HC_ACTION || lParam == NULL) + return CallNextHookEx(NULL, nCode, wParam, lParam); + + MOUSEHOOKSTRUCT* pStruct = (MOUSEHOOKSTRUCT*)lParam; + + // Find the CefBrowser associated with the current window hierarchy. + CefWindowHandle windowHandle = pStruct->hwnd; + CefRefPtr cefBrowser; + std::map>::iterator it; + WaitForSingleObject(g_browsers_lock_, INFINITE); + while (windowHandle != NULL) { + it = g_browsers_.find(windowHandle); + if (it != g_browsers_.end()) { + cefBrowser = it->second; + break; + } + windowHandle = GetParent(windowHandle); + } + ReleaseMutex(g_browsers_lock_); + + if (!cefBrowser) + return CallNextHookEx(NULL, nCode, wParam, lParam); + + // We're creating the scoped JNI env here so it can be re-used for + // the following subfunctions, which all need an env internally, + // without having the invoking thread constantly attaching and + // detaching from the JVM (which is ugly, especially if a debugger + // is attached, but also generally detrimental to performance) + ScopedJNIEnv env; + if (!env) + return CallNextHookEx(NULL, nCode, wParam, lParam); + + int mouseButton = getMouseButton(wParam); + // Horizonal wheel event is the same as vertical wheel event + // with pressed shift button. + int modifiers = getModifiers(wParam == WM_MOUSEHWHEEL); + + int mouseEvent = getMouseEvent(wParam); + switch (wParam) { + // Handle horizontal mouse wheel event. + // The vertical mouse wheel is already recognized in Java. + // case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: + mouseButton = + GET_WHEEL_DELTA_WPARAM(((MOUSEHOOKSTRUCTEX*)pStruct)->mouseData); + break; + default: + break; + } + + if (mouseEvent != 0) { + // Forward params to the CefWindowHandle of Java-Canvas + CefRefPtr client = + (ClientHandler*)cefBrowser->GetHost()->GetClient().get(); + CefRefPtr handler = client->GetWindowHandler(); + handler->OnMouseEvent(cefBrowser, mouseEvent, pStruct->pt.x, pStruct->pt.y, + modifiers, mouseButton); + } + + return CallNextHookEx(NULL, nCode, wParam, lParam); +} + +void AddCefBrowser(CefRefPtr browser) { + if (!browser.get()) + return; + CefWindowHandle browserHandle = browser->GetHost()->GetWindowHandle(); + if (!browserHandle) + return; + + WaitForSingleObject(g_browsers_lock_, INFINITE); + std::pair> pair = + std::make_pair(browserHandle, browser); + g_browsers_.insert(pair); + ReleaseMutex(g_browsers_lock_); + + if (g_mouse_monitor_ == NULL) { + DWORD threadId = GetWindowThreadProcessId(browserHandle, NULL); + g_mouse_monitor_ = + SetWindowsHookEx(WH_MOUSE, util::MouseProc, NULL, threadId); + g_mouse_monitor_refs_ = 1; + } else { + g_mouse_monitor_refs_++; + } +} + +void DestroyCefBrowser(CefRefPtr browser) { + if (!browser.get()) + return; + CefWindowHandle browserHandle = browser->GetHost()->GetWindowHandle(); + if (!browserHandle) + return; + + WaitForSingleObject(g_browsers_lock_, INFINITE); + size_t erased = g_browsers_.erase(browserHandle); + DCHECK_EQ(1U, erased); + ReleaseMutex(g_browsers_lock_); + + ::DestroyWindow(browserHandle); + + if (g_mouse_monitor_ == NULL) + return; + g_mouse_monitor_refs_--; + if (g_mouse_monitor_refs_ <= 0) { + UnhookWindowsHookEx(g_mouse_monitor_); + g_mouse_monitor_ = NULL; + } +} + +CefWindowHandle GetWindowHandle(JNIEnv* env, jobject canvas) { + return GetHwndOfCanvas(canvas, env); +} + +void SetParent(CefWindowHandle browserHandle, + CefWindowHandle parentHandle, + base::OnceClosure callback) { + if (parentHandle == kNullWindowHandle) + parentHandle = TempWindow::GetWindowHandle(); + if (parentHandle != kNullWindowHandle && browserHandle != kNullWindowHandle) + ::SetParent(browserHandle, parentHandle); + std::move(callback).Run(); +} + +void SetWindowBounds(CefWindowHandle browserHandle, + const CefRect& contentRect) { + HRGN contentRgn = CreateRectRgn(contentRect.x, contentRect.y, + contentRect.x + contentRect.width, + contentRect.y + contentRect.height); + SetWindowRgn(GetParent(browserHandle), contentRgn, TRUE); +} + +void SetWindowSize(CefWindowHandle browserHandle, int width, int height) { + SetWindowPos(browserHandle, NULL, 0, 0, width, height, + SWP_NOZORDER | SWP_NOMOVE); +} + +#endif // USING_JAVA + +} // namespace util diff --git a/lib/jcef/native/window_handler.cpp b/lib/jcef/native/window_handler.cpp new file mode 100644 index 0000000..701bc70 --- /dev/null +++ b/lib/jcef/native/window_handler.cpp @@ -0,0 +1,52 @@ +// 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. + +#include "window_handler.h" + +#include "jni_util.h" + +WindowHandler::WindowHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +bool WindowHandler::GetRect(CefRefPtr browser, CefRect& rect) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIBrowser jbrowser(env, browser); + return GetRect(jbrowser, rect); +} + +bool WindowHandler::GetRect(jobject browser, CefRect& rect) { + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIObjectResult jreturn(env); + JNI_CALL_METHOD(env, handle_, "getRect", + "(Lorg/cef/browser/CefBrowser;)Ljava/awt/Rectangle;", Object, + jreturn, browser); + if (jreturn) { + rect = GetJNIRect(env, jreturn); + return true; + } + return false; +} + +void WindowHandler::OnMouseEvent(CefRefPtr browser, + int mouseEvent, + int absX, + int absY, + int modifier, + int button) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + JNI_CALL_VOID_METHOD(env, handle_, "onMouseEvent", + "(Lorg/cef/browser/CefBrowser;IIIII)V", jbrowser.get(), + (jint)mouseEvent, (jint)absX, (jint)absY, (jint)modifier, + (jint)button); +} diff --git a/lib/jcef/native/window_handler.h b/lib/jcef/native/window_handler.h new file mode 100644 index 0000000..a901939 --- /dev/null +++ b/lib/jcef/native/window_handler.h @@ -0,0 +1,38 @@ +// 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. + +#ifndef JCEF_NATIVE_WINDOW_HANDLER_H_ +#define JCEF_NATIVE_WINDOW_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_base.h" +#include "include/cef_browser.h" + +#include "jni_scoped_helpers.h" + +// WindowHandler implementation. +class WindowHandler : public CefBaseRefCounted { + public: + WindowHandler(JNIEnv* env, jobject handler); + + // WindowHandler methods + bool GetRect(CefRefPtr browser, CefRect& rect); + bool GetRect(jobject browser, CefRect& rect); + void OnMouseEvent(CefRefPtr browser, + int mouseEvent, + int absX, + int absY, + int modifier, + int button); + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(WindowHandler); +}; + +#endif // JCEF_NATIVE_WINDOW_HANDLER_H_ diff --git a/lib/jcef/native/write_handler.cpp b/lib/jcef/native/write_handler.cpp new file mode 100644 index 0000000..e73fd44 --- /dev/null +++ b/lib/jcef/native/write_handler.cpp @@ -0,0 +1,64 @@ +// 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 "write_handler.h" + +#include "jni_util.h" +#include "util.h" + +WriteHandler::WriteHandler(JNIEnv* env, jobject jOutputStream) + : handle_(env, jOutputStream) {} + +WriteHandler::~WriteHandler() { + ScopedJNIEnv env; + if (!env) + return; + + if (handle_) { + JNI_CALL_VOID_METHOD(env, handle_, "close", "()V"); + } +} + +size_t WriteHandler::Write(const void* ptr, size_t size, size_t n) { + base::AutoLock lock_scope(lock_); + size_t rv = n; + + ScopedJNIEnv env; + if (!env) + return rv; + + jbyteArray jbyteArray = env->NewByteArray((jsize)(size * n)); + env->SetByteArrayRegion(jbyteArray, 0, (jsize)(size * n), (const jbyte*)ptr); + + JNI_CALL_VOID_METHOD_EX(env, handle_, "write", "([B)V", jbyteArray); + if (env->ExceptionOccurred()) { + env->ExceptionClear(); + rv = 0; + } + offset_ += (rv * size); + env->DeleteLocalRef(jbyteArray); + + return rv; +} + +int WriteHandler::Seek(int64_t offset, int whence) { + // not supported by Javas OutputStream + return -1; +} + +int64_t WriteHandler::Tell() { + return offset_; +} + +int WriteHandler::Flush() { + ScopedJNIEnv env; + if (env) { + JNI_CALL_VOID_METHOD(env, handle_, "flush", "()V"); + } + return 0; +} + +bool WriteHandler::MayBlock() { + return false; +} diff --git a/lib/jcef/native/write_handler.h b/lib/jcef/native/write_handler.h new file mode 100644 index 0000000..f9bd854 --- /dev/null +++ b/lib/jcef/native/write_handler.h @@ -0,0 +1,39 @@ +// 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 JCEF_NATIVE_WRITE_HANDLER_H_ +#define JCEF_NATIVE_WRITE_HANDLER_H_ +#pragma once + +#include + +#include "include/base/cef_lock.h" +#include "include/cef_stream.h" + +#include "jni_scoped_helpers.h" + +// WriteHandler implementation. +class WriteHandler : public CefWriteHandler { + public: + WriteHandler(JNIEnv* env, jobject jOutputStream); + virtual ~WriteHandler(); + + // CefWriteHandler methods + virtual size_t Write(const void* ptr, size_t size, size_t n) override; + virtual int Seek(int64_t offset, int whence) override; + virtual int64_t Tell() override; + virtual int Flush() override; + virtual bool MayBlock() override; + + protected: + ScopedJNIObjectGlobal handle_; + size_t offset_ = 0; + + base::Lock lock_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(WriteHandler); +}; + +#endif // JCEF_NATIVE_WRITE_HANDLER_H_ diff --git a/lib/jcef/third_party/appbundler/AppBundler.html b/lib/jcef/third_party/appbundler/AppBundler.html new file mode 100644 index 0000000..85b2f33 --- /dev/null +++ b/lib/jcef/third_party/appbundler/AppBundler.html @@ -0,0 +1,197 @@ + + + + + + + +AppBundler Task + + + +

AppBundler

+

Description

+

Generates a native launcher for a Java application.

+ +

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
outputdirectoryThe output folder for the generated bundle.Yes
nameThe name of the application. + Corresponds to the CFBundleName key in the Info.plist file.Yes
displaynameThe display name of the application. + Corresponds to the CFBundleDisplayName key in the Info.plist file.Yes
identifierAn identifier string that specifies the application type. + Corresponds to the CFBundleIdentifier key in the Info.plist file.Yes
iconThe icon file for the application. + Corresponds to the CFBundleIconFile key in the Info.plist file.No
shortversionThe release version number string for the application. + Corresponds to the CFBundleShortVersionString key in the Info.plist + file.No
signatureThe four-letter code identifying the application creator. + Corresponds to the CFBundleSignature key in the Info.plist file.No
copyrightThe copyright notice for the application. + Corresponds to the NSHumanReadableCopyright key in the Info.plist + file.No
applicationCategoryThe application category. + Corresponds to the LSApplicationCategoryType key in the Info.plist + file.No
mainclassnameThe name of the bundled application's main class.Yes
+ +

Parameters specified as nested elements

+

runtime

+

A fileset representing the Java +runtime environment to embed in the application.

+ +

This element is optional. If specified, the base directory of the fileset must point to the +root directory of a valid Java runtime environment. The contents of the runtime will be copied to +the Contents/PlugIns/ folder of the generated application bundle.

+ +

By default, only the contents of the jre/ directory will be included with the bundled +application. All executable content (i.e. bin/, jre/bin/) is excluded. Additional +content can be included or excluded using nested <include> and +<exclude> elements, respectively.

+ +

If this element is omitted, a Java runtime environment will not be copied into the generated +bundle, and target systems must have a shared JRE installed in +/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/ in order to run the application.

+ +

classpath

+

A fileset representing the class +path of the bundled application. Corresponds to the java.class.path system property. +Entries will be copied to the Contents/Java/ folder of the generated bundle.

+ +

librarypath

+

A fileset representing the library +path of the bundled application. Corresponds to the java.library.path system property. +Entries will be copied to the Contents/MacOS/ folder of the generated bundle.

+ +

option

+

Specifies a command-line option to be passed to the JVM at startup.

+ + + + + + + + + + + +
AttributeDescriptionRequired
valueThe option value. Occurrences of the string "$APP_ROOT" will be replaced with + the absolute file system path to the application bundle.Yes
+ +

argument

+

Specifies a command-line argument to be passed to the bundled application at startup.

+ + + + + + + + + + + +
AttributeDescriptionRequired
valueThe argument value. Occurrences of the string "$APP_ROOT" will be replaced with + the absolute file system path to the application bundle.Yes
+ +

Examples

+

Generate a launcher for the "Swing Set" demo, bundling the JRE defined by the JAVA_HOME +environment variable with the resulting executable.

+
+<-- Import environment variables -->
+<property environment="env"/>
+
+<-- Define the appbundler task -->
+<taskdef name="bundleapp" classname="com.oracle.appbundler.AppBundlerTask"/>
+
+<-- Create the app bundle -->
+<target name="bundle-swingset" depends="package">
+    <bundleapp outputdirectory="."
+        name="Test"
+        displayname="Test"
+        identifier="com.oracle.javafx.swing.Test"
+        shortversion="1.0"
+        applicationCategory="public.app-category.developer-tools"
+        mainclassname="com/javafx/main/Main">
+        <runtime dir="${env.JAVA_HOME}"/>
+        <classpath file="${user.home}/bin/javafx-samples-2.2.0/SwingInterop.jar"/>
+        <option value="-Dapple.laf.useScreenMenuBar=true"/>
+    </bundleapp>
+</target>
+
+ + + \ No newline at end of file diff --git a/lib/jcef/third_party/appbundler/README.jcef b/lib/jcef/third_party/appbundler/README.jcef new file mode 100644 index 0000000..2384e4f --- /dev/null +++ b/lib/jcef/third_party/appbundler/README.jcef @@ -0,0 +1,15 @@ +Name: Java Application Bundler +Short Name: appbundler +URL: https://github.com/TheInfiniteKind/appbundler/ +Version: 1.0 (commit b0857c9b) +License: GPL-2.0 + +Description: +Packages a Java application as Mac app bundle. + +See the project URL for related documentation. + +Local Modifications: +1. Clone the repo using Git. +2. Run `ant` from the top-level directory. +3. Copy the resulting /appbundler/bin/appbundler-1.0ea.jar file to this directory. diff --git a/lib/jcef/third_party/appbundler/appbundler-1.0.jar b/lib/jcef/third_party/appbundler/appbundler-1.0.jar new file mode 100644 index 0000000..7663198 Binary files /dev/null and b/lib/jcef/third_party/appbundler/appbundler-1.0.jar differ diff --git a/lib/jcef/third_party/appbundler/appbundler.LICENSE.txt b/lib/jcef/third_party/appbundler/appbundler.LICENSE.txt new file mode 100644 index 0000000..464a74b --- /dev/null +++ b/lib/jcef/third_party/appbundler/appbundler.LICENSE.txt @@ -0,0 +1,123 @@ +The GNU General Public License (GPL-2.0) +Version 2, June 1991 +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + +a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + +b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + +c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + +a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + +b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + +c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + +One line to give the program's name and a brief idea of what it does. +Copyright (C) + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + +Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. + +signature of Ty Coon, 1 April 1989 +Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. diff --git a/lib/jcef/third_party/cef/README.jcef b/lib/jcef/third_party/cef/README.jcef new file mode 100644 index 0000000..7cac801 --- /dev/null +++ b/lib/jcef/third_party/cef/README.jcef @@ -0,0 +1,11 @@ +Name: Chromium Embedded Framework +Short Name: cef +URL: https://github.com/chromiumembedded/cef +License: BSD + +Description: +CEF binary distribution. Downloaded during CMake configuration. +See the top-level CMakeLists.txt file for usage. + +Local Modifications: +None. diff --git a/lib/jcef/third_party/cef/res/CefIcon.icns b/lib/jcef/third_party/cef/res/CefIcon.icns new file mode 100644 index 0000000..1f27069 Binary files /dev/null and b/lib/jcef/third_party/cef/res/CefIcon.icns differ diff --git a/lib/jcef/third_party/jogamp/README.jcef b/lib/jcef/third_party/jogamp/README.jcef new file mode 100644 index 0000000..e9080ea --- /dev/null +++ b/lib/jcef/third_party/jogamp/README.jcef @@ -0,0 +1,20 @@ +Name: Java™ libraries for 3D Graphics, Multimedia and Processing +Short Name: jogamp +URL: http://jogamp.org/ +Version: jogl-2.4.0, gluegen-2.4.0 +License: Mixed (see LICENSE.txt files) + +Description: +This library is used to provide OpenGL bindings. Download the platform 7z +files from https://jogamp.org/deployment/v2.4.0/jar/ and extract the +required jar files from the jar/ directory. + +See http://jogamp.org/wiki/index.php/Downloading_and_installing_JOGL for +related documentation. + +Local Modifications: +Patch OSXUtil.DestroyNSWindow in jogl-all.jar to dispatch via +RunOnMainThread when called from a background thread, matching how +CreateNSWindow is already handled. The issue includes a script for +applying this patch to the original 2.4.0 jar version. +https://github.com/chromiumembedded/java-cef/issues/514#issuecomment-3825848565 diff --git a/lib/jcef/third_party/jogamp/gluegen.LICENSE.txt b/lib/jcef/third_party/jogamp/gluegen.LICENSE.txt new file mode 100644 index 0000000..1b21c36 --- /dev/null +++ b/lib/jcef/third_party/jogamp/gluegen.LICENSE.txt @@ -0,0 +1,182 @@ +The GlueGen source code is mostly licensed under the New BSD 2-clause license, +however it contains other licensed material as well. + +Other licensed material is compatible with the 'New BSD 2-Clause License', +if not stated otherwise. + +'New BSD 2-Clause License' incompatible materials are optional, they are: + + NONE + +Below you find a detailed list of licenses used in this project. + ++++ + +The content of folder 'make/lib' contains build-time only +Java binaries (JAR) to ease the build setup. +Each JAR file has it's corresponding LICENSE file containing the +source location and license text. None of these binaries are contained in any way +by the generated and deployed GlueGen binaries. + ++++ + +L.1) The GlueGen source tree contains code from the JogAmp Community + which is covered by the Simplified BSD 2-clause license: + + Copyright 2010 JogAmp Community. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are + permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. 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. + + THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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. + + The views and conclusions contained in the software and documentation are those of the + authors and should not be interpreted as representing official policies, either expressed + or implied, of JogAmp Community. + + You can address the JogAmp Community via: + Web http://jogamp.org/ + Forum/Mailinglist http://jogamp.762907.n3.nabble.com/ + Chatrooms + IRC irc.freenode.net #jogamp + Jabber conference.jabber.org room: jogamp (deprecated!) + Repository http://jogamp.org/git/ + Email mediastream _at_ jogamp _dot_ org + + +L.2) The GlueGen source tree contains code from Sun Microsystems, Inc. + which is covered by the New BSD 3-clause license: + + Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistribution of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistribution 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 Sun Microsystems, Inc. or the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + This software is provided "AS IS," without a warranty of any kind. ALL + EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + You acknowledge that this software is not designed or intended for use + in the design, construction, operation or maintenance of any nuclear + facility. + +L.3) The GlueGen source tree contains CGRAM http://www.antlr.org/grammar/cgram/, + a ANSI-C parser implementation using ANTLR, which is being used + in the compile time part only. + It is covered by the Original BSD 4-clause license: + + Copyright (c) 1998-2000, Non, Inc. + 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. + + All advertising materials mentioning features or use of this + software must display the following acknowledgement: + + This product includes software developed by Non, Inc. and + its contributors. + + Neither name of the company 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 COMPANY 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. + +A.1) The GlueGen source tree contains code from The Apache Software Foundation + which is covered by the Apache License Version 2.0 + + Apache Harmony - Open Source Java SE + ===================================== + + + + Author: The Apache Software Foundation (http://www.apache.org/). + + Copyright 2006, 2010 The Apache Software Foundation. + + Apache License Version 2.0, January 2004 + http://www.apache.org/licenses/LICENSE-2.0 + Or within this repository: doc/licenses/Apache.LICENSE-2.0 + + Files: + - src/java/com/jogamp/common/net/Uri.java + (derived from java.net.URI.Helper and heavily modified) + +A.2) The GlueGen source tree contains code from Ben Mankin, a.k.a 'Shevek', + which is covered by the Apache License Version 2.0 + + JCPP - A Java C Preprocessor + ============================= + + + + + Author: Ben Mankin, a.k.a 'Shevek' (http://www.anarres.org/about/). + + Copyright (c) 2007-2008, Shevek + + Apache License Version 2.0, January 2004 + http://www.apache.org/licenses/LICENSE-2.0 + Or within this repository: doc/licenses/Apache.LICENSE-2.0 + + Files: + The complete git submodule 'jcpp', + which is a patched version of the original mentioned above. + + Used for the compile-time module gluegen.jar only. + diff --git a/lib/jcef/third_party/jogamp/jar/gluegen-rt-natives-linux-amd64.jar b/lib/jcef/third_party/jogamp/jar/gluegen-rt-natives-linux-amd64.jar new file mode 100644 index 0000000..00e9d72 Binary files /dev/null and b/lib/jcef/third_party/jogamp/jar/gluegen-rt-natives-linux-amd64.jar differ diff --git a/lib/jcef/third_party/jogamp/jar/gluegen-rt-natives-macosx-universal.jar b/lib/jcef/third_party/jogamp/jar/gluegen-rt-natives-macosx-universal.jar new file mode 100644 index 0000000..7ad092b Binary files /dev/null and b/lib/jcef/third_party/jogamp/jar/gluegen-rt-natives-macosx-universal.jar differ diff --git a/lib/jcef/third_party/jogamp/jar/gluegen-rt-natives-windows-amd64.jar b/lib/jcef/third_party/jogamp/jar/gluegen-rt-natives-windows-amd64.jar new file mode 100644 index 0000000..992a566 Binary files /dev/null and b/lib/jcef/third_party/jogamp/jar/gluegen-rt-natives-windows-amd64.jar differ diff --git a/lib/jcef/third_party/jogamp/jar/gluegen-rt.jar b/lib/jcef/third_party/jogamp/jar/gluegen-rt.jar new file mode 100644 index 0000000..2025bf8 Binary files /dev/null and b/lib/jcef/third_party/jogamp/jar/gluegen-rt.jar differ diff --git a/lib/jcef/third_party/jogamp/jar/jogl-all-natives-linux-amd64.jar b/lib/jcef/third_party/jogamp/jar/jogl-all-natives-linux-amd64.jar new file mode 100644 index 0000000..edc5703 Binary files /dev/null and b/lib/jcef/third_party/jogamp/jar/jogl-all-natives-linux-amd64.jar differ diff --git a/lib/jcef/third_party/jogamp/jar/jogl-all-natives-macosx-universal.jar b/lib/jcef/third_party/jogamp/jar/jogl-all-natives-macosx-universal.jar new file mode 100644 index 0000000..7dda364 Binary files /dev/null and b/lib/jcef/third_party/jogamp/jar/jogl-all-natives-macosx-universal.jar differ diff --git a/lib/jcef/third_party/jogamp/jar/jogl-all-natives-windows-amd64.jar b/lib/jcef/third_party/jogamp/jar/jogl-all-natives-windows-amd64.jar new file mode 100644 index 0000000..d8f66a1 Binary files /dev/null and b/lib/jcef/third_party/jogamp/jar/jogl-all-natives-windows-amd64.jar differ diff --git a/lib/jcef/third_party/jogamp/jar/jogl-all.jar b/lib/jcef/third_party/jogamp/jar/jogl-all.jar new file mode 100644 index 0000000..64503dd Binary files /dev/null and b/lib/jcef/third_party/jogamp/jar/jogl-all.jar differ diff --git a/lib/jcef/third_party/jogamp/jogl.LICENSE.txt b/lib/jcef/third_party/jogamp/jogl.LICENSE.txt new file mode 100644 index 0000000..02d605c --- /dev/null +++ b/lib/jcef/third_party/jogamp/jogl.LICENSE.txt @@ -0,0 +1,430 @@ +The JOGL source code is mostly licensed under the 'New BSD 2-Clause License', +however it contains other licensed material as well. + +Other licensed material is compatible with the 'New BSD 2-Clause License', +if not stated otherwise. + +'New BSD 2-Clause License' incompatible materials are optional, they are: + + A.7) The JOGL source tree _may_ contain code from Oculus VR, Inc. + which is covered by it's own permissive Oculus VR Rift SDK Software License. + (Optional, see A.7 below for details) + +Below you find a detailed list of licenses used in this project. + ++++ + +The content of folder 'make/lib' contains build- and test-time only +Java binaries (JAR) to ease the build setup. +Each JAR file has it's corresponding LICENSE file containing the +source location and license text. None of these binaries are contained in any way +by the generated and deployed JOGL binaries. + ++++ + +L.1) The JOGL source tree contains code from the JogAmp Community + which is covered by the Simplified BSD 2-clause license: + + Copyright 2010 JogAmp Community. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are + permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. 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. + + THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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. + + The views and conclusions contained in the software and documentation are those of the + authors and should not be interpreted as representing official policies, either expressed + or implied, of JogAmp Community. + + You can address the JogAmp Community via: + Web http://jogamp.org/ + Forum/Mailinglist http://forum.jogamp.org + Chatrooms + IRC irc.freenode.net #jogamp + Jabber conference.jabber.org room: jogamp (deprecated!) + Repository http://jogamp.org/git/ + Email mediastream _at_ jogamp _dot_ org + + +L.2) The JOGL source tree contains code from Sun Microsystems, Inc. + which is covered by the New BSD 3-clause license: + + Copyright (c) 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistribution of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistribution 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 Sun Microsystems, Inc. or the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + This software is provided "AS IS," without a warranty of any kind. ALL + EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + You acknowledge that this software is not designed or intended for use + in the design, construction, operation or maintenance of any nuclear + facility. + +L.3) The JOGL source tree contains code ported from the OpenGL sample + implementation by Silicon Graphics, Inc. This code is licensed under + the SGI Free Software License B, Version 2.0 + + License Applicability. Except to the extent portions of this file are + made subject to an alternative license as permitted in the SGI Free + Software License B, Version 2.0 (the "License"), the contents of this + file are subject only to the provisions of the License. You may not use + this file except in compliance with the License. You may obtain a copy + of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + + http://oss.sgi.com/projects/FreeB + http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf + Or within this repository: doc/licenses/SGIFreeSWLicB.2.0.pdf + + Note that, as provided in the License, the Software is distributed on an + "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + +L.4) The JOGL source tree contains code from the LWJGL project which is + similarly covered by the New BSD 3-clause license: + + Copyright (c) 2002-2004 LWJGL Project + 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 'LWJGL' 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. + +L.5) The JOGL source tree also contains a Java port of Brian Paul's Tile + Rendering library, used with permission of the author under the + New BSD 3-clause license instead of the original LGPL: + + Copyright (c) 1997-2005 Brian Paul. All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistribution of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistribution 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 Brian Paul or the names of contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + This software is provided "AS IS," without a warranty of any + kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + EXCLUDED. THE COPYRIGHT HOLDERS AND CONTRIBUTORS SHALL NOT BE + LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO + EVENT WILL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY + LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + INABILITY TO USE THIS SOFTWARE, EVEN IF THE COPYRIGHT HOLDERS OR + CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +A.1) The JOGL source tree also contains header files from Khronos, + reflecting OpenKODE, EGL, OpenGL ES1, OpenGL ES2 and OpenGL. + + http://www.khronos.org/legal/license/ + + Files: + make/stub_includes/opengl/** + make/stub_includes/egl/** + make/stub_includes/khr/** + make/stub_includes/openmax/** + + Copyright (c) 2007-2010 The Khronos Group Inc. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and/or associated documentation files (the + "Materials"), to deal in the Materials without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Materials, and to + permit persons to whom the Materials are furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Materials. + + THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + + +A.2) The JOGL source tree contains code from The Apache Software Foundation + which is covered by the Apache License Version 2.0 + + Apache Harmony - Open Source Java SE + ===================================== + + + + Author: The Apache Software Foundation (http://www.apache.org/). + + Copyright 2006, 2010 The Apache Software Foundation. + + Apache License Version 2.0, January 2004 + http://www.apache.org/licenses/LICENSE-2.0 + Or within this repository: doc/licenses/Apache.LICENSE-2.0 + + Files: + src/jogamp/graph/geom/plane/AffineTransform.java + src/jogamp/graph/geom/plane/IllegalPathStateException.java + src/jogamp/graph/geom/plane/NoninvertibleTransformException.java + src/jogamp/graph/geom/plane/PathIterator.java + src/jogamp/graph/geom/plane/Path2D.java + src/jogamp/graph/math/plane/Crossing.java + src/org/apache/harmony/misc/HashCode.java + + +A.3) The JOGL source tree contains code from David Schweinsberg + which is covered by the Apache License Version 1.1 and Version 2.0 + + Typecast + ======== + + Typecast is a font development environment for OpenType font technology. + + + + Author: David Schweinsberg + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Apache Licenses + http://www.apache.org/licenses/ + + Apache License Version 1.1 + http://www.apache.org/licenses/LICENSE-1.1 + Or within this repository: doc/licenses/Apache.LICENSE-1.1 + Files: + src/jogl/classes/jogamp/graph/font/typecast/ot/* + src/jogl/classes/jogamp/graph/font/typecast/ot/table/* + + Apache License Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + Or within this repository: doc/licenses/Apache.LICENSE-2.0 + src/jogl/classes/jogamp/graph/font/typecast/ot/* + src/jogl/classes/jogamp/graph/font/typecast/ot/mac/* + src/jogl/classes/jogamp/graph/font/typecast/ot/table/* + src/jogl/classes/jogamp/graph/font/typecast/tt/engine/* + +A.4) The JOGL source tree contains fonts from Ubuntu + which is covered by the UBUNTU FONT LICENCE Version 1.0 + + Ubuntu Font Family + ================== + + The Ubuntu Font Family are libre fonts funded by Canonical Ltd on behalf of the Ubuntu project. + + + + Copyright 2010 Canonical Ltd. + Licensed under the Ubuntu Font Licence 1.0 + + Author: Canonical Ltd., Dalton Maag + + UBUNTU FONT LICENCE + Version 1.0 + http://font.ubuntu.com/ufl/ubuntu-font-licence-1.0.txt + Or within this repository: doc/licenses/ubuntu-font-licence-1.0.txt + + Files: + src/jogamp/graph/font/fonts/ubuntu/* + +A.5) The JOGL source tree also contains header files from NVIDIA, + reflecting Cg. + + Files: + make/stub_includes/cg/CG/** + + Copyright (c) 2002, NVIDIA Corporation + + NVIDIA Corporation("NVIDIA") supplies this software to you in consideration + of your agreement to the following terms, and your use, installation, + modification or redistribution of this NVIDIA software constitutes + acceptance of these terms. If you do not agree with these terms, please do + not use, install, modify or redistribute this NVIDIA software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, NVIDIA grants you a personal, non-exclusive license, + under NVIDIA's copyrights in this original NVIDIA software (the "NVIDIA + Software"), to use, reproduce, modify and redistribute the NVIDIA + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the NVIDIA Software, you must retain the + copyright notice of NVIDIA, this notice and the following text and + disclaimers in all such redistributions of the NVIDIA Software. Neither the + name, trademarks, service marks nor logos of NVIDIA Corporation may be used + to endorse or promote products derived from the NVIDIA Software without + specific prior written permission from NVIDIA. Except as expressly stated + in this notice, no other rights or licenses express or implied, are granted + by NVIDIA herein, including but not limited to any patent rights that may be + infringed by your derivative works or by other works in which the NVIDIA + Software may be incorporated. No hardware is licensed hereunder. + + THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR ITS USE AND OPERATION + EITHER ALONE OR IN COMBINATION WITH OTHER PRODUCTS. + + IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, + EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOST + PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY OUT OF THE USE, + REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE NVIDIA SOFTWARE, + HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING + NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF NVIDIA HAS BEEN ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +A.6) The JOGL source tree contains code from Hernan J. Gonzalez and Shawn Hartsock + which is covered by the Apache License Version 2.0 + + PNGJ + ==== + + PNGJ: Java library for reading and writing PNG images. + + Version 1.12 (3 Dec 2012) + + + + Author: Hernan J. Gonzalez and Shawn Hartsock + + Copyright (C) 2004 The Apache Software Foundation. All rights reserved. + + Apache Licenses + http://www.apache.org/licenses/ + + Apache License Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + Or within this repository: doc/licenses/Apache.LICENSE-2.0 + src/jogl/classes/jogamp/opengl/util/pngj/** + + +A.7) The JOGL source tree _may_ contain code from Oculus VR, Inc. + which is covered by it's own permissive Oculus VR Rift SDK Software License. + + This code _can_ be included to produce a binding + and hence support for the Oculus VR Rift. + + The code is included _and_ it's build artifacts will be released, + if the git sub-module oculusvr-sdk is included in the jogl source repository + as true for current official JogAmp builds and releases! + + If using JogAmp JOGL builds with oculusvr-sdk support, + but the user prefers to _not_ use it for license or other reasons, + the user can simply remove the artifacts 'jar/atomics/oculusvr*jar'. + No other produced artifact is affected. + + While the Oculus VR Rift SDK Software License is permissive, + it's differences to the New BSD license shall be mentioned, see below! + + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + Copyright © 2014 Oculus VR, Inc. All rights reserved. + + Oculus VR, Inc. Software Development Kit License Agreement + + Human-Readable Summary: + + - You are Free to: + + - Use, modify, and distribute the Oculus VR Rift SDK in source and binary + form with your applications/software. + + - With the Following Restrictions: + + - You can only distribute or re-distribute the source code to LibOVR in + whole, not in part. + + - Modifications to the Oculus VR Rift SDK in source or binary form must + be shared with Oculus VR. + + - If your applications cause health and safety issues, you may lose your + right to use the Oculus VR Rift SDK, including LibOVR. + + - The Oculus VR Rift SDK may not be used to interface with unapproved commercial + virtual reality mobile or non-mobile products or hardware. + + - This human-readable Summary is not a license. It is simply a convenient + reference for understanding the full Oculus VR Rift SDK License Agreement. + The Summary is written as a user-friendly interface to the full Oculus VR Rift + SDK License below. This Summary itself has no legal value, and its contents do + not appear in the actual license. + + Full-length Legal Copy may be found at: + http://www.oculusvr.com/licenses/LICENSE-3.1 + http://jogamp.org/git/?p=oculusvr-sdk.git;a=blob;f=LICENSE.txt;hb=HEAD + Or within this repository: oculusvr-sdk/LICENSE.txt + diff --git a/lib/jcef/third_party/junit/README.jcef b/lib/jcef/third_party/junit/README.jcef new file mode 100644 index 0000000..57eba79 --- /dev/null +++ b/lib/jcef/third_party/junit/README.jcef @@ -0,0 +1,11 @@ +Name: JUnit +Short Name: junit +URL: https://junit.org/junit5/ +Version: 5.4.2 +License: Mixed (see LICENSE.txt files in *.jar) + +Description: +Command-line Java application for launching the JUnit Platform from the console. + +Local Modifications: +None. diff --git a/lib/jcef/third_party/junit/junit-platform-console-standalone-1.4.2.jar b/lib/jcef/third_party/junit/junit-platform-console-standalone-1.4.2.jar new file mode 100644 index 0000000..a261a12 Binary files /dev/null and b/lib/jcef/third_party/junit/junit-platform-console-standalone-1.4.2.jar differ diff --git a/lib/jcef/tools/buildtools/LICENSE b/lib/jcef/tools/buildtools/LICENSE new file mode 100644 index 0000000..a7531cf --- /dev/null +++ b/lib/jcef/tools/buildtools/LICENSE @@ -0,0 +1,27 @@ +// Copyright (c) 2009 The Chromium Authors. 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 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. diff --git a/lib/jcef/tools/buildtools/README.jcef b/lib/jcef/tools/buildtools/README.jcef new file mode 100644 index 0000000..298b17d --- /dev/null +++ b/lib/jcef/tools/buildtools/README.jcef @@ -0,0 +1,13 @@ +Name: depot_tools +Short Name: depot_tools +URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git +Date: 21 Sep 2022 +Revision: 08bb5c487f +License: BSD +License File: LICENSE + +Description: +Select tools extracted from depot_tools. + +Local Modifications: +- Remove dependency on vpython. diff --git a/lib/jcef/tools/buildtools/download_from_google_storage.py b/lib/jcef/tools/buildtools/download_from_google_storage.py new file mode 100644 index 0000000..fb3fb98 --- /dev/null +++ b/lib/jcef/tools/buildtools/download_from_google_storage.py @@ -0,0 +1,645 @@ +#!/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 + +import hashlib +import optparse +import os + +try: + import Queue as queue +except ImportError: # For Py3 compatibility + import queue + +import re +import shutil +import stat +import sys +import tarfile +import threading +import time + +import subprocess2 + + +# Env vars that tempdir can be gotten from; minimally, this +# needs to match python's tempfile module and match normal +# unix standards. +_TEMPDIR_ENV_VARS = ('TMPDIR', 'TEMP', 'TMP') + +GSUTIL_DEFAULT_PATH = os.path.join( + os.path.dirname(os.path.abspath(__file__)), 'gsutil.py') +# Maps sys.platform to what we actually want to call them. +PLATFORM_MAPPING = { + 'cygwin': 'win', + 'darwin': 'mac', + 'linux': 'linux', # Python 3.3+. + 'linux2': 'linux', # Python < 3.3 uses "linux2" / "linux3". + 'win32': 'win', + 'aix6': 'aix', + 'aix7': 'aix', +} + +if sys.version_info.major == 2: + # pylint: disable=redefined-builtin + class FileNotFoundError(IOError): + pass + + +class InvalidFileError(IOError): + pass + + +class InvalidPlatformError(Exception): + pass + + +def GetNormalizedPlatform(): + """Returns the result of sys.platform accounting for cygwin. + Under cygwin, this will always return "win32" like the native Python.""" + if sys.platform == 'cygwin': + return 'win32' + return sys.platform + +# Common utilities +class Gsutil(object): + """Call gsutil with some predefined settings. This is a convenience object, + and is also immutable. + + HACK: This object is used directly by the external script + `/win_toolchain/get_toolchain_if_necessary.py` + """ + + MAX_TRIES = 5 + RETRY_BASE_DELAY = 5.0 + RETRY_DELAY_MULTIPLE = 1.3 + + 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 + + def get_sub_env(self): + env = os.environ.copy() + if self.boto_path == os.devnull: + env['AWS_CREDENTIAL_FILE'] = '' + env['BOTO_CONFIG'] = '' + elif self.boto_path: + env['AWS_CREDENTIAL_FILE'] = self.boto_path + env['BOTO_CONFIG'] = self.boto_path + + if PLATFORM_MAPPING[sys.platform] != 'win': + env.update((x, "/tmp") for x in _TEMPDIR_ENV_VARS) + + return env + + def call(self, *args): + 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] + cmd.extend(args) + ((out, err), code) = subprocess2.communicate( + cmd, + stdout=subprocess2.PIPE, + stderr=subprocess2.PIPE, + env=self.get_sub_env()) + + out = out.decode('utf-8', 'replace') + err = err.decode('utf-8', 'replace') + + # Parse output. + status_code_match = re.search('status=([0-9]+)', err) + if status_code_match: + return (int(status_code_match.group(1)), out, err) + if ('You are attempting to access protected data with ' + 'no configured credentials.' in err): + return (403, out, err) + if 'matched no objects' in err: + return (404, out, err) + return (code, out, err) + + def check_call_with_retries(self, *args): + delay = self.RETRY_BASE_DELAY + for i in range(self.MAX_TRIES): + code, out, err = self.check_call(*args) + if not code or i == self.MAX_TRIES - 1: + break + + time.sleep(delay) + delay *= self.RETRY_DELAY_MULTIPLE + + return code, out, err + + +def check_platform(target): + """Checks if any parent directory of target matches (win|mac|linux).""" + assert os.path.isabs(target) + root, target_name = os.path.split(target) + if not target_name: + return None + if target_name in ('linux', 'mac', 'win'): + return target_name + return check_platform(root) + + +def get_sha1(filename): + sha1 = hashlib.sha1() + with open(filename, 'rb') as f: + while True: + # Read in 1mb chunks, so it doesn't all have to be loaded into memory. + chunk = f.read(1024*1024) + if not chunk: + break + sha1.update(chunk) + return sha1.hexdigest() + + +# Download-specific code starts here + +def enumerate_input(input_filename, directory, recursive, ignore_errors, output, + sha1_file, auto_platform): + if sha1_file: + if not os.path.exists(input_filename): + if not ignore_errors: + raise FileNotFoundError( + '{} not found when attempting enumerate files to download.'.format( + input_filename)) + print('%s not found.' % input_filename, file=sys.stderr) + with open(input_filename, 'rb') as f: + sha1_match = re.match(b'^([A-Za-z0-9]{40})$', f.read(1024).rstrip()) + if sha1_match: + yield (sha1_match.groups(1)[0].decode('utf-8'), output) + return + if not ignore_errors: + raise InvalidFileError('No sha1 sum found in %s.' % input_filename) + print('No sha1 sum found in %s.' % input_filename, file=sys.stderr) + return + + if not directory: + yield (input_filename, output) + return + + for root, dirs, files in os.walk(input_filename): + if not recursive: + for item in dirs[:]: + dirs.remove(item) + else: + for exclude in ['.svn', '.git']: + if exclude in dirs: + dirs.remove(exclude) + for filename in files: + full_path = os.path.join(root, filename) + if full_path.endswith('.sha1'): + if auto_platform: + # Skip if the platform does not match. + target_platform = check_platform(os.path.abspath(full_path)) + if not target_platform: + err = ('--auto_platform passed in but no platform name found in ' + 'the path of %s' % full_path) + if not ignore_errors: + raise InvalidFileError(err) + print(err, file=sys.stderr) + continue + current_platform = PLATFORM_MAPPING[sys.platform] + if current_platform != target_platform: + continue + + with open(full_path, 'rb') as f: + sha1_match = re.match(b'^([A-Za-z0-9]{40})$', f.read(1024).rstrip()) + if sha1_match: + yield ( + sha1_match.groups(1)[0].decode('utf-8'), + full_path.replace('.sha1', '') + ) + else: + if not ignore_errors: + raise InvalidFileError('No sha1 sum found in %s.' % filename) + print('No sha1 sum found in %s.' % filename, file=sys.stderr) + + +def _validate_tar_file(tar, prefix): + def _validate(tarinfo): + """Returns false if the tarinfo is something we explicitly forbid.""" + if tarinfo.issym() or tarinfo.islnk(): + return False + if ('../' in tarinfo.name or + '..\\' in tarinfo.name or + not tarinfo.name.startswith(prefix)): + return False + return True + return all(map(_validate, tar.getmembers())) + +def _downloader_worker_thread(thread_num, q, force, base_url, + gsutil, out_q, ret_codes, verbose, extract, + delete=True): + while True: + input_sha1_sum, output_filename = q.get() + if input_sha1_sum is None: + return + extract_dir = None + if extract: + if not output_filename.endswith('.tar.gz'): + out_q.put('%d> Error: %s is not a tar.gz archive.' % ( + thread_num, output_filename)) + ret_codes.put((1, '%s is not a tar.gz archive.' % (output_filename))) + continue + extract_dir = output_filename[:-len('.tar.gz')] + if os.path.exists(output_filename) and not force: + 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) + + 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((code, 'Failed to fetch file %s for %s. [Err: %s]' % + (file_url, output_filename, err))) + continue + + remote_sha1 = get_sha1(output_filename) + if remote_sha1 != input_sha1_sum: + msg = ('%d> ERROR remote sha1 (%s) does not match expected sha1 (%s).' % + (thread_num, remote_sha1, input_sha1_sum)) + out_q.put(msg) + ret_codes.put((20, msg)) + continue + + if extract: + if not tarfile.is_tarfile(output_filename): + out_q.put('%d> Error: %s is not a tar.gz archive.' % ( + thread_num, output_filename)) + ret_codes.put((1, '%s is not a tar.gz archive.' % (output_filename))) + continue + with tarfile.open(output_filename, 'r:gz') as tar: + dirname = os.path.dirname(os.path.abspath(output_filename)) + # If there are long paths inside the tarball we can get extraction + # errors on windows due to the 260 path length limit (this includes + # pwd). Use the extended path syntax. + if sys.platform == 'win32': + dirname = '\\\\?\\%s' % dirname + if not _validate_tar_file(tar, os.path.basename(extract_dir)): + out_q.put('%d> Error: %s contains files outside %s.' % ( + thread_num, output_filename, extract_dir)) + ret_codes.put((1, '%s contains invalid entries.' % (output_filename))) + continue + if os.path.exists(extract_dir): + try: + shutil.rmtree(extract_dir) + out_q.put('%d> Removed %s...' % (thread_num, extract_dir)) + except OSError: + out_q.put('%d> Warning: Can\'t delete: %s' % ( + thread_num, extract_dir)) + ret_codes.put((1, 'Can\'t delete %s.' % (extract_dir))) + continue + out_q.put('%d> Extracting %d entries from %s to %s' % + (thread_num, len(tar.getmembers()),output_filename, + extract_dir)) + 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 + # Google Storage will not be set when uploading from Windows, so if + # this script is running under cygwin and we're downloading an + # executable, it will be unrunnable from inside cygwin without this. + st = os.stat(output_filename) + os.chmod(output_filename, st.st_mode | stat.S_IEXEC) + elif sys.platform != 'win32': + # On non-Windows platforms, key off of the custom header + # "x-goog-meta-executable". + code, out, err = gsutil.check_call('stat', file_url) + if code != 0: + out_q.put('%d> %s' % (thread_num, err)) + ret_codes.put((code, err)) + elif re.search(r'executable:\s*1', out): + st = os.stat(output_filename) + os.chmod(output_filename, st.st_mode | stat.S_IEXEC) + + +class PrinterThread(threading.Thread): + def __init__(self, output_queue): + super(PrinterThread, self).__init__() + self.output_queue = output_queue + self.did_print_anything = False + + def run(self): + while True: + line = self.output_queue.get() + # It's plausible we want to print empty lines: Explicit `is None`. + if line is None: + break + self.did_print_anything = True + print(line) + + +def _data_exists(input_sha1_sum, output_filename, extract): + """Returns True if the data exists locally and matches the sha1. + + This conservatively returns False for error cases. + + Args: + 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: 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 + is not checked. + """ + extract_dir = None + if extract: + if not output_filename.endswith('.tar.gz'): + # This will cause an error later. Conservativly return False to not bail + # out too early. + return False + extract_dir = output_filename[:-len('.tar.gz')] + if os.path.exists(output_filename): + if not extract or os.path.exists(extract_dir): + if get_sha1(output_filename) == input_sha1_sum: + return True + return False + + +def download_from_google_storage( + input_filename, base_url, gsutil, num_threads, directory, recursive, + force, output, ignore_errors, sha1_file, verbose, auto_platform, extract): + + # Tuples of sha1s and paths. + input_data = list(enumerate_input( + input_filename, directory, recursive, ignore_errors, output, sha1_file, + auto_platform)) + + # Sequentially check for the most common case and see if we can bail out + # early before making any slow calls to gsutil. + if not force and all( + _data_exists(sha1, path, extract) for sha1, path in input_data): + return 0 + + # Call this once to ensure gsutil's update routine is called only once. Only + # needs to be done if we'll process input data in parallel, which can lead to + # a race in gsutil's self-update on the first call. Note, this causes a + # network call, therefore any fast bailout should be done before this point. + if len(input_data) > 1: + gsutil.check_call('version') + + # Start up all the worker threads. + all_threads = [] + download_start = time.time() + stdout_queue = queue.Queue() + work_queue = queue.Queue() + ret_codes = queue.Queue() + ret_codes.put((0, None)) + for thread_num in range(num_threads): + t = threading.Thread( + target=_downloader_worker_thread, + args=[thread_num, work_queue, force, base_url, + gsutil, stdout_queue, ret_codes, verbose, extract]) + t.daemon = True + t.start() + all_threads.append(t) + printer_thread = PrinterThread(stdout_queue) + printer_thread.daemon = True + printer_thread.start() + + # Populate our work queue. + for sha1, path in input_data: + work_queue.put((sha1, path)) + for _ in all_threads: + work_queue.put((None, None)) # Used to tell worker threads to stop. + + # Wait for all downloads to finish. + for t in all_threads: + t.join() + stdout_queue.put(None) + printer_thread.join() + + # See if we ran into any errors. + max_ret_code = 0 + for ret_code, message in ret_codes.queue: + max_ret_code = max(ret_code, max_ret_code) + if message: + print(message, file=sys.stderr) + + # Only print summary if any work was done. + if printer_thread.did_print_anything: + print('Downloading %d files took %1f second(s)' % + (len(input_data), time.time() - download_start)) + return max_ret_code + + +def main(args): + usage = ('usage: %prog [options] target\n' + 'Target must be:\n' + ' (default) a sha1 sum ([A-Za-z0-9]{40}).\n' + ' (-s or --sha1_file) a .sha1 file, containing a sha1 sum on ' + 'the first line.\n' + ' (-d or --directory) A directory to scan for .sha1 files.') + parser = optparse.OptionParser(usage) + parser.add_option('-o', '--output', + help='Specify the output file name. Defaults to: ' + '(a) Given a SHA1 hash, the name is the SHA1 hash. ' + '(b) Given a .sha1 file or directory, the name will ' + 'match (.*).sha1.') + parser.add_option('-b', '--bucket', + help='Google Storage bucket to fetch from.') + parser.add_option('-e', '--boto', + help='Specify a custom boto file.') + parser.add_option('-c', '--no_resume', action='store_true', + help='DEPRECATED: Resume download if file is ' + 'partially downloaded.') + parser.add_option('-f', '--force', action='store_true', + help='Force download even if local file exists.') + parser.add_option('-i', '--ignore_errors', action='store_true', + help='Don\'t throw error if we find an invalid .sha1 file.') + parser.add_option('-r', '--recursive', action='store_true', + help='Scan folders recursively for .sha1 files. ' + 'Must be used with -d/--directory') + parser.add_option('-t', '--num_threads', default=1, type='int', + help='Number of downloader threads to run.') + parser.add_option('-d', '--directory', action='store_true', + help='The target is a directory. ' + 'Cannot be used with -s/--sha1_file.') + parser.add_option('-s', '--sha1_file', action='store_true', + help='The target is a file containing a sha1 sum. ' + 'Cannot be used with -d/--directory.') + parser.add_option('-g', '--config', action='store_true', + help='Alias for "gsutil config". Run this if you want ' + 'to initialize your saved Google Storage ' + 'credentials. This will create a read-only ' + 'credentials file in ~/.boto.depot_tools.') + parser.add_option('-n', '--no_auth', action='store_true', + help='Skip auth checking. Use if it\'s known that the ' + 'target bucket is a public bucket.') + parser.add_option('-p', '--platform', + help='A regular expression that is compared against ' + 'Python\'s sys.platform. If this option is specified, ' + 'the download will happen only if there is a match.') + parser.add_option('-a', '--auto_platform', + action='store_true', + help='Detects if any parent folder of the target matches ' + '(linux|mac|win). If so, the script will only ' + 'process files that are in the paths that ' + 'that matches the current platform.') + parser.add_option('-u', '--extract', + action='store_true', + help='Extract a downloaded tar.gz file. ' + 'Leaves the tar.gz file around for sha1 verification' + 'If a directory with the same name as the tar.gz ' + 'file already exists, is deleted (to get a ' + 'clean state in case of update.)') + parser.add_option('-v', '--verbose', action='store_true', default=True, + help='DEPRECATED: Defaults to True. Use --no-verbose ' + 'to suppress.') + parser.add_option('-q', '--quiet', action='store_false', dest='verbose', + help='Suppresses diagnostic and progress information.') + + (options, args) = parser.parse_args() + + # Make sure we should run at all based on platform matching. + if options.platform: + if options.auto_platform: + parser.error('--platform can not be specified with --auto_platform') + if not re.match(options.platform, GetNormalizedPlatform()): + if options.verbose: + print('The current platform doesn\'t match "%s", skipping.' % + options.platform) + return 0 + + # Set the boto file to /dev/null if we don't need auth. + if options.no_auth: + if (set(('http_proxy', 'https_proxy')).intersection( + env.lower() for env in os.environ) and + 'NO_AUTH_BOTO_CONFIG' not in os.environ): + print('NOTICE: You have PROXY values set in your environment, but gsutil' + 'in depot_tools does not (yet) obey them.', + file=sys.stderr) + print('Also, --no_auth prevents the normal BOTO_CONFIG environment' + 'variable from being used.', + file=sys.stderr) + print('To use a proxy in this situation, please supply those settings' + 'in a .boto file pointed to by the NO_AUTH_BOTO_CONFIG environment' + 'variable.', + file=sys.stderr) + options.boto = os.environ.get('NO_AUTH_BOTO_CONFIG', os.devnull) + + # Make sure gsutil exists where we expect it to. + if os.path.exists(GSUTIL_DEFAULT_PATH): + gsutil = Gsutil(GSUTIL_DEFAULT_PATH, + boto_path=options.boto) + else: + parser.error('gsutil not found in %s, bad depot_tools checkout?' % + GSUTIL_DEFAULT_PATH) + + # Passing in -g/--config will run our copy of GSUtil, then quit. + if options.config: + print('===Note from depot_tools===') + print('If you do not have a project ID, enter "0" when asked for one.') + print('===End note from depot_tools===') + print() + gsutil.check_call('version') + return gsutil.call('config') + + if not args: + parser.error('Missing target.') + if len(args) > 1: + parser.error('Too many targets.') + if not options.bucket: + parser.error('Missing bucket. Specify bucket with --bucket.') + if options.sha1_file and options.directory: + parser.error('Both --directory and --sha1_file are specified, ' + 'can only specify one.') + if options.recursive and not options.directory: + parser.error('--recursive specified but --directory not specified.') + if options.output and options.directory: + parser.error('--directory is specified, so --output has no effect.') + if (not (options.sha1_file or options.directory) + and options.auto_platform): + parser.error('--auto_platform must be specified with either ' + '--sha1_file or --directory') + + input_filename = args[0] + + # Set output filename if not specified. + if not options.output and not options.directory: + if not options.sha1_file: + # Target is a sha1 sum, so output filename would also be the sha1 sum. + options.output = input_filename + elif options.sha1_file: + # Target is a .sha1 file. + if not input_filename.endswith('.sha1'): + parser.error('--sha1_file is specified, but the input filename ' + 'does not end with .sha1, and no --output is specified. ' + 'Either make sure the input filename has a .sha1 ' + 'extension, or specify --output.') + options.output = input_filename[:-5] + else: + parser.error('Unreachable state.') + + base_url = 'gs://%s' % options.bucket + + try: + return download_from_google_storage( + input_filename, base_url, gsutil, options.num_threads, options.directory, + options.recursive, options.force, options.output, options.ignore_errors, + options.sha1_file, options.verbose, options.auto_platform, + options.extract) + except FileNotFoundError as e: + print("Fatal error: {}".format(e)) + return 1 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/lib/jcef/tools/buildtools/gsutil.py b/lib/jcef/tools/buildtools/gsutil.py new file mode 100644 index 0000000..cff91fa --- /dev/null +++ b/lib/jcef/tools/buildtools/gsutil.py @@ -0,0 +1,196 @@ +#!/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. + +"""Run a pinned gsutil.""" + + +import argparse +import base64 +import contextlib +import hashlib +import json +import os +import shutil +import subprocess +import sys +import tempfile +import time + +try: + import urllib2 as urllib +except ImportError: # For Py3 compatibility + import urllib.request as urllib + +import zipfile + + +GSUTIL_URL = 'https://storage.googleapis.com/pub/' +API_URL = 'https://www.googleapis.com/storage/v1/b/pub/o/' + +THIS_DIR = os.path.dirname(os.path.abspath(__file__)) +DEFAULT_BIN_DIR = os.path.join(THIS_DIR, 'external_bin', 'gsutil') + +IS_WINDOWS = os.name == 'nt' + +VERSION = '4.68' + + +class InvalidGsutilError(Exception): + pass + + +def download_gsutil(version, target_dir): + """Downloads gsutil into the target_dir.""" + filename = 'gsutil_%s.zip' % version + target_filename = os.path.join(target_dir, filename) + + # Check if the target exists already. + if os.path.exists(target_filename): + md5_calc = hashlib.md5() + with open(target_filename, 'rb') as f: + while True: + buf = f.read(4096) + if not buf: + break + md5_calc.update(buf) + local_md5 = md5_calc.hexdigest() + + metadata_url = '%s%s' % (API_URL, filename) + metadata = json.load(urllib.urlopen(metadata_url)) + remote_md5 = base64.b64decode(metadata['md5Hash']).decode('utf-8') + + if local_md5 == remote_md5: + return target_filename + os.remove(target_filename) + + # Do the download. + url = '%s%s' % (GSUTIL_URL, filename) + u = urllib.urlopen(url) + with open(target_filename, 'wb') as f: + while True: + buf = u.read(4096) + if not buf: + break + f.write(buf) + return target_filename + + +@contextlib.contextmanager +def temporary_directory(base): + tmpdir = tempfile.mkdtemp(prefix='t', dir=base) + try: + yield tmpdir + finally: + if os.path.isdir(tmpdir): + shutil.rmtree(tmpdir) + + +def ensure_gsutil(version, target, clean): + bin_dir = os.path.join(target, 'gsutil_%s' % version) + gsutil_bin = os.path.join(bin_dir, 'gsutil', 'gsutil') + gsutil_flag = os.path.join(bin_dir, 'gsutil', 'install.flag') + # We assume that if gsutil_flag exists, then we have a good version + # of the gsutil package. + if not clean and os.path.isfile(gsutil_flag): + # Everything is awesome! we're all done here. + return gsutil_bin + + if not os.path.exists(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') + try: + os.rename(bin_dir, cleanup_path) + except (OSError, IOError): + cleanup_path = None + if cleanup_path: + shutil.rmtree(cleanup_path) + + 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) + + 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() + # Drop a flag file. + with open(gsutil_flag, 'w') as f: + f.write('This flag file is dropped by gsutil.py') + + return gsutil_bin + + +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) + + # 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('--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() + if args.args and args.args[0] == '--': + args.args.pop(0) + if extras: + args.args = extras + args.args + return args + + +def main(): + args = parse_args() + return run_gsutil(args.target, args.args, clean=args.clean) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/lib/jcef/tools/buildtools/linux64/clang-format.sha1 b/lib/jcef/tools/buildtools/linux64/clang-format.sha1 new file mode 100644 index 0000000..6f3349c --- /dev/null +++ b/lib/jcef/tools/buildtools/linux64/clang-format.sha1 @@ -0,0 +1 @@ +dd736afb28430c9782750fc0fd5f0ed497399263 \ No newline at end of file diff --git a/lib/jcef/tools/buildtools/mac/clang-format.arm64.sha1 b/lib/jcef/tools/buildtools/mac/clang-format.arm64.sha1 new file mode 100644 index 0000000..46f9b3c --- /dev/null +++ b/lib/jcef/tools/buildtools/mac/clang-format.arm64.sha1 @@ -0,0 +1 @@ +f1424c44ee758922823d6b37de43705955c99d7e \ No newline at end of file diff --git a/lib/jcef/tools/buildtools/mac/clang-format.x64.sha1 b/lib/jcef/tools/buildtools/mac/clang-format.x64.sha1 new file mode 100644 index 0000000..3a23ea2 --- /dev/null +++ b/lib/jcef/tools/buildtools/mac/clang-format.x64.sha1 @@ -0,0 +1 @@ +a1b33be85faf2578f3101d7806e443e1c0949498 \ No newline at end of file diff --git a/lib/jcef/tools/buildtools/subprocess2.py b/lib/jcef/tools/buildtools/subprocess2.py new file mode 100644 index 0000000..7df49da --- /dev/null +++ b/lib/jcef/tools/buildtools/subprocess2.py @@ -0,0 +1,258 @@ +# coding=utf-8 +# 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. +"""Collection of subprocess wrapper functions. + +In theory you shouldn't need anything else in subprocess, or this module failed. +""" + +import codecs +import errno +import io +import logging +import os +import subprocess +import sys +import threading + +# Cache the string-escape codec to ensure subprocess can find it later. +# See crbug.com/912292#c2 for context. +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 + + +class CalledProcessError(subprocess.CalledProcessError): + """Augment the standard exception with more data.""" + def __init__(self, returncode, cmd, cwd, stdout, stderr): + super(CalledProcessError, self).__init__(returncode, cmd, output=stdout) + self.stdout = self.output # for backward compatibility. + self.stderr = stderr + self.cwd = cwd + + def __str__(self): + out = 'Command %r returned non-zero exit status %s' % ( + ' '.join(self.cmd), self.returncode) + if self.cwd: + out += ' in ' + self.cwd + 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): + """Occurs when cygwin's fork() emulation fails due to rebased dll.""" + + +## Utility functions + + +def kill_pid(pid): + """Kills a process by its process id.""" + try: + # Unable to import 'module' + # pylint: disable=no-member,F0401 + import signal + return os.kill(pid, signal.SIGTERM) + except ImportError: + pass + + +def get_english_env(env): + """Forces LANG and/or LANGUAGE to be English. + + Forces encoding to utf-8 for subprocesses. + + Returns None if it is unnecessary. + """ + if sys.platform == 'win32': + return None + env = env or os.environ + + # Test if it is necessary at all. + is_english = lambda name: env.get(name, 'en').startswith('en') + + if is_english('LANG') and is_english('LANGUAGE'): + return None + + # Requires modifications. + env = env.copy() + def fix_lang(name): + if not is_english(name): + env[name] = 'en_US.UTF-8' + fix_lang('LANG') + fix_lang('LANGUAGE') + return env + + +class Popen(subprocess.Popen): + """Wraps subprocess.Popen() with various workarounds. + + - Forces English output since it's easier to parse the stdout if it is always + in English. + - Sets shell=True on windows by default. You can override this by forcing + shell parameter to a value. + - 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 + exceptions generated by cygwin when it fails trying to emulate fork(). + """ + # subprocess.Popen.__init__() is not threadsafe; there is a race between + # creating the exec-error pipe for the child and setting it to CLOEXEC during + # which another thread can fork and cause the pipe to be inherited by its + # descendents, which will cause the current Popen to hang until all those + # descendents exit. Protect this with a lock so that only one fork/exec can + # happen at a time. + popen_lock = threading.Lock() + + 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 + # called with a list because it only tries to execute the first item in + # the list. + kwargs['shell'] = bool(sys.platform=='win32') + + if isinstance(args, basestring): + tmp_str = args + elif isinstance(args, (list, tuple)): + tmp_str = ' '.join(args) + else: + raise CalledProcessError(None, args, kwargs.get('cwd'), None, None) + if kwargs.get('cwd', None): + tmp_str += '; cwd=%s' % kwargs['cwd'] + logging.debug(tmp_str) + + try: + with self.popen_lock: + super(Popen, self).__init__(args, **kwargs) + except OSError as e: + if e.errno == errno.EAGAIN and sys.platform == 'cygwin': + # Convert fork() emulation failure into a CygwinRebaseError(). + raise CygwinRebaseError( + e.errno, + args, + kwargs.get('cwd'), + None, + 'Visit ' + 'http://code.google.com/p/chromium/wiki/CygwinDllRemappingFailure ' + 'to learn how to fix this error; you need to rebase your cygwin ' + 'dlls') + # Popen() can throw OSError when cwd or args[0] doesn't exist. + raise OSError('Execution failed with error: %s.\n' + 'Check that %s or %s exist and have execution permission.' + % (str(e), kwargs.get('cwd'), args[0])) + + +def communicate(args, **kwargs): + """Wraps subprocess.Popen().communicate(). + + Returns ((stdout, stderr), returncode). + + - If the subprocess runs for |nag_timer| seconds without producing terminal + output, print a warning to stderr. + - Automatically passes stdin content as input so do not specify stdin=PIPE. + """ + stdin = None + # When stdin is passed as an argument, use it as the actual input data and + # set the Popen() parameter accordingly. + if 'stdin' in kwargs and isinstance(kwargs['stdin'], basestring): + stdin = kwargs['stdin'] + kwargs['stdin'] = PIPE + + proc = Popen(args, **kwargs) + return proc.communicate(stdin), proc.returncode + + +def call(args, **kwargs): + """Emulates subprocess.call(). + + 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'] = DEVNULL + if kwargs.get('stderr') == PIPE: + kwargs['stderr'] = DEVNULL + return communicate(args, **kwargs)[1] + + +def check_call_out(args, **kwargs): + """Improved version of subprocess.check_call(). + + Returns (stdout, stderr), unlike subprocess.check_call(). + """ + out, returncode = communicate(args, **kwargs) + if returncode: + raise CalledProcessError( + returncode, args, kwargs.get('cwd'), out[0], out[1]) + return out + + +def check_call(args, **kwargs): + """Emulate subprocess.check_call().""" + check_call_out(args, **kwargs) + return 0 + + +def capture(args, **kwargs): + """Captures stdout of a process call and returns it. + + Returns stdout. + + - Discards returncode. + - Blocks stdin by default if not specified since no output will be visible. + """ + kwargs.setdefault('stdin', DEVNULL) + + # Like check_output, deny the caller from using stdout arg. + return communicate(args, stdout=PIPE, **kwargs)[0][0] + + +def check_output(args, **kwargs): + """Emulates subprocess.check_output(). + + Captures stdout of a process call and returns stdout only. + + - Throws if return code is not 0. + - Works even prior to python 2.7. + - 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', 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/lib/jcef/tools/buildtools/win/clang-format.exe.sha1 b/lib/jcef/tools/buildtools/win/clang-format.exe.sha1 new file mode 100644 index 0000000..c7efe6f --- /dev/null +++ b/lib/jcef/tools/buildtools/win/clang-format.exe.sha1 @@ -0,0 +1 @@ +66882fadbf9e99cc00b8677d8c1e7e8b3cfdf4fe \ No newline at end of file diff --git a/lib/jcef/tools/clang_util.py b/lib/jcef/tools/clang_util.py new file mode 100644 index 0000000..90632d5 --- /dev/null +++ b/lib/jcef/tools/clang_util.py @@ -0,0 +1,39 @@ +# Copyright (c) 2017 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 + +from __future__ import absolute_import +from __future__ import print_function +from exec_util import exec_cmd +import os +import sys + +# Script directory. +script_dir = os.path.dirname(__file__) +root_dir = os.path.join(script_dir, os.pardir) + +if sys.platform == 'win32': + clang_format_exe = 'buildtools/win/clang-format.exe' +elif sys.platform == 'darwin': + clang_format_exe = 'buildtools/mac/clang-format' +elif sys.platform.startswith('linux'): + clang_format_exe = 'buildtools/linux64/clang-format' +else: + raise Exception("Unsupported platform: %s" % sys.platform) + + +def clang_format(file_name, file_contents): + # -assume-filename is necessary to find the .clang-format file and determine + # the language when specifying contents via stdin. + result = exec_cmd("%s -assume-filename=%s" % + (os.path.join(script_dir, clang_format_exe), + file_name), root_dir, file_contents.encode('utf-8')) + if result['err'] != '': + print("clang-format error: %s" % result['err']) + if result['out'] != '': + output = result['out'] + if sys.platform == 'win32': + # Convert to Unix line endings. + output = output.replace("\r", "") + return output + return None diff --git a/lib/jcef/tools/compile.bat b/lib/jcef/tools/compile.bat new file mode 100644 index 0000000..061dcb6 --- /dev/null +++ b/lib/jcef/tools/compile.bat @@ -0,0 +1,37 @@ +@echo off +:: Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +:: reserved. Use of this source code is governed by a BSD-style license +:: that can be found in the LICENSE file. + +set RETURNCODE= +setlocal +cd .. + +if "%1" == "" ( +echo ERROR: Please specify a target platform: win32 or win64 +set ERRORLEVEL=1 +goto end +) + +set OUT_PATH=".\out\%1" +set CLS_PATH=".\third_party\jogamp\jar\*;.\third_party\junit\*;.\java" + +if not exist %OUT_PATH% mkdir %OUT_PATH% +javac -Xdiags:verbose -cp %CLS_PATH% -d %OUT_PATH% java/tests/detailed/*.java java/tests/junittests/*.java java/tests/simple/*.java java/org/cef/*.java java/org/cef/browser/*.java java/org/cef/callback/*.java java/org/cef/handler/*.java java/org/cef/misc/*.java java/org/cef/network/*.java + +:: Copy MANIFEST.MF +xcopy /sfy .\java\manifest %OUT_PATH%\manifest\ + +:: Copy resource files. +xcopy /sfy .\java\tests\detailed\handler\*.html %OUT_PATH%\tests\detailed\handler\ +xcopy /sfy .\java\tests\detailed\handler\*.png %OUT_PATH%\tests\detailed\handler\ + +:end +endlocal & set RETURNCODE=%ERRORLEVEL% +goto omega + +:returncode +exit /B %RETURNCODE% + +:omega +call :returncode %RETURNCODE% diff --git a/lib/jcef/tools/compile.sh b/lib/jcef/tools/compile.sh new file mode 100644 index 0000000..93bdeeb --- /dev/null +++ b/lib/jcef/tools/compile.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file. + +if [ -z "$1" ]; then + echo "ERROR: Please specify a target platform: linux32 or linux64" +else + DIR="$( cd "$( dirname "$0" )" && cd .. && pwd )" + OUT_PATH="${DIR}/out/$1" + JAVA_PATH="${DIR}/java" + CLS_PATH="${DIR}/third_party/jogamp/jar/*:${DIR}/third_party/junit/*:${JAVA_PATH}" + + if [ ! -d "$OUT_PATH" ]; then + mkdir -p "$OUT_PATH" + fi + + javac -Xdiags:verbose -cp "$CLS_PATH" -d "$OUT_PATH" "${JAVA_PATH}"/tests/detailed/*.java "${JAVA_PATH}"/tests/junittests/*.java "${JAVA_PATH}"/tests/simple/*.java "${JAVA_PATH}"/org/cef/*.java "${JAVA_PATH}"/org/cef/browser/*.java "${JAVA_PATH}"/org/cef/callback/*.java "${JAVA_PATH}"/org/cef/handler/*.java "${JAVA_PATH}"/org/cef/misc/*.java "${JAVA_PATH}"/org/cef/network/*.java + + # Copy MANIFEST.MF + rsync -a "${JAVA_PATH}"/manifest/MANIFEST.MF $OUT_PATH/manifest/ + + # Copy resource files. + cp -f "${JAVA_PATH}"/tests/detailed/handler/*.html "$OUT_PATH/tests/detailed/handler" + cp -f "${JAVA_PATH}"/tests/detailed/handler/*.png "$OUT_PATH/tests/detailed/handler" +fi + diff --git a/lib/jcef/tools/date_util.py b/lib/jcef/tools/date_util.py new file mode 100644 index 0000000..4c17620 --- /dev/null +++ b/lib/jcef/tools/date_util.py @@ -0,0 +1,16 @@ +# Copyright (c) 2011 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. + +from __future__ import absolute_import +import datetime + + +def get_year(): + """ Returns the current year. """ + return str(datetime.datetime.now().year) + + +def get_date(): + """ Returns the current date. """ + return datetime.datetime.now().strftime('%B %d, %Y') diff --git a/lib/jcef/tools/distrib/EXCLUDE_FILES.txt b/lib/jcef/tools/distrib/EXCLUDE_FILES.txt new file mode 100644 index 0000000..1dc4901 --- /dev/null +++ b/lib/jcef/tools/distrib/EXCLUDE_FILES.txt @@ -0,0 +1,2 @@ +README.redistrib.txt +README.standard.txt diff --git a/lib/jcef/tools/distrib/README.footer.txt b/lib/jcef/tools/distrib/README.footer.txt new file mode 100644 index 0000000..ae9aa23 --- /dev/null +++ b/lib/jcef/tools/distrib/README.footer.txt @@ -0,0 +1,8 @@ +LICENSING +--------- + +The JCEF project is BSD licensed. Please read the LICENSE.txt files included with +this binary distribution for licensing terms and conditions. Other software +included in this distribution is provided under other licenses. Please visit +"about:credits" in a JCEF-based application for complete Chromium and third-party +licensing information. diff --git a/lib/jcef/tools/distrib/README.header.txt b/lib/jcef/tools/distrib/README.header.txt new file mode 100644 index 0000000..046ad62 --- /dev/null +++ b/lib/jcef/tools/distrib/README.header.txt @@ -0,0 +1,18 @@ +Java Chromium Embedded Framework (JCEF) Binary Distribution for $PLATFORM$ +------------------------------------------------------------------------------- + +Date: $DATE$ + +JCEF Version: $JCEF_VER$ +JCEF URL: $JCEF_URL$ + @$JCEF_REV$ + +CEF Version: $CEF_VER$ +CEF URL: $CEF_URL$ + +Chromium Verison: $CHROMIUM_VER$ +Chromium URL: $CHROMIUM_URL$ + +This distribution contains all components necessary to build and distribute a +Java application using JCEF on the $PLATFORM$ platform. Please see the LICENSING +section of this document for licensing terms and conditions. diff --git a/lib/jcef/tools/distrib/linux32/README.redistrib.txt b/lib/jcef/tools/distrib/linux32/README.redistrib.txt new file mode 100644 index 0000000..63dbf53 --- /dev/null +++ b/lib/jcef/tools/distrib/linux32/README.redistrib.txt @@ -0,0 +1,71 @@ +REDISTRIBUTION +-------------- + +This binary distribution contains the below components. + +Required components: + +The following components are required. JCEF will not function without them. + +* Java archives. + jcef.jar + gluegen-rt.jar + gluegen-rt-natives-linux-i586.jar + jogl-all.jar + jogl-all-natives-linux-i586.jar + +* CEF JNI library. + libjcef.so + +* CEF JNI process helper. + jcef_helper + +* CEF core library. + * libcef.so + +* Unicode support data. + * icudtl.dat + +* V8 snapshot data. + * natives_blob.bin + * snapshot_blob.bin + +Optional components: + +The following components are optional. If they are missing JCEF will continue to +run but any related functionality may become broken or disabled. + +* Localized resources. + Locale file loading can be disabled completely using + CefSettings.pack_loading_disabled. The locales directory path can be + customized using CefSettings.locales_dir_path. + + * locales/ + Directory containing localized resources used by CEF, Chromium and Blink. A + .pak file is loaded from this directory based on the value of environment + variables which are read with the following precedence order: LANGUAGE, + LC_ALL, LC_MESSAGES and LANG. Only configured locales need to be + distributed. If no locale is configured the default locale of "en-US" will + be used. Without these files arbitrary Web components may display + incorrectly. + +* Other resources. + Pack file loading can be disabled completely using + CefSettings.pack_loading_disabled. The resources directory path can be + customized using CefSettings.resources_dir_path. + + * cef.pak + * cef_100_percent.pak + * cef_200_percent.pak + These files contain non-localized resources used by CEF, Chromium and Blink. + Without these files arbitrary Web components may display incorrectly. + + * cef_extensions.pak + This file contains non-localized resources required for extension loading. + Pass the `--disable-extensions` command-line flag to disable use of this + file. Without this file components that depend on the extension system, + such as the PDF viewer, will not function. + + * devtools_resources.pak + This file contains non-localized resources required for Chrome Developer + Tools. Without this file Chrome Developer Tools will not function. diff --git a/lib/jcef/tools/distrib/linux32/README.standard.txt b/lib/jcef/tools/distrib/linux32/README.standard.txt new file mode 100644 index 0000000..d5ef07d --- /dev/null +++ b/lib/jcef/tools/distrib/linux32/README.standard.txt @@ -0,0 +1,20 @@ +CONTENTS +-------- + +bin Contains Java archives, native library files and the MainFrame + sample application. + +docs Contains documentation for the org.cef package. + + +USAGE +----- + +1. Install a 32-bit version of the Oracle Java 7 runtime. +2. Execute the run.sh script to run the MainFrame sample application. +3. Optionally recompile the sample application and update jcef-tests.jar + by running the compile.sh script. + +Please visit the JCEF Website for additional usage information. + +https://github.com/chromiumembedded/java-cef diff --git a/lib/jcef/tools/distrib/linux32/compile.sh b/lib/jcef/tools/distrib/linux32/compile.sh new file mode 100644 index 0000000..6bee820 --- /dev/null +++ b/lib/jcef/tools/distrib/linux32/compile.sh @@ -0,0 +1,14 @@ +#!/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. + +# Determine the absolute path to the current directory. +DIR="$( cd "$( dirname "$0" )" && pwd )" +BIN_DIR="${DIR}/bin" + +# Compile the test program. +javac -cp "${BIN_DIR}:${BIN_DIR}/*" "${BIN_DIR}"/tests/detailed/*.java "${BIN_DIR}"/tests/detailed/dialog/*.java "${BIN_DIR}"/tests/detailed/handler/*.java "${BIN_DIR}"/tests/detailed/ui/*.java "${BIN_DIR}"/tests/simple/*.java + +# Create the test JAR file. +jar -cf "${BIN_DIR}"/jcef-tests.jar -C "${BIN_DIR}" tests diff --git a/lib/jcef/tools/distrib/linux32/run.sh b/lib/jcef/tools/distrib/linux32/run.sh new file mode 100644 index 0000000..a085a0c --- /dev/null +++ b/lib/jcef/tools/distrib/linux32/run.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file. + +# Determine the absolute path to the current directory. +DIR="$( cd "$( dirname "$0" )" && pwd )" +LIB_PATH="$DIR/bin/lib/linux32" + +if [ -z "$1" ]; then + EXAMPLE="detailed" +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}" +else + LD_LIBRARY_PATH="$LIB_PATH" +fi +export LD_LIBRARY_PATH + +# Preload libcef.so to avoid crashes. +LD_PRELOAD=libcef.so java -cp "${DIR}/bin:${DIR}/bin/*" -Djava.library.path="$LIB_PATH" tests.${EXAMPLE}.MainFrame "$@" diff --git a/lib/jcef/tools/distrib/linux64/README.redistrib.txt b/lib/jcef/tools/distrib/linux64/README.redistrib.txt new file mode 100644 index 0000000..6a5607c --- /dev/null +++ b/lib/jcef/tools/distrib/linux64/README.redistrib.txt @@ -0,0 +1,71 @@ +REDISTRIBUTION +-------------- + +This binary distribution contains the below components. + +Required components: + +The following components are required. JCEF will not function without them. + +* Java archives. + jcef.jar + gluegen-rt.jar + gluegen-rt-natives-linux-amd64.jar + jogl-all.jar + jogl-all-natives-linux-amd64.jar + +* CEF JNI library. + libjcef.so + +* CEF JNI process helper. + jcef_helper + +* CEF core library. + * libcef.so + +* Unicode support data. + * icudtl.dat + +* V8 snapshot data. + * natives_blob.bin + * snapshot_blob.bin + +Optional components: + +The following components are optional. If they are missing JCEF will continue to +run but any related functionality may become broken or disabled. + +* Localized resources. + Locale file loading can be disabled completely using + CefSettings.pack_loading_disabled. The locales directory path can be + customized using CefSettings.locales_dir_path. + + * locales/ + Directory containing localized resources used by CEF, Chromium and Blink. A + .pak file is loaded from this directory based on the value of environment + variables which are read with the following precedence order: LANGUAGE, + LC_ALL, LC_MESSAGES and LANG. Only configured locales need to be + distributed. If no locale is configured the default locale of "en-US" will + be used. Without these files arbitrary Web components may display + incorrectly. + +* Other resources. + Pack file loading can be disabled completely using + CefSettings.pack_loading_disabled. The resources directory path can be + customized using CefSettings.resources_dir_path. + + * cef.pak + * cef_100_percent.pak + * cef_200_percent.pak + These files contain non-localized resources used by CEF, Chromium and Blink. + Without these files arbitrary Web components may display incorrectly. + + * cef_extensions.pak + This file contains non-localized resources required for extension loading. + Pass the `--disable-extensions` command-line flag to disable use of this + file. Without this file components that depend on the extension system, + such as the PDF viewer, will not function. + + * devtools_resources.pak + This file contains non-localized resources required for Chrome Developer + Tools. Without this file Chrome Developer Tools will not function. diff --git a/lib/jcef/tools/distrib/linux64/README.standard.txt b/lib/jcef/tools/distrib/linux64/README.standard.txt new file mode 100644 index 0000000..f1da247 --- /dev/null +++ b/lib/jcef/tools/distrib/linux64/README.standard.txt @@ -0,0 +1,20 @@ +CONTENTS +-------- + +bin Contains Java archives, native library files and the MainFrame + sample application. + +docs Contains documentation for the org.cef package. + + +USAGE +----- + +1. Install a 64-bit version of the Oracle Java 7 runtime. +2. Execute the run.sh script to run the MainFrame sample application. +3. Optionally recompile the sample application and update jcef-tests.jar + by running the compile.sh script. + +Please visit the JCEF Website for additional usage information. + +https://github.com/chromiumembedded/java-cef diff --git a/lib/jcef/tools/distrib/linux64/compile.sh b/lib/jcef/tools/distrib/linux64/compile.sh new file mode 100644 index 0000000..6bee820 --- /dev/null +++ b/lib/jcef/tools/distrib/linux64/compile.sh @@ -0,0 +1,14 @@ +#!/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. + +# Determine the absolute path to the current directory. +DIR="$( cd "$( dirname "$0" )" && pwd )" +BIN_DIR="${DIR}/bin" + +# Compile the test program. +javac -cp "${BIN_DIR}:${BIN_DIR}/*" "${BIN_DIR}"/tests/detailed/*.java "${BIN_DIR}"/tests/detailed/dialog/*.java "${BIN_DIR}"/tests/detailed/handler/*.java "${BIN_DIR}"/tests/detailed/ui/*.java "${BIN_DIR}"/tests/simple/*.java + +# Create the test JAR file. +jar -cf "${BIN_DIR}"/jcef-tests.jar -C "${BIN_DIR}" tests diff --git a/lib/jcef/tools/distrib/linux64/run.sh b/lib/jcef/tools/distrib/linux64/run.sh new file mode 100644 index 0000000..b3fccc2 --- /dev/null +++ b/lib/jcef/tools/distrib/linux64/run.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file. + +# Determine the absolute path to the current directory. +DIR="$( cd "$( dirname "$0" )" && pwd )" +LIB_PATH="$DIR/bin/lib/linux64" + +if [ -z "$1" ]; then + EXAMPLE="detailed" +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}" +else + LD_LIBRARY_PATH="$LIB_PATH" +fi +export LD_LIBRARY_PATH + +# Preload libcef.so to avoid crashes. +LD_PRELOAD=libcef.so java -cp "${DIR}/bin:${DIR}/bin/*" -Djava.library.path="$LIB_PATH" tests.${EXAMPLE}.MainFrame "$@" diff --git a/lib/jcef/tools/distrib/macosx64/README.redistrib.txt b/lib/jcef/tools/distrib/macosx64/README.redistrib.txt new file mode 100644 index 0000000..e1d3424 --- /dev/null +++ b/lib/jcef/tools/distrib/macosx64/README.redistrib.txt @@ -0,0 +1,119 @@ +REDISTRIBUTION +-------------- + +This binary distribution contains the below components. Components listed under +the "required" section must be redistributed with all applications using JCEF. +Components listed under the "optional" section may be excluded if the related +features will not be used. + +Applications using JCEF on OS X must follow a specific app bundle structure. +Replace "jcef_app" in the below example with your application name. + +jcef_app.app/ + Contents/ + Frameworks/ + Chromium Embedded Framework.framework/ + Chromium Embedded Framework <= main application library + Resources/ + cef.pak <= non-localized resources and strings + cef_100_percent.pak <====^ + cef_200_percent.pak <====^ + cef_extensions.pak <=====^ + devtools_resources.pak <=^ + crash_inspector, crash_report_sender <= breakpad support + icudtl.dat <= unicode support + natives_blob.bin, snapshot_blob.bin <= V8 initial snapshot + en.lproj/, ... <= locale-specific resources and strings + Info.plist + jcef Helper.app/ + Contents/ + Info.plist + MacOS/ + jcef Helper <= helper executable + Pkginfo + Info.plist + Java/ + *.jar <= Required JAR files + libjcef.dylib <= CEF JNI library + MacOS/ + JavaAppLauncher <= Java bootstrap executable + Pkginfo + Resources/ + CefIcon.icns + en.lproj/Localizable.strings + +The "Chromium Embedded Framework.framework" is an unversioned framework that +contains CEF binaries and resources. Binaries (libjcef.dylib, jcef Helper, +etc) are linked to the "Chromium Embedded Framework" library using +install_name_tool and a path relative to @executable_path. + +The "jcef Helper" app is used for executing separate processes (renderer, +plugin, etc) with different characteristics. It needs to have a separate app +bundle and Info.plist file so that, among other things, it doesn’t show dock +icons. + +Required components: + +The following components are required. CEF will not function without them. + +* Java archives + jcef.jar + gluegen-rt.jar + gluegen-rt-natives-macosx-universal.jar + jogl-all.jar + jogl-all-natives-macosx-universal.jar + +* CEF JNI library + libjcef.dylib + +* CEF core library. + * Chromium Embedded Framework.framework/Chromium Embedded Framework + +* Unicode support data. + * Chromium Embedded Framework.framework/Resources/icudtl.dat + +* V8 snapshot data. + * Chromium Embedded Framework.framework/Resources/natives_blob.bin + * Chromium Embedded Framework.framework/Resources/snapshot_blob.bin + +Optional components: + +The following components are optional. If they are missing CEF will continue to +run but any related functionality may become broken or disabled. + +* Localized resources. + Locale file loading can be disabled completely using + CefSettings.pack_loading_disabled. + + * Chromium Embedded Framework.framework/Resources/*.lproj/ + Directory containing localized resources used by CEF, Chromium and Blink. A + .pak file is loaded from this directory based on the CefSettings.locale + value. Only configured locales need to be distributed. If no locale is + configured the default locale of "en" will be used. Without these files + arbitrary Web components may display incorrectly. + +* Other resources. + Pack file loading can be disabled completely using + CefSettings.pack_loading_disabled. + + * Chromium Embedded Framework.framework/Resources/cef.pak + * Chromium Embedded Framework.framework/Resources/cef_100_percent.pak + * Chromium Embedded Framework.framework/Resources/cef_200_percent.pak + These files contain non-localized resources used by CEF, Chromium and Blink. + Without these files arbitrary Web components may display incorrectly. + + * Chromium Embedded Framework.framework/Resources/cef_extensions.pak + This file contains non-localized resources required for extension loading. + Pass the `--disable-extensions` command-line flag to disable use of this + file. Without this file components that depend on the extension system, + such as the PDF viewer, will not function. + + * Chromium Embedded Framework.framework/Resources/devtools_resources.pak + This file contains non-localized resources required for Chrome Developer + Tools. Without this file Chrome Developer Tools will not function. + +* Breakpad support. + * Chromium Embedded Framework.framework/Resources/crash_inspector + * Chromium Embedded Framework.framework/Resources/crash_report_sender + * Chromium Embedded Framework.framework/Resources/Info.plist + Without these files breakpad support (crash reporting) will not function. diff --git a/lib/jcef/tools/distrib/macosx64/README.standard.txt b/lib/jcef/tools/distrib/macosx64/README.standard.txt new file mode 100644 index 0000000..38a3b51 --- /dev/null +++ b/lib/jcef/tools/distrib/macosx64/README.standard.txt @@ -0,0 +1,21 @@ +CONTENTS +-------- + +bin Contains the jcef_app whose contents include Java archives and + native library files. + +docs Contains documentation for the org.cef package. + +tests Contains the MainFrame sample application. + +USAGE +----- + +1. Install a 64-bit version of the Oracle Java 7 runtime. +2. Launch jcef_app to run the MainFrame sample application. +3. Optionally recompile the sample application and update jcef-tests.jar + in the jcef_app bundle by running the compile.sh script. + +Please visit the JCEF Website for additional usage information. + +https://github.com/chromiumembedded/java-cef diff --git a/lib/jcef/tools/distrib/macosx64/compile.sh b/lib/jcef/tools/distrib/macosx64/compile.sh new file mode 100644 index 0000000..f32a759 --- /dev/null +++ b/lib/jcef/tools/distrib/macosx64/compile.sh @@ -0,0 +1,13 @@ +#!/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. + +# Compile the test program. +javac -cp "./bin/jcef_app.app/Contents/Java/*":"." ./tests/detailed/*.java + +# Create the test JAR file. +jar -cf tests/jcef-tests.jar tests/detailed/*.class tests/detailed/dialog/*.class tests/detailed/handler/*.class tests/detailed/ui/*.class + +# Insert the test JAR file into the app bundle. +cp -f tests/jcef-tests.jar "./bin/jcef_app.app/Contents/Java/" diff --git a/lib/jcef/tools/distrib/win32/README.redistrib.txt b/lib/jcef/tools/distrib/win32/README.redistrib.txt new file mode 100644 index 0000000..648b85f --- /dev/null +++ b/lib/jcef/tools/distrib/win32/README.redistrib.txt @@ -0,0 +1,77 @@ +REDISTRIBUTION +-------------- + +This binary distribution contains the below components. + +Required components: + +The following components are required. JCEF will not function without them. + +* Java archives. + jcef.jar + gluegen-rt.jar + gluegen-rt-natives-windows-i586.jar + jogl-all.jar + jogl-all-natives-windows-i586.jar + +* CEF JNI library. + jcef.dll + +* CEF JNI process helper. + jcef_helper.exe + +* CEF core library. + * libcef.dll + +* Unicode support data. + * icudtl.dat + +* V8 snapshot data. + * natives_blob.bin + * snapshot_blob.bin + +Optional components: + +The following components are optional. If they are missing JCEF will continue to +run but any related functionality may become broken or disabled. + +* Localized resources. + Locale file loading can be disabled completely using + CefSettings.pack_loading_disabled. The locales directory path can be + customized using CefSettings.locales_dir_path. + + * locales/ + Directory containing localized resources used by CEF, Chromium and Blink. A + .pak file is loaded from this directory based on the CefSettings.locale + value. Only configured locales need to be distributed. If no locale is + configured the default locale of "en-US" will be used. Without these files + arbitrary Web components may display incorrectly. + +* Other resources. + Pack file loading can be disabled completely using + CefSettings.pack_loading_disabled. The resources directory path can be + customized using CefSettings.resources_dir_path. + + * cef.pak + * cef_100_percent.pak + * cef_200_percent.pak + These files contain non-localized resources used by CEF, Chromium and Blink. + Without these files arbitrary Web components may display incorrectly. + + * cef_extensions.pak + This file contains non-localized resources required for extension loading. + Pass the `--disable-extensions` command-line flag to disable use of this + file. Without this file components that depend on the extension system, + such as the PDF viewer, will not function. + + * devtools_resources.pak + This file contains non-localized resources required for Chrome Developer + Tools. Without this file Chrome Developer Tools will not function. + +* Angle and Direct3D support. + * d3dcompiler_43.dll (required for Windows XP) + * d3dcompiler_47.dll (required for Windows Vista and newer) + * libEGL.dll + * libGLESv2.dll + Without these files HTML5 accelerated content like 2D canvas, 3D CSS and WebGL + will not function. diff --git a/lib/jcef/tools/distrib/win32/README.standard.txt b/lib/jcef/tools/distrib/win32/README.standard.txt new file mode 100644 index 0000000..b24a0d3 --- /dev/null +++ b/lib/jcef/tools/distrib/win32/README.standard.txt @@ -0,0 +1,21 @@ +CONTENTS +-------- + +bin Contains Java archives, native library files and the MainFrame + sample application. + +docs Contains documentation for the org.cef package. + + +USAGE +----- + +1. Install a 32-bit version of the Java 7 runtime. +2. Add the Java bin folder to your system PATH. +3. Execute the run.bat script to run the MainFrame sample application. +4. Optionally recompile the sample application and update jcef-tests.jar + by running the compile.bat script. + +Please visit the JCEF Website for additional usage information. + +https://github.com/chromiumembedded/java-cef diff --git a/lib/jcef/tools/distrib/win32/compile.bat b/lib/jcef/tools/distrib/win32/compile.bat new file mode 100644 index 0000000..c5ef72f --- /dev/null +++ b/lib/jcef/tools/distrib/win32/compile.bat @@ -0,0 +1,11 @@ +:: 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. + +:: Compile the test program. +javac -cp "./bin;./bin/*" ./bin/tests/detailed/*.java ./bin/tests/detailed/dialog/*.java ./bin/tests/detailed/handler/*.java ./bin/tests/detailed/ui/*.java ./bin/tests/simple/*.java + +:: Create the test JAR file. +cd bin +jar -cf jcef-tests.jar tests/detailed/*.class tests/detailed/dialog/*.class tests/detailed/handler/*.class tests/detailed/ui/*.class tests/simple/*.java +cd .. \ No newline at end of file diff --git a/lib/jcef/tools/distrib/win32/run.bat b/lib/jcef/tools/distrib/win32/run.bat new file mode 100644 index 0000000..b519fb2 --- /dev/null +++ b/lib/jcef/tools/distrib/win32/run.bat @@ -0,0 +1,5 @@ +:: Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +:: reserved. Use of this source code is governed by a BSD-style license +:: that can be found in the LICENSE file. + +java -cp "./bin;./bin/*" -Djava.library.path=./bin/lib/win32 tests.detailed.MainFrame diff --git a/lib/jcef/tools/distrib/win64/README.redistrib.txt b/lib/jcef/tools/distrib/win64/README.redistrib.txt new file mode 100644 index 0000000..974e4e4 --- /dev/null +++ b/lib/jcef/tools/distrib/win64/README.redistrib.txt @@ -0,0 +1,77 @@ +REDISTRIBUTION +-------------- + +This binary distribution contains the below components. + +Required components: + +The following components are required. JCEF will not function without them. + +* Java archives. + jcef.jar + gluegen-rt.jar + gluegen-rt-natives-windows-amd64.jar + jogl-all.jar + jogl-all-natives-windows-amd64.jar + +* CEF JNI library. + jcef.dll + +* CEF JNI process helper. + jcef_helper.exe + +* CEF core library. + * libcef.dll + +* Unicode support data. + * icudtl.dat + +* V8 snapshot data. + * natives_blob.bin + * snapshot_blob.bin + +Optional components: + +The following components are optional. If they are missing JCEF will continue to +run but any related functionality may become broken or disabled. + +* Localized resources. + Locale file loading can be disabled completely using + CefSettings.pack_loading_disabled. The locales directory path can be + customized using CefSettings.locales_dir_path. + + * locales/ + Directory containing localized resources used by CEF, Chromium and Blink. A + .pak file is loaded from this directory based on the CefSettings.locale + value. Only configured locales need to be distributed. If no locale is + configured the default locale of "en-US" will be used. Without these files + arbitrary Web components may display incorrectly. + +* Other resources. + Pack file loading can be disabled completely using + CefSettings.pack_loading_disabled. The resources directory path can be + customized using CefSettings.resources_dir_path. + + * cef.pak + * cef_100_percent.pak + * cef_200_percent.pak + These files contain non-localized resources used by CEF, Chromium and Blink. + Without these files arbitrary Web components may display incorrectly. + + * cef_extensions.pak + This file contains non-localized resources required for extension loading. + Pass the `--disable-extensions` command-line flag to disable use of this + file. Without this file components that depend on the extension system, + such as the PDF viewer, will not function. + + * devtools_resources.pak + This file contains non-localized resources required for Chrome Developer + Tools. Without this file Chrome Developer Tools will not function. + +* Angle and Direct3D support. + * d3dcompiler_43.dll (required for Windows XP) + * d3dcompiler_47.dll (required for Windows Vista and newer) + * libEGL.dll + * libGLESv2.dll + Without these files HTML5 accelerated content like 2D canvas, 3D CSS and WebGL + will not function. diff --git a/lib/jcef/tools/distrib/win64/README.standard.txt b/lib/jcef/tools/distrib/win64/README.standard.txt new file mode 100644 index 0000000..a17a257 --- /dev/null +++ b/lib/jcef/tools/distrib/win64/README.standard.txt @@ -0,0 +1,21 @@ +CONTENTS +-------- + +bin Contains Java archives, native library files and the MainFrame + sample application. + +docs Contains documentation for the org.cef package. + + +USAGE +----- + +1. Install a 64-bit version of the Java 7 runtime. +2. Add the Java bin folder to your system PATH. +3. Execute the run.bat script to run the MainFrame sample application. +4. Optionally recompile the sample application and update jcef-tests.jar + by running the compile.bat script. + +Please visit the JCEF Website for additional usage information. + +https://github.com/chromiumembedded/java-cef diff --git a/lib/jcef/tools/distrib/win64/compile.bat b/lib/jcef/tools/distrib/win64/compile.bat new file mode 100644 index 0000000..c5ef72f --- /dev/null +++ b/lib/jcef/tools/distrib/win64/compile.bat @@ -0,0 +1,11 @@ +:: 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. + +:: Compile the test program. +javac -cp "./bin;./bin/*" ./bin/tests/detailed/*.java ./bin/tests/detailed/dialog/*.java ./bin/tests/detailed/handler/*.java ./bin/tests/detailed/ui/*.java ./bin/tests/simple/*.java + +:: Create the test JAR file. +cd bin +jar -cf jcef-tests.jar tests/detailed/*.class tests/detailed/dialog/*.class tests/detailed/handler/*.class tests/detailed/ui/*.class tests/simple/*.java +cd .. \ No newline at end of file diff --git a/lib/jcef/tools/distrib/win64/run.bat b/lib/jcef/tools/distrib/win64/run.bat new file mode 100644 index 0000000..89893ad --- /dev/null +++ b/lib/jcef/tools/distrib/win64/run.bat @@ -0,0 +1,5 @@ +:: Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +:: reserved. Use of this source code is governed by a BSD-style license +:: that can be found in the LICENSE file. + +java -cp "./bin;./bin/*" -Djava.library.path=./bin/lib/win64 tests.detailed.MainFrame diff --git a/lib/jcef/tools/exec_util.py b/lib/jcef/tools/exec_util.py new file mode 100644 index 0000000..a6c2347 --- /dev/null +++ b/lib/jcef/tools/exec_util.py @@ -0,0 +1,41 @@ +# 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 + +from __future__ import absolute_import +from subprocess import Popen, PIPE +import sys + + +def exec_cmd(cmd, path, input_string=None): + """ Execute the specified command and return the result. """ + out = '' + err = '' + ret = -1 + parts = cmd.split() + try: + if input_string is None: + process = Popen( + parts, + cwd=path, + stdout=PIPE, + stderr=PIPE, + shell=(sys.platform == 'win32')) + out, err = process.communicate() + ret = process.returncode + else: + process = Popen( + parts, + cwd=path, + stdin=PIPE, + stdout=PIPE, + stderr=PIPE, + shell=(sys.platform == 'win32')) + out, err = process.communicate(input=input_string) + ret = process.returncode + except IOError as e: + (errno, strerror) = e.args + raise + except: + raise + return {'out': out.decode('utf-8'), 'err': err.decode('utf-8'), 'ret': ret} diff --git a/lib/jcef/tools/file_util.py b/lib/jcef/tools/file_util.py new file mode 100644 index 0000000..0741f6f --- /dev/null +++ b/lib/jcef/tools/file_util.py @@ -0,0 +1,168 @@ +# Copyright (c) 2011 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. + +from __future__ import absolute_import +from glob import iglob +from io import open +import os +import shutil +import sys +import time + + +def read_file(name, normalize=True): + """ Read a file. """ + try: + with open(name, 'r', encoding='utf-8') as f: + # read the data + data = f.read() + if normalize: + # normalize line endings + data = data.replace("\r\n", "\n") + return data + except IOError as e: + (errno, strerror) = e.args + sys.stderr.write('Failed to read file ' + name + ': ' + strerror) + raise + + +def write_file(name, data): + """ Write a file. """ + try: + with open(name, 'w', encoding='utf-8') as f: + # write the data + if sys.version_info.major == 2: + f.write(data.decode('utf-8')) + else: + f.write(data) + except IOError as e: + (errno, strerror) = e.args + sys.stderr.write('Failed to write file ' + name + ': ' + strerror) + raise + + +def path_exists(name): + """ Returns true if the path currently exists. """ + return os.path.exists(name) + + +def backup_file(name): + """ Rename the file to a name that includes the current time stamp. """ + move_file(name, name + '.' + time.strftime('%Y-%m-%d-%H-%M-%S')) + + +def copy_file(src, dst, quiet=True): + """ Copy a file. """ + try: + shutil.copy2(src, dst) + if not quiet: + sys.stdout.write('Transferring ' + src + ' file.\n') + except IOError as e: + (errno, strerror) = e.args + sys.stderr.write('Failed to copy file from ' + src + ' to ' + dst + ': ' + + strerror) + raise + + +def move_file(src, dst, quiet=True): + """ Move a file. """ + try: + shutil.move(src, dst) + if not quiet: + sys.stdout.write('Moving ' + src + ' file.\n') + except IOError as e: + (errno, strerror) = e.args + sys.stderr.write('Failed to move file from ' + src + ' to ' + dst + ': ' + + strerror) + raise + + +def copy_files(src_glob, dst_folder, quiet=True): + """ Copy multiple files. """ + for fname in iglob(src_glob): + dst = os.path.join(dst_folder, os.path.basename(fname)) + if os.path.isdir(fname): + copy_dir(fname, dst, quiet) + else: + copy_file(fname, dst, quiet) + + +def remove_file(name, quiet=True): + """ Remove the specified file. """ + try: + if path_exists(name): + os.remove(name) + if not quiet: + sys.stdout.write('Removing ' + name + ' file.\n') + except IOError as e: + (errno, strerror) = e.args + sys.stderr.write('Failed to remove file ' + name + ': ' + strerror) + raise + + +def copy_dir(src, dst, quiet=True): + """ Copy a directory tree. """ + try: + remove_dir(dst, quiet) + shutil.copytree(src, dst) + if not quiet: + sys.stdout.write('Transferring ' + src + ' directory.\n') + except IOError as e: + (errno, strerror) = e.args + sys.stderr.write('Failed to copy directory from ' + src + ' to ' + dst + + ': ' + strerror) + raise + + +def remove_dir(name, quiet=True): + """ Remove the specified directory. """ + try: + if path_exists(name): + shutil.rmtree(name) + if not quiet: + sys.stdout.write('Removing ' + name + ' directory.\n') + except IOError as e: + (errno, strerror) = e.args + sys.stderr.write('Failed to remove directory ' + name + ': ' + strerror) + raise + + +def make_dir(name, quiet=True): + """ Create the specified directory. """ + try: + if not path_exists(name): + if not quiet: + sys.stdout.write('Creating ' + name + ' directory.\n') + os.makedirs(name) + except IOError as e: + (errno, strerror) = e.args + sys.stderr.write('Failed to create directory ' + name + ': ' + strerror) + raise + + +def get_files(search_glob): + """ Returns all files matching the search glob. """ + # Sort the result for consistency across platforms. + return sorted(iglob(search_glob)) + + +def read_version_file(file, args): + """ Read and parse a version file (key=value pairs, one per line). """ + lines = read_file(file).split("\n") + for line in lines: + parts = line.split('=', 1) + if len(parts) == 2: + args[parts[0]] = parts[1] + + +def eval_file(src): + """ Loads and evaluates the contents of the specified file. """ + return eval(read_file(src), {'__builtins__': None}, None) + + +def normalize_path(path): + """ Normalizes the path separator to match the Unix standard. """ + if sys.platform == 'win32': + return path.replace('\\', '/') + return path diff --git a/lib/jcef/tools/fix_style.bat b/lib/jcef/tools/fix_style.bat new file mode 100644 index 0000000..ae87444 --- /dev/null +++ b/lib/jcef/tools/fix_style.bat @@ -0,0 +1,2 @@ +@echo off +python tools\fix_style.py %* diff --git a/lib/jcef/tools/fix_style.py b/lib/jcef/tools/fix_style.py new file mode 100644 index 0000000..e0debae --- /dev/null +++ b/lib/jcef/tools/fix_style.py @@ -0,0 +1,145 @@ +# Copyright (c) 2017 The Chromium Embedded Framework Authors. +# Portions copyright (c) 2011 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. + +from __future__ import absolute_import +from __future__ import print_function +import os, re, sys +from clang_util import clang_format +from file_util import eval_file, get_files, read_file, write_file +from git_util import get_changed_files +from yapf_util import yapf_format + +# File extensions that can be formatted. +DEFAULT_LINT_WHITELIST_REGEX = r"(.*\.cpp|.*\.cc|.*\.h|.*\.java|.*\.mm|.*\.py)$" +DEFAULT_LINT_BLACKLIST_REGEX = r"$^" + +# Directories containing these path components will be ignored. +IGNORE_DIRECTORIES = [] + +# Script directory. +script_dir = os.path.dirname(__file__) +root_dir = os.path.join(script_dir, os.pardir) + + +def msg(filename, status): + if sys.platform == 'win32': + # Use Unix path separator. + filename = filename.replace("\\", "/") + + if len(filename) > 60: + # Truncate the file path in a nice way. + filename = filename[-57:] + pos = filename.find("/") + if pos > 0: + filename = filename[pos:] + filename = "..." + filename + + print("%-60s %s" % (filename, status)) + + +updatect = 0 + + +def read_config(): + style_cfg = os.path.join(root_dir, ".style.cfg") + if os.path.exists(style_cfg): + config = eval_file(style_cfg) + if 'ignore_directories' in config: + global IGNORE_DIRECTORIES + IGNORE_DIRECTORIES = config['ignore_directories'] + + +def update_file(filename): + oldcontents = read_file(filename) + if len(oldcontents) == 0: + msg(filename, "empty") + return + + if os.path.splitext(filename)[1] == ".py": + # Format Python files using YAPF. + newcontents = yapf_format(filename, oldcontents) + else: + # Format C/C++/ObjC/Java files using clang-format. + newcontents = clang_format(filename, oldcontents) + + if newcontents is None: + raise Exception("Failed to process %s" % filename) + + if newcontents != oldcontents: + msg(filename, "fixed") + global updatect + updatect += 1 + write_file(filename, newcontents) + else: + msg(filename, "ok") + return + + +def fix_style(filenames, white_list=None, black_list=None): + """ Execute clang-format with the specified arguments. """ + if not white_list: + white_list = DEFAULT_LINT_WHITELIST_REGEX + white_regex = re.compile(white_list) + if not black_list: + black_list = DEFAULT_LINT_BLACKLIST_REGEX + black_regex = re.compile(black_list) + + for filename in filenames: + # Ignore files from specific directories. + ignore = False + for dir_part in filename.split(os.sep): + if dir_part in IGNORE_DIRECTORIES: + msg(filename, "ignored") + ignore = True + break + if ignore: + continue + + if filename.find('*') > 0: + # Expand wildcards. + filenames.extend(get_files(filename)) + continue + + if os.path.isdir(filename): + # Add directory contents. + filenames.extend(get_files(os.path.join(filename, "*"))) + continue + + if not os.path.exists(filename): + files = get_changed_files(".", filename) + if len(files) > 0: + filenames.extend(files) + else: + msg(filename, "missing") + continue + + if white_regex.match(filename): + if black_regex.match(filename): + msg(filename, "ignored") + else: + update_file(filename) + else: + msg(filename, "skipped") + + +if __name__ == "__main__": + if len(sys.argv) == 1: + print("Usage: %s [file-path|git-hash|unstaged|staged] ...\n" % sys.argv[0]) + print(" Format C, C++ and ObjC files using Chromium's clang-format style.") + print("\nOptions:") + print(" file-path\tProcess the specified file or directory.") + print(" \t\tDirectories will be processed recursively.") + print(" \t\tThe \"*\" wildcard character is supported.") + print(" git-hash\tProcess all files changed in the specified Git commit.") + print(" unstaged\tProcess all unstaged files in the Git repo.") + print(" staged\t\tProcess all staged files in the Git repo.") + sys.exit(1) + + # Read the configuration file. + read_config() + + # Process anything passed on the command-line. + fix_style(sys.argv[1:]) + print('Done - Wrote %d files.' % updatect) diff --git a/lib/jcef/tools/fix_style.sh b/lib/jcef/tools/fix_style.sh new file mode 100644 index 0000000..042c01f --- /dev/null +++ b/lib/jcef/tools/fix_style.sh @@ -0,0 +1,2 @@ +#!/bin/sh +python3 tools/fix_style.py $@ diff --git a/lib/jcef/tools/git_util.py b/lib/jcef/tools/git_util.py new file mode 100644 index 0000000..51935e3 --- /dev/null +++ b/lib/jcef/tools/git_util.py @@ -0,0 +1,126 @@ +# 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 + +from __future__ import absolute_import +from exec_util import exec_cmd +import os +import sys + +# Git must be in the system PATH. +git_exe = 'git' + + +def is_checkout(path): + """ Returns true if the path represents a git checkout. """ + return os.path.isdir(os.path.join(path, '.git')) + + +def get_hash(path='.', branch='HEAD'): + """ Returns the git hash for the specified branch/tag/hash. """ + cmd = "%s rev-parse %s" % (git_exe, branch) + result = exec_cmd(cmd, path) + if result['out'] != '': + return result['out'].strip() + return 'Unknown' + + +def get_url(path='.'): + """ Returns the origin url for the specified path. """ + cmd = "%s config --get remote.origin.url" % git_exe + result = exec_cmd(cmd, path) + if result['out'] != '': + return result['out'].strip() + return 'Unknown' + + +def get_commit_number(path='.', branch='HEAD'): + """ Returns the number of commits in the specified branch/tag/hash. """ + cmd = "%s rev-list --count %s" % (git_exe, branch) + result = exec_cmd(cmd, path) + if result['out'] != '': + return result['out'].strip() + return '0' + + +def get_changed_files(path, hash): + """ Retrieves the list of changed files. """ + if hash == 'unstaged': + cmd = "%s diff --name-only" % git_exe + elif hash == 'staged': + cmd = "%s diff --name-only --cached" % git_exe + else: + cmd = "%s diff-tree --no-commit-id --name-only -r %s" % (git_exe, hash) + result = exec_cmd(cmd, path) + if result['out'] != '': + files = result['out'] + if sys.platform == 'win32': + # Convert to Unix line endings. + files = files.replace('\r\n', '\n') + return files.strip().split("\n") + return [] + + +def write_indented_output(output): + """ Apply a fixed amount of intent to lines before printing. """ + if output == '': + return + for line in output.split('\n'): + line = line.strip() + if len(line) == 0: + continue + sys.stdout.write('\t%s\n' % line) + + +def git_apply_patch_file(patch_path, patch_dir): + """ Apply |patch_path| to files in |patch_dir|. """ + patch_name = os.path.basename(patch_path) + sys.stdout.write('\nApply %s in %s\n' % (patch_name, patch_dir)) + + if not os.path.isfile(patch_path): + sys.stdout.write('... patch file does not exist.\n') + return 'fail' + + patch_string = open(patch_path, 'rb').read() + if sys.platform == 'win32': + # Convert the patch to Unix line endings. This is necessary to avoid + # whitespace errors with git apply. + patch_string = patch_string.replace(b'\r\n', b'\n') + + # Git apply fails silently if not run relative to a respository root. + if not is_checkout(patch_dir): + sys.stdout.write('... patch directory is not a repository root.\n') + return 'fail' + + config = '-p0 --ignore-whitespace' + + # Output patch contents. + cmd = '%s apply %s --numstat' % (git_exe, config) + result = exec_cmd(cmd, patch_dir, patch_string) + write_indented_output(result['out'].replace('', patch_name)) + + # Reverse check to see if the patch has already been applied. + cmd = '%s apply %s --reverse --check' % (git_exe, config) + result = exec_cmd(cmd, patch_dir, patch_string) + if result['err'].find('error:') < 0: + sys.stdout.write('... already applied (skipping).\n') + return 'skip' + + # Normal check to see if the patch can be applied cleanly. + cmd = '%s apply %s --check' % (git_exe, config) + result = exec_cmd(cmd, patch_dir, patch_string) + if result['err'].find('error:') >= 0: + sys.stdout.write('... failed to apply:\n') + write_indented_output(result['err'].replace('', patch_name)) + return 'fail' + + # Apply the patch file. This should always succeed because the previous + # command succeeded. + cmd = '%s apply %s' % (git_exe, config) + result = exec_cmd(cmd, patch_dir, patch_string) + if result['err'] == '': + sys.stdout.write('... successfully applied.\n') + else: + sys.stdout.write('... successfully applied (with warnings):\n') + write_indented_output(result['err'].replace('', patch_name)) + return 'apply' diff --git a/lib/jcef/tools/make_all_jni_headers.bat b/lib/jcef/tools/make_all_jni_headers.bat new file mode 100644 index 0000000..19cb286 --- /dev/null +++ b/lib/jcef/tools/make_all_jni_headers.bat @@ -0,0 +1,56 @@ +@echo off +:: Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +:: reserved. Use of this source code is governed by a BSD-style license +:: that can be found in the LICENSE file. + +set RETURNCODE= +setlocal + +if "%1" == "" ( +echo ERROR: Please specify a target platform: win32 or win64 +set ERRORLEVEL=1 +goto end +) + +:: Make sure the source files have been compiled. +call compile.bat %1 + +call make_jni_header.bat %1 org.cef.CefApp +call make_jni_header.bat %1 org.cef.browser.CefBrowser_N +call make_jni_header.bat %1 org.cef.browser.CefFrame_N +call make_jni_header.bat %1 org.cef.browser.CefMessageRouter_N +call make_jni_header.bat %1 org.cef.browser.CefRequestContext_N +call make_jni_header.bat %1 org.cef.callback.CefAuthCallback_N +call make_jni_header.bat %1 org.cef.callback.CefBeforeDownloadCallback_N +call make_jni_header.bat %1 org.cef.callback.CefCommandLine_N +call make_jni_header.bat %1 org.cef.callback.CefCallback_N +call make_jni_header.bat %1 org.cef.callback.CefContextMenuParams_N +call make_jni_header.bat %1 org.cef.callback.CefDownloadItem_N +call make_jni_header.bat %1 org.cef.callback.CefDownloadItemCallback_N +call make_jni_header.bat %1 org.cef.callback.CefDragData_N +call make_jni_header.bat %1 org.cef.callback.CefFileDialogCallback_N +call make_jni_header.bat %1 org.cef.callback.CefJSDialogCallback_N +call make_jni_header.bat %1 org.cef.callback.CefMenuModel_N +call make_jni_header.bat %1 org.cef.callback.CefPrintDialogCallback_N +call make_jni_header.bat %1 org.cef.callback.CefPrintJobCallback_N +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 +call make_jni_header.bat %1 org.cef.network.CefRequest_N +call make_jni_header.bat %1 org.cef.network.CefResponse_N +call make_jni_header.bat %1 org.cef.network.CefURLRequest_N + +:end +endlocal & set RETURNCODE=%ERRORLEVEL% +goto omega + +:returncode +exit /B %RETURNCODE% + +:omega +call :returncode %RETURNCODE% diff --git a/lib/jcef/tools/make_all_jni_headers.sh b/lib/jcef/tools/make_all_jni_headers.sh new file mode 100644 index 0000000..b4dd312 --- /dev/null +++ b/lib/jcef/tools/make_all_jni_headers.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file. + +if [ -z "$1" ]; then + echo "ERROR: Please specify a target platform: linux32, linux64 or macosx64" +else + DIR="$( cd "$( dirname "$0" )" && pwd )" + "${DIR}"/make_jni_header.sh $1 org.cef.CefApp + "${DIR}"/make_jni_header.sh $1 org.cef.browser.CefBrowser_N + "${DIR}"/make_jni_header.sh $1 org.cef.browser.CefFrame_N + "${DIR}"/make_jni_header.sh $1 org.cef.browser.CefMessageRouter_N + "${DIR}"/make_jni_header.sh $1 org.cef.browser.CefRequestContext_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefAuthCallback_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefBeforeDownloadCallback_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefCommandLine_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefCallback_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefContextMenuParams_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefDownloadItem_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefDownloadItemCallback_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefDragData_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefFileDialogCallback_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefJSDialogCallback_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefMenuModel_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefPrintDialogCallback_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefPrintJobCallback_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefQueryCallback_N + "${DIR}"/make_jni_header.sh $1 org.cef.callback.CefSchemeRegistrar_N + "${DIR}"/make_jni_header.sh $1 org.cef.handler.CefClientHandler + "${DIR}"/make_jni_header.sh $1 org.cef.misc.CefPrintSettings_N + "${DIR}"/make_jni_header.sh $1 org.cef.network.CefCookieManager_N + "${DIR}"/make_jni_header.sh $1 org.cef.network.CefPostData_N + "${DIR}"/make_jni_header.sh $1 org.cef.network.CefPostDataElement_N + "${DIR}"/make_jni_header.sh $1 org.cef.network.CefRequest_N + "${DIR}"/make_jni_header.sh $1 org.cef.network.CefResponse_N + "${DIR}"/make_jni_header.sh $1 org.cef.network.CefURLRequest_N +fi + diff --git a/lib/jcef/tools/make_distrib.bat b/lib/jcef/tools/make_distrib.bat new file mode 100644 index 0000000..ff09d9c --- /dev/null +++ b/lib/jcef/tools/make_distrib.bat @@ -0,0 +1,103 @@ +@echo off +:: Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +:: reserved. Use of this source code is governed by a BSD-style license +:: that can be found in the LICENSE file. + +set RETURNCODE= +setlocal + +cd .. + +if "%1" == "" ( +echo ERROR: Please specify a target platform: win32 or win64 +set ERRORLEVEL=1 +goto end +) +set DISTRIB_PLATFORM="%1" +set DISTRIB_PATH=".\binary_distrib\%1" +set DISTRIB_BIN_PATH="%DISTRIB_PATH%\bin" +set DISTRIB_DOCS_PATH="%DISTRIB_PATH%\docs" +set DISTRIB_LIB_PATH="%DISTRIB_PATH%\bin\lib\%1" +set OUT_PATH=".\out\%1" + +set OUT_BINARY_PATH=".\jcef_build\native\Release" +if not exist %OUT_BINARY_PATH% ( +echo ERROR: Native Release build output path does not exist +goto end +) + +set OUT_DOCS_PATH=".\out\docs" +set SOURCE_PATH=".\java" +set JOGAMP_PATH=".\third_party\jogamp" +set JOGAMP_JAR_PATH="%JOGAMP_PATH%\jar" +set TOOLS_DISTRIB_PATH=".\tools\distrib\%1" + +if "%1" == "win32" ( +set JOGAMP_JAR_SUFFIX="i586" +) else ( +set JOGAMP_JAR_SUFFIX="amd64" +) + +:: Create the JCEF jar file. +cd tools +call make_jar.bat %1 +cd .. + +:: Create the JCEF documentation. +cd tools +call make_docs.bat +cd .. + +:: Copy JAR files to the bin directory. +if not exist %DISTRIB_BIN_PATH% mkdir %DISTRIB_BIN_PATH% +copy %JOGAMP_JAR_PATH%\gluegen-rt.jar %DISTRIB_BIN_PATH% +copy %JOGAMP_JAR_PATH%\gluegen-rt-natives-windows-%JOGAMP_JAR_SUFFIX%.jar %DISTRIB_BIN_PATH% +copy %JOGAMP_JAR_PATH%\jogl-all.jar %DISTRIB_BIN_PATH% +copy %JOGAMP_JAR_PATH%\jogl-all-natives-windows-%JOGAMP_JAR_SUFFIX%.jar %DISTRIB_BIN_PATH% +copy %OUT_PATH%\jcef.jar %DISTRIB_BIN_PATH% + +:: Copy test programs and its sources to the bin directory. +copy %OUT_PATH%\jcef-tests.jar %DISTRIB_BIN_PATH% +xcopy /sfy %SOURCE_PATH%\tests\* %DISTRIB_BIN_PATH%\tests\ + +:: Copy CEF Release files to the lib directory. +if not exist %DISTRIB_LIB_PATH% mkdir %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\chrome_elf.dll %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\d3dcompiler_43.dll %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\d3dcompiler_47.dll %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\icudt.dll %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\jcef.dll %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\jcef_helper.exe %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\icudtl.dat %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\libcef.dll %DISTRIB_LIB_PATH% +copy %OUT_BINARY_PATH%\libEGL.dll %DISTRIB_LIB_PATH% +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% + +:: Copy documentation to the docs directory. +xcopy /sfy %OUT_DOCS_PATH%\* %DISTRIB_DOCS_PATH%\ + +:: Create README.txt +call python tools\make_readme.py --output-dir %DISTRIB_PATH%\ --platform %DISTRIB_PLATFORM% + +:: Copy miscellaneous files to the root directory. +copy .\LICENSE.txt %DISTRIB_PATH% +xcopy /sfy %JOGAMP_PATH%\*.LICENSE.txt %DISTRIB_PATH% +:: Cannot use a variable substitution for /exclude because otherwise xcopy will fail. +xcopy /sfy %TOOLS_DISTRIB_PATH%\* %DISTRIB_PATH% /exclude:.\tools\distrib\EXCLUDE_FILES.txt + +:end +endlocal & set RETURNCODE=%ERRORLEVEL% +goto omega + +:returncode +exit /B %RETURNCODE% + +:omega +call :returncode %RETURNCODE% diff --git a/lib/jcef/tools/make_distrib.sh b/lib/jcef/tools/make_distrib.sh new file mode 100644 index 0000000..5a9721d --- /dev/null +++ b/lib/jcef/tools/make_distrib.sh @@ -0,0 +1,106 @@ +#!/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 build target: linux32, linux64 or macosx64" +else + DIR="$( cd "$( dirname "$0" )" && cd .. && pwd )" + DISTRIB_PLATFORM="$1" + DISTRIB_PATH="${DIR}/binary_distrib/$1" + DISTRIB_BIN_PATH="$DISTRIB_PATH/bin" + DISTRIB_DOCS_PATH="$DISTRIB_PATH/docs" + OUT_PATH="${DIR}/out" + OUT_DOCS_PATH="${DIR}/out/docs" + SOURCE_PATH="${DIR}/java" + JOGAMP_PATH="${DIR}/third_party/jogamp" + TOOLS_DISTRIB_PATH="${DIR}/tools/distrib/$1" + EXCLUDE_FILE="${DIR}/tools/distrib/EXCLUDE_FILES.txt" + + if [ ! -d "$DISTRIB_BIN_PATH" ]; then + mkdir -p "$DISTRIB_BIN_PATH" + fi + + # Create the JCEF documentation. + "${DIR}"/tools/make_docs.sh + + # Copy documentation to the docs directory. + cp -rf "$OUT_DOCS_PATH" "$DISTRIB_DOCS_PATH" + + # Create README.txt + python "${DIR}"/tools/make_readme.py --output-dir "$DISTRIB_PATH/" --platform $DISTRIB_PLATFORM + + # Copy miscellaneous files to the root directory. + cp -f "${DIR}"/LICENSE.txt "$DISTRIB_PATH" + cp -f "$JOGAMP_PATH"/*.LICENSE.txt "$DISTRIB_PATH" + rsync -a --exclude-from "$EXCLUDE_FILE" "$TOOLS_DISTRIB_PATH/" "$DISTRIB_PATH/" + + if [ $1 == "macosx64" ]; then + OUT_BINARY_PATH="${DIR}/jcef_build/native/Release" + if [ ! -d "$OUT_BINARY_PATH" ]; then + echo "ERROR: Native Release build output path does not exist" + exit 1 + fi + + # Copy test program source file to the tests directory. + cp -rf "$SOURCE_PATH"/tests "$DISTRIB_PATH" + + # Everything else is contained in the app bundle. + cp -rf "$OUT_BINARY_PATH"/jcef_app.app ""$DISTRIB_BIN_PATH + else + DISTRIB_LIB_PATH="$DISTRIB_PATH/bin/lib/$1" + JOGAMP_JAR_PATH="$JOGAMP_PATH/jar" + OUT_BINARY_PATH="$OUT_PATH/Release" + + # Alternately look in the CMake output path. + if [ ! -d "$OUT_BINARY_PATH" ]; then + OUT_BINARY_PATH="${DIR}/jcef_build/native/Release" + fi + if [ ! -d "$OUT_BINARY_PATH" ]; then + echo "ERROR: Native Release build output path does not exist" + exit 1 + fi + + # Create the JCEF JAR file. + "${DIR}"/tools/make_jar.sh $1 + + # Copy JAR files to the bin directory. + cp -f "$JOGAMP_JAR_PATH"/gluegen-rt.jar "$DISTRIB_BIN_PATH" + cp -f "$JOGAMP_JAR_PATH"/jogl-all.jar "$DISTRIB_BIN_PATH" + + if [ $1 == "linux32" ]; then + JOGAMP_JAR_SUFFIX="i586" + else + JOGAMP_JAR_SUFFIX="amd64" + fi + cp -f "$JOGAMP_JAR_PATH"/gluegen-rt-natives-linux-$JOGAMP_JAR_SUFFIX.jar "$DISTRIB_BIN_PATH" + cp -f "$JOGAMP_JAR_PATH"/jogl-all-natives-linux-$JOGAMP_JAR_SUFFIX.jar "$DISTRIB_BIN_PATH" + cp -f "$OUT_PATH"/$1/jcef.jar "$DISTRIB_BIN_PATH" + + # Copy test program source and JAR file to the bin directory. + cp -rf "$SOURCE_PATH"/tests "$DISTRIB_BIN_PATH" + cp -f "$OUT_PATH"/$1/jcef-tests.jar "$DISTRIB_BIN_PATH" + + # Copy CEF Release files to the lib directory. + if [ ! -d "$DISTRIB_LIB_PATH" ]; then + mkdir -p "$DISTRIB_LIB_PATH" + fi + + cp -f "$OUT_BINARY_PATH"/chrome-sandbox "$DISTRIB_LIB_PATH" + cp -f "$OUT_BINARY_PATH"/libjcef.so "$DISTRIB_LIB_PATH" + cp -f "$OUT_BINARY_PATH"/jcef_helper "$DISTRIB_LIB_PATH" + cp -f "$OUT_BINARY_PATH"/icudtl.dat "$DISTRIB_LIB_PATH" + cp -f "$OUT_BINARY_PATH"/libcef.so "$DISTRIB_LIB_PATH" + cp -f "$OUT_BINARY_PATH"/libEGL.so "$DISTRIB_LIB_PATH" + cp -f "$OUT_BINARY_PATH"/libGLESv2.so "$DISTRIB_LIB_PATH" + cp -f "$OUT_BINARY_PATH"/snapshot_blob.bin "$DISTRIB_LIB_PATH" + 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 -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/lib/jcef/tools/make_docs.bat b/lib/jcef/tools/make_docs.bat new file mode 100644 index 0000000..cf3b1c7 --- /dev/null +++ b/lib/jcef/tools/make_docs.bat @@ -0,0 +1,24 @@ +@echo off +:: Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +:: reserved. Use of this source code is governed by a BSD-style license +:: that can be found in the LICENSE file. + +set RETURNCODE= +setlocal + +cd ..\java + +set OUT_PATH="..\out\docs" + +if not exist %OUT_PATH% mkdir %OUT_PATH% +javadoc -Xdoclint:none -windowtitle "CEF3 Java API Docs" -footer "
Chromium Embedded Framework (CEF) Copyright © 2013 Marshall A. Greenblatt
" -nodeprecated -d %OUT_PATH% -link http://docs.oracle.com/javase/7/docs/api/ -subpackages org.cef + +:end +endlocal & set RETURNCODE=%ERRORLEVEL% +goto omega + +:returncode +exit /B %RETURNCODE% + +:omega +call :returncode %RETURNCODE% diff --git a/lib/jcef/tools/make_docs.sh b/lib/jcef/tools/make_docs.sh new file mode 100644 index 0000000..782ecfe --- /dev/null +++ b/lib/jcef/tools/make_docs.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file. + +DIR="$( cd "$( dirname "$0" )" && cd .. && pwd )" +OUT_PATH="${DIR}/out/docs" + +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/lib/jcef/tools/make_jar.bat b/lib/jcef/tools/make_jar.bat new file mode 100644 index 0000000..7a1a008 --- /dev/null +++ b/lib/jcef/tools/make_jar.bat @@ -0,0 +1,26 @@ +@echo off +:: Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +:: reserved. Use of this source code is governed by a BSD-style license +:: that can be found in the LICENSE file. + +set RETURNCODE= +setlocal + +if "%1" == "" ( +echo ERROR: Please specify a build target: win32 or win64 +set ERRORLEVEL=1 +goto end +) +cd ..\out\%1 +jar -cmf manifest\MANIFEST.MF jcef.jar org/cef/*.class org/cef/browser/*.class org/cef/callback/*.class org/cef/handler/*.class org/cef/misc/*.class org/cef/network/*.class +jar -cf jcef-tests.jar tests/detailed/*.class tests/detailed/dialog/*.class tests/detailed/handler/* tests/detailed/ui/*.class + +:end +endlocal & set RETURNCODE=%ERRORLEVEL% +goto omega + +:returncode +exit /B %RETURNCODE% + +:omega +call :returncode %RETURNCODE% diff --git a/lib/jcef/tools/make_jar.sh b/lib/jcef/tools/make_jar.sh new file mode 100644 index 0000000..93338e3 --- /dev/null +++ b/lib/jcef/tools/make_jar.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file. + +if [ -z "$1" ]; then + echo "ERROR: Please specify a build target: linux32 or linux64" +else + DIR="$( cd "$( dirname "$0" )" && cd .. && pwd )" + OUT_DIR="${DIR}/out/$1" + jar -cmf "${OUT_DIR}"/manifest/MANIFEST.MF "${OUT_DIR}"/jcef.jar -C "${OUT_DIR}" org + jar -cf "${OUT_DIR}"/jcef-tests.jar -C "${OUT_DIR}" tests +fi diff --git a/lib/jcef/tools/make_jni_header.bat b/lib/jcef/tools/make_jni_header.bat new file mode 100644 index 0000000..b9907e3 --- /dev/null +++ b/lib/jcef/tools/make_jni_header.bat @@ -0,0 +1,45 @@ +@echo off +:: Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +:: reserved. Use of this source code is governed by a BSD-style license +:: that can be found in the LICENSE file. + +set RETURNCODE= +setlocal + +cd .. + +if "%1" == "" ( +echo ERROR: Please specify a target platform: win32 or win64 +set ERRORLEVEL=1 +goto end +) + +if "%2" == "" ( +echo ERROR: Please specify a class name +set ERRORLEVEL=1 +goto end +) + +set OUT_PATH=".\native" +set CLS_PATH=".\third_party\jogamp\jar\*;.\out\%1" +set CLS_NAME="" + +SET TMP="%2" +:loop +for /F "tokens=1,* delims=." %%F in (%TMP%) DO ( + set CLS_NAME="%%F" + set TMP="%%G" + goto loop +) + +call javah.exe -force -classpath %CLS_PATH% -o %OUT_PATH%/%CLS_NAME%.h %2 + +:end +endlocal & set RETURNCODE=%ERRORLEVEL% +goto omega + +:returncode +exit /B %RETURNCODE% + +:omega +call :returncode %RETURNCODE% diff --git a/lib/jcef/tools/make_jni_header.sh b/lib/jcef/tools/make_jni_header.sh new file mode 100644 index 0000000..e59bd44 --- /dev/null +++ b/lib/jcef/tools/make_jni_header.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file. + +if [ -z "$1" ]; then + echo "ERROR: Please specify a target platform: linux32, linux64 or macosx64" +else + if [ -z "$2" ]; then + echo "ERROR: Please specify a class name" + else + DIR="$( cd "$( dirname "$0" )" && cd .. && pwd )" + if [ $1 == "macosx64" ]; then + CLS_OUT_PATH="${DIR}/jcef_build/native/Release" + if [ ! -d "$CLS_OUT_PATH" ]; then + CLS_OUT_PATH="${DIR}/jcef_build/native/Debug" + fi + else + CLS_OUT_PATH="${DIR}/out/$1" + fi + + HEADER_PATH="${DIR}/native" + CLS_PATH="${DIR}/third_party/jogamp/jar/*:${CLS_OUT_PATH}" + CLS_NAME="${2##*.}" + + javah -force -classpath "$CLS_PATH" -o "$HEADER_PATH/$CLS_NAME.h" $2 + fi +fi + diff --git a/lib/jcef/tools/make_readme.bat b/lib/jcef/tools/make_readme.bat new file mode 100644 index 0000000..dfc6313 --- /dev/null +++ b/lib/jcef/tools/make_readme.bat @@ -0,0 +1,30 @@ +@echo off +:: 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. + +set RETURNCODE= +setlocal + +cd .. +if "%1" == "" ( +echo ERROR: Please specify a target platform: win32 or win64 +set ERRORLEVEL=1 +goto end +) + +set DISTRIB_PATH=".\binary_distrib\%1" +if not exist %DISTRIB_PATH% mkdir %DISTRIB_PATH% + +:: Create README.txt +call python tools\make_readme.py --output-dir %DISTRIB_PATH%\ --platform %1 + +:end +endlocal & set RETURNCODE=%ERRORLEVEL% +goto omega + +:returncode +exit /B %RETURNCODE% + +:omega +call :returncode %RETURNCODE% diff --git a/lib/jcef/tools/make_readme.py b/lib/jcef/tools/make_readme.py new file mode 100644 index 0000000..29fc817 --- /dev/null +++ b/lib/jcef/tools/make_readme.py @@ -0,0 +1,146 @@ +# 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. + +from __future__ import absolute_import +from __future__ import print_function +from date_util import * +from file_util import * +from optparse import OptionParser +import os +import re +from readme_util import read_readme_file +import shlex +import subprocess +import git_util as git +import sys +import zipfile + + +def get_readme_component(name): + """ Loads a README file component. """ + paths = [] + # platform directory + paths.append(os.path.join(script_dir, 'distrib', platform)) + + # shared directory + paths.append(os.path.join(script_dir, 'distrib')) + + # load the file if it exists + for path in paths: + file = os.path.join(path, 'README.' + name + '.txt') + if path_exists(file): + return read_file(file) + + raise Exception('Readme component not found: ' + name) + + +def create_readme(): + """ Creates the README.TXT file. """ + # gather the components + header_data = get_readme_component('header') + mode_data = get_readme_component('standard') + redistrib_data = get_readme_component('redistrib') + footer_data = get_readme_component('footer') + + # format the file + data = header_data + '\n\n' + mode_data + '\n\n' + redistrib_data + '\n\n' + footer_data + data = data.replace('$JCEF_URL$', jcef_url) + data = data.replace('$JCEF_REV$', jcef_commit_hash) + data = data.replace('$JCEF_VER$', jcef_ver) + data = data.replace('$CEF_URL$', cef_url) + data = data.replace('$CEF_VER$', cef_ver) + data = data.replace('$CHROMIUM_URL$', chromium_url) + data = data.replace('$CHROMIUM_VER$', chromium_ver) + data = data.replace('$DATE$', date) + + if platform == 'win32': + platform_str = 'Windows 32-bit' + elif platform == 'win64': + platform_str = 'Windows 64-bit' + elif platform == 'macosx64': + platform_str = 'Mac OS-X 64-bit' + elif platform == 'linux32': + platform_str = 'Linux 32-bit' + elif platform == 'linux64': + platform_str = 'Linux 64-bit' + + data = data.replace('$PLATFORM$', platform_str) + + write_file(os.path.join(output_dir, 'README.txt'), data.encode('utf-8')) + if not options.quiet: + sys.stdout.write('Creating README.TXT file.\n') + + +# cannot be loaded as a module +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + +# parse command-line options +disc = """ +This utility builds the JCEF README.txt for the distribution. +""" + +parser = OptionParser(description=disc) +parser.add_option( + '--output-dir', + dest='outputdir', + metavar='DIR', + help='output directory [required]') +parser.add_option( + '--platform', + dest='platform', + help='target platform for distribution [required]') +parser.add_option( + '-q', + '--quiet', + action='store_true', + dest='quiet', + default=False, + help='do not output detailed status information') +(options, args) = parser.parse_args() + +# the outputdir option is required +if options.outputdir is None or options.platform is None: + parser.print_help(sys.stderr) + sys.exit(1) +output_dir = options.outputdir + +# Test the operating system. +platform = options.platform +if (platform != 'linux32' and platform != 'linux64' and + platform != 'macosx64' and platform != 'win32' and platform != 'win64'): + print('Unsupported target \"' + platform + '\"') + sys.exit(1) + +# script directory +script_dir = os.path.dirname(__file__) + +# JCEF root directory +jcef_dir = os.path.abspath(os.path.join(script_dir, os.pardir)) + +# Read and parse the CEF version file. +args = {} +read_readme_file(os.path.join(jcef_dir, 'jcef_build', 'README.txt'), args) + +# retrieve url and revision information for CEF +if not git.is_checkout(jcef_dir): + raise Exception('Not a valid checkout: %s' % (jcef_dir)) + +jcef_commit_number = git.get_commit_number(jcef_dir) +jcef_commit_hash = git.get_hash(jcef_dir) +jcef_url = git.get_url(jcef_dir) +jcef_ver = '%s.%s.%s.%s+g%s' % (args['CEF_MAJOR'], args['CEF_MINOR'], + args['CEF_PATCH'], jcef_commit_number, + jcef_commit_hash[:7]) + +date = get_date() + +cef_ver = args['CEF_VER'] +cef_url = args['CEF_URL'] +chromium_ver = args['CHROMIUM_VER'] +chromium_url = args['CHROMIUM_URL'] + +# create the README.TXT file +create_readme() diff --git a/lib/jcef/tools/make_readme.sh b/lib/jcef/tools/make_readme.sh new file mode 100644 index 0000000..c3d75f4 --- /dev/null +++ b/lib/jcef/tools/make_readme.sh @@ -0,0 +1,17 @@ +#!/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 target platform: linux32, linux64 or macosx64" +else + DIR="$( cd "$( dirname "$0" )" && cd .. && pwd )" + DISTRIB_PATH="${DIR}/binary_distrib/$1" + if [ ! -d "$DISTRIB_PATH" ]; then + mkdir -p "$DISTRIB_PATH" + fi + + # Create README.txt + python "${DIR}"/tools/make_readme.py --output-dir "$DISTRIB_PATH/" --platform $1 +fi diff --git a/lib/jcef/tools/make_version_header.py b/lib/jcef/tools/make_version_header.py new file mode 100644 index 0000000..a0186d9 --- /dev/null +++ b/lib/jcef/tools/make_version_header.py @@ -0,0 +1,136 @@ +# 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. + +from __future__ import absolute_import +from date_util import * +from file_util import * +import git_util as git +from optparse import OptionParser +import re +from readme_util import read_readme_file +import sys + +# cannot be loaded as a module +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit(1) + +# script directory +script_dir = os.path.dirname(__file__) + +# JCEF root directory +jcef_dir = os.path.abspath(os.path.join(script_dir, os.pardir)) + +# parse command-line options +disc = """ +This utility creates the version header file. +""" + +parser = OptionParser(description=disc) +parser.add_option( + '--header', + dest='header', + metavar='FILE', + help='output version header file [required]') +parser.add_option( + '--cef-path', + dest='cefpath', + help='path to the CEF binary distribution [required]') +parser.add_option( + '-q', + '--quiet', + action='store_true', + dest='quiet', + default=False, + help='do not output detailed status information') +(options, args) = parser.parse_args() + +# the header option is required +if options.header is None or options.cefpath is None: + parser.print_help(sys.stdout) + sys.exit(1) + + +def write_svn_header(header): + """ Creates the header file for the current revision + if the information has changed or if the file doesn't already exist. """ + + if path_exists(header): + oldcontents = read_file(header) + else: + oldcontents = '' + + if not git.is_checkout(jcef_dir): + raise Exception('Not a valid checkout') + + commit_number = git.get_commit_number(jcef_dir) + commit_hash = git.get_hash(jcef_dir) + + year = get_year() + + # Read and parse the CEF version file. + args = {} + read_readme_file(os.path.join(options.cefpath, 'README.txt'), args) + + version = '%s.%s.%s.%s+g%s' % (args['CEF_MAJOR'], args['CEF_MINOR'], + args['CEF_PATCH'], commit_number, + commit_hash[:7]) + + newcontents = '// Copyright (c) '+year+' The Chromium Embedded Framework Authors. All rights\n'+\ + '// reserved. Use of this source code is governed by a BSD-style license that\n'+\ + '// can be found in the LICENSE file.\n'+\ + '//\n'+\ + '// Redistribution and use in source and binary forms, with or without\n'+\ + '// modification, are permitted provided that the following conditions are\n'+\ + '// met:\n'+\ + '//\n'+\ + '// * Redistributions of source code must retain the above copyright\n'+\ + '// notice, this list of conditions and the following disclaimer.\n'+\ + '// * Redistributions in binary form must reproduce the above\n'+\ + '// copyright notice, this list of conditions and the following disclaimer\n'+\ + '// in the documentation and/or other materials provided with the\n'+\ + '// distribution.\n'+\ + '// * Neither the name of Google Inc. nor the name Chromium Embedded\n'+\ + '// Framework nor the names of its contributors may be used to endorse\n'+\ + '// or promote products derived from this software without specific prior\n'+\ + '// written permission.\n'+\ + '//\n'+\ + '// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n'+\ + '// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n'+\ + '// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n'+\ + '// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n'+\ + '// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n'+\ + '// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n'+\ + '// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n'+\ + '// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n'+\ + '// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n'+\ + '// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n'+\ + '// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n'+\ + '//\n'+\ + '// ---------------------------------------------------------------------------\n'+\ + '//\n'+\ + '// This file is generated by the make_version_header.py tool.\n'+\ + '//\n\n'+\ + '#ifndef JCEF_INCLUDE_JCEF_VERSION_H_\n'+\ + '#define JCEF_INCLUDE_JCEF_VERSION_H_\n\n'+\ + '#define JCEF_VERSION "' + version + '"\n'+\ + '#define JCEF_COMMIT_NUMBER ' + commit_number + '\n'+\ + '#define JCEF_COMMIT_HASH "' + commit_hash + '"\n'+\ + '#define JCEF_COPYRIGHT_YEAR ' + year + '\n\n'+\ + '#define DO_MAKE_STRING(p) #p\n'+\ + '#define MAKE_STRING(p) DO_MAKE_STRING(p)\n\n'+\ + '#endif // JCEF_INCLUDE_JCEF_VERSION_H_\n' + if newcontents != oldcontents: + write_file(header, newcontents) + return True + + return False + + +written = write_svn_header(options.header) +if not options.quiet: + if written: + sys.stdout.write('File ' + options.header + ' updated.\n') + else: + sys.stdout.write('File ' + options.header + ' is already up to date.\n') diff --git a/lib/jcef/tools/readme_util.py b/lib/jcef/tools/readme_util.py new file mode 100644 index 0000000..4c3f023 --- /dev/null +++ b/lib/jcef/tools/readme_util.py @@ -0,0 +1,27 @@ +from __future__ import absolute_import +from file_util import read_file + + +def read_readme_file(file, args): + """ Read a README.txt and try to parse its containing version numbers """ + lines = read_file(file).split("\n") + for line in lines: + parts = line.split(':', 1) + if len(parts) != 2: + continue + if parts[0].startswith('CEF Version'): + args['CEF_VER'] = parts[1].strip() + subparts = parts[1].split('+') + if len(subparts) != 3: + raise Exception('Failed to parse CEF Version: %s' % parts[1]) + verparts = subparts[0].strip().split('.') + if len(verparts) >= 3: + args['CEF_MAJOR'] = verparts[0] + args['CEF_MINOR'] = verparts[1] + args['CEF_PATCH'] = verparts[2] + elif parts[0].startswith('CEF URL'): + args['CEF_URL'] = parts[1].strip() + elif parts[0].startswith('Chromium Version'): + args['CHROMIUM_VER'] = parts[1].strip() + elif parts[0].startswith('Chromium URL'): + args['CHROMIUM_URL'] = parts[1].strip() diff --git a/lib/jcef/tools/run.bat b/lib/jcef/tools/run.bat new file mode 100644 index 0000000..bfc35ee --- /dev/null +++ b/lib/jcef/tools/run.bat @@ -0,0 +1,62 @@ +@echo off +:: Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +:: reserved. Use of this source code is governed by a BSD-style license +:: that can be found in the LICENSE file. + +set RETURNCODE= +setlocal + +cd .. + +if "%1" == "" ( +echo ERROR: Please specify a target platform: win32 or win64 +set ERRORLEVEL=1 +goto end +) + +if "%2" == "" ( +echo ERROR: Please specify a build type: Debug or Release +set ERRORLEVEL=1 +goto end +) + +if "%3" == "" ( +echo ERROR: Please specify a run type: detailed or simple +set ERRORLEVEL=1 +goto end +) + +set OUT_PATH=.\out\%~1 + +set LIB_PATH=.\jcef_build\native\%~2 +if not exist %LIB_PATH% ( +echo ERROR: Native build output path does not exist +goto end +) + +set CLS_PATH=.\third_party\jogamp\jar\*;%OUT_PATH% +set RUN_TYPE=%~3 + +:: Remove the first three params (%1, %2 and %3) and pass the rest to java. +set RESTVAR= +shift +shift +shift +:loop1 +if "%1"=="" goto after_loop +set RESTVAR=%RESTVAR% %1 +shift +goto loop1 +:after_loop + +java -cp %CLS_PATH% -Djava.library.path=%LIB_PATH% tests.%RUN_TYPE%.MainFrame %RESTVAR% + +:end +endlocal & set RETURNCODE=%ERRORLEVEL% +goto omega + +:returncode +exit /B %RETURNCODE% + +:omega +call :returncode %RETURNCODE% diff --git a/lib/jcef/tools/run.sh b/lib/jcef/tools/run.sh new file mode 100644 index 0000000..9d0408e --- /dev/null +++ b/lib/jcef/tools/run.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file. + +if [ -z "$1" ]; then + echo "ERROR: Please specify a target platform: linux32 or linux64" +else + if [ -z "$2" ]; then + echo "ERROR: Please specify a build type: Debug or Release" + elif [ -z "$3" ]; then + echo "ERROR: Please specify a run type: detailed or simple" + else + DIR="$( cd "$( dirname "$0" )" && cd .. && pwd )" + OUT_PATH="${DIR}/out/$1" + + LIB_PATH="${DIR}/jcef_build/native/$2" + if [ ! -d "$LIB_PATH" ]; then + echo "ERROR: Native build output path does not exist" + 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" + + # Necessary for jcef_helper to find libcef.so. + if [ -n "$LD_LIBRARY_PATH" ]; then + LD_LIBRARY_PATH="$LIB_PATH:${LD_LIBRARY_PATH}" + else + LD_LIBRARY_PATH="$LIB_PATH" + fi + export LD_LIBRARY_PATH + + # Remove the first three params ($1, $2 and $3) and pass the rest to java. + shift + shift + shift + + LD_PRELOAD=libcef.so java -cp "$CLS_PATH" -Djava.library.path="$LIB_PATH" tests.$RUN_TYPE.MainFrame "$@" + fi +fi + diff --git a/lib/jcef/tools/run_tests.bat b/lib/jcef/tools/run_tests.bat new file mode 100644 index 0000000..9eb9bd1 --- /dev/null +++ b/lib/jcef/tools/run_tests.bat @@ -0,0 +1,63 @@ +@echo off +:: Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +:: reserved. Use of this source code is governed by a BSD-style license +:: that can be found in the LICENSE file. + +set RETURNCODE= +setlocal + +cd .. + +if "%1" == "" ( +echo ERROR: Please specify a target platform: win32 or win64 +set ERRORLEVEL=1 +goto end +) + +if "%2" == "" ( +echo ERROR: Please specify a build type: Debug or Release +set ERRORLEVEL=1 +goto end +) + +if "%JAVA_HOME%" == "" ( +echo ERROR: Please set the JAVA_HOME environment variable +set ERRORLEVEL=1 +goto end +) + +set OUT_PATH=.\out\%~1 + +set LIB_PATH=.\jcef_build\native\%~2 +if not exist %LIB_PATH% ( +echo ERROR: Native build output path does not exist +goto end +) + +set CLS_PATH=.\third_party\jogamp\jar\*;%OUT_PATH% + +:: Remove the first two params (%1 and %2) and pass the rest to java. +set RESTVAR= +shift +shift +:loop1 +if "%1"=="" goto after_loop +set RESTVAR=%RESTVAR% %1 +shift +goto loop1 +:after_loop + +:: JUnit can fail to load JVM DLLs if you don't explicitly set the PATH. +set PATH="%JAVA_HOME%\bin" + +java -Djava.library.path=%LIB_PATH% -jar .\third_party\junit\junit-platform-console-standalone-1.4.2.jar -cp %OUT_PATH% --disable-ansi-colors --select-package tests.junittests %RESTVAR% + +:end +endlocal & set RETURNCODE=%ERRORLEVEL% +goto omega + +:returncode +exit /B %RETURNCODE% + +:omega +call :returncode %RETURNCODE% diff --git a/lib/jcef/tools/run_tests.sh b/lib/jcef/tools/run_tests.sh new file mode 100644 index 0000000..ac9457e --- /dev/null +++ b/lib/jcef/tools/run_tests.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file. + +if [ -z "$1" ]; then + echo "ERROR: Please specify a target platform: linux32 or linux64" +else + if [ -z "$2" ]; then + echo "ERROR: Please specify a build type: Debug or Release" + else + DIR="$( cd "$( dirname "$0" )" && cd .. && pwd )" + OUT_PATH="${DIR}/out/$1" + + LIB_PATH="${DIR}/jcef_build/native/$2" + if [ ! -d "$LIB_PATH" ]; then + echo "ERROR: Native build output path does not exist" + exit 1 + fi + + CLS_PATH="${DIR}/third_party/jogamp/jar/*:$OUT_PATH" + + # Necessary for jcef_helper to find libcef.so. + if [ -n "$LD_LIBRARY_PATH" ]; then + LD_LIBRARY_PATH="$LIB_PATH:${LD_LIBRARY_PATH}" + else + LD_LIBRARY_PATH="$LIB_PATH" + fi + export LD_LIBRARY_PATH + + # Remove the first two params ($1 and $2) and pass the rest to java. + shift + shift + + LD_PRELOAD=libcef.so java -Djava.library.path="$LIB_PATH" -jar "${DIR}"/third_party/junit/junit-platform-console-standalone-*.jar -cp "$OUT_PATH" --select-package tests.junittests "$@" + fi +fi + diff --git a/lib/jcef/tools/yapf/LICENSE b/lib/jcef/tools/yapf/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/lib/jcef/tools/yapf/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib/jcef/tools/yapf/README.cef b/lib/jcef/tools/yapf/README.cef new file mode 100644 index 0000000..44e7ced --- /dev/null +++ b/lib/jcef/tools/yapf/README.cef @@ -0,0 +1,14 @@ +Name: yapf +Short Name: yapf +URL: https://github.com/google/yapf +Date: 28 May 2017 +Version: 0.16.2 +Revision: 9f168a12 +License: Apache 2.0 +License File: LICENSE + +Description: +A formatter for Python files. + +Local Modifications: +None diff --git a/lib/jcef/tools/yapf/__main__.py b/lib/jcef/tools/yapf/__main__.py new file mode 100644 index 0000000..88f1ec6 --- /dev/null +++ b/lib/jcef/tools/yapf/__main__.py @@ -0,0 +1,16 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import yapf + +yapf.run_main() diff --git a/lib/jcef/tools/yapf/yapf/__init__.py b/lib/jcef/tools/yapf/yapf/__init__.py new file mode 100644 index 0000000..9258052 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/__init__.py @@ -0,0 +1,303 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""YAPF. + +YAPF uses the algorithm in clang-format to figure out the "best" formatting for +Python code. It looks at the program as a series of "unwrappable lines" --- +i.e., lines which, if there were no column limit, we would place all tokens on +that line. It then uses a priority queue to figure out what the best formatting +is --- i.e., the formatting with the least penalty. + +It differs from tools like autopep8 and pep8ify in that it doesn't just look for +violations of the style guide, but looks at the module as a whole, making +formatting decisions based on what's the best format for each line. + +If no filenames are specified, YAPF reads the code from stdin. +""" +from __future__ import print_function + +import argparse +import logging +import os +import sys + +from yapf.yapflib import errors +from yapf.yapflib import file_resources +from yapf.yapflib import py3compat +from yapf.yapflib import style +from yapf.yapflib import yapf_api + +__version__ = '0.16.2' + + +def main(argv): + """Main program. + + Arguments: + argv: command-line arguments, such as sys.argv (including the program name + in argv[0]). + + Returns: + 0 if there were no changes, non-zero otherwise. + + Raises: + YapfError: if none of the supplied files were Python files. + """ + parser = argparse.ArgumentParser(description='Formatter for Python code.') + parser.add_argument( + '-v', + '--version', + action='store_true', + help='show version number and exit') + + diff_inplace_group = parser.add_mutually_exclusive_group() + diff_inplace_group.add_argument( + '-d', + '--diff', + action='store_true', + help='print the diff for the fixed source') + diff_inplace_group.add_argument( + '-i', + '--in-place', + action='store_true', + help='make changes to files in place') + + lines_recursive_group = parser.add_mutually_exclusive_group() + lines_recursive_group.add_argument( + '-r', + '--recursive', + action='store_true', + help='run recursively over directories') + lines_recursive_group.add_argument( + '-l', + '--lines', + metavar='START-END', + action='append', + default=None, + help='range of lines to reformat, one-based') + + parser.add_argument( + '-e', + '--exclude', + metavar='PATTERN', + action='append', + default=None, + help='patterns for files to exclude from formatting') + parser.add_argument( + '--style', + action='store', + help=('specify formatting style: either a style name (for example "pep8" ' + 'or "google"), or the name of a file with style settings. The ' + 'default is pep8 unless a %s or %s file located in one of the ' + 'parent directories of the source file (or current directory for ' + 'stdin)' % (style.LOCAL_STYLE, style.SETUP_CONFIG))) + parser.add_argument( + '--style-help', + action='store_true', + help=('show style settings and exit; this output can be ' + 'saved to .style.yapf to make your settings ' + 'permanent')) + parser.add_argument( + '--no-local-style', + action='store_true', + help="don't search for local style definition") + parser.add_argument('--verify', action='store_true', help=argparse.SUPPRESS) + parser.add_argument( + '-p', + '--parallel', + action='store_true', + help=('Run yapf in parallel when formatting multiple files. Requires ' + 'concurrent.futures in Python 2.X')) + + parser.add_argument('files', nargs='*') + args = parser.parse_args(argv[1:]) + + if args.version: + print('yapf {}'.format(__version__)) + return 0 + + if args.style_help: + style.SetGlobalStyle(style.CreateStyleFromConfig(args.style)) + print('[style]') + for option, docstring in sorted(style.Help().items()): + for line in docstring.splitlines(): + print('#', line and ' ' or '', line, sep='') + print(option.lower(), '=', style.Get(option), sep='') + print() + return 0 + + if args.lines and len(args.files) > 1: + parser.error('cannot use -l/--lines with more than one file') + + lines = _GetLines(args.lines) if args.lines is not None else None + if not args.files: + # No arguments specified. Read code from stdin. + if args.in_place or args.diff: + parser.error('cannot use --in-place or --diff flags when reading ' + 'from stdin') + + original_source = [] + while True: + try: + # Use 'raw_input' instead of 'sys.stdin.read', because otherwise the + # user will need to hit 'Ctrl-D' more than once if they're inputting + # the program by hand. 'raw_input' throws an EOFError exception if + # 'Ctrl-D' is pressed, which makes it easy to bail out of this loop. + original_source.append(py3compat.raw_input()) + except EOFError: + break + + style_config = args.style + if style_config is None and not args.no_local_style: + style_config = file_resources.GetDefaultStyleForDir(os.getcwd()) + + source = [line.rstrip() for line in original_source] + reformatted_source, _ = yapf_api.FormatCode( + py3compat.unicode('\n'.join(source) + '\n'), + filename='', + style_config=style_config, + lines=lines, + verify=args.verify) + file_resources.WriteReformattedCode('', reformatted_source) + return 0 + + files = file_resources.GetCommandLineFiles(args.files, args.recursive, + args.exclude) + if not files: + raise errors.YapfError('Input filenames did not match any python files') + + FormatFiles( + files, + lines, + style_config=args.style, + no_local_style=args.no_local_style, + in_place=args.in_place, + print_diff=args.diff, + verify=args.verify, + parallel=args.parallel) + return 0 + + +def FormatFiles(filenames, + lines, + style_config=None, + no_local_style=False, + in_place=False, + print_diff=False, + verify=True, + parallel=False): + """Format a list of files. + + Arguments: + filenames: (list of unicode) A list of files to reformat. + lines: (list of tuples of integers) A list of tuples of lines, [start, end], + that we want to format. The lines are 1-based indexed. This argument + overrides the 'args.lines'. It can be used by third-party code (e.g., + IDEs) when reformatting a snippet of code. + style_config: (string) Style name or file path. + no_local_style: (string) If style_config is None don't search for + directory-local style configuration. + in_place: (bool) Modify the files in place. + print_diff: (bool) Instead of returning the reformatted source, return a + diff that turns the formatted source into reformatter source. + verify: (bool) True if reformatted code should be verified for syntax. + parallel: (bool) True if should format multiple files in parallel. + + Returns: + True if the source code changed in any of the files being formatted. + """ + changed = False + if parallel: + import multiprocessing # pylint: disable=g-import-not-at-top + import concurrent.futures # pylint: disable=g-import-not-at-top + workers = min(multiprocessing.cpu_count(), len(filenames)) + with concurrent.futures.ProcessPoolExecutor(workers) as executor: + future_formats = [ + executor.submit(_FormatFile, filename, lines, style_config, + no_local_style, in_place, print_diff, verify) + for filename in filenames + ] + for future in concurrent.futures.as_completed(future_formats): + changed |= future.result() + else: + for filename in filenames: + changed |= _FormatFile(filename, lines, style_config, no_local_style, + in_place, print_diff, verify) + return changed + + +def _FormatFile(filename, + lines, + style_config=None, + no_local_style=False, + in_place=False, + print_diff=False, + verify=True): + logging.info('Reformatting %s', filename) + if style_config is None and not no_local_style: + style_config = ( + file_resources.GetDefaultStyleForDir(os.path.dirname(filename))) + try: + reformatted_code, encoding, has_change = yapf_api.FormatFile( + filename, + in_place=in_place, + style_config=style_config, + lines=lines, + print_diff=print_diff, + verify=verify, + logger=logging.warning) + if not in_place and reformatted_code: + file_resources.WriteReformattedCode(filename, reformatted_code, in_place, + encoding) + return has_change + except SyntaxError as e: + e.filename = filename + raise + + +def _GetLines(line_strings): + """Parses the start and end lines from a line string like 'start-end'. + + Arguments: + line_strings: (array of string) A list of strings representing a line + range like 'start-end'. + + Returns: + A list of tuples of the start and end line numbers. + + Raises: + ValueError: If the line string failed to parse or was an invalid line range. + """ + lines = [] + for line_string in line_strings: + # The 'list' here is needed by Python 3. + line = list(map(int, line_string.split('-', 1))) + if line[0] < 1: + raise errors.YapfError('invalid start of line range: %r' % line) + if line[0] > line[1]: + raise errors.YapfError('end comes before start in line range: %r', line) + lines.append(tuple(line)) + return lines + + +def run_main(): # pylint: disable=invalid-name + try: + sys.exit(main(sys.argv)) + except errors.YapfError as e: + sys.stderr.write('yapf: ' + str(e) + '\n') + sys.exit(1) + + +if __name__ == '__main__': + run_main() diff --git a/lib/jcef/tools/yapf/yapf/yapflib/__init__.py b/lib/jcef/tools/yapf/yapf/yapflib/__init__.py new file mode 100644 index 0000000..80217ac --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/lib/jcef/tools/yapf/yapf/yapflib/blank_line_calculator.py b/lib/jcef/tools/yapf/yapf/yapflib/blank_line_calculator.py new file mode 100644 index 0000000..bcd7a86 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/blank_line_calculator.py @@ -0,0 +1,183 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Calculate the number of blank lines between top-level entities. + +Calculates how many blank lines we need between classes, functions, and other +entities at the same level. + + CalculateBlankLines(): the main function exported by this module. + +Annotations: + newlines: The number of newlines required before the node. +""" + +from lib2to3 import pytree + +from yapf.yapflib import py3compat +from yapf.yapflib import pytree_utils +from yapf.yapflib import pytree_visitor + +_NO_BLANK_LINES = 1 +_ONE_BLANK_LINE = 2 +_TWO_BLANK_LINES = 3 + +_PYTHON_STATEMENTS = frozenset({ + 'small_stmt', 'expr_stmt', 'print_stmt', 'del_stmt', 'pass_stmt', + 'break_stmt', 'continue_stmt', 'return_stmt', 'raise_stmt', 'yield_stmt', + 'import_stmt', 'global_stmt', 'exec_stmt', 'assert_stmt', 'if_stmt', + 'while_stmt', 'for_stmt', 'try_stmt', 'with_stmt', 'nonlocal_stmt', + 'async_stmt', 'simple_stmt' +}) + + +def CalculateBlankLines(tree): + """Run the blank line calculator visitor over the tree. + + This modifies the tree in place. + + Arguments: + tree: the top-level pytree node to annotate with subtypes. + """ + blank_line_calculator = _BlankLineCalculator() + blank_line_calculator.Visit(tree) + + +class _BlankLineCalculator(pytree_visitor.PyTreeVisitor): + """_BlankLineCalculator - see file-level docstring for a description.""" + + def __init__(self): + self.class_level = 0 + self.function_level = 0 + self.last_comment_lineno = 0 + self.last_was_decorator = False + self.last_was_class_or_function = False + + def Visit_simple_stmt(self, node): # pylint: disable=invalid-name + self.DefaultNodeVisit(node) + if pytree_utils.NodeName(node.children[0]) == 'COMMENT': + self.last_comment_lineno = node.children[0].lineno + + def Visit_decorator(self, node): # pylint: disable=invalid-name + if (self.last_comment_lineno and + self.last_comment_lineno == node.children[0].lineno - 1): + self._SetNumNewlines(node.children[0], _NO_BLANK_LINES) + else: + self._SetNumNewlines(node.children[0], self._GetNumNewlines(node)) + for child in node.children: + self.Visit(child) + self.last_was_decorator = True + + def Visit_classdef(self, node): # pylint: disable=invalid-name + self.last_was_class_or_function = False + index = self._SetBlankLinesBetweenCommentAndClassFunc(node) + self.last_was_decorator = False + self.class_level += 1 + for child in node.children[index:]: + self.Visit(child) + self.class_level -= 1 + self.last_was_class_or_function = True + + def Visit_funcdef(self, node): # pylint: disable=invalid-name + self.last_was_class_or_function = False + index = self._SetBlankLinesBetweenCommentAndClassFunc(node) + if _AsyncFunction(node): + index = self._SetBlankLinesBetweenCommentAndClassFunc( + node.prev_sibling.parent) + self._SetNumNewlines(node.children[0], None) + else: + index = self._SetBlankLinesBetweenCommentAndClassFunc(node) + self.last_was_decorator = False + self.function_level += 1 + for child in node.children[index:]: + self.Visit(child) + self.function_level -= 1 + self.last_was_class_or_function = True + + def DefaultNodeVisit(self, node): + """Override the default visitor for Node. + + This will set the blank lines required if the last entity was a class or + function. + + Arguments: + node: (pytree.Node) The node to visit. + """ + if self.last_was_class_or_function: + if pytree_utils.NodeName(node) in _PYTHON_STATEMENTS: + leaf = _GetFirstChildLeaf(node) + self._SetNumNewlines(leaf, self._GetNumNewlines(leaf)) + self.last_was_class_or_function = False + super(_BlankLineCalculator, self).DefaultNodeVisit(node) + + def _SetBlankLinesBetweenCommentAndClassFunc(self, node): + """Set the number of blanks between a comment and class or func definition. + + Class and function definitions have leading comments as children of the + classdef and functdef nodes. + + Arguments: + node: (pytree.Node) The classdef or funcdef node. + + Returns: + The index of the first child past the comment nodes. + """ + index = 0 + while pytree_utils.IsCommentStatement(node.children[index]): + # Standalone comments are wrapped in a simple_stmt node with the comment + # node as its only child. + self.Visit(node.children[index].children[0]) + if not self.last_was_decorator: + self._SetNumNewlines(node.children[index].children[0], _ONE_BLANK_LINE) + index += 1 + if (index and node.children[index].lineno - + 1 == node.children[index - 1].children[0].lineno): + self._SetNumNewlines(node.children[index], _NO_BLANK_LINES) + else: + if self.last_comment_lineno + 1 == node.children[index].lineno: + num_newlines = _NO_BLANK_LINES + else: + num_newlines = self._GetNumNewlines(node) + self._SetNumNewlines(node.children[index], num_newlines) + return index + + def _GetNumNewlines(self, node): + if self.last_was_decorator: + return _NO_BLANK_LINES + elif self._IsTopLevel(node): + return _TWO_BLANK_LINES + return _ONE_BLANK_LINE + + def _SetNumNewlines(self, node, num_newlines): + pytree_utils.SetNodeAnnotation(node, pytree_utils.Annotation.NEWLINES, + num_newlines) + + def _IsTopLevel(self, node): + return (not (self.class_level or self.function_level) and + _StartsInZerothColumn(node)) + + +def _StartsInZerothColumn(node): + return (_GetFirstChildLeaf(node).column == 0 or + (_AsyncFunction(node) and node.prev_sibling.column == 0)) + + +def _AsyncFunction(node): + return (py3compat.PY3 and node.prev_sibling and + pytree_utils.NodeName(node.prev_sibling) == 'ASYNC') + + +def _GetFirstChildLeaf(node): + if isinstance(node, pytree.Leaf): + return node + return _GetFirstChildLeaf(node.children[0]) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/comment_splicer.py b/lib/jcef/tools/yapf/yapf/yapflib/comment_splicer.py new file mode 100644 index 0000000..7c79e80 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/comment_splicer.py @@ -0,0 +1,374 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Comment splicer for lib2to3 trees. + +The lib2to3 syntax tree produced by the parser holds comments and whitespace in +prefix attributes of nodes, rather than nodes themselves. This module provides +functionality to splice comments out of prefixes and into nodes of their own, +making them easier to process. + + SpliceComments(): the main function exported by this module. +""" + +from lib2to3 import pygram +from lib2to3 import pytree +from lib2to3.pgen2 import token + +from yapf.yapflib import pytree_utils + + +def SpliceComments(tree): + """Given a pytree, splice comments into nodes of their own right. + + Extract comments from the prefixes where they are housed after parsing. + The prefixes that previously housed the comments become empty. + + Args: + tree: a pytree.Node - the tree to work on. The tree is modified by this + function. + """ + # The previous leaf node encountered in the traversal. + # This is a list because Python 2.x doesn't have 'nonlocal' :) + prev_leaf = [None] + _AnnotateIndents(tree) + + def _VisitNodeRec(node): + # This loop may insert into node.children, so we'll iterate over a copy. + for child in node.children[:]: + if isinstance(child, pytree.Node): + # Nodes don't have prefixes. + _VisitNodeRec(child) + else: + if child.prefix.lstrip().startswith('#'): + # We have a comment prefix in this child, so splicing is needed. + comment_prefix = child.prefix + comment_lineno = child.lineno - comment_prefix.count('\n') + comment_column = child.column + + # Remember the leading indentation of this prefix and clear it. + # Mopping up the prefix is important because we may go over this same + # child in the next iteration... + child_prefix = child.prefix.lstrip('\n') + prefix_indent = child_prefix[:child_prefix.find('#')] + if '\n' in prefix_indent: + prefix_indent = prefix_indent[prefix_indent.rfind('\n') + 1:] + child.prefix = '' + + if child.type == token.NEWLINE: + # If the prefix was on a NEWLINE leaf, it's part of the line so it + # will be inserted after the previously encountered leaf. + # We can't just insert it before the NEWLINE node, because as a + # result of the way pytrees are organized, this node can be under + # an inappropriate parent. + comment_column -= len(comment_prefix) + comment_column += len(comment_prefix) - len(comment_prefix.lstrip()) + pytree_utils.InsertNodesAfter( + _CreateCommentsFromPrefix( + comment_prefix, + comment_lineno, + comment_column, + standalone=False), prev_leaf[0]) + elif child.type == token.DEDENT: + # Comment prefixes on DEDENT nodes also deserve special treatment, + # because their final placement depends on their prefix. + # We'll look for an ancestor of this child with a matching + # indentation, and insert the comment after it. + ancestor_at_indent = _FindAncestorAtIndent(child, prefix_indent) + if ancestor_at_indent.type == token.DEDENT: + comments = comment_prefix.split('\n') + + # lib2to3 places comments that should be separated into the same + # DEDENT node. For example, "comment 1" and "comment 2" will be + # combined. + # + # def _(): + # for x in y: + # pass + # # comment 1 + # + # # comment 2 + # pass + # + # In this case, we need to split them up ourselves. + before = [] + after = [] + after_lineno = comment_lineno + + index = 0 + while index < len(comments): + cmt = comments[index] + if not cmt.strip() or cmt.startswith(prefix_indent + '#'): + before.append(cmt) + else: + after_lineno += index + after.extend(comments[index:]) + break + index += 1 + + # Special case where the comment is inserted in the same + # indentation level as the DEDENT it was originally attached to. + pytree_utils.InsertNodesBefore( + _CreateCommentsFromPrefix( + '\n'.join(before) + '\n', + comment_lineno, + comment_column, + standalone=True), ancestor_at_indent) + if after: + after_column = len(after[0]) - len(after[0].lstrip()) + comment_column -= comment_column - after_column + pytree_utils.InsertNodesAfter( + _CreateCommentsFromPrefix( + '\n'.join(after) + '\n', + after_lineno, + comment_column, + standalone=True), _FindNextAncestor(ancestor_at_indent)) + else: + pytree_utils.InsertNodesAfter( + _CreateCommentsFromPrefix( + comment_prefix, + comment_lineno, + comment_column, + standalone=True), ancestor_at_indent) + else: + # Otherwise there are two cases. + # + # 1. The comment is on its own line + # 2. The comment is part of an expression. + # + # Unfortunately, it's fairly difficult to distinguish between the + # two in lib2to3 trees. The algorithm here is to determine whether + # child is the first leaf in the statement it belongs to. If it is, + # then the comment (which is a prefix) belongs on a separate line. + # If it is not, it means the comment is buried deep in the statement + # and is part of some expression. + stmt_parent = _FindStmtParent(child) + + for leaf_in_parent in stmt_parent.leaves(): + if leaf_in_parent.type == token.NEWLINE: + continue + elif id(leaf_in_parent) == id(child): + # This comment stands on its own line, and it has to be inserted + # into the appropriate parent. We'll have to find a suitable + # parent to insert into. See comments above + # _STANDALONE_LINE_NODES for more details. + node_with_line_parent = _FindNodeWithStandaloneLineParent(child) + pytree_utils.InsertNodesBefore( + _CreateCommentsFromPrefix( + comment_prefix, comment_lineno, 0, standalone=True), + node_with_line_parent) + break + else: + if comment_lineno == prev_leaf[0].lineno: + comment_lines = comment_prefix.splitlines() + value = comment_lines[0].lstrip() + if value.rstrip('\n'): + comment_column = prev_leaf[0].column + comment_column += len(prev_leaf[0].value) + comment_column += ( + len(comment_lines[0]) - len(comment_lines[0].lstrip())) + comment_leaf = pytree.Leaf( + type=token.COMMENT, + value=value.rstrip('\n'), + context=('', (comment_lineno, comment_column))) + pytree_utils.InsertNodesAfter([comment_leaf], prev_leaf[0]) + comment_prefix = '\n'.join(comment_lines[1:]) + comment_lineno += 1 + + rindex = (0 if '\n' not in comment_prefix.rstrip() else + comment_prefix.rstrip().rindex('\n') + 1) + comment_column = (len(comment_prefix[rindex:]) - + len(comment_prefix[rindex:].lstrip())) + comments = _CreateCommentsFromPrefix( + comment_prefix, + comment_lineno, + comment_column, + standalone=False) + pytree_utils.InsertNodesBefore(comments, child) + break + + prev_leaf[0] = child + + _VisitNodeRec(tree) + + +def _CreateCommentsFromPrefix(comment_prefix, + comment_lineno, + comment_column, + standalone=False): + """Create pytree nodes to represent the given comment prefix. + + Args: + comment_prefix: (unicode) the text of the comment from the node's prefix. + comment_lineno: (int) the line number for the start of the comment. + comment_column: (int) the column for the start of the comment. + standalone: (bool) determines if the comment is standalone or not. + + Returns: + The simple_stmt nodes if this is a standalone comment, otherwise a list of + new COMMENT leafs. The prefix may consist of multiple comment blocks, + separated by blank lines. Each block gets its own leaf. + """ + # The comment is stored in the prefix attribute, with no lineno of its + # own. So we only know at which line it ends. To find out at which line it + # starts, look at how many newlines the comment itself contains. + comments = [] + + lines = comment_prefix.split('\n') + index = 0 + while index < len(lines): + comment_block = [] + while index < len(lines) and lines[index].lstrip().startswith('#'): + comment_block.append(lines[index].strip()) + index += 1 + + if comment_block: + new_lineno = comment_lineno + index - 1 + comment_block[0] = comment_block[0].strip() + comment_block[-1] = comment_block[-1].strip() + comment_leaf = pytree.Leaf( + type=token.COMMENT, + value='\n'.join(comment_block), + context=('', (new_lineno, comment_column))) + comment_node = comment_leaf if not standalone else pytree.Node( + pygram.python_symbols.simple_stmt, [comment_leaf]) + comments.append(comment_node) + + while index < len(lines) and not lines[index].lstrip(): + index += 1 + + return comments + + +# "Standalone line nodes" are tree nodes that have to start a new line in Python +# code (and cannot follow a ';' or ':'). Other nodes, like 'expr_stmt', serve as +# parents of other nodes but can come later in a line. This is a list of +# standalone line nodes in the grammar. It is meant to be exhaustive +# *eventually*, and we'll modify it with time as we discover more corner cases +# in the parse tree. +# +# When splicing a standalone comment (i.e. a comment that appears on its own +# line, not on the same line with other code), it's important to insert it into +# an appropriate parent of the node it's attached to. An appropriate parent +# is the first "standaline line node" in the parent chain of a node. +_STANDALONE_LINE_NODES = frozenset([ + 'suite', 'if_stmt', 'while_stmt', 'for_stmt', 'try_stmt', 'with_stmt', + 'funcdef', 'classdef', 'decorated', 'file_input' +]) + + +def _FindNodeWithStandaloneLineParent(node): + """Find a node whose parent is a 'standalone line' node. + + See the comment above _STANDALONE_LINE_NODES for more details. + + Arguments: + node: node to start from + + Returns: + Suitable node that's either the node itself or one of its ancestors. + """ + if pytree_utils.NodeName(node.parent) in _STANDALONE_LINE_NODES: + return node + else: + # This is guaranteed to terminate because 'file_input' is the root node of + # any pytree. + return _FindNodeWithStandaloneLineParent(node.parent) + + +# "Statement nodes" are standalone statements. The don't have to start a new +# line. +_STATEMENT_NODES = frozenset(['simple_stmt']) | _STANDALONE_LINE_NODES + + +def _FindStmtParent(node): + """Find the nearest parent of node that is a statement node. + + Arguments: + node: node to start from + + Returns: + Nearest parent (or node itself, if suitable). + """ + if pytree_utils.NodeName(node) in _STATEMENT_NODES: + return node + else: + return _FindStmtParent(node.parent) + + +def _FindAncestorAtIndent(node, indent): + """Find an ancestor of node with the given indentation. + + Arguments: + node: node to start from. This must not be the tree root. + indent: indentation string for the ancestor we're looking for. + See _AnnotateIndents for more details. + + Returns: + An ancestor node with suitable indentation. If no suitable ancestor is + found, the closest ancestor to the tree root is returned. + """ + if node.parent.parent is None: + # Our parent is the tree root, so there's nowhere else to go. + return node + + # If the parent has an indent annotation, and it's shorter than node's + # indent, this is a suitable ancestor. + # The reason for "shorter" rather than "equal" is that comments may be + # improperly indented (i.e. by three spaces, where surrounding statements + # have either zero or two or four), and we don't want to propagate them all + # the way to the root. + parent_indent = pytree_utils.GetNodeAnnotation( + node.parent, pytree_utils.Annotation.CHILD_INDENT) + if parent_indent is not None and indent.startswith(parent_indent): + return node + else: + # Keep looking up the tree. + return _FindAncestorAtIndent(node.parent, indent) + + +def _FindNextAncestor(node): + if node.parent is None: + return node + + if node.parent.next_sibling is not None: + return node.parent.next_sibling + + return _FindNextAncestor(node.parent) + + +def _AnnotateIndents(tree): + """Annotate the tree with child_indent annotations. + + A child_indent annotation on a node specifies the indentation (as a string, + like " ") of its children. It is inferred from the INDENT child of a node. + + Arguments: + tree: root of a pytree. The pytree is modified to add annotations to nodes. + + Raises: + RuntimeError: if the tree is malformed. + """ + # Annotate the root of the tree with zero indent. + if tree.parent is None: + pytree_utils.SetNodeAnnotation(tree, pytree_utils.Annotation.CHILD_INDENT, + '') + for child in tree.children: + if child.type == token.INDENT: + child_indent = pytree_utils.GetNodeAnnotation( + tree, pytree_utils.Annotation.CHILD_INDENT) + if child_indent is not None and child_indent != child.value: + raise RuntimeError('inconsistent indentation for child', (tree, child)) + pytree_utils.SetNodeAnnotation(tree, pytree_utils.Annotation.CHILD_INDENT, + child.value) + _AnnotateIndents(child) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/continuation_splicer.py b/lib/jcef/tools/yapf/yapf/yapflib/continuation_splicer.py new file mode 100644 index 0000000..74ea1a0 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/continuation_splicer.py @@ -0,0 +1,52 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Insert "continuation" nodes into lib2to3 tree. + +The "backslash-newline" continuation marker is shoved into the node's prefix. +Pull them out and make it into nodes of their own. + + SpliceContinuations(): the main funciton exported by this module. +""" + +from lib2to3 import pytree + +from yapf.yapflib import format_token + + +def SpliceContinuations(tree): + """Given a pytree, splice the continuation marker into nodes. + + Arguments: + tree: (pytree.Node) The tree to work on. The tree is modified by this + function. + """ + + def RecSplicer(node): + """Inserts a continuation marker into the node.""" + if isinstance(node, pytree.Leaf): + if node.prefix.lstrip().startswith('\\\n'): + new_lineno = node.lineno - node.prefix.count('\n') + return pytree.Leaf( + type=format_token.CONTINUATION, + value=node.prefix, + context=('', (new_lineno, 0))) + return None + num_inserted = 0 + for index, child in enumerate(node.children[:]): + continuation_node = RecSplicer(child) + if continuation_node: + node.children.insert(index + num_inserted, continuation_node) + num_inserted += 1 + + RecSplicer(tree) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/errors.py b/lib/jcef/tools/yapf/yapf/yapflib/errors.py new file mode 100644 index 0000000..aa8f3ea --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/errors.py @@ -0,0 +1,23 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""YAPF error object.""" + + +class YapfError(Exception): + """Parent class for user errors or input errors. + + Exceptions of this type are handled by the command line tool + and result in clear error messages, as opposed to backtraces. + """ + pass diff --git a/lib/jcef/tools/yapf/yapf/yapflib/file_resources.py b/lib/jcef/tools/yapf/yapf/yapflib/file_resources.py new file mode 100644 index 0000000..e7f9acd --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/file_resources.py @@ -0,0 +1,169 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Interface to file resources. + +This module provides functions for interfacing with files: opening, writing, and +querying. +""" + +import fnmatch +import os +import re + +from lib2to3.pgen2 import tokenize + +from yapf.yapflib import errors +from yapf.yapflib import py3compat +from yapf.yapflib import style + +CR = '\r' +LF = '\n' +CRLF = '\r\n' + + +def GetDefaultStyleForDir(dirname): + """Return default style name for a given directory. + + Looks for .style.yapf or setup.cfg in the parent directories. + + Arguments: + dirname: (unicode) The name of the directory. + + Returns: + The filename if found, otherwise return the global default (pep8). + """ + dirname = os.path.abspath(dirname) + while True: + # See if we have a .style.yapf file. + style_file = os.path.join(dirname, style.LOCAL_STYLE) + if os.path.exists(style_file): + return style_file + + # See if we have a setup.cfg file with a '[yapf]' section. + config_file = os.path.join(dirname, style.SETUP_CONFIG) + if os.path.exists(config_file): + with open(config_file) as fd: + config = py3compat.ConfigParser() + config.read_file(fd) + if config.has_section('yapf'): + return config_file + + dirname = os.path.dirname(dirname) + if (not dirname or not os.path.basename(dirname) or + dirname == os.path.abspath(os.path.sep)): + break + + global_file = os.path.expanduser(style.GLOBAL_STYLE) + if os.path.exists(global_file): + return global_file + + return style.DEFAULT_STYLE + + +def GetCommandLineFiles(command_line_file_list, recursive, exclude): + """Return the list of files specified on the command line.""" + return _FindPythonFiles(command_line_file_list, recursive, exclude) + + +def WriteReformattedCode(filename, + reformatted_code, + in_place=False, + encoding=''): + """Emit the reformatted code. + + Write the reformatted code into the file, if in_place is True. Otherwise, + write to stdout. + + Arguments: + filename: (unicode) The name of the unformatted file. + reformatted_code: (unicode) The reformatted code. + in_place: (bool) If True, then write the reformatted code to the file. + encoding: (unicode) The encoding of the file. + """ + if in_place: + with py3compat.open_with_encoding( + filename, mode='w', encoding=encoding, newline='') as fd: + fd.write(reformatted_code) + else: + py3compat.EncodeAndWriteToStdout(reformatted_code) + + +def LineEnding(lines): + """Retrieve the line ending of the original source.""" + endings = {CRLF: 0, CR: 0, LF: 0} + for line in lines: + if line.endswith(CRLF): + endings[CRLF] += 1 + elif line.endswith(CR): + endings[CR] += 1 + elif line.endswith(LF): + endings[LF] += 1 + return (sorted(endings, key=endings.get, reverse=True) or [LF])[0] + + +def _FindPythonFiles(filenames, recursive, exclude): + """Find all Python files.""" + python_files = [] + for filename in filenames: + if os.path.isdir(filename): + if recursive: + # TODO(morbo): Look into a version of os.walk that can handle recursion. + python_files.extend( + os.path.join(dirpath, f) + for dirpath, _, filelist in os.walk(filename) for f in filelist + if IsPythonFile(os.path.join(dirpath, f))) + else: + raise errors.YapfError( + "directory specified without '--recursive' flag: %s" % filename) + elif os.path.isfile(filename): + python_files.append(filename) + + if exclude: + return [ + f for f in python_files + if not any(fnmatch.fnmatch(f, p) for p in exclude) + ] + + return python_files + + +def IsPythonFile(filename): + """Return True if filename is a Python file.""" + if os.path.splitext(filename)[1] == '.py': + return True + + try: + with open(filename, 'rb') as fd: + encoding = tokenize.detect_encoding(fd.readline)[0] + + # Check for correctness of encoding. + with py3compat.open_with_encoding( + filename, mode='r', encoding=encoding) as fd: + fd.read() + except UnicodeDecodeError: + encoding = 'latin-1' + except (IOError, SyntaxError): + # If we fail to detect encoding (or the encoding cookie is incorrect - which + # will make detect_encoding raise SyntaxError), assume it's not a Python + # file. + return False + + try: + with py3compat.open_with_encoding( + filename, mode='r', encoding=encoding) as fd: + first_line = fd.readlines()[0] + except (IOError, IndexError): + return False + + return re.match(r'^#!.*\bpython[23]?\b', first_line) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/format_decision_state.py b/lib/jcef/tools/yapf/yapf/yapflib/format_decision_state.py new file mode 100644 index 0000000..3c17dc4 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/format_decision_state.py @@ -0,0 +1,799 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Implements a format decision state object that manages whitespace decisions. + +Each token is processed one at a time, at which point its whitespace formatting +decisions are made. A graph of potential whitespace formattings is created, +where each node in the graph is a format decision state object. The heuristic +tries formatting the token with and without a newline before it to determine +which one has the least penalty. Therefore, the format decision state object for +each decision needs to be its own unique copy. + +Once the heuristic determines the best formatting, it makes a non-dry run pass +through the code to commit the whitespace formatting. + + FormatDecisionState: main class exported by this module. +""" + +from yapf.yapflib import format_token +from yapf.yapflib import split_penalty +from yapf.yapflib import style +from yapf.yapflib import unwrapped_line + +_COMPOUND_STMTS = frozenset( + {'for', 'while', 'if', 'elif', 'with', 'except', 'def', 'class'}) + + +class FormatDecisionState(object): + """The current state when indenting an unwrapped line. + + The FormatDecisionState object is meant to be copied instead of referenced. + + Attributes: + first_indent: The indent of the first token. + column: The number of used columns in the current line. + next_token: The next token to be formatted. + paren_level: The level of nesting inside (), [], and {}. + start_of_line_level: The paren_level at the start of this line. + lowest_level_on_line: The lowest paren_level on the current line. + newline: Indicates if a newline is added along the edge to this format + decision state node. + previous: The previous format decision state in the decision tree. + stack: A stack (of _ParenState) keeping track of properties applying to + parenthesis levels. + ignore_stack_for_comparison: Ignore the stack of _ParenState for state + comparison. + """ + + def __init__(self, line, first_indent): + """Initializer. + + Initializes to the state after placing the first token from 'line' at + 'first_indent'. + + Arguments: + line: (UnwrappedLine) The unwrapped line we're currently processing. + first_indent: (int) The indent of the first token. + """ + self.next_token = line.first + self.column = first_indent + self.line = line + self.paren_level = 0 + self.start_of_line_level = 0 + self.lowest_level_on_line = 0 + self.ignore_stack_for_comparison = False + self.stack = [_ParenState(first_indent, first_indent)] + self.first_indent = first_indent + self.newline = False + self.previous = None + self.column_limit = style.Get('COLUMN_LIMIT') + + def Clone(self): + """Clones a FormatDecisionState object.""" + new = FormatDecisionState(self.line, self.first_indent) + new.next_token = self.next_token + new.column = self.column + new.line = self.line + new.paren_level = self.paren_level + new.start_of_line_level = self.start_of_line_level + new.lowest_level_on_line = self.lowest_level_on_line + new.ignore_stack_for_comparison = self.ignore_stack_for_comparison + new.first_indent = self.first_indent + new.newline = self.newline + new.previous = self.previous + new.stack = [state.Clone() for state in self.stack] + return new + + def __eq__(self, other): + # Note: 'first_indent' is implicit in the stack. Also, we ignore 'previous', + # because it shouldn't have a bearing on this comparison. (I.e., it will + # report equal if 'next_token' does.) + return (self.next_token == other.next_token and + self.column == other.column and + self.paren_level == other.paren_level and + self.start_of_line_level == other.start_of_line_level and + self.lowest_level_on_line == other.lowest_level_on_line and + (self.ignore_stack_for_comparison or + other.ignore_stack_for_comparison or self.stack == other.stack)) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.next_token, self.column, self.paren_level, + self.start_of_line_level, self.lowest_level_on_line)) + + def __repr__(self): + return ('column::%d, next_token::%s, paren_level::%d, stack::[\n\t%s' % + (self.column, repr(self.next_token), self.paren_level, + '\n\t'.join(repr(s) for s in self.stack) + ']')) + + def CanSplit(self, must_split): + """Determine if we can split before the next token. + + Arguments: + must_split: (bool) A newline was required before this token. + + Returns: + True if the line can be split before the next token. + """ + current = self.next_token + + if current.is_pseudo_paren: + return False + + if (not must_split and + format_token.Subtype.DICTIONARY_KEY_PART in current.subtypes and + format_token.Subtype.DICTIONARY_KEY not in current.subtypes and + not style.Get('ALLOW_MULTILINE_DICTIONARY_KEYS')): + # In some situations, a dictionary may be multiline, but pylint doesn't + # like it. So don't allow it unless forced to. + return False + + return current.can_break_before + + def MustSplit(self): + """Returns True if the line must split before the next token.""" + current = self.next_token + previous = current.previous_token + + if current.is_pseudo_paren: + return False + + if current.must_break_before: + return True + + if not previous: + return False + + if self.stack[-1].split_before_closing_bracket and current.value in '}]': + # Split before the closing bracket if we can. + return current.node_split_penalty != split_penalty.UNBREAKABLE + + # Prevent splitting before the first argument in compound statements + # with the exception of function declarations. + if (style.Get('SPLIT_BEFORE_FIRST_ARGUMENT') and + self.line.first.value != 'def' and + self.line.first.value in _COMPOUND_STMTS): + return False + + ########################################################################### + # List Splitting + if (style.Get('DEDENT_CLOSING_BRACKETS') or + style.Get('SPLIT_BEFORE_FIRST_ARGUMENT')): + bracket = current if current.ClosesScope() else previous + if format_token.Subtype.SUBSCRIPT_BRACKET not in bracket.subtypes: + if bracket.OpensScope(): + if style.Get('COALESCE_BRACKETS'): + if current.OpensScope(): + # Prefer to keep all opening brackets together. + return False + + if (not _IsLastScopeInLine(bracket) or + unwrapped_line.IsSurroundedByBrackets(bracket)): + last_token = bracket.matching_bracket + else: + last_token = _LastTokenInLine(bracket.matching_bracket) + + if not self._FitsOnLine(bracket, last_token): + # Split before the first element if the whole list can't fit on a + # single line. + self.stack[-1].split_before_closing_bracket = True + return True + + elif style.Get('DEDENT_CLOSING_BRACKETS') and current.ClosesScope(): + # Split before and dedent the closing bracket. + return self.stack[-1].split_before_closing_bracket + + if (current.is_name or current.is_string) and previous.value == ',': + # If the list has function calls in it and the full list itself cannot + # fit on the line, then we want to split. Otherwise, we'll get something + # like this: + # + # X = [ + # Bar(xxx='some string', + # yyy='another long string', + # zzz='a third long string'), Bar( + # xxx='some string', + # yyy='another long string', + # zzz='a third long string') + # ] + # + # or when a string formatting syntax. + func_call_or_string_format = False + if current.is_name: + tok = current.next_token + while tok and (tok.is_name or tok.value == '.'): + tok = tok.next_token + func_call_or_string_format = tok and tok.value == '(' + elif current.is_string: + tok = current.next_token + while tok and tok.is_string: + tok = tok.next_token + func_call_or_string_format = tok and tok.value == '%' + if func_call_or_string_format: + open_bracket = unwrapped_line.IsSurroundedByBrackets(current) + if open_bracket and open_bracket.value in '[{': + if not self._FitsOnLine(open_bracket, open_bracket.matching_bracket): + return True + + ########################################################################### + # Dict/Set Splitting + if (style.Get('EACH_DICT_ENTRY_ON_SEPARATE_LINE') and + format_token.Subtype.DICTIONARY_KEY in current.subtypes and + not current.is_comment): + # Place each dictionary entry onto its own line. + if previous.value == '{' and previous.previous_token: + opening = _GetOpeningBracket(previous.previous_token) + if (opening and opening.value == '(' and opening.previous_token and + opening.previous_token.is_name): + # This is a dictionary that's an argument to a function. + if self._FitsOnLine(previous, previous.matching_bracket): + return False + return True + + if (style.Get('SPLIT_BEFORE_DICT_SET_GENERATOR') and + format_token.Subtype.DICT_SET_GENERATOR in current.subtypes): + # Split before a dict/set generator. + return True + + if (format_token.Subtype.DICTIONARY_VALUE in current.subtypes or + (previous.is_pseudo_paren and previous.value == '(' and + not current.is_comment)): + # Split before the dictionary value if we can't fit every dictionary + # entry on its own line. + if not current.OpensScope(): + opening = _GetOpeningBracket(current) + if not self._EachDictEntryFitsOnOneLine(opening): + return True + + if previous.value == '{': + # Split if the dict/set cannot fit on one line and ends in a comma. + closing = previous.matching_bracket + if (not self._FitsOnLine(previous, closing) and + closing.previous_token.value == ','): + self.stack[-1].split_before_closing_bracket = True + return True + + ########################################################################### + # Argument List Splitting + if (style.Get('SPLIT_BEFORE_NAMED_ASSIGNS') and not current.is_comment and + format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN_ARG_LIST in + current.subtypes): + if (previous.value not in {'=', ':', '*', '**'} and + current.value not in ':=,)' and not _IsFunctionDefinition(previous)): + # If we're going to split the lines because of named arguments, then we + # want to split after the opening bracket as well. But not when this is + # part of a function definition. + if previous.value == '(': + # Make sure we don't split after the opening bracket if the + # continuation indent is greater than the opening bracket: + # + # a( + # b=1, + # c=2) + if (self._FitsOnLine(previous, previous.matching_bracket) and + unwrapped_line.IsSurroundedByBrackets(previous)): + # An argument to a function is a function call with named + # assigns. + return False + + column = self.column - self.stack[-1].last_space + return column > style.Get('CONTINUATION_INDENT_WIDTH') + + opening = _GetOpeningBracket(current) + if opening: + arglist_length = (opening.matching_bracket.total_length - + opening.total_length + self.stack[-1].indent) + return arglist_length > self.column_limit + + if style.Get('SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED'): + # Split before arguments in a function call or definition if the + # arguments are terminated by a comma. + opening = _GetOpeningBracket(current) + if opening and opening.previous_token and opening.previous_token.is_name: + if previous.value in '(,': + if opening.matching_bracket.previous_token.value == ',': + return True + + if ((current.is_name or current.value in {'*', '**'}) and + previous.value == ','): + # If we have a function call within an argument list and it won't fit on + # the remaining line, but it will fit on a line by itself, then go ahead + # and split before the call. + opening = _GetOpeningBracket(current) + if (opening and opening.value == '(' and opening.previous_token and + (opening.previous_token.is_name or + opening.previous_token.value in {'*', '**'})): + is_func_call = False + token = current + while token: + if token.value == '(': + is_func_call = True + break + if (not (token.is_name or token.value in {'*', '**'}) and + token.value != '.'): + break + token = token.next_token + + if is_func_call: + if not self._FitsOnLine(current, opening.matching_bracket): + return True + + pprevious = previous.previous_token + if (current.is_name and pprevious and pprevious.is_name and + previous.value == '('): + if (not self._FitsOnLine(previous, previous.matching_bracket) and + _IsFunctionCallWithArguments(current)): + # There is a function call, with more than 1 argument, where the first + # argument is itself a function call with arguments. In this specific + # case, if we split after the first argument's opening '(', then the + # formatting will look bad for the rest of the arguments. E.g.: + # + # outer_function_call(inner_function_call( + # inner_arg1, inner_arg2), + # outer_arg1, outer_arg2) + # + # Instead, enforce a split before that argument to keep things looking + # good. + return True + + if (previous.OpensScope() and not current.OpensScope() and + format_token.Subtype.SUBSCRIPT_BRACKET not in previous.subtypes): + if not current.is_comment: + if pprevious and not pprevious.is_keyword and not pprevious.is_name: + # We want to split if there's a comment in the container. + token = current + while token != previous.matching_bracket: + if token.is_comment: + return True + token = token.next_token + + if previous.value == '(': + pptoken = previous.previous_token + if not pptoken or not pptoken.is_name: + # Split after the opening of a tuple if it doesn't fit on the current + # line and it's not a function call. + if self._FitsOnLine(previous, previous.matching_bracket): + return False + elif not self._FitsOnLine(previous, previous.matching_bracket): + if (self.column_limit - self.column) / float(self.column_limit) < 0.3: + # Try not to squish all of the arguments off to the right. + return current.next_token != previous.matching_bracket + else: + # Split after the opening of a container if it doesn't fit on the + # current line or if it has a comment. + if not self._FitsOnLine(previous, previous.matching_bracket): + return True + + ########################################################################### + # List Comprehension Splitting + if (format_token.Subtype.COMP_FOR in current.subtypes and + format_token.Subtype.COMP_FOR not in previous.subtypes): + # Split at the beginning of a list comprehension. + length = _GetLengthOfSubtype(current, format_token.Subtype.COMP_FOR, + format_token.Subtype.COMP_IF) + if length + self.column > self.column_limit: + return True + + if (format_token.Subtype.COMP_IF in current.subtypes and + format_token.Subtype.COMP_IF not in previous.subtypes): + # Split at the beginning of an if expression. + length = _GetLengthOfSubtype(current, format_token.Subtype.COMP_IF) + if length + self.column > self.column_limit: + return True + + ########################################################################### + # Original Formatting Splitting + # These checks rely upon the original formatting. This is in order to + # attempt to keep hand-written code in the same condition as it was before. + # However, this may cause the formatter to fail to be idempotent. + if (style.Get('SPLIT_BEFORE_BITWISE_OPERATOR') and current.value in '&|' and + previous.lineno < current.lineno): + # Retain the split before a bitwise operator. + return True + + if (current.is_comment and + previous.lineno < current.lineno - current.value.count('\n')): + # If a comment comes in the middle of an unwrapped line (like an if + # conditional with comments interspersed), then we want to split if the + # original comments were on a separate line. + return True + + return False + + def AddTokenToState(self, newline, dry_run, must_split=False): + """Add a token to the format decision state. + + Allow the heuristic to try out adding the token with and without a newline. + Later on, the algorithm will determine which one has the lowest penalty. + + Arguments: + newline: (bool) Add the token on a new line if True. + dry_run: (bool) Don't commit whitespace changes to the FormatToken if + True. + must_split: (bool) A newline was required before this token. + + Returns: + The penalty of splitting after the current token. + """ + penalty = 0 + if newline: + penalty = self._AddTokenOnNewline(dry_run, must_split) + else: + self._AddTokenOnCurrentLine(dry_run) + + return self.MoveStateToNextToken() + penalty + + def _AddTokenOnCurrentLine(self, dry_run): + """Puts the token on the current line. + + Appends the next token to the state and updates information necessary for + indentation. + + Arguments: + dry_run: (bool) Commit whitespace changes to the FormatToken if True. + """ + current = self.next_token + previous = current.previous_token + + spaces = current.spaces_required_before + if not dry_run: + current.AddWhitespacePrefix(newlines_before=0, spaces=spaces) + + if previous.OpensScope(): + if not current.is_comment: + # Align closing scopes that are on a newline with the opening scope: + # + # foo = [a, + # b, + # ] + self.stack[-1].closing_scope_indent = self.column - 1 + if style.Get('ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT'): + self.stack[-1].closing_scope_indent += 1 + self.stack[-1].indent = self.column + spaces + else: + self.stack[-1].closing_scope_indent = ( + self.stack[-1].indent - style.Get('CONTINUATION_INDENT_WIDTH')) + + self.column += spaces + + def _AddTokenOnNewline(self, dry_run, must_split): + """Adds a line break and necessary indentation. + + Appends the next token to the state and updates information necessary for + indentation. + + Arguments: + dry_run: (bool) Don't commit whitespace changes to the FormatToken if + True. + must_split: (bool) A newline was required before this token. + + Returns: + The split penalty for splitting after the current state. + """ + current = self.next_token + previous = current.previous_token + + self.column = self._GetNewlineColumn() + + if not dry_run: + current.AddWhitespacePrefix(newlines_before=1, spaces=self.column) + + if not current.is_comment: + self.stack[-1].last_space = self.column + self.start_of_line_level = self.paren_level + self.lowest_level_on_line = self.paren_level + + if (previous.OpensScope() or + (previous.is_comment and previous.previous_token is not None and + previous.previous_token.OpensScope())): + self.stack[-1].closing_scope_indent = max( + 0, self.stack[-1].indent - style.Get('CONTINUATION_INDENT_WIDTH')) + + split_before_closing_bracket = True + if style.Get('COALESCE_BRACKETS'): + split_before_closing_bracket = False + + self.stack[-1].split_before_closing_bracket = split_before_closing_bracket + + # Calculate the split penalty. + penalty = current.split_penalty + + if must_split: + # Don't penalize for a must split. + return penalty + + if previous.is_pseudo_paren and previous.value == '(': + # Small penalty for splitting after a pseudo paren. + penalty += 50 + + # Add a penalty for each increasing newline we add, but don't penalize for + # splitting before an if-expression or list comprehension. + if current.value not in {'if', 'for'}: + last = self.stack[-1] + last.num_line_splits += 1 + penalty += (style.Get('SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT') * + last.num_line_splits) + + if current.OpensScope() and previous.OpensScope(): + # Prefer to keep opening brackets coalesced (unless it's at the beginning + # of a function call). + pprev = previous.previous_token + if not pprev or not pprev.is_name: + penalty += 10 + + return penalty + 10 + + def _GetNewlineColumn(self): + """Return the new column on the newline.""" + current = self.next_token + previous = current.previous_token + top_of_stack = self.stack[-1] + + if current.spaces_required_before > 2 or self.line.disable: + return current.spaces_required_before + + if current.OpensScope(): + return top_of_stack.indent if self.paren_level else self.first_indent + + if current.ClosesScope(): + if (previous.OpensScope() or + (previous.is_comment and previous.previous_token is not None and + previous.previous_token.OpensScope())): + return max(0, + top_of_stack.indent - style.Get('CONTINUATION_INDENT_WIDTH')) + return top_of_stack.closing_scope_indent + + if (previous and previous.is_string and current.is_string and + format_token.Subtype.DICTIONARY_VALUE in current.subtypes): + return previous.column + + if style.Get('INDENT_DICTIONARY_VALUE'): + if previous and (previous.value == ':' or previous.is_pseudo_paren): + if format_token.Subtype.DICTIONARY_VALUE in current.subtypes: + return top_of_stack.indent + + if (self.line.first.value in _COMPOUND_STMTS and + (not style.Get('DEDENT_CLOSING_BRACKETS') or + style.Get('SPLIT_BEFORE_FIRST_ARGUMENT'))): + token_indent = (len(self.line.first.whitespace_prefix.split('\n')[-1]) + + style.Get('INDENT_WIDTH')) + if token_indent == top_of_stack.indent: + return top_of_stack.indent + style.Get('CONTINUATION_INDENT_WIDTH') + + return top_of_stack.indent + + def MoveStateToNextToken(self): + """Calculate format decision state information and move onto the next token. + + Before moving onto the next token, we first calculate the format decision + state given the current token and its formatting decisions. Then the format + decision state is set up so that the next token can be added. + + Returns: + The penalty for the number of characters over the column limit. + """ + current = self.next_token + if not current.OpensScope() and not current.ClosesScope(): + self.lowest_level_on_line = min(self.lowest_level_on_line, + self.paren_level) + + # If we encounter an opening bracket, we add a level to our stack to prepare + # for the subsequent tokens. + if current.OpensScope(): + last = self.stack[-1] + new_indent = style.Get('CONTINUATION_INDENT_WIDTH') + last.last_space + + self.stack.append(_ParenState(new_indent, self.stack[-1].last_space)) + self.paren_level += 1 + + # If we encounter a closing bracket, we can remove a level from our + # parenthesis stack. + if len(self.stack) > 1 and current.ClosesScope(): + self.stack[-2].last_space = self.stack[-1].last_space + self.stack.pop() + self.paren_level -= 1 + + is_multiline_string = current.is_string and '\n' in current.value + if is_multiline_string: + # This is a multiline string. Only look at the first line. + self.column += len(current.value.split('\n')[0]) + elif not current.is_pseudo_paren: + self.column += len(current.value) + + self.next_token = self.next_token.next_token + + # Calculate the penalty for overflowing the column limit. + penalty = 0 + if not current.is_pylint_comment and self.column > self.column_limit: + excess_characters = self.column - self.column_limit + penalty += style.Get('SPLIT_PENALTY_EXCESS_CHARACTER') * excess_characters + + if is_multiline_string: + # If this is a multiline string, the column is actually the + # end of the last line in the string. + self.column = len(current.value.split('\n')[-1]) + + return penalty + + def _FitsOnLine(self, start, end): + """Determines if line between start and end can fit on the current line.""" + length = end.total_length - start.total_length + if not start.is_pseudo_paren: + length += len(start.value) + return length + self.column <= self.column_limit + + def _EachDictEntryFitsOnOneLine(self, opening): + """Determine if each dict elems can fit on one line.""" + + def PreviousNonCommentToken(tok): + tok = tok.previous_token + while tok.is_comment: + tok = tok.previous_token + return tok + + def ImplicitStringConcatenation(tok): + num_strings = 0 + if tok.is_pseudo_paren: + tok = tok.next_token + while tok.is_string: + num_strings += 1 + tok = tok.next_token + return num_strings > 1 + + closing = opening.matching_bracket + entry_start = opening.next_token + current = opening.next_token.next_token + + while current and current != closing: + if format_token.Subtype.DICTIONARY_KEY in current.subtypes: + prev = PreviousNonCommentToken(current) + length = prev.total_length - entry_start.total_length + length += len(entry_start.value) + if length + self.stack[-2].indent >= self.column_limit: + return False + entry_start = current + if current.OpensScope(): + if ((current.value == '{' or + (current.is_pseudo_paren and current.next_token.value == '{') and + format_token.Subtype.DICTIONARY_VALUE in current.subtypes) or + ImplicitStringConcatenation(current)): + # A dictionary entry that cannot fit on a single line shouldn't matter + # to this calcuation. If it can't fit on a single line, then the + # opening should be on the same line as the key and the rest on + # newlines after it. But the other entries should be on single lines + # if possible. + if current.matching_bracket: + current = current.matching_bracket + while current: + if current == closing: + return True + if format_token.Subtype.DICTIONARY_KEY in current.subtypes: + entry_start = current + break + current = current.next_token + else: + current = current.matching_bracket + else: + current = current.next_token + + # At this point, current is the closing bracket. Go back one to get the the + # end of the dictionary entry. + current = PreviousNonCommentToken(current) + length = current.total_length - entry_start.total_length + length += len(entry_start.value) + return length + self.stack[-2].indent <= self.column_limit + + +def _IsFunctionCallWithArguments(token): + while token: + if token.value == '(': + token = token.next_token + return token and token.value != ')' + elif token.name not in {'NAME', 'DOT'}: + break + token = token.next_token + return False + + +def _GetLengthOfSubtype(token, subtype, exclude=None): + current = token + while (current.next_token and subtype in current.subtypes and + (exclude is None or exclude not in current.subtypes)): + current = current.next_token + return current.total_length - token.total_length + 1 + + +def _GetOpeningBracket(current): + """Get the opening bracket containing the current token.""" + if current.matching_bracket and not current.is_pseudo_paren: + return current.matching_bracket + while current: + if current.ClosesScope(): + current = current.matching_bracket + elif current.is_pseudo_paren: + current = current.previous_token + elif current.OpensScope(): + return current + current = current.previous_token + return None + + +def _LastTokenInLine(current): + while not current.is_comment and current.next_token: + current = current.next_token + return current + + +def _IsFunctionDefinition(current): + prev = current.previous_token + return (current.value == '(' and prev and + format_token.Subtype.FUNC_DEF in prev.subtypes) + + +def _IsLastScopeInLine(current): + while current: + current = current.next_token + if current and current.OpensScope(): + return False + return True + + +class _ParenState(object): + """Maintains the state of the bracket enclosures. + + A stack of _ParenState objects are kept so that we know how to indent relative + to the brackets. + + Attributes: + indent: The column position to which a specified parenthesis level needs to + be indented. + last_space: The column position of the last space on each level. + split_before_closing_bracket: Whether a newline needs to be inserted before + the closing bracket. We only want to insert a newline before the closing + bracket if there also was a newline after the beginning left bracket. + num_line_splits: Number of line splits this _ParenState contains already. + Each subsequent line split gets an increasing penalty. + """ + + # TODO(morbo): This doesn't track "bin packing." + + def __init__(self, indent, last_space): + self.indent = indent + self.last_space = last_space + self.closing_scope_indent = 0 + self.split_before_closing_bracket = False + self.num_line_splits = 0 + + def Clone(self): + state = _ParenState(self.indent, self.last_space) + state.closing_scope_indent = self.closing_scope_indent + state.split_before_closing_bracket = self.split_before_closing_bracket + state.num_line_splits = self.num_line_splits + return state + + def __repr__(self): + return '[indent::%d, last_space::%d, closing_scope_indent::%d]' % ( + self.indent, self.last_space, self.closing_scope_indent) + + def __eq__(self, other): + return hash(self) == hash(other) + + def __ne__(self, other): + return not self == other + + def __hash__(self, *args, **kwargs): + return hash((self.indent, self.last_space, self.closing_scope_indent, + self.split_before_closing_bracket, self.num_line_splits)) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/format_token.py b/lib/jcef/tools/yapf/yapf/yapflib/format_token.py new file mode 100644 index 0000000..de270cf --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/format_token.py @@ -0,0 +1,283 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Pytree nodes with extra formatting information. + +This is a thin wrapper around a pytree.Leaf node. +""" + +import keyword +import re + +from lib2to3.pgen2 import token + +from yapf.yapflib import py3compat +from yapf.yapflib import pytree_utils +from yapf.yapflib import style + +CONTINUATION = token.N_TOKENS +token.N_TOKENS += 1 + + +class Subtype(object): + """Subtype information about tokens. + + Gleaned from parsing the code. Helps determine the best formatting. + """ + NONE = 0 + UNARY_OPERATOR = 1 + BINARY_OPERATOR = 2 + SUBSCRIPT_COLON = 3 + SUBSCRIPT_BRACKET = 4 + DEFAULT_OR_NAMED_ASSIGN = 5 + DEFAULT_OR_NAMED_ASSIGN_ARG_LIST = 6 + VARARGS_LIST = 7 + VARARGS_STAR = 8 + KWARGS_STAR_STAR = 9 + ASSIGN_OPERATOR = 10 + DICTIONARY_KEY = 11 + DICTIONARY_KEY_PART = 12 + DICTIONARY_VALUE = 13 + DICT_SET_GENERATOR = 14 + COMP_FOR = 15 + COMP_IF = 16 + FUNC_DEF = 17 + DECORATOR = 18 + + +class FormatToken(object): + """A wrapper around pytree Leaf nodes. + + This represents the token plus additional information useful for reformatting + the code. + + Attributes: + next_token: The token in the unwrapped line after this token or None if this + is the last token in the unwrapped line. + previous_token: The token in the unwrapped line before this token or None if + this is the first token in the unwrapped line. + matching_bracket: If a bracket token ('[', '{', or '(') the matching + bracket. + whitespace_prefix: The prefix for the whitespace. + spaces_required_before: The number of spaces required before a token. This + is a lower-bound for the formatter and not a hard requirement. For + instance, a comment may have n required spaces before it. But the + formatter won't place n spaces before all comments. Only those that are + moved to the end of a line of code. The formatter may use different + spacing when appropriate. + can_break_before: True if we're allowed to break before this token. + must_break_before: True if we're required to break before this token. + total_length: The total length of the unwrapped line up to and including + whitespace and this token. However, this doesn't include the initial + indentation amount. + split_penalty: The penalty for splitting the line before this token. + """ + + def __init__(self, node): + """Constructor. + + Arguments: + node: (pytree.Leaf) The node that's being wrapped. + """ + self.node = node + self.next_token = None + self.previous_token = None + self.matching_bracket = None + self.whitespace_prefix = '' + self.can_break_before = False + self.must_break_before = False + self.total_length = 0 # TODO(morbo): Think up a better name. + self.split_penalty = 0 + + if self.is_comment: + self.spaces_required_before = style.Get('SPACES_BEFORE_COMMENT') + else: + self.spaces_required_before = 0 + + if self.is_continuation: + self.value = self.node.value.rstrip() + else: + self.value = self.node.value + + def AddWhitespacePrefix(self, newlines_before, spaces=0, indent_level=0): + """Register a token's whitespace prefix. + + This is the whitespace that will be output before a token's string. + + Arguments: + newlines_before: (int) The number of newlines to place before the token. + spaces: (int) The number of spaces to place before the token. + indent_level: (int) The indentation level. + """ + indent_char = '\t' if style.Get('USE_TABS') else ' ' + token_indent_char = indent_char if newlines_before > 0 else ' ' + indent_before = (indent_char * indent_level * style.Get('INDENT_WIDTH') + + token_indent_char * spaces) + + if self.is_comment: + comment_lines = [s.lstrip() for s in self.value.splitlines()] + self.node.value = ('\n' + indent_before).join(comment_lines) + + # Update our own value since we are changing node value + self.value = self.node.value + + if not self.whitespace_prefix: + self.whitespace_prefix = ( + '\n' * (self.newlines or newlines_before) + indent_before) + else: + self.whitespace_prefix += indent_before + + def AdjustNewlinesBefore(self, newlines_before): + """Change the number of newlines before this token.""" + self.whitespace_prefix = ( + '\n' * newlines_before + self.whitespace_prefix.lstrip('\n')) + + def RetainHorizontalSpacing(self, first_column, depth): + """Retains a token's horizontal spacing.""" + previous = self.previous_token + if previous is None: + return + + cur_lineno = self.lineno + prev_lineno = previous.lineno + if previous.is_multiline_string: + prev_lineno += previous.value.count('\n') + + if (cur_lineno != prev_lineno or + (previous.is_pseudo_paren and previous.value != ')' and + cur_lineno != previous.previous_token.lineno)): + self.spaces_required_before = ( + self.column - first_column + depth * style.Get('INDENT_WIDTH')) + return + + cur_column = self.node.column + prev_column = previous.node.column + prev_len = len(previous.value) + + if previous.is_pseudo_paren and previous.value == ')': + prev_column -= 1 + prev_len = 0 + + if previous.is_multiline_string: + prev_len = len(previous.value.split('\n')[-1]) + if '\n' in previous.value: + prev_column = 0 # Last line starts in column 0. + self.spaces_required_before = cur_column - (prev_column + prev_len) + + def OpensScope(self): + return self.value in pytree_utils.OPENING_BRACKETS + + def ClosesScope(self): + return self.value in pytree_utils.CLOSING_BRACKETS + + def __repr__(self): + msg = 'FormatToken(name={0}, value={1}'.format(self.name, self.value) + msg += ', pseudo)' if self.is_pseudo_paren else ')' + return msg + + @property + @py3compat.lru_cache() + def node_split_penalty(self): + """Split penalty attached to the pytree node of this token.""" + return pytree_utils.GetNodeAnnotation( + self.node, pytree_utils.Annotation.SPLIT_PENALTY, default=0) + + @property + def newlines(self): + """The number of newlines needed before this token.""" + return pytree_utils.GetNodeAnnotation(self.node, + pytree_utils.Annotation.NEWLINES) + + @property + def must_split(self): + """Return true if the token requires a split before it.""" + return pytree_utils.GetNodeAnnotation(self.node, + pytree_utils.Annotation.MUST_SPLIT) + + @property + def column(self): + """The original column number of the node in the source.""" + return self.node.column + + @property + def lineno(self): + """The original line number of the node in the source.""" + return self.node.lineno + + @property + @py3compat.lru_cache() + def subtypes(self): + """Extra type information for directing formatting.""" + value = pytree_utils.GetNodeAnnotation(self.node, + pytree_utils.Annotation.SUBTYPE) + return [Subtype.NONE] if value is None else value + + @property + @py3compat.lru_cache() + def is_binary_op(self): + """Token is a binary operator.""" + return Subtype.BINARY_OPERATOR in self.subtypes + + @property + @py3compat.lru_cache() + def name(self): + """A string representation of the node's name.""" + return pytree_utils.NodeName(self.node) + + @property + def is_comment(self): + return self.node.type == token.COMMENT + + @property + def is_continuation(self): + return self.node.type == CONTINUATION + + @property + @py3compat.lru_cache() + def is_keyword(self): + return keyword.iskeyword(self.value) + + @property + @py3compat.lru_cache() + def is_name(self): + return self.node.type == token.NAME and not self.is_keyword + + @property + def is_number(self): + return self.node.type == token.NUMBER + + @property + def is_string(self): + return self.node.type == token.STRING + + @property + @py3compat.lru_cache() + def is_multiline_string(self): + return (self.is_string and + re.match(r'^[uUbB]?[rR]?(?P"""|\'\'\').*(?P=delim)$', + self.value, re.DOTALL) is not None) + + @property + @py3compat.lru_cache() + def is_docstring(self): + return self.is_multiline_string and not self.node.prev_sibling + + @property + @py3compat.lru_cache() + def is_pseudo_paren(self): + return hasattr(self.node, 'is_pseudo') and self.node.is_pseudo + + @property + def is_pylint_comment(self): + return self.is_comment and re.match(r'#.*\bpylint:\s*(disable|enable)=', + self.value) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/line_joiner.py b/lib/jcef/tools/yapf/yapf/yapflib/line_joiner.py new file mode 100644 index 0000000..860fce7 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/line_joiner.py @@ -0,0 +1,109 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Join unwrapped lines together. + +Determine how many lines can be joined into one line. For instance, we could +join these statements into one line: + + if a == 42: + continue + +like this: + + if a == 42: continue + +There are a few restrictions: + + 1. The lines should have been joined in the original source. + 2. The joined lines must not go over the column boundary if placed on the same + line. + 3. They need to be very simple statements. + +Note: Because we don't allow the use of a semicolon to separate statements, it +follows that there can only be at most two lines to join. +""" + +from yapf.yapflib import style + +_CLASS_OR_FUNC = frozenset({'def', 'class'}) + + +def CanMergeMultipleLines(lines, last_was_merged=False): + """Determine if multiple lines can be joined into one. + + Arguments: + lines: (list of UnwrappedLine) This is a splice of UnwrappedLines from the + full code base. + last_was_merged: (bool) The last line was merged. + + Returns: + True if two consecutive lines can be joined together. In reality, this will + only happen if two consecutive lines can be joined, due to the style guide. + """ + # The indentation amount for the starting line (number of spaces). + indent_amt = lines[0].depth * style.Get('INDENT_WIDTH') + if len(lines) == 1 or indent_amt > style.Get('COLUMN_LIMIT'): + return False + + if (len(lines) >= 3 and lines[2].depth >= lines[1].depth and + lines[0].depth != lines[2].depth): + # If lines[2]'s depth is greater than or equal to line[1]'s depth, we're not + # looking at a single statement (e.g., if-then, while, etc.). A following + # line with the same depth as the first line isn't part of the lines we + # would want to combine. + return False # Don't merge more than two lines together. + + if lines[0].first.value in _CLASS_OR_FUNC: + # Don't join lines onto the starting line of a class or function. + return False + + limit = style.Get('COLUMN_LIMIT') - indent_amt + if lines[0].last.total_length < limit: + limit -= lines[0].last.total_length + + if lines[0].first.value == 'if': + return _CanMergeLineIntoIfStatement(lines, limit) + if last_was_merged and lines[0].first.value in {'elif', 'else'}: + return _CanMergeLineIntoIfStatement(lines, limit) + + # TODO(morbo): Other control statements? + + return False + + +def _CanMergeLineIntoIfStatement(lines, limit): + """Determine if we can merge a short if-then statement into one line. + + Two lines of an if-then statement can be merged if they were that way in the + original source, fit on the line without going over the column limit, and are + considered "simple" statements --- typically statements like 'pass', + 'continue', and 'break'. + + Arguments: + lines: (list of UnwrappedLine) The lines we are wanting to merge. + limit: (int) The amount of space remaining on the line. + + Returns: + True if the lines can be merged, False otherwise. + """ + if len(lines[1].tokens) == 1 and lines[1].last.is_multiline_string: + # This might be part of a multiline shebang. + return True + if lines[0].lineno != lines[1].lineno: + # Don't merge lines if the original lines weren't merged. + return False + if lines[1].last.total_length >= limit: + # Don't merge lines if the result goes over the column limit. + return False + return style.Get('JOIN_MULTIPLE_LINES') diff --git a/lib/jcef/tools/yapf/yapf/yapflib/py3compat.py b/lib/jcef/tools/yapf/yapf/yapflib/py3compat.py new file mode 100644 index 0000000..2886c38 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/py3compat.py @@ -0,0 +1,113 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Utilities for Python2 / Python3 compatibility.""" + +import io +import os +import sys + +PY3 = sys.version_info[0] >= 3 +PY36 = sys.version_info[0] >= 3 and sys.version_info[1] >= 6 + +if PY3: + StringIO = io.StringIO + BytesIO = io.BytesIO + + import codecs + + def open_with_encoding(filename, mode, encoding, newline=''): # pylint: disable=unused-argument + return codecs.open(filename, mode=mode, encoding=encoding) + + import functools + lru_cache = functools.lru_cache + + range = range + ifilter = filter + raw_input = input + + import configparser + + # Mappings from strings to booleans (such as '1' to True, 'false' to False, + # etc.) + CONFIGPARSER_BOOLEAN_STATES = configparser.ConfigParser.BOOLEAN_STATES +else: + import __builtin__ + import cStringIO + StringIO = BytesIO = cStringIO.StringIO + + open_with_encoding = io.open + + # Python 2.7 doesn't have a native LRU cache, so do nothing. + def lru_cache(maxsize=128, typed=False): + + def fake_wrapper(user_function): + return user_function + + return fake_wrapper + + range = xrange + + from itertools import ifilter + raw_input = raw_input + + import ConfigParser as configparser + CONFIGPARSER_BOOLEAN_STATES = configparser.ConfigParser._boolean_states # pylint: disable=protected-access + + +def EncodeAndWriteToStdout(s, encoding='utf-8'): + """Encode the given string and emit to stdout. + + The string may contain non-ascii characters. This is a problem when stdout is + redirected, because then Python doesn't know the encoding and we may get a + UnicodeEncodeError. + + Arguments: + s: (string) The string to encode. + encoding: (string) The encoding of the string. + """ + if PY3: + sys.stdout.buffer.write(s.encode(encoding)) + elif sys.platform == 'win32': + # On python 2 and Windows universal newline transformation will be in + # effect on stdout. Python 2 will not let us avoid the easily because + # it happens based on whether the file handle is opened in O_BINARY or + # O_TEXT state. However we can tell Windows itself to change the current + # mode, and python 2 will follow suit. However we must take care to change + # the mode on the actual external stdout not just the current sys.stdout + # which may have been monkey-patched inside the python environment. + import msvcrt # pylint: disable=g-import-not-at-top + if sys.__stdout__ is sys.stdout: + msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) + sys.stdout.write(s.encode(encoding)) + else: + sys.stdout.write(s.encode(encoding)) + + +if PY3: + unicode = str # pylint: disable=redefined-builtin,invalid-name +else: + + def unicode(s): # pylint: disable=invalid-name + """Force conversion of s to unicode.""" + return __builtin__.unicode(s, 'utf-8') + + +# In Python 3.2+, readfp is deprecated in favor of read_file, which doesn't +# exist in Python 2 yet. To avoid deprecation warnings, subclass ConfigParser to +# fix this - now read_file works across all Python versions we care about. +class ConfigParser(configparser.ConfigParser): + if not PY3: + + def read_file(self, fp, source=None): + self.readfp(fp, filename=source) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/pytree_unwrapper.py b/lib/jcef/tools/yapf/yapf/yapflib/pytree_unwrapper.py new file mode 100644 index 0000000..c67c1c6 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/pytree_unwrapper.py @@ -0,0 +1,376 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""PyTreeUnwrapper - produces a list of unwrapped lines from a pytree. + +[for a description of what an unwrapped line is, see unwrapped_line.py] + +This is a pytree visitor that goes over a parse tree and produces a list of +UnwrappedLine containers from it, each with its own depth and containing all +the tokens that could fit on the line if there were no maximal line-length +limitations. + +Note: a precondition to running this visitor and obtaining correct results is +for the tree to have its comments spliced in as nodes. Prefixes are ignored. + +For most uses, the convenience function UnwrapPyTree should be sufficient. +""" + +# The word "token" is overloaded within this module, so for clarity rename +# the imported pgen2.token module. +from lib2to3 import pytree +from lib2to3.pgen2 import token as grammar_token + +from yapf.yapflib import pytree_utils +from yapf.yapflib import pytree_visitor +from yapf.yapflib import split_penalty +from yapf.yapflib import unwrapped_line + + +def UnwrapPyTree(tree): + """Create and return a list of unwrapped lines from the given pytree. + + Arguments: + tree: the top-level pytree node to unwrap. + + Returns: + A list of UnwrappedLine objects. + """ + unwrapper = PyTreeUnwrapper() + unwrapper.Visit(tree) + uwlines = unwrapper.GetUnwrappedLines() + uwlines.sort(key=lambda x: x.lineno) + return uwlines + + +# Grammar tokens considered as whitespace for the purpose of unwrapping. +_WHITESPACE_TOKENS = frozenset([ + grammar_token.NEWLINE, grammar_token.DEDENT, grammar_token.INDENT, + grammar_token.ENDMARKER +]) + + +class PyTreeUnwrapper(pytree_visitor.PyTreeVisitor): + """PyTreeUnwrapper - see file-level docstring for detailed description. + + Note: since this implements PyTreeVisitor and node names in lib2to3 are + underscore_separated, the visiting methods of this class are named as + Visit_node_name. invalid-name pragmas are added to each such method to silence + a style warning. This is forced on us by the usage of lib2to3, and re-munging + method names to make them different from actual node names sounded like a + confusing and brittle affair that wasn't worth it for this small & controlled + deviation from the style guide. + + To understand the connection between visitor methods in this class, some + familiarity with the Python grammar is required. + """ + + def __init__(self): + # A list of all unwrapped lines finished visiting so far. + self._unwrapped_lines = [] + + # Builds up a "current" unwrapped line while visiting pytree nodes. Some + # nodes will finish a line and start a new one. + self._cur_unwrapped_line = unwrapped_line.UnwrappedLine(0) + + # Current indentation depth. + self._cur_depth = 0 + + def GetUnwrappedLines(self): + """Fetch the result of the tree walk. + + Note: only call this after visiting the whole tree. + + Returns: + A list of UnwrappedLine objects. + """ + # Make sure the last line that was being populated is flushed. + self._StartNewLine() + return self._unwrapped_lines + + def _StartNewLine(self): + """Finish current line and start a new one. + + Place the currently accumulated line into the _unwrapped_lines list and + start a new one. + """ + if self._cur_unwrapped_line.tokens: + self._unwrapped_lines.append(self._cur_unwrapped_line) + _MatchBrackets(self._cur_unwrapped_line) + _AdjustSplitPenalty(self._cur_unwrapped_line) + self._cur_unwrapped_line = unwrapped_line.UnwrappedLine(self._cur_depth) + + _STMT_TYPES = frozenset({ + 'if_stmt', + 'while_stmt', + 'for_stmt', + 'try_stmt', + 'expect_clause', + 'with_stmt', + 'funcdef', + 'classdef', + }) + + # pylint: disable=invalid-name,missing-docstring + def Visit_simple_stmt(self, node): + # A 'simple_stmt' conveniently represents a non-compound Python statement, + # i.e. a statement that does not contain other statements. + + # When compound nodes have a single statement as their suite, the parser + # can leave it in the tree directly without creating a suite. But we have + # to increase depth in these cases as well. However, don't increase the + # depth of we have a simple_stmt that's a comment node. This represents a + # standalone comment and in the case of it coming directly after the + # funcdef, it is a "top" comment for the whole function. + # TODO(eliben): add more relevant compound statements here. + single_stmt_suite = (node.parent and + pytree_utils.NodeName(node.parent) in self._STMT_TYPES) + is_comment_stmt = pytree_utils.IsCommentStatement(node) + if single_stmt_suite and not is_comment_stmt: + self._cur_depth += 1 + self._StartNewLine() + self.DefaultNodeVisit(node) + if single_stmt_suite and not is_comment_stmt: + self._cur_depth -= 1 + + def _VisitCompoundStatement(self, node, substatement_names): + """Helper for visiting compound statements. + + Python compound statements serve as containers for other statements. Thus, + when we encounter a new compound statement we start a new unwrapped line. + + Arguments: + node: the node to visit. + substatement_names: set of node names. A compound statement will be + recognized as a NAME node with a name in this set. + """ + for child in node.children: + # A pytree is structured in such a way that a single 'if_stmt' node will + # contain all the 'if', 'elif' and 'else' nodes as children (similar + # structure applies to 'while' statements, 'try' blocks, etc). Therefore, + # we visit all children here and create a new line before the requested + # set of nodes. + if (child.type == grammar_token.NAME and + child.value in substatement_names): + self._StartNewLine() + self.Visit(child) + + _IF_STMT_ELEMS = frozenset({'if', 'else', 'elif'}) + + def Visit_if_stmt(self, node): # pylint: disable=invalid-name + self._VisitCompoundStatement(node, self._IF_STMT_ELEMS) + + _WHILE_STMT_ELEMS = frozenset({'while', 'else'}) + + def Visit_while_stmt(self, node): # pylint: disable=invalid-name + self._VisitCompoundStatement(node, self._WHILE_STMT_ELEMS) + + _FOR_STMT_ELEMS = frozenset({'for', 'else'}) + + def Visit_for_stmt(self, node): # pylint: disable=invalid-name + self._VisitCompoundStatement(node, self._FOR_STMT_ELEMS) + + _TRY_STMT_ELEMS = frozenset({'try', 'except', 'else', 'finally'}) + + def Visit_try_stmt(self, node): # pylint: disable=invalid-name + self._VisitCompoundStatement(node, self._TRY_STMT_ELEMS) + + _EXCEPT_STMT_ELEMS = frozenset({'except'}) + + def Visit_except_clause(self, node): # pylint: disable=invalid-name + self._VisitCompoundStatement(node, self._EXCEPT_STMT_ELEMS) + + _FUNC_DEF_ELEMS = frozenset({'def'}) + + def Visit_funcdef(self, node): # pylint: disable=invalid-name + self._VisitCompoundStatement(node, self._FUNC_DEF_ELEMS) + + def Visit_async_funcdef(self, node): # pylint: disable=invalid-name + self._StartNewLine() + index = 0 + for child in node.children: + index += 1 + self.Visit(child) + if pytree_utils.NodeName(child) == 'ASYNC': + break + for child in node.children[index].children: + self.Visit(child) + + _CLASS_DEF_ELEMS = frozenset({'class'}) + + def Visit_classdef(self, node): # pylint: disable=invalid-name + self._VisitCompoundStatement(node, self._CLASS_DEF_ELEMS) + + def Visit_async_stmt(self, node): # pylint: disable=invalid-name + self._StartNewLine() + index = 0 + for child in node.children: + index += 1 + self.Visit(child) + if pytree_utils.NodeName(child) == 'ASYNC': + break + for child in node.children[index].children: + self.Visit(child) + + def Visit_decorators(self, node): # pylint: disable=invalid-name + for child in node.children: + self._StartNewLine() + self.Visit(child) + + def Visit_decorated(self, node): # pylint: disable=invalid-name + for child in node.children: + self._StartNewLine() + self.Visit(child) + + _WITH_STMT_ELEMS = frozenset({'with'}) + + def Visit_with_stmt(self, node): # pylint: disable=invalid-name + self._VisitCompoundStatement(node, self._WITH_STMT_ELEMS) + + def Visit_suite(self, node): # pylint: disable=invalid-name + # A 'suite' starts a new indentation level in Python. + self._cur_depth += 1 + self._StartNewLine() + self.DefaultNodeVisit(node) + self._cur_depth -= 1 + + def Visit_listmaker(self, node): # pylint: disable=invalid-name + _DetermineMustSplitAnnotation(node) + self.DefaultNodeVisit(node) + + def Visit_dictsetmaker(self, node): # pylint: disable=invalid-name + _DetermineMustSplitAnnotation(node) + self.DefaultNodeVisit(node) + + def Visit_import_as_names(self, node): # pylint: disable=invalid-name + if node.prev_sibling.value == '(': + _DetermineMustSplitAnnotation(node) + self.DefaultNodeVisit(node) + + def Visit_testlist_gexp(self, node): # pylint: disable=invalid-name + if _ContainsComments(node): + _DetermineMustSplitAnnotation(node) + self.DefaultNodeVisit(node) + + def Visit_arglist(self, node): # pylint: disable=invalid-name + _DetermineMustSplitAnnotation(node) + self.DefaultNodeVisit(node) + + def Visit_typedargslist(self, node): # pylint: disable=invalid-name + _DetermineMustSplitAnnotation(node) + self.DefaultNodeVisit(node) + + def DefaultLeafVisit(self, leaf): + """Default visitor for tree leaves. + + A tree leaf is always just gets appended to the current unwrapped line. + + Arguments: + leaf: the leaf to visit. + """ + if leaf.type in _WHITESPACE_TOKENS: + self._StartNewLine() + elif leaf.type != grammar_token.COMMENT or leaf.value.strip(): + if leaf.value == ';': + # Split up multiple statements on one line. + self._StartNewLine() + else: + # Add non-whitespace tokens and comments that aren't empty. + self._cur_unwrapped_line.AppendNode(leaf) + + +_BRACKET_MATCH = {')': '(', '}': '{', ']': '['} + + +def _MatchBrackets(uwline): + """Visit the node and match the brackets. + + For every open bracket ('[', '{', or '('), find the associated closing bracket + and "match" them up. I.e., save in the token a pointer to its associated open + or close bracket. + + Arguments: + uwline: (UnwrappedLine) An unwrapped line. + """ + bracket_stack = [] + for token in uwline.tokens: + if token.value in pytree_utils.OPENING_BRACKETS: + bracket_stack.append(token) + elif token.value in pytree_utils.CLOSING_BRACKETS: + bracket_stack[-1].matching_bracket = token + token.matching_bracket = bracket_stack[-1] + bracket_stack.pop() + + +def _AdjustSplitPenalty(uwline): + """Visit the node and adjust the split penalties if needed. + + A token shouldn't be split if it's not within a bracket pair. Mark any token + that's not within a bracket pair as "unbreakable". + + Arguments: + uwline: (UnwrappedLine) An unwrapped line. + """ + bracket_level = 0 + for index, token in enumerate(uwline.tokens): + if index and not bracket_level: + pytree_utils.SetNodeAnnotation(token.node, + pytree_utils.Annotation.SPLIT_PENALTY, + split_penalty.UNBREAKABLE) + if token.value in pytree_utils.OPENING_BRACKETS: + bracket_level += 1 + elif token.value in pytree_utils.CLOSING_BRACKETS: + bracket_level -= 1 + + +def _DetermineMustSplitAnnotation(node): + """Enforce a split in the list if the list ends with a comma.""" + if not _ContainsComments(node): + if (not isinstance(node.children[-1], pytree.Leaf) or + node.children[-1].value != ','): + return + num_children = len(node.children) + index = 0 + _SetMustSplitOnFirstLeaf(node.children[0]) + while index < num_children - 1: + child = node.children[index] + if isinstance(child, pytree.Leaf) and child.value == ',': + next_child = node.children[index + 1] + if next_child.type == grammar_token.COMMENT: + index += 1 + if index >= num_children - 1: + break + _SetMustSplitOnFirstLeaf(node.children[index + 1]) + index += 1 + + +def _ContainsComments(node): + """Return True if the list has a comment in it.""" + if isinstance(node, pytree.Leaf): + return node.type == grammar_token.COMMENT + for child in node.children: + if _ContainsComments(child): + return True + return False + + +def _SetMustSplitOnFirstLeaf(node): + """Set the "must split" annotation on the first leaf node.""" + + def FindFirstLeaf(node): + if isinstance(node, pytree.Leaf): + return node + return FindFirstLeaf(node.children[0]) + + pytree_utils.SetNodeAnnotation( + FindFirstLeaf(node), pytree_utils.Annotation.MUST_SPLIT, True) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/pytree_utils.py b/lib/jcef/tools/yapf/yapf/yapflib/pytree_utils.py new file mode 100644 index 0000000..60fd955 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/pytree_utils.py @@ -0,0 +1,297 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""pytree-related utilities. + +This module collects various utilities related to the parse trees produced by +the lib2to3 library. + + NodeName(): produces a string name for pytree nodes. + ParseCodeToTree(): convenience wrapper around lib2to3 interfaces to parse + a given string with code to a pytree. + InsertNodeBefore(): insert a node before another in a pytree. + InsertNodeAfter(): insert a node after another in a pytree. + {Get,Set}NodeAnnotation(): manage custom annotations on pytree nodes. +""" + +import ast +from lib2to3 import pygram +from lib2to3 import pytree +from lib2to3.pgen2 import driver +from lib2to3.pgen2 import parse +from lib2to3.pgen2 import token + +# TODO(eliben): We may want to get rid of this filtering at some point once we +# have a better understanding of what information we need from the tree. Then, +# these tokens may be filtered out from the tree before the tree gets to the +# unwrapper. +NONSEMANTIC_TOKENS = frozenset(['DEDENT', 'INDENT', 'NEWLINE', 'ENDMARKER']) + +OPENING_BRACKETS = frozenset({'(', '[', '{'}) +CLOSING_BRACKETS = frozenset({')', ']', '}'}) + + +class Annotation(object): + """Annotation names associated with pytrees.""" + CHILD_INDENT = 'child_indent' + NEWLINES = 'newlines' + MUST_SPLIT = 'must_split' + SPLIT_PENALTY = 'split_penalty' + SUBTYPE = 'subtype' + + +def NodeName(node): + """Produce a string name for a given node. + + For a Leaf this is the token name, and for a Node this is the type. + + Arguments: + node: a tree node + + Returns: + Name as a string. + """ + # Nodes with values < 256 are tokens. Values >= 256 are grammar symbols. + if node.type < 256: + return token.tok_name[node.type] + else: + return pygram.python_grammar.number2symbol[node.type] + + +# lib2to3 thoughtfully provides pygram.python_grammar_no_print_statement for +# parsing Python 3 code that wouldn't parse otherwise (when 'print' is used in a +# context where a keyword is disallowed). +# It forgets to do the same for 'exec' though. Luckily, Python is amenable to +# monkey-patching. +_GRAMMAR_FOR_PY3 = pygram.python_grammar_no_print_statement.copy() +del _GRAMMAR_FOR_PY3.keywords['exec'] + +_GRAMMAR_FOR_PY2 = pygram.python_grammar.copy() +del _GRAMMAR_FOR_PY2.keywords['nonlocal'] + + +def ParseCodeToTree(code): + """Parse the given code to a lib2to3 pytree. + + Arguments: + code: a string with the code to parse. + + Raises: + SyntaxError if the code is invalid syntax. + parse.ParseError if some other parsing failure. + + Returns: + The root node of the parsed tree. + """ + # This function is tiny, but the incantation for invoking the parser correctly + # is sufficiently magical to be worth abstracting away. + try: + # Try to parse using a Python 3 grammar, which is more permissive (print and + # exec are not keywords). + parser_driver = driver.Driver(_GRAMMAR_FOR_PY3, convert=pytree.convert) + tree = parser_driver.parse_string(code, debug=False) + except parse.ParseError: + # Now try to parse using a Python 2 grammar; If this fails, then + # there's something else wrong with the code. + try: + parser_driver = driver.Driver(_GRAMMAR_FOR_PY2, convert=pytree.convert) + tree = parser_driver.parse_string(code, debug=False) + except parse.ParseError: + # Raise a syntax error if the code is invalid python syntax. + try: + ast.parse(code) + except SyntaxError as e: + raise e + else: + raise + return _WrapEndMarker(tree) + + +def _WrapEndMarker(tree): + """Wrap a single ENDMARKER token in a "file_input" node. + + Arguments: + tree: (pytree.Node) The root node of the parsed tree. + + Returns: + The root node of the parsed tree. If the tree is a single ENDMARKER node, + then that node is wrapped in a "file_input" node. That will ensure we don't + skip comments attached to that node. + """ + if isinstance(tree, pytree.Leaf) and tree.type == token.ENDMARKER: + return pytree.Node(pygram.python_symbols.file_input, [tree]) + return tree + + +def InsertNodesBefore(new_nodes, target): + """Insert new_nodes before the given target location in the tree. + + Arguments: + new_nodes: a sequence of new nodes to insert (the nodes should not be in the + tree). + target: the target node before which the new node node will be inserted. + + Raises: + RuntimeError: if the tree is corrupted, or the insertion would corrupt it. + """ + for node in new_nodes: + _InsertNodeAt(node, target, after=False) + + +def InsertNodesAfter(new_nodes, target): + """Insert new_nodes after the given target location in the tree. + + Arguments: + new_nodes: a sequence of new nodes to insert (the nodes should not be in the + tree). + target: the target node after which the new node node will be inserted. + + Raises: + RuntimeError: if the tree is corrupted, or the insertion would corrupt it. + """ + for node in reversed(new_nodes): + _InsertNodeAt(node, target, after=True) + + +def _InsertNodeAt(new_node, target, after=False): + """Underlying implementation for node insertion. + + Arguments: + new_node: a new node to insert (this node should not be in the tree). + target: the target node. + after: if True, new_node is inserted after target. Otherwise, it's inserted + before target. + + Returns: + nothing + + Raises: + RuntimeError: if the tree is corrupted, or the insertion would corrupt it. + """ + + # Protect against attempts to insert nodes which already belong to some tree. + if new_node.parent is not None: + raise RuntimeError('inserting node which already has a parent', + (new_node, new_node.parent)) + + # The code here is based on pytree.Base.next_sibling + parent_of_target = target.parent + if parent_of_target is None: + raise RuntimeError('expected target node to have a parent', (target,)) + + for i, child in enumerate(parent_of_target.children): + if child is target: + insertion_index = i + 1 if after else i + parent_of_target.insert_child(insertion_index, new_node) + return + + raise RuntimeError('unable to find insertion point for target node', + (target,)) + + +# The following constant and functions implement a simple custom annotation +# mechanism for pytree nodes. We attach new attributes to nodes. Each attribute +# is prefixed with _NODE_ANNOTATION_PREFIX. These annotations should only be +# managed through GetNodeAnnotation and SetNodeAnnotation. +_NODE_ANNOTATION_PREFIX = '_yapf_annotation_' + + +def GetNodeAnnotation(node, annotation, default=None): + """Get annotation value from a node. + + Arguments: + node: the node. + annotation: annotation name - a string. + default: the default value to return if there's no annotation. + + Returns: + Value of the annotation in the given node. If the node doesn't have this + particular annotation name yet, returns default. + """ + return getattr(node, _NODE_ANNOTATION_PREFIX + annotation, default) + + +def SetNodeAnnotation(node, annotation, value): + """Set annotation value on a node. + + Arguments: + node: the node. + annotation: annotation name - a string. + value: annotation value to set. + """ + setattr(node, _NODE_ANNOTATION_PREFIX + annotation, value) + + +def AppendNodeAnnotation(node, annotation, value): + """Appends an annotation value to a list of annotations on the node. + + Arguments: + node: the node. + annotation: annotation name - a string. + value: annotation value to set. + """ + attr = GetNodeAnnotation(node, annotation, set()) + attr.add(value) + SetNodeAnnotation(node, annotation, attr) + + +def RemoveSubtypeAnnotation(node, value): + """Removes an annotation value from the subtype annotations on the node. + + Arguments: + node: the node. + value: annotation value to remove. + """ + attr = GetNodeAnnotation(node, Annotation.SUBTYPE) + if attr and value in attr: + attr.remove(value) + SetNodeAnnotation(node, Annotation.SUBTYPE, attr) + + +def DumpNodeToString(node): + """Dump a string representation of the given node. For debugging. + + Arguments: + node: the node. + + Returns: + The string representation. + """ + if isinstance(node, pytree.Leaf): + fmt = '{name}({value}) [lineno={lineno}, column={column}, prefix={prefix}]' + return fmt.format( + name=NodeName(node), + value=_PytreeNodeRepr(node), + lineno=node.lineno, + column=node.column, + prefix=repr(node.prefix)) + else: + fmt = '{node} [{len} children] [child_indent="{indent}"]' + return fmt.format( + node=NodeName(node), + len=len(node.children), + indent=GetNodeAnnotation(node, Annotation.CHILD_INDENT)) + + +def _PytreeNodeRepr(node): + """Like pytree.Node.__repr__, but names instead of numbers for tokens.""" + if isinstance(node, pytree.Node): + return '%s(%s, %r)' % (node.__class__.__name__, NodeName(node), + [_PytreeNodeRepr(c) for c in node.children]) + if isinstance(node, pytree.Leaf): + return '%s(%s, %r)' % (node.__class__.__name__, NodeName(node), node.value) + + +def IsCommentStatement(node): + return (NodeName(node) == 'simple_stmt' and + node.children[0].type == token.COMMENT) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/pytree_visitor.py b/lib/jcef/tools/yapf/yapf/yapflib/pytree_visitor.py new file mode 100644 index 0000000..3f1ab0b --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/pytree_visitor.py @@ -0,0 +1,135 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Generic visitor pattern for pytrees. + +The lib2to3 parser produces a "pytree" - syntax tree consisting of Node +and Leaf types. This module implements a visitor pattern for such trees. + +It also exports a basic "dumping" visitor that dumps a textual representation of +a pytree into a stream. + + PyTreeVisitor: a generic visitor pattern fo pytrees. + PyTreeDumper: a configurable "dumper" for displaying pytrees. + DumpPyTree(): a convenience function to dump a pytree. +""" + +import sys + +from lib2to3 import pytree + +from yapf.yapflib import pytree_utils + + +class PyTreeVisitor(object): + """Visitor pattern for pytree trees. + + Methods named Visit_XXX will be invoked when a node with type XXX is + encountered in the tree. The type is either a token type (for Leaf nodes) or + grammar symbols (for Node nodes). The return value of Visit_XXX methods is + ignored by the visitor. + + Visitors can modify node contents but must not change the tree structure + (e.g. add/remove children and move nodes around). + + This is a very common visitor pattern in Python code; it's also used in the + Python standard library ast module for providing AST visitors. + + Note: this makes names that aren't style conformant, so such visitor methods + need to be marked with # pylint: disable=invalid-name We don't have a choice + here, because lib2to3 nodes have under_separated names. + + For more complex behavior, the visit, DefaultNodeVisit and DefaultLeafVisit + methods can be overridden. Don't forget to invoke DefaultNodeVisit for nodes + that may have children - otherwise the children will not be visited. + """ + + def Visit(self, node): + """Visit a node.""" + method = 'Visit_{0}'.format(pytree_utils.NodeName(node)) + if hasattr(self, method): + # Found a specific visitor for this node + getattr(self, method)(node) + else: + if isinstance(node, pytree.Leaf): + self.DefaultLeafVisit(node) + else: + self.DefaultNodeVisit(node) + + def DefaultNodeVisit(self, node): + """Default visitor for Node: visits the node's children depth-first. + + This method is invoked when no specific visitor for the node is defined. + + Arguments: + node: the node to visit + """ + for child in node.children: + self.Visit(child) + + def DefaultLeafVisit(self, leaf): + """Default visitor for Leaf: no-op. + + This method is invoked when no specific visitor for the leaf is defined. + + Arguments: + leaf: the leaf to visit + """ + pass + + +def DumpPyTree(tree, target_stream=sys.stdout): + """Convenience function for dumping a given pytree. + + This function presents a very minimal interface. For more configurability (for + example, controlling how specific node types are displayed), use PyTreeDumper + directly. + + Arguments: + tree: the tree to dump. + target_stream: the stream to dump the tree to. A file-like object. By + default will dump into stdout. + """ + dumper = PyTreeDumper(target_stream) + dumper.Visit(tree) + + +class PyTreeDumper(PyTreeVisitor): + """Visitor that dumps the tree to a stream. + + Implements the PyTreeVisitor interface. + """ + + def __init__(self, target_stream=sys.stdout): + """Create a tree dumper. + + Arguments: + target_stream: the stream to dump the tree to. A file-like object. By + default will dump into stdout. + """ + self._target_stream = target_stream + self._current_indent = 0 + + def _DumpString(self, s): + self._target_stream.write('{0}{1}\n'.format(' ' * self._current_indent, s)) + + def DefaultNodeVisit(self, node): + # Dump information about the current node, and then use the generic + # DefaultNodeVisit visitor to dump each of its children. + self._DumpString(pytree_utils.DumpNodeToString(node)) + self._current_indent += 2 + super(PyTreeDumper, self).DefaultNodeVisit(node) + self._current_indent -= 2 + + def DefaultLeafVisit(self, leaf): + self._DumpString(pytree_utils.DumpNodeToString(leaf)) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/reformatter.py b/lib/jcef/tools/yapf/yapf/yapflib/reformatter.py new file mode 100644 index 0000000..fd8f317 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/reformatter.py @@ -0,0 +1,588 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Decide what the format for the code should be. + +The `unwrapped_line.UnwrappedLine`s are now ready to be formatted. +UnwrappedLines that can be merged together are. The best formatting is returned +as a string. + + Reformat(): the main function exported by this module. +""" + +from __future__ import unicode_literals +import collections +import heapq +import re + +from lib2to3 import pytree +from lib2to3.pgen2 import token + +from yapf.yapflib import format_decision_state +from yapf.yapflib import format_token +from yapf.yapflib import line_joiner +from yapf.yapflib import pytree_utils +from yapf.yapflib import style +from yapf.yapflib import verifier + + +def Reformat(uwlines, verify=False): + """Reformat the unwrapped lines. + + Arguments: + uwlines: (list of unwrapped_line.UnwrappedLine) Lines we want to format. + verify: (bool) True if reformatted code should be verified for syntax. + + Returns: + A string representing the reformatted code. + """ + final_lines = [] + prev_uwline = None # The previous line. + indent_width = style.Get('INDENT_WIDTH') + + for uwline in _SingleOrMergedLines(uwlines): + first_token = uwline.first + _FormatFirstToken(first_token, uwline.depth, prev_uwline, final_lines) + + indent_amt = indent_width * uwline.depth + state = format_decision_state.FormatDecisionState(uwline, indent_amt) + state.MoveStateToNextToken() + + if not uwline.disable: + if uwline.first.is_comment: + uwline.first.node.value = uwline.first.node.value.rstrip() + elif uwline.last.is_comment: + uwline.last.node.value = uwline.last.node.value.rstrip() + if prev_uwline and prev_uwline.disable: + # Keep the vertical spacing between a disabled and enabled formatting + # region. + _RetainVerticalSpacingBetweenTokens(uwline.first, prev_uwline.last) + if any(tok.is_comment for tok in uwline.tokens): + _RetainVerticalSpacingBeforeComments(uwline) + + if (_LineContainsI18n(uwline) or uwline.disable or + _LineHasContinuationMarkers(uwline)): + _RetainHorizontalSpacing(uwline) + _RetainVerticalSpacing(uwline, prev_uwline) + _EmitLineUnformatted(state) + elif _CanPlaceOnSingleLine(uwline) and not any(tok.must_split + for tok in uwline.tokens): + # The unwrapped line fits on one line. + while state.next_token: + state.AddTokenToState(newline=False, dry_run=False) + else: + if not _AnalyzeSolutionSpace(state): + # Failsafe mode. If there isn't a solution to the line, then just emit + # it as is. + state = format_decision_state.FormatDecisionState(uwline, indent_amt) + state.MoveStateToNextToken() + _RetainHorizontalSpacing(uwline) + _RetainVerticalSpacing(uwline, prev_uwline) + _EmitLineUnformatted(state) + + final_lines.append(uwline) + prev_uwline = uwline + return _FormatFinalLines(final_lines, verify) + + +def _RetainHorizontalSpacing(uwline): + """Retain all horizontal spacing between tokens.""" + for tok in uwline.tokens: + tok.RetainHorizontalSpacing(uwline.first.column, uwline.depth) + + +def _RetainVerticalSpacing(cur_uwline, prev_uwline): + prev_tok = None + if prev_uwline is not None: + prev_tok = prev_uwline.last + for cur_tok in cur_uwline.tokens: + _RetainVerticalSpacingBetweenTokens(cur_tok, prev_tok) + prev_tok = cur_tok + + +def _RetainVerticalSpacingBetweenTokens(cur_tok, prev_tok): + """Retain vertical spacing between two tokens.""" + if prev_tok is None: + return + + if prev_tok.is_string: + prev_lineno = prev_tok.lineno + prev_tok.value.count('\n') + elif prev_tok.is_pseudo_paren: + if not prev_tok.previous_token.is_multiline_string: + prev_lineno = prev_tok.previous_token.lineno + else: + prev_lineno = prev_tok.lineno + else: + prev_lineno = prev_tok.lineno + + if cur_tok.is_comment: + cur_lineno = cur_tok.lineno - cur_tok.value.count('\n') + else: + cur_lineno = cur_tok.lineno + + cur_tok.AdjustNewlinesBefore(cur_lineno - prev_lineno) + + +def _RetainVerticalSpacingBeforeComments(uwline): + """Retain vertical spacing before comments.""" + prev_token = None + for tok in uwline.tokens: + if tok.is_comment and prev_token: + if tok.lineno - tok.value.count('\n') - prev_token.lineno > 1: + tok.AdjustNewlinesBefore(ONE_BLANK_LINE) + + prev_token = tok + + +def _EmitLineUnformatted(state): + """Emit the line without formatting. + + The line contains code that if reformatted would break a non-syntactic + convention. E.g., i18n comments and function calls are tightly bound by + convention. Instead, we calculate when / if a newline should occur and honor + that. But otherwise the code emitted will be the same as the original code. + + Arguments: + state: (format_decision_state.FormatDecisionState) The format decision + state. + """ + prev_lineno = None + while state.next_token: + previous_token = state.next_token.previous_token + previous_lineno = previous_token.lineno + + if previous_token.is_multiline_string: + previous_lineno += previous_token.value.count('\n') + + if previous_token.is_continuation: + newline = False + else: + newline = (prev_lineno is not None and + state.next_token.lineno > previous_lineno) + + prev_lineno = state.next_token.lineno + state.AddTokenToState(newline=newline, dry_run=False) + + +def _LineContainsI18n(uwline): + """Return true if there are i18n comments or function calls in the line. + + I18n comments and pseudo-function calls are closely related. They cannot + be moved apart without breaking i18n. + + Arguments: + uwline: (unwrapped_line.UnwrappedLine) The line currently being formatted. + + Returns: + True if the line contains i18n comments or function calls. False otherwise. + """ + if style.Get('I18N_COMMENT'): + for tok in uwline.tokens: + if tok.is_comment and re.match(style.Get('I18N_COMMENT'), tok.value): + # Contains an i18n comment. + return True + + if style.Get('I18N_FUNCTION_CALL'): + length = len(uwline.tokens) + index = 0 + while index < length - 1: + if (uwline.tokens[index + 1].value == '(' and + uwline.tokens[index].value in style.Get('I18N_FUNCTION_CALL')): + return True + index += 1 + + return False + + +def _LineHasContinuationMarkers(uwline): + """Return true if the line has continuation markers in it.""" + return any(tok.is_continuation for tok in uwline.tokens) + + +def _CanPlaceOnSingleLine(uwline): + """Determine if the unwrapped line can go on a single line. + + Arguments: + uwline: (unwrapped_line.UnwrappedLine) The line currently being formatted. + + Returns: + True if the line can or should be added to a single line. False otherwise. + """ + indent_amt = style.Get('INDENT_WIDTH') * uwline.depth + last = uwline.last + last_index = -1 + if last.is_pylint_comment: + last = last.previous_token + last_index = -2 + if last is None: + return True + return (last.total_length + indent_amt <= style.Get('COLUMN_LIMIT') and + not any(tok.is_comment for tok in uwline.tokens[:last_index])) + + +def _FormatFinalLines(final_lines, verify): + """Compose the final output from the finalized lines.""" + formatted_code = [] + for line in final_lines: + formatted_line = [] + for tok in line.tokens: + if not tok.is_pseudo_paren: + formatted_line.append(tok.whitespace_prefix) + formatted_line.append(tok.value) + else: + if (not tok.next_token.whitespace_prefix.startswith('\n') and + not tok.next_token.whitespace_prefix.startswith(' ')): + if (tok.previous_token.value == ':' or + tok.next_token.value not in ',}])'): + formatted_line.append(' ') + + formatted_code.append(''.join(formatted_line)) + if verify: + verifier.VerifyCode(formatted_code[-1]) + + return ''.join(formatted_code) + '\n' + + +class _StateNode(object): + """An edge in the solution space from 'previous.state' to 'state'. + + Attributes: + state: (format_decision_state.FormatDecisionState) The format decision state + for this node. + newline: If True, then on the edge from 'previous.state' to 'state' a + newline is inserted. + previous: (_StateNode) The previous state node in the graph. + """ + + # TODO(morbo): Add a '__cmp__' method. + + def __init__(self, state, newline, previous): + self.state = state.Clone() + self.newline = newline + self.previous = previous + + def __repr__(self): # pragma: no cover + return 'StateNode(state=[\n{0}\n], newline={1})'.format( + self.state, self.newline) + + +# A tuple of (penalty, count) that is used to prioritize the BFS. In case of +# equal penalties, we prefer states that were inserted first. During state +# generation, we make sure that we insert states first that break the line as +# late as possible. +_OrderedPenalty = collections.namedtuple('OrderedPenalty', ['penalty', 'count']) + +# An item in the prioritized BFS search queue. The 'StateNode's 'state' has +# the given '_OrderedPenalty'. +_QueueItem = collections.namedtuple('QueueItem', + ['ordered_penalty', 'state_node']) + + +def _AnalyzeSolutionSpace(initial_state): + """Analyze the entire solution space starting from initial_state. + + This implements a variant of Dijkstra's algorithm on the graph that spans + the solution space (LineStates are the nodes). The algorithm tries to find + the shortest path (the one with the lowest penalty) from 'initial_state' to + the state where all tokens are placed. + + Arguments: + initial_state: (format_decision_state.FormatDecisionState) The initial state + to start the search from. + + Returns: + True if a formatting solution was found. False otherwise. + """ + count = 0 + seen = set() + p_queue = [] + + # Insert start element. + node = _StateNode(initial_state, False, None) + heapq.heappush(p_queue, _QueueItem(_OrderedPenalty(0, count), node)) + + count += 1 + while p_queue: + item = p_queue[0] + penalty = item.ordered_penalty.penalty + node = item.state_node + if not node.state.next_token: + break + heapq.heappop(p_queue) + + if count > 10000: + node.state.ignore_stack_for_comparison = True + + if node.state in seen: + continue + + seen.add(node.state) + + # FIXME(morbo): Add a 'decision' element? + + count = _AddNextStateToQueue(penalty, node, False, count, p_queue) + count = _AddNextStateToQueue(penalty, node, True, count, p_queue) + + if not p_queue: + # We weren't able to find a solution. Do nothing. + return False + + _ReconstructPath(initial_state, heapq.heappop(p_queue).state_node) + return True + + +def _AddNextStateToQueue(penalty, previous_node, newline, count, p_queue): + """Add the following state to the analysis queue. + + Assume the current state is 'previous_node' and has been reached with a + penalty of 'penalty'. Insert a line break if 'newline' is True. + + Arguments: + penalty: (int) The penalty associated with the path up to this point. + previous_node: (_StateNode) The last _StateNode inserted into the priority + queue. + newline: (bool) Add a newline if True. + count: (int) The number of elements in the queue. + p_queue: (heapq) The priority queue representing the solution space. + + Returns: + The updated number of elements in the queue. + """ + must_split = previous_node.state.MustSplit() + if newline and not previous_node.state.CanSplit(must_split): + # Don't add a newline if the token cannot be split. + return count + if not newline and must_split: + # Don't add a token we must split but where we aren't splitting. + return count + + node = _StateNode(previous_node.state, newline, previous_node) + penalty += node.state.AddTokenToState( + newline=newline, dry_run=True, must_split=must_split) + heapq.heappush(p_queue, _QueueItem(_OrderedPenalty(penalty, count), node)) + return count + 1 + + +def _ReconstructPath(initial_state, current): + """Reconstruct the path through the queue with lowest penalty. + + Arguments: + initial_state: (format_decision_state.FormatDecisionState) The initial state + to start the search from. + current: (_StateNode) The node in the decision graph that is the end point + of the path with the least penalty. + """ + path = collections.deque() + + while current.previous: + path.appendleft(current) + current = current.previous + + for node in path: + initial_state.AddTokenToState(newline=node.newline, dry_run=False) + + +def _FormatFirstToken(first_token, indent_depth, prev_uwline, final_lines): + """Format the first token in the unwrapped line. + + Add a newline and the required indent before the first token of the unwrapped + line. + + Arguments: + first_token: (format_token.FormatToken) The first token in the unwrapped + line. + indent_depth: (int) The line's indentation depth. + prev_uwline: (list of unwrapped_line.UnwrappedLine) The unwrapped line + previous to this line. + final_lines: (list of unwrapped_line.UnwrappedLine) The unwrapped lines + that have already been processed. + """ + first_token.AddWhitespacePrefix( + _CalculateNumberOfNewlines(first_token, indent_depth, prev_uwline, + final_lines), + indent_level=indent_depth) + + +NO_BLANK_LINES = 1 +ONE_BLANK_LINE = 2 +TWO_BLANK_LINES = 3 + + +def _CalculateNumberOfNewlines(first_token, indent_depth, prev_uwline, + final_lines): + """Calculate the number of newlines we need to add. + + Arguments: + first_token: (format_token.FormatToken) The first token in the unwrapped + line. + indent_depth: (int) The line's indentation depth. + prev_uwline: (list of unwrapped_line.UnwrappedLine) The unwrapped line + previous to this line. + final_lines: (list of unwrapped_line.UnwrappedLine) The unwrapped lines + that have already been processed. + + Returns: + The number of newlines needed before the first token. + """ + # TODO(morbo): Special handling for imports. + # TODO(morbo): Create a knob that can tune these. + if prev_uwline is None: + # The first line in the file. Don't add blank lines. + # FIXME(morbo): Is this correct? + if first_token.newlines is not None: + pytree_utils.SetNodeAnnotation(first_token.node, + pytree_utils.Annotation.NEWLINES, None) + return 0 + + if first_token.is_docstring: + if (prev_uwline.first.value == 'class' and + style.Get('BLANK_LINE_BEFORE_CLASS_DOCSTRING')): + # Enforce a blank line before a class's docstring. + return ONE_BLANK_LINE + # The docstring shouldn't have a newline before it. + return NO_BLANK_LINES + + prev_last_token = prev_uwline.last + if prev_last_token.is_docstring: + if (not indent_depth and first_token.value in {'class', 'def', 'async'}): + # Separate a class or function from the module-level docstring with two + # blank lines. + return TWO_BLANK_LINES + if _NoBlankLinesBeforeCurrentToken(prev_last_token.value, first_token, + prev_last_token): + return NO_BLANK_LINES + else: + return ONE_BLANK_LINE + + if first_token.value in {'class', 'def', 'async', '@'}: + # TODO(morbo): This can go once the blank line calculator is more + # sophisticated. + if not indent_depth: + # This is a top-level class or function. + is_inline_comment = prev_last_token.whitespace_prefix.count('\n') == 0 + if (not prev_uwline.disable and prev_last_token.is_comment and + not is_inline_comment): + # This token follows a non-inline comment. + if _NoBlankLinesBeforeCurrentToken(prev_last_token.value, first_token, + prev_last_token): + # Assume that the comment is "attached" to the current line. + # Therefore, we want two blank lines before the comment. + index = len(final_lines) - 1 + while index > 0: + if not final_lines[index - 1].is_comment: + break + index -= 1 + if final_lines[index - 1].first.value == '@': + final_lines[index].first.AdjustNewlinesBefore(NO_BLANK_LINES) + else: + prev_last_token.AdjustNewlinesBefore(TWO_BLANK_LINES) + if first_token.newlines is not None: + pytree_utils.SetNodeAnnotation( + first_token.node, pytree_utils.Annotation.NEWLINES, None) + return NO_BLANK_LINES + elif prev_uwline.first.value in {'class', 'def', 'async'}: + if not style.Get('BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF'): + pytree_utils.SetNodeAnnotation(first_token.node, + pytree_utils.Annotation.NEWLINES, None) + return NO_BLANK_LINES + + # Calculate how many newlines were between the original lines. We want to + # retain that formatting if it doesn't violate one of the style guide rules. + if first_token.is_comment: + first_token_lineno = first_token.lineno - first_token.value.count('\n') + else: + first_token_lineno = first_token.lineno + + prev_last_token_lineno = prev_last_token.lineno + if prev_last_token.is_multiline_string: + prev_last_token_lineno += prev_last_token.value.count('\n') + + if first_token_lineno - prev_last_token_lineno > 1: + return ONE_BLANK_LINE + + return NO_BLANK_LINES + + +def _SingleOrMergedLines(uwlines): + """Generate the lines we want to format. + + Arguments: + uwlines: (list of unwrapped_line.UnwrappedLine) Lines we want to format. + + Yields: + Either a single line, if the current line cannot be merged with the + succeeding line, or the next two lines merged into one line. + """ + index = 0 + last_was_merged = False + while index < len(uwlines): + if uwlines[index].disable: + uwline = uwlines[index] + index += 1 + while index < len(uwlines): + column = uwline.last.column + 2 + if uwlines[index].lineno != uwline.lineno: + break + if uwline.last.value != ':': + leaf = pytree.Leaf( + type=token.SEMI, value=';', context=('', (uwline.lineno, column))) + uwline.AppendToken(format_token.FormatToken(leaf)) + for tok in uwlines[index].tokens: + uwline.AppendToken(tok) + index += 1 + yield uwline + elif line_joiner.CanMergeMultipleLines(uwlines[index:], last_was_merged): + # TODO(morbo): This splice is potentially very slow. Come up with a more + # performance-friendly way of determining if two lines can be merged. + next_uwline = uwlines[index + 1] + for tok in next_uwline.tokens: + uwlines[index].AppendToken(tok) + if (len(next_uwline.tokens) == 1 and + next_uwline.first.is_multiline_string): + # This may be a multiline shebang. In that case, we want to retain the + # formatting. Otherwise, it could mess up the shell script's syntax. + uwlines[index].disable = True + yield uwlines[index] + index += 2 + last_was_merged = True + else: + yield uwlines[index] + index += 1 + last_was_merged = False + + +def _NoBlankLinesBeforeCurrentToken(text, cur_token, prev_token): + """Determine if there are no blank lines before the current token. + + The previous token is a docstring or comment. The prev_token_lineno is the + start of the text of that token. Counting the number of newlines in its text + gives us the extent and thus where the line number of the end of the + docstring or comment. After that, we just compare it to the current token's + line number to see if there are blank lines between them. + + Arguments: + text: (unicode) The text of the docstring or comment before the current + token. + cur_token: (format_token.FormatToken) The current token in the unwrapped + line. + prev_token: (format_token.FormatToken) The previous token in the unwrapped + line. + + Returns: + True if there is no blank line before the current token. + """ + cur_token_lineno = cur_token.lineno + if cur_token.is_comment: + cur_token_lineno -= cur_token.value.count('\n') + num_newlines = text.count('\n') if not prev_token.is_comment else 0 + return prev_token.lineno + num_newlines == cur_token_lineno - 1 diff --git a/lib/jcef/tools/yapf/yapf/yapflib/split_penalty.py b/lib/jcef/tools/yapf/yapf/yapflib/split_penalty.py new file mode 100644 index 0000000..3ef4d8c --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/split_penalty.py @@ -0,0 +1,559 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Computation of split penalties before/between tokens.""" + +from lib2to3 import pytree + +from yapf.yapflib import format_token +from yapf.yapflib import py3compat +from yapf.yapflib import pytree_utils +from yapf.yapflib import pytree_visitor +from yapf.yapflib import style + +# TODO(morbo): Document the annotations in a centralized place. E.g., the +# README file. +UNBREAKABLE = 1000 * 1000 +NAMED_ASSIGN = 8500 +DOTTED_NAME = 4000 +VERY_STRONGLY_CONNECTED = 3500 +STRONGLY_CONNECTED = 3000 + +OR_TEST = 1000 +AND_TEST = 1100 +NOT_TEST = 1200 +COMPARISON = 1300 +STAR_EXPR = 1300 +EXPR = 1400 +XOR_EXPR = 1500 +AND_EXPR = 1700 +SHIFT_EXPR = 1800 +ARITH_EXPR = 1900 +TERM = 2000 +FACTOR = 2100 +POWER = 2200 +ATOM = 2300 +ONE_ELEMENT_ARGUMENT = 2500 + + +def ComputeSplitPenalties(tree): + """Compute split penalties on tokens in the given parse tree. + + Arguments: + tree: the top-level pytree node to annotate with penalties. + """ + _SplitPenaltyAssigner().Visit(tree) + + +class _SplitPenaltyAssigner(pytree_visitor.PyTreeVisitor): + """Assigns split penalties to tokens, based on parse tree structure. + + Split penalties are attached as annotations to tokens. + """ + + def Visit_import_as_names(self, node): # pyline: disable=invalid-name + # import_as_names ::= import_as_name (',' import_as_name)* [','] + self.DefaultNodeVisit(node) + prev_child = None + for child in node.children: + if (prev_child and isinstance(prev_child, pytree.Leaf) and + prev_child.value == ','): + _SetSplitPenalty(child, style.Get('SPLIT_PENALTY_IMPORT_NAMES')) + prev_child = child + + def Visit_classdef(self, node): # pylint: disable=invalid-name + # classdef ::= 'class' NAME ['(' [arglist] ')'] ':' suite + # + # NAME + _SetUnbreakable(node.children[1]) + if len(node.children) > 4: + # opening '(' + _SetUnbreakable(node.children[2]) + # ':' + _SetUnbreakable(node.children[-2]) + self.DefaultNodeVisit(node) + + def Visit_funcdef(self, node): # pylint: disable=invalid-name + # funcdef ::= 'def' NAME parameters ['->' test] ':' suite + # + # Can't break before the function name and before the colon. The parameters + # are handled by child iteration. + colon_idx = 1 + while pytree_utils.NodeName(node.children[colon_idx]) == 'simple_stmt': + colon_idx += 1 + _SetUnbreakable(node.children[colon_idx]) + arrow_idx = -1 + while colon_idx < len(node.children): + if isinstance(node.children[colon_idx], pytree.Leaf): + if node.children[colon_idx].value == ':': + break + if node.children[colon_idx].value == '->': + arrow_idx = colon_idx + colon_idx += 1 + _SetUnbreakable(node.children[colon_idx]) + self.DefaultNodeVisit(node) + if arrow_idx > 0: + _SetSplitPenalty(_LastChildNode(node.children[arrow_idx - 1]), 0) + _SetUnbreakable(node.children[arrow_idx]) + _SetStronglyConnected(node.children[arrow_idx + 1]) + + def Visit_lambdef(self, node): # pylint: disable=invalid-name + # lambdef ::= 'lambda' [varargslist] ':' test + # Loop over the lambda up to and including the colon. + if style.Get('ALLOW_MULTILINE_LAMBDAS'): + _SetStronglyConnected(node) + else: + self._SetUnbreakableOnChildren(node) + + def Visit_parameters(self, node): # pylint: disable=invalid-name + # parameters ::= '(' [typedargslist] ')' + self.DefaultNodeVisit(node) + + # Can't break before the opening paren of a parameter list. + _SetUnbreakable(node.children[0]) + if not style.Get('DEDENT_CLOSING_BRACKETS'): + _SetStronglyConnected(node.children[-1]) + + def Visit_arglist(self, node): # pylint: disable=invalid-name + # arglist ::= argument (',' argument)* [','] + self.DefaultNodeVisit(node) + index = 1 + while index < len(node.children): + child = node.children[index] + if isinstance(child, pytree.Leaf) and child.value == ',': + _SetUnbreakable(child) + index += 1 + + def Visit_argument(self, node): # pylint: disable=invalid-name + # argument ::= test [comp_for] | test '=' test # Really [keyword '='] test + self.DefaultNodeVisit(node) + + index = 1 + while index < len(node.children) - 1: + child = node.children[index] + if isinstance(child, pytree.Leaf) and child.value == '=': + _SetSplitPenalty(_FirstChildNode(node.children[index]), NAMED_ASSIGN) + _SetSplitPenalty( + _FirstChildNode(node.children[index + 1]), NAMED_ASSIGN) + index += 1 + + def Visit_dotted_name(self, node): # pylint: disable=invalid-name + # dotted_name ::= NAME ('.' NAME)* + self._SetUnbreakableOnChildren(node) + + def Visit_dictsetmaker(self, node): # pylint: disable=invalid-name + # dictsetmaker ::= ( (test ':' test + # (comp_for | (',' test ':' test)* [','])) | + # (test (comp_for | (',' test)* [','])) ) + for child in node.children: + self.Visit(child) + if pytree_utils.NodeName(child) == 'COLON': + # This is a key to a dictionary. We don't want to split the key if at + # all possible. + _SetStronglyConnected(child) + + def Visit_trailer(self, node): # pylint: disable=invalid-name + # trailer ::= '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME + self.DefaultNodeVisit(node) + if node.children[0].value == '.': + self._SetUnbreakableOnChildren(node) + _SetSplitPenalty(node.children[1], DOTTED_NAME) + elif len(node.children) == 2: + # Don't split an empty argument list if at all possible. + _SetSplitPenalty(node.children[1], VERY_STRONGLY_CONNECTED) + elif len(node.children) == 3: + name = pytree_utils.NodeName(node.children[1]) + if name == 'power': + if pytree_utils.NodeName(node.children[1].children[0]) != 'atom': + # Don't split an argument list with one element if at all possible. + _SetStronglyConnected(node.children[1], node.children[2]) + _SetSplitPenalty( + _FirstChildNode(node.children[1]), ONE_ELEMENT_ARGUMENT) + elif (pytree_utils.NodeName(node.children[0]) == 'LSQB' and + len(node.children[1].children) > 2 and + (name.endswith('_test') or name.endswith('_expr'))): + _SetStronglyConnected(node.children[1].children[0]) + _SetStronglyConnected(node.children[1].children[2]) + + # Still allow splitting around the operator. + split_before = ((name.endswith('_test') and + style.Get('SPLIT_BEFORE_LOGICAL_OPERATOR')) or + (name.endswith('_expr') and + style.Get('SPLIT_BEFORE_BITWISE_OPERATOR'))) + if split_before: + _SetSplitPenalty(_LastChildNode(node.children[1].children[1]), 0) + else: + _SetSplitPenalty(_FirstChildNode(node.children[1].children[2]), 0) + + # Don't split the ending bracket of a subscript list. + _SetVeryStronglyConnected(node.children[-1]) + elif name not in { + 'arglist', 'argument', 'term', 'or_test', 'and_test', 'comparison', + 'atom' + }: + # Don't split an argument list with one element if at all possible. + _SetStronglyConnected(node.children[1], node.children[2]) + + def Visit_power(self, node): # pylint: disable=invalid-name,missing-docstring + # power ::= atom trailer* ['**' factor] + self.DefaultNodeVisit(node) + + # When atom is followed by a trailer, we can not break between them. + # E.g. arr[idx] - no break allowed between 'arr' and '['. + if (len(node.children) > 1 and + pytree_utils.NodeName(node.children[1]) == 'trailer'): + # children[1] itself is a whole trailer: we don't want to + # mark all of it as unbreakable, only its first token: (, [ or . + _SetUnbreakable(node.children[1].children[0]) + + # A special case when there are more trailers in the sequence. Given: + # atom tr1 tr2 + # The last token of tr1 and the first token of tr2 comprise an unbreakable + # region. For example: foo.bar.baz(1) + # We can't put breaks between either of the '.', '(', or '[' and the names + # *preceding* them. + prev_trailer_idx = 1 + while prev_trailer_idx < len(node.children) - 1: + cur_trailer_idx = prev_trailer_idx + 1 + cur_trailer = node.children[cur_trailer_idx] + if pytree_utils.NodeName(cur_trailer) == 'trailer': + # Now we know we have two trailers one after the other + prev_trailer = node.children[prev_trailer_idx] + if prev_trailer.children[-1].value != ')': + # Set the previous node unbreakable if it's not a function call: + # atom tr1() tr2 + # It may be necessary (though undesirable) to split up a previous + # function call's parentheses to the next line. + _SetStronglyConnected(prev_trailer.children[-1]) + _SetStronglyConnected(cur_trailer.children[0]) + prev_trailer_idx = cur_trailer_idx + else: + break + + # We don't want to split before the last ')' of a function call. This also + # takes care of the special case of: + # atom tr1 tr2 ... trn + # where the 'tr#' are trailers that may end in a ')'. + for trailer in node.children[1:]: + if pytree_utils.NodeName(trailer) != 'trailer': + break + if trailer.children[0].value in '([': + if len(trailer.children) > 2: + subtypes = pytree_utils.GetNodeAnnotation( + trailer.children[0], pytree_utils.Annotation.SUBTYPE) + if subtypes and format_token.Subtype.SUBSCRIPT_BRACKET in subtypes: + _SetStronglyConnected(_FirstChildNode(trailer.children[1])) + + last_child_node = _LastChildNode(trailer) + if last_child_node.value.strip().startswith('#'): + last_child_node = last_child_node.prev_sibling + if not style.Get('DEDENT_CLOSING_BRACKETS'): + if _LastChildNode(last_child_node.prev_sibling).value != ',': + if last_child_node.value == ']': + _SetUnbreakable(last_child_node) + else: + _SetSplitPenalty(last_child_node, VERY_STRONGLY_CONNECTED) + else: + # If the trailer's children are '()', then make it a strongly + # connected region. It's sometimes necessary, though undesirable, to + # split the two. + _SetStronglyConnected(trailer.children[-1]) + + # If the original source has a "builder" style calls, then we should allow + # the reformatter to retain that. + _AllowBuilderStyleCalls(node) + + def Visit_subscript(self, node): # pylint: disable=invalid-name + # subscript ::= test | [test] ':' [test] [sliceop] + _SetStronglyConnected(*node.children) + self.DefaultNodeVisit(node) + + def Visit_comp_for(self, node): # pylint: disable=invalid-name + # comp_for ::= 'for' exprlist 'in' testlist_safe [comp_iter] + _SetSplitPenalty(_FirstChildNode(node), 0) + _SetStronglyConnected(*node.children[1:]) + self.DefaultNodeVisit(node) + + def Visit_comp_if(self, node): # pylint: disable=invalid-name + # comp_if ::= 'if' old_test [comp_iter] + _SetSplitPenalty(node.children[0], + style.Get('SPLIT_PENALTY_BEFORE_IF_EXPR')) + _SetStronglyConnected(*node.children[1:]) + self.DefaultNodeVisit(node) + + def Visit_or_test(self, node): # pylint: disable=invalid-name + # or_test ::= and_test ('or' and_test)* + self.DefaultNodeVisit(node) + _IncreasePenalty(node, OR_TEST) + index = 1 + while index + 1 < len(node.children): + if style.Get('SPLIT_BEFORE_LOGICAL_OPERATOR'): + _DecrementSplitPenalty(_FirstChildNode(node.children[index]), OR_TEST) + else: + _DecrementSplitPenalty( + _FirstChildNode(node.children[index + 1]), OR_TEST) + index += 2 + + def Visit_and_test(self, node): # pylint: disable=invalid-name + # and_test ::= not_test ('and' not_test)* + self.DefaultNodeVisit(node) + _IncreasePenalty(node, AND_TEST) + index = 1 + while index + 1 < len(node.children): + if style.Get('SPLIT_BEFORE_LOGICAL_OPERATOR'): + _DecrementSplitPenalty(_FirstChildNode(node.children[index]), AND_TEST) + else: + _DecrementSplitPenalty( + _FirstChildNode(node.children[index + 1]), AND_TEST) + index += 2 + + def Visit_not_test(self, node): # pylint: disable=invalid-name + # not_test ::= 'not' not_test | comparison + self.DefaultNodeVisit(node) + _IncreasePenalty(node, NOT_TEST) + + def Visit_comparison(self, node): # pylint: disable=invalid-name + # comparison ::= expr (comp_op expr)* + self.DefaultNodeVisit(node) + if len(node.children) == 3 and _StronglyConnectedCompOp(node): + _SetSplitPenalty(_FirstChildNode(node.children[1]), STRONGLY_CONNECTED) + _SetSplitPenalty(_FirstChildNode(node.children[2]), STRONGLY_CONNECTED) + else: + _IncreasePenalty(node, COMPARISON) + + def Visit_star_expr(self, node): # pylint: disable=invalid-name + # star_expr ::= '*' expr + self.DefaultNodeVisit(node) + _IncreasePenalty(node, STAR_EXPR) + + def Visit_expr(self, node): # pylint: disable=invalid-name + # expr ::= xor_expr ('|' xor_expr)* + self.DefaultNodeVisit(node) + _IncreasePenalty(node, EXPR) + index = 1 + while index < len(node.children) - 1: + child = node.children[index] + if isinstance(child, pytree.Leaf) and child.value == '|': + if style.Get('SPLIT_BEFORE_BITWISE_OPERATOR'): + _SetSplitPenalty(child, style.Get('SPLIT_PENALTY_BITWISE_OPERATOR')) + else: + _SetSplitPenalty( + _FirstChildNode(node.children[index + 1]), + style.Get('SPLIT_PENALTY_BITWISE_OPERATOR')) + index += 1 + + def Visit_xor_expr(self, node): # pylint: disable=invalid-name + # xor_expr ::= and_expr ('^' and_expr)* + self.DefaultNodeVisit(node) + _IncreasePenalty(node, XOR_EXPR) + + def Visit_and_expr(self, node): # pylint: disable=invalid-name + # and_expr ::= shift_expr ('&' shift_expr)* + self.DefaultNodeVisit(node) + _IncreasePenalty(node, AND_EXPR) + + def Visit_shift_expr(self, node): # pylint: disable=invalid-name + # shift_expr ::= arith_expr (('<<'|'>>') arith_expr)* + self.DefaultNodeVisit(node) + _IncreasePenalty(node, SHIFT_EXPR) + + def Visit_arith_expr(self, node): # pylint: disable=invalid-name + # arith_expr ::= term (('+'|'-') term)* + self.DefaultNodeVisit(node) + _IncreasePenalty(node, ARITH_EXPR) + + def Visit_term(self, node): # pylint: disable=invalid-name + # term ::= factor (('*'|'@'|'/'|'%'|'//') factor)* + _IncreasePenalty(node, TERM) + self.DefaultNodeVisit(node) + + def Visit_factor(self, node): # pyline: disable=invalid-name + # factor ::= ('+'|'-'|'~') factor | power + self.DefaultNodeVisit(node) + _IncreasePenalty(node, FACTOR) + + def Visit_atom(self, node): # pylint: disable=invalid-name + # atom ::= ('(' [yield_expr|testlist_gexp] ')' + # '[' [listmaker] ']' | + # '{' [dictsetmaker] '}') + self.DefaultNodeVisit(node) + if node.children[0].value == '(': + if node.children[-1].value == ')': + if pytree_utils.NodeName(node.parent) == 'if_stmt': + _SetSplitPenalty(node.children[-1], UNBREAKABLE) + else: + if len(node.children) > 2: + _SetSplitPenalty(_FirstChildNode(node.children[1]), EXPR) + _SetSplitPenalty(node.children[-1], ATOM) + elif node.children[0].value in '[{' and len(node.children) == 2: + # Keep empty containers together if we can. + _SetUnbreakable(node.children[-1]) + + def Visit_testlist_gexp(self, node): # pylint: disable=invalid-name + self.DefaultNodeVisit(node) + prev_was_comma = False + for child in node.children: + if isinstance(child, pytree.Leaf) and child.value == ',': + _SetUnbreakable(child) + prev_was_comma = True + else: + if prev_was_comma: + _SetSplitPenalty(_FirstChildNode(child), 0) + prev_was_comma = False + + ############################################################################ + # Helper methods that set the annotations. + + def _SetUnbreakableOnChildren(self, node): + """Set an UNBREAKABLE penalty annotation on children of node.""" + for child in node.children: + self.Visit(child) + start = 2 if hasattr(node.children[0], 'is_pseudo') else 1 + for i in py3compat.range(start, len(node.children)): + _SetUnbreakable(node.children[i]) + + +def _SetUnbreakable(node): + """Set an UNBREAKABLE penalty annotation for the given node.""" + _RecAnnotate(node, pytree_utils.Annotation.SPLIT_PENALTY, UNBREAKABLE) + + +def _SetStronglyConnected(*nodes): + """Set a STRONGLY_CONNECTED penalty annotation for the given nodes.""" + for node in nodes: + _RecAnnotate(node, pytree_utils.Annotation.SPLIT_PENALTY, + STRONGLY_CONNECTED) + + +def _SetVeryStronglyConnected(*nodes): + """Set a VERY_STRONGLY_CONNECTED penalty annotation for the given nodes.""" + for node in nodes: + _RecAnnotate(node, pytree_utils.Annotation.SPLIT_PENALTY, + VERY_STRONGLY_CONNECTED) + + +def _SetExpressionPenalty(node, penalty): + """Set a penalty annotation on children nodes.""" + + def RecExpression(node, first_child_leaf): + if node is first_child_leaf: + return + + if isinstance(node, pytree.Leaf): + if node.value in {'(', 'for', 'if'}: + return + penalty_annotation = pytree_utils.GetNodeAnnotation( + node, pytree_utils.Annotation.SPLIT_PENALTY, default=0) + if penalty_annotation < penalty: + _SetSplitPenalty(node, penalty) + else: + for child in node.children: + RecExpression(child, first_child_leaf) + + RecExpression(node, _FirstChildNode(node)) + + +def _IncreasePenalty(node, amt): + """Increase a penalty annotation on children nodes.""" + + def RecExpression(node, first_child_leaf): + if node is first_child_leaf: + return + + if isinstance(node, pytree.Leaf): + if node.value in {'(', 'for', 'if'}: + return + penalty = pytree_utils.GetNodeAnnotation( + node, pytree_utils.Annotation.SPLIT_PENALTY, default=0) + _SetSplitPenalty(node, penalty + amt) + else: + for child in node.children: + RecExpression(child, first_child_leaf) + + RecExpression(node, _FirstChildNode(node)) + + +def _RecAnnotate(tree, annotate_name, annotate_value): + """Recursively set the given annotation on all leafs of the subtree. + + Takes care to only increase the penalty. If the node already has a higher + or equal penalty associated with it, this is a no-op. + + Args: + tree: subtree to annotate + annotate_name: name of the annotation to set + annotate_value: value of the annotation to set + """ + for child in tree.children: + _RecAnnotate(child, annotate_name, annotate_value) + if isinstance(tree, pytree.Leaf): + cur_annotate = pytree_utils.GetNodeAnnotation( + tree, annotate_name, default=0) + if cur_annotate < annotate_value: + pytree_utils.SetNodeAnnotation(tree, annotate_name, annotate_value) + + +def _StronglyConnectedCompOp(op): + if (len(op.children[1].children) == 2 and + pytree_utils.NodeName(op.children[1]) == 'comp_op' and + _FirstChildNode(op.children[1]).value == 'not' and + _LastChildNode(op.children[1]).value == 'in'): + return True + if (isinstance(op.children[1], pytree.Leaf) and + op.children[1].value in {'==', 'in'}): + return True + return False + + +def _DecrementSplitPenalty(node, amt): + penalty = pytree_utils.GetNodeAnnotation( + node, pytree_utils.Annotation.SPLIT_PENALTY, default=amt) + penalty = penalty - amt if amt < penalty else 0 + _SetSplitPenalty(node, penalty) + + +def _SetSplitPenalty(node, penalty): + pytree_utils.SetNodeAnnotation(node, pytree_utils.Annotation.SPLIT_PENALTY, + penalty) + + +def _AllowBuilderStyleCalls(node): + """Allow splitting before '.' if it's a builder style function call.""" + + def RecGetLeaves(node): + if isinstance(node, pytree.Leaf): + return [node] + children = [] + for child in node.children: + children += RecGetLeaves(child) + return children + + list_of_children = RecGetLeaves(node) + prev_child = None + for child in list_of_children: + if child.value == '.': + if prev_child.lineno != child.lineno: + _SetSplitPenalty(child, 0) + prev_child = child + + +def _FirstChildNode(node): + if isinstance(node, pytree.Leaf): + return node + return _FirstChildNode(node.children[0]) + + +def _LastChildNode(node): + if isinstance(node, pytree.Leaf): + return node + return _LastChildNode(node.children[-1]) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/style.py b/lib/jcef/tools/yapf/yapf/yapflib/style.py new file mode 100644 index 0000000..14be59e --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/style.py @@ -0,0 +1,489 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Python formatting style settings.""" + +import os +import re +import textwrap + +from yapf.yapflib import errors +from yapf.yapflib import py3compat + + +class StyleConfigError(errors.YapfError): + """Raised when there's a problem reading the style configuration.""" + pass + + +def Get(setting_name): + """Get a style setting.""" + return _style[setting_name] + + +def Help(): + """Return dict mapping style names to help strings.""" + return _STYLE_HELP + + +def SetGlobalStyle(style): + """Set a style dict.""" + global _style + global _GLOBAL_STYLE_FACTORY + factory = _GetStyleFactory(style) + if factory: + _GLOBAL_STYLE_FACTORY = factory + _style = style + + +_STYLE_HELP = dict( + ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT=textwrap.dedent("""\ + Align closing bracket with visual indentation."""), + ALLOW_MULTILINE_LAMBDAS=textwrap.dedent("""\ + Allow lambdas to be formatted on more than one line."""), + ALLOW_MULTILINE_DICTIONARY_KEYS=textwrap.dedent("""\ + Allow dictionary keys to exist on multiple lines. For example: + + x = { + ('this is the first element of a tuple', + 'this is the second element of a tuple'): + value, + }"""), + BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=textwrap.dedent("""\ + Insert a blank line before a 'def' or 'class' immediately nested + within another 'def' or 'class'. For example: + + class Foo: + # <------ this blank line + def method(): + ..."""), + BLANK_LINE_BEFORE_CLASS_DOCSTRING=textwrap.dedent("""\ + Insert a blank line before a class-level docstring."""), + COALESCE_BRACKETS=textwrap.dedent("""\ + Do not split consecutive brackets. Only relevant when + dedent_closing_brackets is set. For example: + + call_func_that_takes_a_dict( + { + 'key1': 'value1', + 'key2': 'value2', + } + ) + + would reformat to: + + call_func_that_takes_a_dict({ + 'key1': 'value1', + 'key2': 'value2', + })"""), + COLUMN_LIMIT=textwrap.dedent("""\ + The column limit."""), + CONTINUATION_INDENT_WIDTH=textwrap.dedent("""\ + Indent width used for line continuations."""), + DEDENT_CLOSING_BRACKETS=textwrap.dedent("""\ + Put closing brackets on a separate line, dedented, if the bracketed + expression can't fit in a single line. Applies to all kinds of brackets, + including function definitions and calls. For example: + + config = { + 'key1': 'value1', + 'key2': 'value2', + } # <--- this bracket is dedented and on a separate line + + time_series = self.remote_client.query_entity_counters( + entity='dev3246.region1', + key='dns.query_latency_tcp', + transform=Transformation.AVERAGE(window=timedelta(seconds=60)), + start_ts=now()-timedelta(days=3), + end_ts=now(), + ) # <--- this bracket is dedented and on a separate line"""), + EACH_DICT_ENTRY_ON_SEPARATE_LINE=textwrap.dedent("""\ + Place each dictionary entry onto its own line."""), + I18N_COMMENT=textwrap.dedent("""\ + The regex for an i18n comment. The presence of this comment stops + reformatting of that line, because the comments are required to be + next to the string they translate."""), + I18N_FUNCTION_CALL=textwrap.dedent("""\ + The i18n function call names. The presence of this function stops + reformattting on that line, because the string it has cannot be moved + away from the i18n comment."""), + INDENT_DICTIONARY_VALUE=textwrap.dedent("""\ + Indent the dictionary value if it cannot fit on the same line as the + dictionary key. For example: + + config = { + 'key1': + 'value1', + 'key2': value1 + + value2, + }"""), + INDENT_WIDTH=textwrap.dedent("""\ + The number of columns to use for indentation."""), + JOIN_MULTIPLE_LINES=textwrap.dedent("""\ + Join short lines into one line. E.g., single line 'if' statements."""), + SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET=textwrap.dedent("""\ + Insert a space between the ending comma and closing bracket of a list, + etc."""), + SPACES_AROUND_POWER_OPERATOR=textwrap.dedent("""\ + Use spaces around the power operator."""), + SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN=textwrap.dedent("""\ + Use spaces around default or named assigns."""), + SPACES_BEFORE_COMMENT=textwrap.dedent("""\ + The number of spaces required before a trailing comment."""), + SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED=textwrap.dedent("""\ + Split before arguments if the argument list is terminated by a + comma."""), + SPLIT_BEFORE_BITWISE_OPERATOR=textwrap.dedent("""\ + Set to True to prefer splitting before '&', '|' or '^' rather than + after."""), + SPLIT_BEFORE_DICT_SET_GENERATOR=textwrap.dedent("""\ + Split before a dictionary or set generator (comp_for). For example, note + the split before the 'for': + + foo = { + variable: 'Hello world, have a nice day!' + for variable in bar if variable != 42 + }"""), + SPLIT_BEFORE_FIRST_ARGUMENT=textwrap.dedent("""\ + If an argument / parameter list is going to be split, then split before + the first argument."""), + SPLIT_BEFORE_LOGICAL_OPERATOR=textwrap.dedent("""\ + Set to True to prefer splitting before 'and' or 'or' rather than + after."""), + SPLIT_BEFORE_NAMED_ASSIGNS=textwrap.dedent("""\ + Split named assignments onto individual lines."""), + SPLIT_PENALTY_AFTER_OPENING_BRACKET=textwrap.dedent("""\ + The penalty for splitting right after the opening bracket."""), + SPLIT_PENALTY_AFTER_UNARY_OPERATOR=textwrap.dedent("""\ + The penalty for splitting the line after a unary operator."""), + SPLIT_PENALTY_BEFORE_IF_EXPR=textwrap.dedent("""\ + The penalty for splitting right before an if expression."""), + SPLIT_PENALTY_BITWISE_OPERATOR=textwrap.dedent("""\ + The penalty of splitting the line around the '&', '|', and '^' + operators."""), + SPLIT_PENALTY_EXCESS_CHARACTER=textwrap.dedent("""\ + The penalty for characters over the column limit."""), + SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT=textwrap.dedent("""\ + The penalty incurred by adding a line split to the unwrapped line. The + more line splits added the higher the penalty."""), + SPLIT_PENALTY_IMPORT_NAMES=textwrap.dedent("""\ + The penalty of splitting a list of "import as" names. For example: + + from a_very_long_or_indented_module_name_yada_yad import (long_argument_1, + long_argument_2, + long_argument_3) + + would reformat to something like: + + from a_very_long_or_indented_module_name_yada_yad import ( + long_argument_1, long_argument_2, long_argument_3) + """), + SPLIT_PENALTY_LOGICAL_OPERATOR=textwrap.dedent("""\ + The penalty of splitting the line around the 'and' and 'or' + operators."""), + USE_TABS=textwrap.dedent("""\ + Use the Tab character for indentation."""), + # BASED_ON_STYLE='Which predefined style this style is based on', +) + + +def CreatePEP8Style(): + return dict( + ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT=True, + ALLOW_MULTILINE_LAMBDAS=False, + ALLOW_MULTILINE_DICTIONARY_KEYS=False, + BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=False, + BLANK_LINE_BEFORE_CLASS_DOCSTRING=False, + COALESCE_BRACKETS=False, + COLUMN_LIMIT=79, + CONTINUATION_INDENT_WIDTH=4, + DEDENT_CLOSING_BRACKETS=False, + EACH_DICT_ENTRY_ON_SEPARATE_LINE=True, + I18N_COMMENT='', + I18N_FUNCTION_CALL='', + INDENT_DICTIONARY_VALUE=False, + INDENT_WIDTH=4, + JOIN_MULTIPLE_LINES=True, + SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET=True, + SPACES_AROUND_POWER_OPERATOR=False, + SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN=False, + SPACES_BEFORE_COMMENT=2, + SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED=False, + SPLIT_BEFORE_BITWISE_OPERATOR=False, + SPLIT_BEFORE_DICT_SET_GENERATOR=True, + SPLIT_BEFORE_FIRST_ARGUMENT=False, + SPLIT_BEFORE_LOGICAL_OPERATOR=False, + SPLIT_BEFORE_NAMED_ASSIGNS=True, + SPLIT_PENALTY_AFTER_OPENING_BRACKET=30, + SPLIT_PENALTY_AFTER_UNARY_OPERATOR=10000, + SPLIT_PENALTY_BEFORE_IF_EXPR=0, + SPLIT_PENALTY_BITWISE_OPERATOR=300, + SPLIT_PENALTY_EXCESS_CHARACTER=4500, + SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT=30, + SPLIT_PENALTY_IMPORT_NAMES=0, + SPLIT_PENALTY_LOGICAL_OPERATOR=300, + USE_TABS=False,) + + +def CreateGoogleStyle(): + style = CreatePEP8Style() + style['ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT'] = False + style['BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF'] = True + style['COLUMN_LIMIT'] = 80 + style['INDENT_WIDTH'] = 4 + style['I18N_COMMENT'] = r'#\..*' + style['I18N_FUNCTION_CALL'] = ['N_', '_'] + style['SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET'] = False + return style + + +def CreateChromiumStyle(): + style = CreateGoogleStyle() + style['ALLOW_MULTILINE_DICTIONARY_KEYS'] = True + style['INDENT_DICTIONARY_VALUE'] = True + style['INDENT_WIDTH'] = 2 + style['JOIN_MULTIPLE_LINES'] = False + style['SPLIT_BEFORE_BITWISE_OPERATOR'] = True + return style + + +def CreateFacebookStyle(): + style = CreatePEP8Style() + style['ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT'] = False + style['COLUMN_LIMIT'] = 80 + style['DEDENT_CLOSING_BRACKETS'] = True + style['JOIN_MULTIPLE_LINES'] = False + style['SPACES_BEFORE_COMMENT'] = 2 + style['SPLIT_PENALTY_AFTER_OPENING_BRACKET'] = 0 + style['SPLIT_PENALTY_BEFORE_IF_EXPR'] = 30 + style['SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT'] = 30 + return style + + +_STYLE_NAME_TO_FACTORY = dict( + pep8=CreatePEP8Style, + chromium=CreateChromiumStyle, + google=CreateGoogleStyle, + facebook=CreateFacebookStyle,) + +_DEFAULT_STYLE_TO_FACTORY = [ + (CreateChromiumStyle(), CreateChromiumStyle), + (CreateFacebookStyle(), CreateFacebookStyle), + (CreateGoogleStyle(), CreateGoogleStyle), + (CreatePEP8Style(), CreatePEP8Style), +] + + +def _GetStyleFactory(style): + for def_style, factory in _DEFAULT_STYLE_TO_FACTORY: + if style == def_style: + return factory + return None + + +def _StringListConverter(s): + """Option value converter for a comma-separated list of strings.""" + return [part.strip() for part in s.split(',')] + + +def _BoolConverter(s): + """Option value converter for a boolean.""" + return py3compat.CONFIGPARSER_BOOLEAN_STATES[s.lower()] + + +# Different style options need to have their values interpreted differently when +# read from the config file. This dict maps an option name to a "converter" +# function that accepts the string read for the option's value from the file and +# returns it wrapper in actual Python type that's going to be meaningful to +# yapf. +# +# Note: this dict has to map all the supported style options. +_STYLE_OPTION_VALUE_CONVERTER = dict( + ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT=_BoolConverter, + ALLOW_MULTILINE_LAMBDAS=_BoolConverter, + ALLOW_MULTILINE_DICTIONARY_KEYS=_BoolConverter, + BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=_BoolConverter, + BLANK_LINE_BEFORE_CLASS_DOCSTRING=_BoolConverter, + COALESCE_BRACKETS=_BoolConverter, + COLUMN_LIMIT=int, + CONTINUATION_INDENT_WIDTH=int, + DEDENT_CLOSING_BRACKETS=_BoolConverter, + EACH_DICT_ENTRY_ON_SEPARATE_LINE=_BoolConverter, + I18N_COMMENT=str, + I18N_FUNCTION_CALL=_StringListConverter, + INDENT_DICTIONARY_VALUE=_BoolConverter, + INDENT_WIDTH=int, + JOIN_MULTIPLE_LINES=_BoolConverter, + SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET=_BoolConverter, + SPACES_AROUND_POWER_OPERATOR=_BoolConverter, + SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN=_BoolConverter, + SPACES_BEFORE_COMMENT=int, + SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED=_BoolConverter, + SPLIT_BEFORE_BITWISE_OPERATOR=_BoolConverter, + SPLIT_BEFORE_DICT_SET_GENERATOR=_BoolConverter, + SPLIT_BEFORE_FIRST_ARGUMENT=_BoolConverter, + SPLIT_BEFORE_LOGICAL_OPERATOR=_BoolConverter, + SPLIT_BEFORE_NAMED_ASSIGNS=_BoolConverter, + SPLIT_PENALTY_AFTER_OPENING_BRACKET=int, + SPLIT_PENALTY_AFTER_UNARY_OPERATOR=int, + SPLIT_PENALTY_BEFORE_IF_EXPR=int, + SPLIT_PENALTY_BITWISE_OPERATOR=int, + SPLIT_PENALTY_EXCESS_CHARACTER=int, + SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT=int, + SPLIT_PENALTY_IMPORT_NAMES=int, + SPLIT_PENALTY_LOGICAL_OPERATOR=int, + USE_TABS=_BoolConverter,) + + +def CreateStyleFromConfig(style_config): + """Create a style dict from the given config. + + Arguments: + style_config: either a style name or a file name. The file is expected to + contain settings. It can have a special BASED_ON_STYLE setting naming the + style which it derives from. If no such setting is found, it derives from + the default style. When style_config is None, the _GLOBAL_STYLE_FACTORY + config is created. + + Returns: + A style dict. + + Raises: + StyleConfigError: if an unknown style option was encountered. + """ + + def GlobalStyles(): + for style, _ in _DEFAULT_STYLE_TO_FACTORY: + yield style + + def_style = False + if style_config is None: + for style in GlobalStyles(): + if _style == style: + def_style = True + break + if not def_style: + return _style + return _GLOBAL_STYLE_FACTORY() + style_factory = _STYLE_NAME_TO_FACTORY.get(style_config.lower()) + if style_factory is not None: + return style_factory() + if style_config.startswith('{'): + # Most likely a style specification from the command line. + config = _CreateConfigParserFromConfigString(style_config) + else: + # Unknown config name: assume it's a file name then. + config = _CreateConfigParserFromConfigFile(style_config) + return _CreateStyleFromConfigParser(config) + + +def _CreateConfigParserFromConfigString(config_string): + """Given a config string from the command line, return a config parser.""" + if config_string[0] != '{' or config_string[-1] != '}': + raise StyleConfigError( + "Invalid style dict syntax: '{}'.".format(config_string)) + config = py3compat.ConfigParser() + config.add_section('style') + for key, value in re.findall(r'([a-zA-Z0-9_]+)\s*[:=]\s*([a-zA-Z0-9_]+)', + config_string): + config.set('style', key, value) + return config + + +def _CreateConfigParserFromConfigFile(config_filename): + """Read the file and return a ConfigParser object.""" + if not os.path.exists(config_filename): + # Provide a more meaningful error here. + raise StyleConfigError( + '"{0}" is not a valid style or file path'.format(config_filename)) + with open(config_filename) as style_file: + config = py3compat.ConfigParser() + config.read_file(style_file) + if config_filename.endswith(SETUP_CONFIG): + if not config.has_section('yapf'): + raise StyleConfigError( + 'Unable to find section [yapf] in {0}'.format(config_filename)) + elif config_filename.endswith(LOCAL_STYLE): + if not config.has_section('style'): + raise StyleConfigError( + 'Unable to find section [style] in {0}'.format(config_filename)) + else: + if not config.has_section('style'): + raise StyleConfigError( + 'Unable to find section [style] in {0}'.format(config_filename)) + return config + + +def _CreateStyleFromConfigParser(config): + """Create a style dict from a configuration file. + + Arguments: + config: a ConfigParser object. + + Returns: + A style dict. + + Raises: + StyleConfigError: if an unknown style option was encountered. + """ + # Initialize the base style. + section = 'yapf' if config.has_section('yapf') else 'style' + if config.has_option('style', 'based_on_style'): + based_on = config.get('style', 'based_on_style').lower() + base_style = _STYLE_NAME_TO_FACTORY[based_on]() + elif config.has_option('yapf', 'based_on_style'): + based_on = config.get('yapf', 'based_on_style').lower() + base_style = _STYLE_NAME_TO_FACTORY[based_on]() + else: + base_style = _GLOBAL_STYLE_FACTORY() + + # Read all options specified in the file and update the style. + for option, value in config.items(section): + if option.lower() == 'based_on_style': + # Now skip this one - we've already handled it and it's not one of the + # recognized style options. + continue + option = option.upper() + if option not in _STYLE_OPTION_VALUE_CONVERTER: + raise StyleConfigError('Unknown style option "{0}"'.format(option)) + try: + base_style[option] = _STYLE_OPTION_VALUE_CONVERTER[option](value) + except ValueError: + raise StyleConfigError( + "'{}' is not a valid setting for {}.".format(value, option)) + return base_style + + +# The default style - used if yapf is not invoked without specifically +# requesting a formatting style. +DEFAULT_STYLE = 'pep8' +DEFAULT_STYLE_FACTORY = CreatePEP8Style +_GLOBAL_STYLE_FACTORY = CreatePEP8Style + +# The name of the file to use for global style definition. +GLOBAL_STYLE = (os.path.join( + os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config'), 'yapf', + 'style')) + +# The name of the file to use for directory-local style definition. +LOCAL_STYLE = '.style.yapf' + +# Alternative place for directory-local style definition. Style should be +# specified in the '[yapf]' section. +SETUP_CONFIG = 'setup.cfg' + +# TODO(eliben): For now we're preserving the global presence of a style dict. +# Refactor this so that the style is passed around through yapf rather than +# being global. +_style = None +SetGlobalStyle(_GLOBAL_STYLE_FACTORY()) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/subtype_assigner.py b/lib/jcef/tools/yapf/yapf/yapflib/subtype_assigner.py new file mode 100644 index 0000000..646cdc8 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/subtype_assigner.py @@ -0,0 +1,416 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Subtype assigner for lib2to3 trees. + +This module assigns extra type information to the lib2to3 trees. This +information is more specific than whether something is an operator or an +identifier. For instance, it can specify if a node in the tree is part of a +subscript. + + AssignSubtypes(): the main function exported by this module. + +Annotations: + subtype: The subtype of a pytree token. See 'format_token' module for a list + of subtypes. +""" + +from lib2to3 import pytree +from lib2to3.pgen2 import token +from lib2to3.pygram import python_symbols as syms + +from yapf.yapflib import format_token +from yapf.yapflib import pytree_utils +from yapf.yapflib import pytree_visitor +from yapf.yapflib import style + + +def AssignSubtypes(tree): + """Run the subtype assigner visitor over the tree, modifying it in place. + + Arguments: + tree: the top-level pytree node to annotate with subtypes. + """ + subtype_assigner = _SubtypeAssigner() + subtype_assigner.Visit(tree) + + +# Map tokens in argument lists to their respective subtype. +_ARGLIST_TOKEN_TO_SUBTYPE = { + '=': format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN, + ':': format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN, + '*': format_token.Subtype.VARARGS_STAR, + '**': format_token.Subtype.KWARGS_STAR_STAR, +} + + +class _SubtypeAssigner(pytree_visitor.PyTreeVisitor): + """_SubtypeAssigner - see file-level docstring for detailed description. + + The subtype is added as an annotation to the pytree token. + """ + + def Visit_dictsetmaker(self, node): # pylint: disable=invalid-name + # dictsetmaker ::= (test ':' test (comp_for | + # (',' test ':' test)* [','])) | + # (test (comp_for | (',' test)* [','])) + for child in node.children: + self.Visit(child) + + comp_for = False + dict_maker = False + + for child in node.children: + if pytree_utils.NodeName(child) == 'comp_for': + comp_for = True + _AppendFirstLeafTokenSubtype(child, + format_token.Subtype.DICT_SET_GENERATOR) + elif pytree_utils.NodeName(child) in ('COLON', 'DOUBLESTAR'): + dict_maker = True + + if not comp_for and dict_maker: + last_was_colon = False + for child in node.children: + if dict_maker: + if pytree_utils.NodeName(child) == 'DOUBLESTAR': + _AppendFirstLeafTokenSubtype(child, + format_token.Subtype.KWARGS_STAR_STAR) + if last_was_colon: + if style.Get('INDENT_DICTIONARY_VALUE'): + _InsertPseudoParentheses(child) + else: + _AppendFirstLeafTokenSubtype( + child, format_token.Subtype.DICTIONARY_VALUE) + elif ( + child is not None and + (isinstance(child, pytree.Node) or + (not child.value.startswith('#') and child.value not in '{:,'))): + # Mark the first leaf of a key entry as a DICTIONARY_KEY. We + # normally want to split before them if the dictionary cannot exist + # on a single line. + _AppendFirstLeafTokenSubtype(child, + format_token.Subtype.DICTIONARY_KEY) + _AppendSubtypeRec(child, format_token.Subtype.DICTIONARY_KEY_PART) + last_was_colon = pytree_utils.NodeName(child) == 'COLON' + + def Visit_expr_stmt(self, node): # pylint: disable=invalid-name + # expr_stmt ::= testlist_star_expr (augassign (yield_expr|testlist) + # | ('=' (yield_expr|testlist_star_expr))*) + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == '=': + _AppendTokenSubtype(child, format_token.Subtype.ASSIGN_OPERATOR) + + def Visit_or_test(self, node): # pylint: disable=invalid-name + # or_test ::= and_test ('or' and_test)* + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == 'or': + _AppendTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR) + + def Visit_and_test(self, node): # pylint: disable=invalid-name + # and_test ::= not_test ('and' not_test)* + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == 'and': + _AppendTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR) + + def Visit_not_test(self, node): # pylint: disable=invalid-name + # not_test ::= 'not' not_test | comparison + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == 'not': + _AppendTokenSubtype(child, format_token.Subtype.UNARY_OPERATOR) + + def Visit_comparison(self, node): # pylint: disable=invalid-name + # comparison ::= expr (comp_op expr)* + # comp_op ::= '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not in'|'is'|'is not' + for child in node.children: + self.Visit(child) + if (isinstance(child, pytree.Leaf) and + child.value in {'<', '>', '==', '>=', '<=', '<>', '!=', 'in', 'is'}): + _AppendTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR) + elif pytree_utils.NodeName(child) == 'comp_op': + for grandchild in child.children: + _AppendTokenSubtype(grandchild, format_token.Subtype.BINARY_OPERATOR) + + def Visit_star_expr(self, node): # pylint: disable=invalid-name + # star_expr ::= '*' expr + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == '*': + _AppendTokenSubtype(child, format_token.Subtype.UNARY_OPERATOR) + + def Visit_expr(self, node): # pylint: disable=invalid-name + # expr ::= xor_expr ('|' xor_expr)* + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == '|': + _AppendTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR) + + def Visit_xor_expr(self, node): # pylint: disable=invalid-name + # xor_expr ::= and_expr ('^' and_expr)* + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == '^': + _AppendTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR) + + def Visit_and_expr(self, node): # pylint: disable=invalid-name + # and_expr ::= shift_expr ('&' shift_expr)* + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == '&': + _AppendTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR) + + def Visit_shift_expr(self, node): # pylint: disable=invalid-name + # shift_expr ::= arith_expr (('<<'|'>>') arith_expr)* + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value in {'<<', '>>'}: + _AppendTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR) + + def Visit_arith_expr(self, node): # pylint: disable=invalid-name + # arith_expr ::= term (('+'|'-') term)* + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value in '+-': + _AppendTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR) + + def Visit_term(self, node): # pylint: disable=invalid-name + # term ::= factor (('*'|'/'|'%'|'//') factor)* + for child in node.children: + self.Visit(child) + if (isinstance(child, pytree.Leaf) and + child.value in {'*', '/', '%', '//'}): + _AppendTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR) + + def Visit_factor(self, node): # pylint: disable=invalid-name + # factor ::= ('+'|'-'|'~') factor | power + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value in '+-~': + _AppendTokenSubtype(child, format_token.Subtype.UNARY_OPERATOR) + + def Visit_power(self, node): # pylint: disable=invalid-name + # power ::= atom trailer* ['**' factor] + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == '**': + _AppendTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR) + + def Visit_trailer(self, node): # pylint: disable=invalid-name + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value in '[]': + _AppendTokenSubtype(child, format_token.Subtype.SUBSCRIPT_BRACKET) + + def Visit_subscript(self, node): # pylint: disable=invalid-name + # subscript ::= test | [test] ':' [test] [sliceop] + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == ':': + _AppendTokenSubtype(child, format_token.Subtype.SUBSCRIPT_COLON) + + def Visit_sliceop(self, node): # pylint: disable=invalid-name + # sliceop ::= ':' [test] + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == ':': + _AppendTokenSubtype(child, format_token.Subtype.SUBSCRIPT_COLON) + + def Visit_argument(self, node): # pylint: disable=invalid-name + # argument ::= + # test [comp_for] | test '=' test + self._ProcessArgLists(node) + + def Visit_arglist(self, node): # pylint: disable=invalid-name + # arglist ::= + # (argument ',')* (argument [','] + # | '*' test (',' argument)* [',' '**' test] + # | '**' test) + self._ProcessArgLists(node) + _SetDefaultOrNamedAssignArgListSubtype(node) + + def Visit_tname(self, node): # pylint: disable=invalid-name + self._ProcessArgLists(node) + _SetDefaultOrNamedAssignArgListSubtype(node) + + def Visit_decorator(self, node): # pylint: disable=invalid-name + # decorator ::= + # '@' dotted_name [ '(' [arglist] ')' ] NEWLINE + for child in node.children: + if isinstance(child, pytree.Leaf) and child.value == '@': + _AppendTokenSubtype(child, subtype=format_token.Subtype.DECORATOR) + self.Visit(child) + + def Visit_funcdef(self, node): # pylint: disable=invalid-name + # funcdef ::= + # 'def' NAME parameters ['->' test] ':' suite + for child in node.children: + if pytree_utils.NodeName(child) == 'NAME' and child.value != 'def': + _AppendTokenSubtype(child, format_token.Subtype.FUNC_DEF) + break + for child in node.children: + self.Visit(child) + + def Visit_typedargslist(self, node): # pylint: disable=invalid-name + # typedargslist ::= + # ((tfpdef ['=' test] ',')* + # ('*' [tname] (',' tname ['=' test])* [',' '**' tname] + # | '**' tname) + # | tfpdef ['=' test] (',' tfpdef ['=' test])* [',']) + self._ProcessArgLists(node) + _SetDefaultOrNamedAssignArgListSubtype(node) + + def Visit_varargslist(self, node): # pylint: disable=invalid-name + # varargslist ::= + # ((vfpdef ['=' test] ',')* + # ('*' [vname] (',' vname ['=' test])* [',' '**' vname] + # | '**' vname) + # | vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) + self._ProcessArgLists(node) + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf) and child.value == '=': + _AppendTokenSubtype(child, format_token.Subtype.VARARGS_LIST) + + def Visit_comp_for(self, node): # pylint: disable=invalid-name + # comp_for ::= 'for' exprlist 'in' testlist_safe [comp_iter] + _AppendSubtypeRec(node, format_token.Subtype.COMP_FOR) + self.DefaultNodeVisit(node) + + def Visit_comp_if(self, node): # pylint: disable=invalid-name + # comp_if ::= 'if' old_test [comp_iter] + _AppendSubtypeRec(node, format_token.Subtype.COMP_IF) + self.DefaultNodeVisit(node) + + def _ProcessArgLists(self, node): + """Common method for processing argument lists.""" + for child in node.children: + self.Visit(child) + if isinstance(child, pytree.Leaf): + _AppendTokenSubtype( + child, + subtype=_ARGLIST_TOKEN_TO_SUBTYPE.get(child.value, + format_token.Subtype.NONE)) + + +def _SetDefaultOrNamedAssignArgListSubtype(node): + """Set named assign subtype on elements in a arg list.""" + + def HasDefaultOrNamedAssignSubtype(node): + """Return True if the arg list has a named assign subtype.""" + if isinstance(node, pytree.Leaf): + if (format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN in + pytree_utils.GetNodeAnnotation(node, pytree_utils.Annotation.SUBTYPE, + set())): + return True + return False + has_subtype = False + for child in node.children: + if pytree_utils.NodeName(child) != 'arglist': + has_subtype |= HasDefaultOrNamedAssignSubtype(child) + return has_subtype + + if HasDefaultOrNamedAssignSubtype(node): + for child in node.children: + if pytree_utils.NodeName(child) != 'COMMA': + _AppendFirstLeafTokenSubtype( + child, format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN_ARG_LIST) + + +def _AppendTokenSubtype(node, subtype): + """Append the token's subtype only if it's not already set.""" + pytree_utils.AppendNodeAnnotation(node, pytree_utils.Annotation.SUBTYPE, + subtype) + + +def _AppendFirstLeafTokenSubtype(node, subtype): + """Append the first leaf token's subtypes.""" + if isinstance(node, pytree.Leaf): + _AppendTokenSubtype(node, subtype) + return + _AppendFirstLeafTokenSubtype(node.children[0], subtype) + + +def _AppendSubtypeRec(node, subtype, force=True): + """Append the leafs in the node to the given subtype.""" + if isinstance(node, pytree.Leaf): + _AppendTokenSubtype(node, subtype) + return + for child in node.children: + _AppendSubtypeRec(child, subtype, force=force) + + +def _InsertPseudoParentheses(node): + """Insert pseudo parentheses so that dicts can be formatted correctly.""" + comment_node = None + if isinstance(node, pytree.Node): + if node.children[-1].type == token.COMMENT: + comment_node = node.children[-1].clone() + node.children[-1].remove() + + first = _GetFirstLeafNode(node) + last = _GetLastLeafNode(node) + + if first == last and first.type == token.COMMENT: + # A comment was inserted before the value, which is a pytree.Leaf. + # Encompass the dictionary's value into an ATOM node. + last = first.next_sibling + new_node = pytree.Node(syms.atom, [first.clone(), last.clone()]) + node.replace(new_node) + node = new_node + last.remove() + + first = _GetFirstLeafNode(node) + last = _GetLastLeafNode(node) + + lparen = pytree.Leaf( + token.LPAR, u'(', context=('', (first.get_lineno(), first.column - 1))) + last_lineno = last.get_lineno() + if last.type == token.STRING and '\n' in last.value: + last_lineno += last.value.count('\n') + + if last.type == token.STRING and '\n' in last.value: + last_column = len(last.value.split('\n')[-1]) + 1 + else: + last_column = last.column + len(last.value) + 1 + rparen = pytree.Leaf( + token.RPAR, u')', context=('', (last_lineno, last_column))) + + lparen.is_pseudo = True + rparen.is_pseudo = True + + if isinstance(node, pytree.Node): + node.insert_child(0, lparen) + node.append_child(rparen) + if comment_node: + node.append_child(comment_node) + _AppendFirstLeafTokenSubtype(node, format_token.Subtype.DICTIONARY_VALUE) + else: + clone = node.clone() + new_node = pytree.Node(syms.atom, [lparen, clone, rparen]) + node.replace(new_node) + _AppendFirstLeafTokenSubtype(clone, format_token.Subtype.DICTIONARY_VALUE) + + +def _GetFirstLeafNode(node): + if isinstance(node, pytree.Leaf): + return node + return _GetFirstLeafNode(node.children[0]) + + +def _GetLastLeafNode(node): + if isinstance(node, pytree.Leaf): + return node + return _GetLastLeafNode(node.children[-1]) diff --git a/lib/jcef/tools/yapf/yapf/yapflib/unwrapped_line.py b/lib/jcef/tools/yapf/yapf/yapflib/unwrapped_line.py new file mode 100644 index 0000000..dc782a9 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/unwrapped_line.py @@ -0,0 +1,497 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""UnwrappedLine primitive for formatting. + +An unwrapped line is the containing data structure produced by the parser. It +collects all nodes (stored in FormatToken objects) that could appear on a +single line if there were no line length restrictions. It's then used by the +parser to perform the wrapping required to comply with the style guide. +""" + +from yapf.yapflib import format_token +from yapf.yapflib import py3compat +from yapf.yapflib import pytree_utils +from yapf.yapflib import split_penalty +from yapf.yapflib import style + + +class UnwrappedLine(object): + """Represents a single unwrapped line in the output. + + Attributes: + depth: indentation depth of this line. This is just a numeric value used to + distinguish lines that are more deeply nested than others. It is not the + actual amount of spaces, which is style-dependent. + """ + + def __init__(self, depth, tokens=None): + """Constructor. + + Creates a new unwrapped line with the given depth an initial list of tokens. + Constructs the doubly-linked lists for format tokens using their built-in + next_token and previous_token attributes. + + Arguments: + depth: indentation depth of this line + tokens: initial list of tokens + """ + self.depth = depth + self._tokens = tokens or [] + self.disable = False + + if self._tokens: + # Set up a doubly linked list. + for index, tok in enumerate(self._tokens[1:]): + # Note, 'index' is the index to the previous token. + tok.previous_token = self._tokens[index] + self._tokens[index].next_token = tok + + def CalculateFormattingInformation(self): + """Calculate the split penalty and total length for the tokens.""" + # Say that the first token in the line should have a space before it. This + # means only that if this unwrapped line is joined with a predecessor line, + # then there will be a space between them. + self.first.spaces_required_before = 1 + self.first.total_length = len(self.first.value) + + prev_token = self.first + prev_length = self.first.total_length + for token in self._tokens[1:]: + if (token.spaces_required_before == 0 and + _SpaceRequiredBetween(prev_token, token)): + token.spaces_required_before = 1 + + tok_len = len(token.value) if not token.is_pseudo_paren else 0 + token.total_length = prev_length + tok_len + token.spaces_required_before + + # The split penalty has to be computed before {must|can}_break_before, + # because these may use it for their decision. + token.split_penalty += _SplitPenalty(prev_token, token) + token.must_break_before = _MustBreakBefore(prev_token, token) + token.can_break_before = (token.must_break_before or + _CanBreakBefore(prev_token, token)) + + prev_length = token.total_length + prev_token = token + + ############################################################################ + # Token Access and Manipulation Methods # + ############################################################################ + + def AppendToken(self, token): + """Append a new FormatToken to the tokens contained in this line.""" + if self._tokens: + token.previous_token = self.last + self.last.next_token = token + self._tokens.append(token) + + def AppendNode(self, node): + """Convenience method to append a pytree node directly. + + Wraps the node with a FormatToken. + + Arguments: + node: the node to append + """ + self.AppendToken(format_token.FormatToken(node)) + + @property + def first(self): + """Returns the first non-whitespace token.""" + return self._tokens[0] + + @property + def last(self): + """Returns the last non-whitespace token.""" + return self._tokens[-1] + + ############################################################################ + # Token -> String Methods # + ############################################################################ + + def AsCode(self, indent_per_depth=2): + """Return a "code" representation of this line. + + The code representation shows how the line would be printed out as code. + + TODO(eliben): for now this is rudimentary for debugging - once we add + formatting capabilities, this method will have other uses (not all tokens + have spaces around them, for example). + + Arguments: + indent_per_depth: how much spaces to indend per depth level. + + Returns: + A string representing the line as code. + """ + indent = ' ' * indent_per_depth * self.depth + tokens_str = ' '.join(tok.value for tok in self._tokens) + return indent + tokens_str + + def __str__(self): # pragma: no cover + return self.AsCode() + + def __repr__(self): # pragma: no cover + tokens_repr = ','.join( + ['{0}({1!r})'.format(tok.name, tok.value) for tok in self._tokens]) + return 'UnwrappedLine(depth={0}, tokens=[{1}])'.format( + self.depth, tokens_repr) + + ############################################################################ + # Properties # + ############################################################################ + + @property + def tokens(self): + """Access the tokens contained within this line. + + The caller must not modify the tokens list returned by this method. + + Returns: + List of tokens in this line. + """ + return self._tokens + + @property + def lineno(self): + """Return the line number of this unwrapped line. + + Returns: + The line number of the first token in this unwrapped line. + """ + return self.first.lineno + + @property + def is_comment(self): + return self.first.is_comment + + +def _IsIdNumberStringToken(tok): + return tok.is_keyword or tok.is_name or tok.is_number or tok.is_string + + +def _IsUnaryOperator(tok): + return format_token.Subtype.UNARY_OPERATOR in tok.subtypes + + +def _SpaceRequiredBetween(left, right): + """Return True if a space is required between the left and right token.""" + lval = left.value + rval = right.value + if (left.is_pseudo_paren and _IsIdNumberStringToken(right) and + left.previous_token and _IsIdNumberStringToken(left.previous_token)): + # Space between keyword... tokens and pseudo parens. + return True + if left.is_pseudo_paren or right.is_pseudo_paren: + # There should be a space after the ':' in a dictionary. + if left.OpensScope(): + return True + # The closing pseudo-paren shouldn't affect spacing. + return False + if left.is_continuation or right.is_continuation: + # The continuation node's value has all of the spaces it needs. + return False + if right.name in pytree_utils.NONSEMANTIC_TOKENS: + # No space before a non-semantic token. + return False + if _IsIdNumberStringToken(left) and _IsIdNumberStringToken(right): + # Spaces between keyword, string, number, and identifier tokens. + return True + if lval == ',' and rval == ':': + # We do want a space between a comma and colon. + return True + if rval in ':,': + # Otherwise, we never want a space before a colon or comma. + return False + if lval == ',' and rval in ']})': + # Add a space between ending ',' and closing bracket if requested. + return style.Get('SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET') + if lval == ',': + # We want a space after a comma. + return True + if lval == 'from' and rval == '.': + # Space before the '.' in an import statement. + return True + if lval == '.' and rval == 'import': + # Space after the '.' in an import statement. + return True + if lval == '=' and rval == '.': + # Space between equal and '.' as in "X = ...". + return True + if ((right.is_keyword or right.is_name) and + (left.is_keyword or left.is_name)): + # Don't merge two keywords/identifiers. + return True + if left.is_string: + if (rval == '=' and format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN_ARG_LIST in + right.subtypes): + # If there is a type hint, then we don't want to add a space between the + # equal sign and the hint. + return False + if rval not in '[)]}.': + # A string followed by something other than a subscript, closing bracket, + # or dot should have a space after it. + return True + if left.is_binary_op and lval != '**' and _IsUnaryOperator(right): + # Space between the binary opertor and the unary operator. + return True + if _IsUnaryOperator(left) and _IsUnaryOperator(right): + # No space between two unary operators. + return False + if left.is_binary_op or right.is_binary_op: + if lval == '**' or rval == '**': + # Space around the "power" operator. + return style.Get('SPACES_AROUND_POWER_OPERATOR') + # Enforce spaces around binary operators. + return True + if (_IsUnaryOperator(left) and lval != 'not' and + (right.is_name or right.is_number or rval == '(')): + # The previous token was a unary op. No space is desired between it and + # the current token. + return False + if (format_token.Subtype.SUBSCRIPT_COLON in left.subtypes or + format_token.Subtype.SUBSCRIPT_COLON in right.subtypes): + # A subscript shouldn't have spaces separating its colons. + return False + if (format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN in left.subtypes or + format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN in right.subtypes): + # A named argument or default parameter shouldn't have spaces around it. + # However, a typed argument should have a space after the colon. + return lval == ':' or style.Get('SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN') + if (format_token.Subtype.VARARGS_LIST in left.subtypes or + format_token.Subtype.VARARGS_LIST in right.subtypes): + return False + if (format_token.Subtype.VARARGS_STAR in left.subtypes or + format_token.Subtype.KWARGS_STAR_STAR in left.subtypes): + # Don't add a space after a vararg's star or a keyword's star-star. + return False + if lval == '@' and format_token.Subtype.DECORATOR in left.subtypes: + # Decorators shouldn't be separated from the 'at' sign. + return False + if lval == '.' or rval == '.': + # Don't place spaces between dots. + return False + if ((lval == '(' and rval == ')') or (lval == '[' and rval == ']') or + (lval == '{' and rval == '}')): + # Empty objects shouldn't be separted by spaces. + return False + if (lval in pytree_utils.OPENING_BRACKETS and + rval in pytree_utils.OPENING_BRACKETS): + # Nested objects' opening brackets shouldn't be separated. + return False + if (lval in pytree_utils.CLOSING_BRACKETS and + rval in pytree_utils.CLOSING_BRACKETS): + # Nested objects' closing brackets shouldn't be separated. + return False + if lval in pytree_utils.CLOSING_BRACKETS and rval in '([': + # A call, set, dictionary, or subscript that has a call or subscript after + # it shouldn't have a space between them. + return False + if lval in pytree_utils.OPENING_BRACKETS and _IsIdNumberStringToken(right): + # Don't separate the opening bracket from the first item. + return False + if left.is_name and rval in '([': + # Don't separate a call or array access from the name. + return False + if rval in pytree_utils.CLOSING_BRACKETS: + # Don't separate the closing bracket from the last item. + # FIXME(morbo): This might be too permissive. + return False + if lval == 'print' and rval == '(': + # Special support for the 'print' function. + return False + if lval in pytree_utils.OPENING_BRACKETS and _IsUnaryOperator(right): + # Don't separate a unary operator from the opening bracket. + return False + if (lval in pytree_utils.OPENING_BRACKETS and + (format_token.Subtype.VARARGS_STAR in right.subtypes or + format_token.Subtype.KWARGS_STAR_STAR in right.subtypes)): + # Don't separate a '*' or '**' from the opening bracket. + return False + if rval == ';': + # Avoid spaces before a semicolon. (Why is there a semicolon?!) + return False + if lval == '(' and rval == 'await': + # Special support for the 'await' keyword. Don't separate the 'await' + # keyword from an opening paren. + return False + return True + + +def _MustBreakBefore(prev_token, cur_token): + """Return True if a line break is required before the current token.""" + if prev_token.is_comment: + # Must break if the previous token was a comment. + return True + if (cur_token.is_string and prev_token.is_string and + IsSurroundedByBrackets(cur_token)): + # We want consecutive strings to be on separate lines. This is a + # reasonable assumption, because otherwise they should have written them + # all on the same line, or with a '+'. + return True + return pytree_utils.GetNodeAnnotation( + cur_token.node, pytree_utils.Annotation.MUST_SPLIT, default=False) + + +def _CanBreakBefore(prev_token, cur_token): + """Return True if a line break may occur before the current token.""" + pval = prev_token.value + cval = cur_token.value + if py3compat.PY3: + if pval == 'yield' and cval == 'from': + # Don't break before a yield argument. + return False + if pval in {'async', 'await'} and cval in {'def', 'with', 'for'}: + # Don't break after sync keywords. + return False + if cur_token.split_penalty >= split_penalty.UNBREAKABLE: + return False + if pval == '@': + # Don't break right after the beginning of a decorator. + return False + if cval == ':': + # Don't break before the start of a block of code. + return False + if cval == ',': + # Don't break before a comma. + return False + if prev_token.is_name and cval == '(': + # Don't break in the middle of a function definition or call. + return False + if prev_token.is_name and cval == '[': + # Don't break in the middle of an array dereference. + return False + if prev_token.is_name and cval == '.': + # Don't break before the '.' in a dotted name. + return False + if cur_token.is_comment and prev_token.lineno == cur_token.lineno: + # Don't break a comment at the end of the line. + return False + if format_token.Subtype.UNARY_OPERATOR in prev_token.subtypes: + # Don't break after a unary token. + return False + return True + + +def IsSurroundedByBrackets(tok): + """Return True if the token is surrounded by brackets.""" + paren_count = 0 + brace_count = 0 + sq_bracket_count = 0 + previous_token = tok.previous_token + while previous_token: + if previous_token.value == ')': + paren_count -= 1 + elif previous_token.value == '}': + brace_count -= 1 + elif previous_token.value == ']': + sq_bracket_count -= 1 + + if previous_token.value == '(': + if paren_count == 0: + return previous_token + paren_count += 1 + elif previous_token.value == '{': + if brace_count == 0: + return previous_token + brace_count += 1 + elif previous_token.value == '[': + if sq_bracket_count == 0: + return previous_token + sq_bracket_count += 1 + + previous_token = previous_token.previous_token + return None + + +_LOGICAL_OPERATORS = frozenset({'and', 'or'}) +_BITWISE_OPERATORS = frozenset({'&', '|', '^'}) +_TERM_OPERATORS = frozenset({'*', '/', '%', '//'}) + + +def _SplitPenalty(prev_token, cur_token): + """Return the penalty for breaking the line before the current token.""" + pval = prev_token.value + cval = cur_token.value + if pval == 'not': + return split_penalty.UNBREAKABLE + + if cur_token.node_split_penalty > 0: + return cur_token.node_split_penalty + + if style.Get('SPLIT_BEFORE_LOGICAL_OPERATOR'): + # Prefer to split before 'and' and 'or'. + if pval in _LOGICAL_OPERATORS: + return style.Get('SPLIT_PENALTY_LOGICAL_OPERATOR') + if cval in _LOGICAL_OPERATORS: + return 0 + else: + # Prefer to split after 'and' and 'or'. + if pval in _LOGICAL_OPERATORS: + return 0 + if cval in _LOGICAL_OPERATORS: + return style.Get('SPLIT_PENALTY_LOGICAL_OPERATOR') + + if style.Get('SPLIT_BEFORE_BITWISE_OPERATOR'): + # Prefer to split before '&', '|', and '^'. + if pval in _BITWISE_OPERATORS: + return style.Get('SPLIT_PENALTY_BITWISE_OPERATOR') + if cval in _BITWISE_OPERATORS: + return 0 + else: + # Prefer to split after '&', '|', and '^'. + if pval in _BITWISE_OPERATORS: + return 0 + if cval in _BITWISE_OPERATORS: + return style.Get('SPLIT_PENALTY_BITWISE_OPERATOR') + + if (format_token.Subtype.COMP_FOR in cur_token.subtypes or + format_token.Subtype.COMP_IF in cur_token.subtypes): + # We don't mind breaking before the 'for' or 'if' of a list comprehension. + return 0 + if format_token.Subtype.UNARY_OPERATOR in prev_token.subtypes: + # Try not to break after a unary operator. + return style.Get('SPLIT_PENALTY_AFTER_UNARY_OPERATOR') + if pval == ',': + # Breaking after a comma is fine, if need be. + return 0 + if prev_token.is_binary_op: + # We would rather not split after an equality operator. + return 20 + if (format_token.Subtype.VARARGS_STAR in prev_token.subtypes or + format_token.Subtype.KWARGS_STAR_STAR in prev_token.subtypes): + # Don't split after a varargs * or kwargs **. + return split_penalty.UNBREAKABLE + if prev_token.OpensScope() and cval != '(': + # Slightly prefer + return style.Get('SPLIT_PENALTY_AFTER_OPENING_BRACKET') + if cval == ':': + # Don't split before a colon. + return split_penalty.UNBREAKABLE + if cval == '=': + # Don't split before an assignment. + return split_penalty.UNBREAKABLE + if (format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN in prev_token.subtypes or + format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN in cur_token.subtypes): + # Don't break before or after an default or named assignment. + return split_penalty.UNBREAKABLE + if cval == '==': + # We would rather not split before an equality operator. + return split_penalty.STRONGLY_CONNECTED + if cur_token.ClosesScope(): + # Give a slight penalty for splitting before the closing scope. + return 100 + if pval in _TERM_OPERATORS or cval in _TERM_OPERATORS: + return 50 + return 0 diff --git a/lib/jcef/tools/yapf/yapf/yapflib/verifier.py b/lib/jcef/tools/yapf/yapf/yapflib/verifier.py new file mode 100644 index 0000000..b16aefb --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/verifier.py @@ -0,0 +1,93 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Verify that the generated code is valid code. + +This takes a line of code and "normalizes" it. I.e., it transforms the snippet +into something that has the potential to compile. + + VerifyCode(): the main function exported by this module. +""" + +import ast +import re +import sys +import textwrap + + +class InternalError(Exception): + """Internal error in verifying formatted code.""" + pass + + +def VerifyCode(code): + """Verify that the reformatted code is syntactically correct. + + Arguments: + code: (unicode) The reformatted code snippet. + + Raises: + SyntaxError if the code was reformatted incorrectly. + """ + try: + compile(textwrap.dedent(code).encode('UTF-8'), '', 'exec') + except SyntaxError: + try: + ast.parse(textwrap.dedent(code.lstrip('\n')).lstrip(), '', 'exec') + except SyntaxError: + try: + normalized_code = _NormalizeCode(code) + compile(normalized_code.encode('UTF-8'), '', 'exec') + except SyntaxError: + raise InternalError(sys.exc_info()[1]) + + +def _NormalizeCode(code): + """Make sure that the code snippet is compilable.""" + code = textwrap.dedent(code.lstrip('\n')).lstrip() + + # Split the code to lines and get rid of all leading full-comment lines as + # they can mess up the normalization attempt. + lines = code.split('\n') + i = 0 + for i, line in enumerate(lines): + line = line.strip() + if line and not line.startswith('#'): + break + code = '\n'.join(lines[i:]) + '\n' + + if re.match(r'(if|while|for|with|def|class|async|await)\b', code): + code += '\n pass' + elif re.match(r'(elif|else)\b', code): + try: + try_code = 'if True:\n pass\n' + code + '\n pass' + ast.parse( + textwrap.dedent(try_code.lstrip('\n')).lstrip(), '', 'exec') + code = try_code + except SyntaxError: + # The assumption here is that the code is on a single line. + code = 'if True: pass\n' + code + elif code.startswith('@'): + code += '\ndef _():\n pass' + elif re.match(r'try\b', code): + code += '\n pass\nexcept:\n pass' + elif re.match(r'(except|finally)\b', code): + code = 'try:\n pass\n' + code + '\n pass' + elif re.match(r'(return|yield)\b', code): + code = 'def _():\n ' + code + elif re.match(r'(continue|break)\b', code): + code = 'while True:\n ' + code + elif re.match(r'print\b', code): + code = 'from __future__ import print_function\n' + code + + return code + '\n' diff --git a/lib/jcef/tools/yapf/yapf/yapflib/yapf_api.py b/lib/jcef/tools/yapf/yapf/yapflib/yapf_api.py new file mode 100644 index 0000000..dd91849 --- /dev/null +++ b/lib/jcef/tools/yapf/yapf/yapflib/yapf_api.py @@ -0,0 +1,295 @@ +# Copyright 2015-2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Entry points for YAPF. + +The main APIs that YAPF exposes to drive the reformatting. + + FormatFile(): reformat a file. + FormatCode(): reformat a string of code. + +These APIs have some common arguments: + + style_config: (string) Either a style name or a path to a file that contains + formatting style settings. If None is specified, use the default style + as set in style.DEFAULT_STYLE_FACTORY + lines: (list of tuples of integers) A list of tuples of lines, [start, end], + that we want to format. The lines are 1-based indexed. It can be used by + third-party code (e.g., IDEs) when reformatting a snippet of code rather + than a whole file. + print_diff: (bool) Instead of returning the reformatted source, return a + diff that turns the formatted source into reformatter source. + verify: (bool) True if reformatted code should be verified for syntax. +""" + +import difflib +import re +import sys + +from lib2to3.pgen2 import tokenize + +from yapf.yapflib import blank_line_calculator +from yapf.yapflib import comment_splicer +from yapf.yapflib import continuation_splicer +from yapf.yapflib import file_resources +from yapf.yapflib import py3compat +from yapf.yapflib import pytree_unwrapper +from yapf.yapflib import pytree_utils +from yapf.yapflib import reformatter +from yapf.yapflib import split_penalty +from yapf.yapflib import style +from yapf.yapflib import subtype_assigner + + +def FormatFile(filename, + style_config=None, + lines=None, + print_diff=False, + verify=False, + in_place=False, + logger=None): + """Format a single Python file and return the formatted code. + + Arguments: + filename: (unicode) The file to reformat. + in_place: (bool) If True, write the reformatted code back to the file. + logger: (io streamer) A stream to output logging. + remaining arguments: see comment at the top of this module. + + Returns: + Tuple of (reformatted_code, encoding, changed). reformatted_code is None if + the file is sucessfully written to (having used in_place). reformatted_code + is a diff if print_diff is True. + + Raises: + IOError: raised if there was an error reading the file. + ValueError: raised if in_place and print_diff are both specified. + """ + _CheckPythonVersion() + + if in_place and print_diff: + raise ValueError('Cannot pass both in_place and print_diff.') + + original_source, newline, encoding = ReadFile(filename, logger) + reformatted_source, changed = FormatCode( + original_source, + style_config=style_config, + filename=filename, + lines=lines, + print_diff=print_diff, + verify=verify) + if reformatted_source.rstrip('\n'): + lines = reformatted_source.rstrip('\n').split('\n') + reformatted_source = newline.join(line for line in lines) + newline + if in_place: + if original_source and original_source != reformatted_source: + file_resources.WriteReformattedCode(filename, reformatted_source, + in_place, encoding) + return None, encoding, changed + + return reformatted_source, encoding, changed + + +def FormatCode(unformatted_source, + filename='', + style_config=None, + lines=None, + print_diff=False, + verify=False): + """Format a string of Python code. + + This provides an alternative entry point to YAPF. + + Arguments: + unformatted_source: (unicode) The code to format. + filename: (unicode) The name of the file being reformatted. + remaining arguments: see comment at the top of this module. + + Returns: + Tuple of (reformatted_source, changed). reformatted_source conforms to the + desired formatting style. changed is True if the source changed. + """ + _CheckPythonVersion() + style.SetGlobalStyle(style.CreateStyleFromConfig(style_config)) + if not unformatted_source.endswith('\n'): + unformatted_source += '\n' + tree = pytree_utils.ParseCodeToTree(unformatted_source) + + # Run passes on the tree, modifying it in place. + comment_splicer.SpliceComments(tree) + continuation_splicer.SpliceContinuations(tree) + subtype_assigner.AssignSubtypes(tree) + split_penalty.ComputeSplitPenalties(tree) + blank_line_calculator.CalculateBlankLines(tree) + + uwlines = pytree_unwrapper.UnwrapPyTree(tree) + for uwl in uwlines: + uwl.CalculateFormattingInformation() + + _MarkLinesToFormat(uwlines, lines) + reformatted_source = reformatter.Reformat(uwlines, verify) + + if unformatted_source == reformatted_source: + return '' if print_diff else reformatted_source, False + + code_diff = _GetUnifiedDiff( + unformatted_source, reformatted_source, filename=filename) + + if print_diff: + return code_diff, code_diff != '' + + return reformatted_source, True + + +def _CheckPythonVersion(): # pragma: no cover + errmsg = 'yapf is only supported for Python 2.7 or 3.4+' + if sys.version_info[0] == 2: + if sys.version_info[1] < 7: + raise RuntimeError(errmsg) + elif sys.version_info[0] == 3: + if sys.version_info[1] < 4: + raise RuntimeError(errmsg) + + +def ReadFile(filename, logger=None): + """Read the contents of the file. + + An optional logger can be specified to emit messages to your favorite logging + stream. If specified, then no exception is raised. This is external so that it + can be used by third-party applications. + + Arguments: + filename: (unicode) The name of the file. + logger: (function) A function or lambda that takes a string and emits it. + + Returns: + The contents of filename. + + Raises: + IOError: raised if there was an error reading the file. + """ + try: + with open(filename, 'rb') as fd: + encoding = tokenize.detect_encoding(fd.readline)[0] + except IOError as err: + if logger: + logger(err) + raise + + try: + # Preserves line endings. + with py3compat.open_with_encoding( + filename, mode='r', encoding=encoding, newline='') as fd: + lines = fd.readlines() + + line_ending = file_resources.LineEnding(lines) + source = '\n'.join(line.rstrip('\r\n') for line in lines) + '\n' + return source, line_ending, encoding + except IOError as err: # pragma: no cover + if logger: + logger(err) + raise + + +DISABLE_PATTERN = r'^#.*\byapf:\s*disable\b' +ENABLE_PATTERN = r'^#.*\byapf:\s*enable\b' + + +def _MarkLinesToFormat(uwlines, lines): + """Skip sections of code that we shouldn't reformat.""" + if lines: + for uwline in uwlines: + uwline.disable = True + + # Sort and combine overlapping ranges. + lines = sorted(lines) + line_ranges = [lines[0]] if len(lines[0]) else [] + index = 1 + while index < len(lines): + current = line_ranges[-1] + if lines[index][0] <= current[1]: + # The ranges overlap, so combine them. + line_ranges[-1] = (current[0], max(lines[index][1], current[1])) + else: + line_ranges.append(lines[index]) + index += 1 + + # Mark lines to format as not being disabled. + index = 0 + for start, end in sorted(line_ranges): + while index < len(uwlines) and uwlines[index].last.lineno < start: + index += 1 + if index >= len(uwlines): + break + + while index < len(uwlines): + if uwlines[index].lineno > end: + break + if (uwlines[index].lineno >= start or + uwlines[index].last.lineno >= start): + uwlines[index].disable = False + index += 1 + + # Now go through the lines and disable any lines explicitly marked as + # disabled. + index = 0 + while index < len(uwlines): + uwline = uwlines[index] + if uwline.is_comment: + if _DisableYAPF(uwline.first.value.strip()): + index += 1 + while index < len(uwlines): + uwline = uwlines[index] + if uwline.is_comment and _EnableYAPF(uwline.first.value.strip()): + break + uwline.disable = True + index += 1 + elif re.search(DISABLE_PATTERN, uwline.last.value.strip(), re.IGNORECASE): + uwline.disable = True + index += 1 + + +def _DisableYAPF(line): + return ( + re.search(DISABLE_PATTERN, line.split('\n')[0].strip(), re.IGNORECASE) or + re.search(DISABLE_PATTERN, line.split('\n')[-1].strip(), re.IGNORECASE)) + + +def _EnableYAPF(line): + return ( + re.search(ENABLE_PATTERN, line.split('\n')[0].strip(), re.IGNORECASE) or + re.search(ENABLE_PATTERN, line.split('\n')[-1].strip(), re.IGNORECASE)) + + +def _GetUnifiedDiff(before, after, filename='code'): + """Get a unified diff of the changes. + + Arguments: + before: (unicode) The original source code. + after: (unicode) The reformatted source code. + filename: (unicode) The code's filename. + + Returns: + The unified diff text. + """ + before = before.splitlines() + after = after.splitlines() + return '\n'.join( + difflib.unified_diff( + before, + after, + filename, + filename, + '(original)', + '(reformatted)', + lineterm='')) + '\n' diff --git a/lib/jcef/tools/yapf_util.py b/lib/jcef/tools/yapf_util.py new file mode 100644 index 0000000..c5add7e --- /dev/null +++ b/lib/jcef/tools/yapf_util.py @@ -0,0 +1,28 @@ +# Copyright (c) 2017 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 + +from __future__ import absolute_import +from __future__ import print_function +from exec_util import exec_cmd +import os +import sys + +# Script directory. +script_dir = os.path.dirname(__file__) +root_dir = os.path.join(script_dir, os.pardir) + + +def yapf_format(file_name, file_contents): + # Reads .style.yapf in the root_dir when specifying contents via stdin. + result = exec_cmd("%s %s/yapf" % (sys.executable, script_dir), root_dir, + file_contents.encode('utf-8')) + if result['err'] != '': + print("yapf error: %s" % result['err']) + if result['out'] != '': + output = result['out'] + if sys.platform == 'win32': + # Convert to Unix line endings. + output = output.replace("\r", "") + return output + return None diff --git a/pom.xml b/pom.xml index 9d55e46..0493f38 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.openjfx javafx-controls - 13 + 21.0.9 org.eclipse.paho diff --git a/src/main/java/efi/projekt/virtueller_gesundheitsassistent/App.java b/src/main/java/efi/projekt/virtueller_gesundheitsassistent/App.java index 43d9576..caa999b 100644 --- a/src/main/java/efi/projekt/virtueller_gesundheitsassistent/App.java +++ b/src/main/java/efi/projekt/virtueller_gesundheitsassistent/App.java @@ -60,7 +60,7 @@ public class App extends Application { // ========================= // MQTT Subscribe // ========================= - mqttService.subscribe("STATE", payload -> + mqttService.subscribe("PREDICTION", payload -> binaryEventService.handlePayload(payload) ); @@ -74,7 +74,7 @@ public class App extends Application { ) ); - Scene scene = new Scene(loader.load(), 1400, 900); + Scene scene = new Scene(loader.load(), 1280, 720); primaryStage.setTitle("Virtueller Gesundheitsassistent"); primaryStage.setScene(scene); diff --git a/src/main/java/efi/projekt/virtueller_gesundheitsassistent/controller/CompactViewController.java b/src/main/java/efi/projekt/virtueller_gesundheitsassistent/controller/CompactViewController.java new file mode 100644 index 0000000..9ed2e24 --- /dev/null +++ b/src/main/java/efi/projekt/virtueller_gesundheitsassistent/controller/CompactViewController.java @@ -0,0 +1,41 @@ +package efi.projekt.virtueller_gesundheitsassistent.controller; + +import efi.projekt.virtueller_gesundheitsassistent.viewmodel.CompactViewModel; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.StackPane; +import javafx.scene.web.WebView; + +/** + * + * @author naumueller + */ +public class CompactViewController { + + @FXML + private StackPane avatarContainer; + + @FXML + private Label statusLabel; + + private CompactViewModel viewModel; + + @FXML + public void initialize() { + viewModel = new CompactViewModel(); + + // Status binden + statusLabel.textProperty().bind(viewModel.statusTextProperty()); + + viewModel = new CompactViewModel(); + + WebView avatar = (WebView) viewModel.getAvatarView(); + + avatarContainer.getChildren().add(avatar); + + // WICHTIG: Größe binden + avatar.prefWidthProperty().bind(avatarContainer.widthProperty()); + avatar.prefHeightProperty().bind(avatarContainer.heightProperty()); + + } +} diff --git a/src/main/java/efi/projekt/virtueller_gesundheitsassistent/viewmodel/CompactViewModel.java b/src/main/java/efi/projekt/virtueller_gesundheitsassistent/viewmodel/CompactViewModel.java new file mode 100644 index 0000000..4d92cca --- /dev/null +++ b/src/main/java/efi/projekt/virtueller_gesundheitsassistent/viewmodel/CompactViewModel.java @@ -0,0 +1,41 @@ +package efi.projekt.virtueller_gesundheitsassistent.viewmodel; + +import efi.projekt.virtueller_gesundheitsassistent.model.AppState; +import efi.projekt.virtueller_gesundheitsassistent.service.PixelStreamingService; +import efi.projekt.virtueller_gesundheitsassistent.service.StateService; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.scene.Node; + +/** + * + * @author naumueller + */ +public class CompactViewModel { + private final AppState appState; + private final StringProperty statusText = new SimpleStringProperty(); + private final PixelStreamingService pixelService; + + public CompactViewModel() { + this.appState = StateService.getState(); + this.pixelService = new PixelStreamingService("http://localhost"); + + updateStatus(); + + appState.problemLevelProperty().addListener((obs, oldVal, newVal) -> { + updateStatus(); + }); + } + + private void updateStatus() { + statusText.set("STATE: " + appState.getProblemLevel().name()); + } + + public StringProperty statusTextProperty() { + return statusText; + } + + public Node getAvatarView() { + return pixelService.getView(); + } +} diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index b4aca24..7ff5f37 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -10,6 +10,8 @@ module efi.projekt.virtueller_gesundheitsassistent { opens efi.projekt.virtueller_gesundheitsassistent to javafx.fxml; + opens efi.projekt.virtueller_gesundheitsassistent.controller to javafx.fxml; exports efi.projekt.virtueller_gesundheitsassistent; + exports efi.projekt.virtueller_gesundheitsassistent.controller; } diff --git a/src/main/resources/efi/projekt/virtueller_gesundheitsassistent/view/designs/CompactView.fxml b/src/main/resources/efi/projekt/virtueller_gesundheitsassistent/view/designs/CompactView.fxml index 18ac1b3..c106f1e 100644 --- a/src/main/resources/efi/projekt/virtueller_gesundheitsassistent/view/designs/CompactView.fxml +++ b/src/main/resources/efi/projekt/virtueller_gesundheitsassistent/view/designs/CompactView.fxml @@ -1,11 +1,12 @@ - - - - - + + + - - - + + + + +