Compare commits

...

No commits in common. "main" and "pre_int" have entirely different histories.

520 changed files with 54968 additions and 1871 deletions

43
.gitignore vendored
View File

@ -1,42 +1 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
.kotlin
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
lib/
logs/
data/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
/nbproject/

10
.idea/.gitignore generated vendored
View File

@ -1,10 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

1
.idea/.name generated
View File

@ -1 +0,0 @@
Virtueller Gesundheitsassistent

7
.idea/encodings.xml generated
View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

15
.idea/misc.xml generated
View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.12 (gesundheitsassistent)" />
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="ms-17" project-jdk-type="JavaSDK" />
</project>

6
.idea/vcs.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

18
README.md Normal file
View File

@ -0,0 +1,18 @@
Virtueller Gesundheitsassistent
Überblick
Dieses Projekt implementiert einen virtuellen Gesundheits- und Fahrassistenten
auf Basis von JavaFX. Die Anwendung visualisiert den aktuellen Zustand des
Fahrers (z.B. Müdigkeit, Ablenkung, Stress) und integriert:
- ein ML-Modell, das Zustände klassifiziert
- eine JavaFX-GUI mit mehreren Designvarianten
- OpenCV für Kamera-Preview
- Unreal Engine Pixel Streaming für einen sprechenden Avatar
- WebSocket-Kommunikation zur Steuerung des Avatars
Features
Architektur
Services
Views & UI-Struktur
Java-Version & Build
MQTT & Datenfluss
OpenCV

BIN
data/health.db Normal file

Binary file not shown.

Binary file not shown.

8
lib/jcef/.clang-format Normal file
View File

@ -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<vector<int> >' in existing files gets formatted to
# 'vector<vector<int>>'. ('Auto' means that clang-format will only use
# 'int>>' if the file already contains at least one such instance.)
Standard: Cpp11

View File

@ -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.

View File

@ -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.

57
lib/jcef/.gitignore vendored Normal file
View File

@ -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

9
lib/jcef/.style.cfg Normal file
View File

@ -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'],
}

2
lib/jcef/.style.yapf Normal file
View File

@ -0,0 +1,2 @@
[style]
based_on_style = chromium

8
lib/jcef/AUTHORS.txt Normal file
View File

@ -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 <magreenblatt@gmail.com>
Kai Klimke, censhare AG <kkl@censhare.com>

317
lib/jcef/CMakeLists.txt Normal file
View File

@ -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}")

29
lib/jcef/LICENSE.txt Normal file
View File

@ -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.

55
lib/jcef/README.md Normal file
View File

@ -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.

54
lib/jcef/appveyor.yml Normal file
View File

@ -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

84
lib/jcef/build.xml Normal file
View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="javaLauncher" default="default" basedir=".">
<property environment="env"/>
<property name="jdk7.path" value="${env.JDK_17}"/>
<property name="out.path" value="${env.OUT_PATH}"/>
<property name="out.name" value="${env.OUT_NAME}"/>
<property name="out.id" value="${env.OUT_ID}"/>
<property name="out.mainclass" value="${env.OUT_MAINCLASS}"/>
<taskdef name="bundleapp"
classname="com.oracle.appbundler.AppBundlerTask"
classpath="third_party/appbundler/appbundler-1.0.jar" />
<path id="class.path">
<fileset dir="third_party/jogamp/jar">
<include name="gluegen-rt.jar"/>
<include name="gluegen-rt-natives-macosx-universal.jar"/>
<include name="jogl-all.jar"/>
<include name="jogl-all-natives-macosx-universal.jar"/>
</fileset>
<fileset dir="third_party/junit" includes="junit*.jar"/>
</path>
<target name="compile">
<mkdir dir="${out.path}"/>
<javac encoding="UTF8" nowarn="on" deprecation="off" debug="on" includeantruntime="false" destdir="${out.path}"
executable="/usr/bin/javac" fork="true" memoryinitialsize="32m" memorymaximumsize="128m" includeJavaRuntime="yes"
target="1.8" source="1.8">
<compilerarg value="-XDignore.symbol.file"/>
<classpath location="${jdk7.path}/jre/lib/rt.jar" />
<classpath refid="class.path"/>
<src path="java/tests/"/>
<src path="java/org/cef/"/>
</javac>
<copy todir="${out.path}">
<fileset dir="java" casesensitive="no">
<exclude name="**/*.java" />
</fileset>
</copy>
</target>
<target name="jar" depends="compile">
<mkdir dir="${out.path}"/>
<jar destfile="${out.path}/jcef.jar" index="true" update="false" manifest="java/manifest/MANIFEST.MF">
<fileset dir="${out.path}">
<include name="org/cef/**"/>
</fileset>
</jar>
<jar destfile="${out.path}/jcef-tests.jar" index="true" update="false">
<fileset dir="${out.path}">
<include name="tests/**"/>
</fileset>
</jar>
</target>
<target name="bundle" depends="jar">
<mkdir dir="${out.path}"/>
<bundleapp outputdirectory="${out.path}"
name="${out.name}"
displayname="${out.name}"
identifier="${out.id}"
mainclassname="${out.mainclass}"
icon="third_party/cef/res/CefIcon.icns">
<classpath dir="${out.path}">
<include name="jcef.jar"/>
<include name="jcef-tests.jar"/>
</classpath>
<classpath dir="third_party/jogamp/jar/">
<include name="gluegen-rt.jar"/>
<include name="gluegen-rt-natives-macosx-universal.jar" />
<include name="jogl-all.jar" />
<include name="jogl-all-natives-macosx-universal.jar" />
</classpath>
<classpath dir="third_party/junit" includes="junit*.jar"/>
<option value="-Djava.library.path=$APP_ROOT/Contents/Java/:$APP_ROOT/Contents/Frameworks/Chromium Embedded Framework.framework/Libraries" />
<option value="--add-opens=java.desktop/sun.awt=ALL-UNNAMED" />
<option value="--add-opens=java.desktop/sun.lwawt=ALL-UNNAMED" />
<option value="--add-opens=java.desktop/sun.lwawt.macosx=ALL-UNNAMED" />
<option value="--add-opens=java.desktop/java.awt=ALL-UNNAMED" />
<option value="--enable-native-access=ALL-UNNAMED" />
</bundleapp>
</target>
</project>

View File

@ -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()

12
lib/jcef/docs/README.md Normal file
View File

@ -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 - <http://magpcss.org/ceforum/viewforum.php?f=17>
* Donations - <http://www.magpcss.org/ceforum/donate.php>

View File

@ -0,0 +1,3 @@
title: JCEF Documentation
description: Java Chromium Embedded Framework documentation
theme: jekyll-theme-minimal

View File

@ -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;
}
}

View File

@ -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 <https://github.com/chromiumembedded/cef>. 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.

View File

@ -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 <package>" 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"
>
<assemblyIdentity
- version="IMVERSION"
+ version="8.0.60.0"
processorArchitecture="X86"
name="Oracle Corporation, Java(tm) 2 Standard Edition"
type="win32"
```
## Configure OpenJDK
Run the following commands in the MinGW shell to configure OpenJDK. If you installed all of the required packages and applied the above patches correctly the configure command should succeed. If you experience errors then debug the problem before proceeding further.
To disable all optimizations in the debug build use `--with-debug-level=slowdebug` instead of `--enable-debug` on the configure line. The resulting folder will then be `windows-*-normal-server-slowdebug` instead of `windows-*-normal-server-fastdebug`.
```sh
cd /c/code/openjdk8
# OpenJDK expects the "VS100COMNTOOLS" variable which is set by the VS2010 install.
# Set it to use the VS2013 install instead.
export VS100COMNTOOLS=$VS120COMNTOOLS
# Don't compress symbol files into .diz ("debug info zip") files.
export ZIP_DEBUGINFO_FILES=0
# 32-bit build.
# Explicitly specify the 32-bit boot JDK path and increase the Java memory limit.
bash ./configure --enable-debug --with-target-bits=32 -with-freetype=/c/code/freetype-2.6.2-src -with-boot-jdk=/c/Program\ Files\ \(x86\)/Java/jdk1.8.0_66/ --with-boot-jdk-jvmargs="-Xmx6G -enableassertions"
# 64-bit build.
bash ./configure --enable-debug --with-target-bits=64 -with-freetype=/c/code/freetype-2.6.2-src
```
## Build OpenJDK
Run the following commands in the MinGW shell to build OpenJDK. VS2013 doesn't create .manifest files so adding MT= disables running of the mt.exe tool. The build should take approximately 20 minutes on a fast machine. The resulting JDK will be output to "C:\code\openjdk8\build\windows-x86_64-normal-server-fastdebug\images\j2sdk-image" (or the 32-bit path as appropriate).
```sh
cd /c/code/openjdk8
make all MT=
```
## Run JCEF with OpenJDK
To use the resulting JDK build with JCEF follow these steps.
1\. Create a Debug build of JCEF as described on the [Branches And Building](branches_and_building.md) page.
2\. Download Debug Symbols for the CEF version from <https://cef-builds.spotifycdn.com/index.html> 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 <string>
+#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=<optimized out>)
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)
```

View File

@ -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 <https://github.com/chromiumembedded/java-cef>.
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 <UserName> with your GitHub user name.
git remote set-url origin https://github.com/<UserName>/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/<UserName>/java-cef.git (fetch)
origin https://github.com/<UserName>/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 <BranchName> with your new branch name.
git checkout -b <BranchName>
```
## 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 <BranchName>
```
## 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 <BranchName> --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 <BranchName> with the name of your branch.
git checkout <BranchName>
# 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 <BranchName>
```
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 <BranchName>
# Delete the branch remotely.
git push origin --delete <BranchName>
```
## 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 <BranchName>
```
## 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
```

View File

@ -0,0 +1,2 @@
Manifest-Version: 1.0
Automatic-Module-Name: jcef

View File

@ -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<CefClient> clients_ = new HashSet<CefClient>();
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<CefClient> clients = new HashSet<CefClient>(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();
}

View File

@ -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;
}
}

View File

@ -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<Integer, CefBrowser> browser_ = new HashMap<Integer, CefBrowser>();
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<String> acceptFilters, Vector<String> acceptExtensions,
Vector<String> 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<CefBrowser> 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<CefPaintEvent> listener) {}
@Override
public void setOnPaintListener(Consumer<CefPaintEvent> listener) {}
@Override
public void removeOnPaintListener(Consumer<CefPaintEvent> listener) {}
@Override
public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y) {
if (browser == null) return false;
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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 <code>setLoader</code> 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);
}
}

View File

@ -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<String> getFrameIdentifiers();
/**
* Returns the names of all existing frames.
* @return The names of all existing frames.
*/
public Vector<String> 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<String> 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.
* <p>
* 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).
* <p>
* 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<BufferedImage> createScreenshot(boolean nativeResolution);
/**
* Set the maximum rate in frames per second (fps) that {@code CefRenderHandler::onPaint}
* will be called for a windowless browser. The actual fps may be
* lower if the browser cannot generate frames at the requested rate. The
* minimum value is 1, and the maximum value is 60 (default 30).
*
* @param frameRate the maximum frame rate
* @throws UnsupportedOperationException if not supported
*/
public void setWindowlessFrameRate(int frameRate);
/**
* Returns the maximum rate in frames per second (fps) that {@code CefRenderHandler::onPaint}
* will be called for a windowless browser. The actual fps may be lower if the browser cannot
* generate frames at the requested rate. The minimum value is 1, and the maximum value is 60
* (default 30).
*
* @return the framerate, 0 if an error occurs
* @throws UnsupportedOperationException if not supported
*/
public CompletableFuture<Integer> getWindowlessFrameRate();
}

View File

@ -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);
}
}

View File

@ -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<Consumer<CefPaintEvent>> 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<CefPaintEvent> listener) {
onPaintListeners.add(listener);
}
@Override
public void setOnPaintListener(Consumer<CefPaintEvent> listener) {
onPaintListeners.clear();
onPaintListeners.add(listener);
}
@Override
public void removeOnPaintListener(Consumer<CefPaintEvent> listener) {
onPaintListeners.remove(listener);
}
@Override
public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects,
ByteBuffer buffer, int width, int height) {
// 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<CefPaintEvent> 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<BufferedImage> 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<BufferedImage> pixelGrabberCallable = new Callable<BufferedImage>() {
@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<BufferedImage> future = new CompletableFuture<BufferedImage>();
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<BufferedImage> future = new CompletableFuture<BufferedImage>() {
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;
}
}
}

View File

@ -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);
}

View File

@ -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<BufferedImage> 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<Integer> getWindowlessFrameRate() {
throw new UnsupportedOperationException(
"You can only get windowless framerate on OSR browser");
}
}

View File

@ -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<Integer> executeDevToolsMethod(String method, String parametersAsJson) {
CompletableFuture<Integer> future = new CompletableFuture<>();
N_ExecuteDevToolsMethod(method, parametersAsJson, new IntCallback() {
@Override
public void onComplete(int generatedMessageId) {
if (generatedMessageId <= 0) {
future.completeExceptionally(new DevToolsException(
String.format("Failed to execute DevTools method %s", method)));
} else {
future.complete(generatedMessageId);
}
}
});
return future;
}
CefRegistration addDevToolsMessageObserver(CefDevToolsMessageObserver observer) {
return N_AddDevToolsMessageObserver(observer);
}
protected abstract CefBrowser_N createDevToolsBrowser(CefClient client, String url,
CefRequestContext context, CefBrowser_N parent, Point inspectAt);
/**
* Create a new browser.
*/
protected void createBrowser(CefClientHandler clientHandler, long windowHandle, String url,
boolean osr, boolean transparent, 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<String> getFrameIdentifiers() {
try {
return N_GetFrameIdentifiers();
} catch (UnsatisfiedLinkError ule) {
ule.printStackTrace();
return null;
}
}
@Override
public Vector<String> 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<String> 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<Integer> getWindowlessFrameRate() {
final CompletableFuture<Integer> future = new CompletableFuture<>();
try {
N_GetWindowlessFrameRate(future::complete);
} catch (UnsatisfiedLinkError ule) {
ule.printStackTrace();
future.complete(0);
}
return future;
}
private interface IntCallback {
void onComplete(int value);
}
private final native boolean N_CreateBrowser(CefClientHandler clientHandler, long windowHandle,
String url, boolean osr, boolean transparent, 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<String> N_GetFrameIdentifiers();
private final native Vector<String> 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<String> acceptFilters, int selectedAcceptFilter,
CefRunFileDialogCallback callback);
private final native void N_StartDownload(String url);
private final native void N_Print();
private final native void N_PrintToPDF(
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);
}

View File

@ -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<Integer, CompletableFuture<String>> queuedCommands_ =
Collections.synchronizedMap(new HashMap<>());
private final Set<EventListener> eventListeners_ =
Collections.synchronizedSet(new LinkedHashSet<>());
private CefRegistration registration_;
private final CefBrowser_N browser_;
/**
* Use {@link CefBrowser#getDevToolsClient()} to get an instance of this class.
*/
CefDevToolsClient(CefBrowser_N browser) {
this.browser_ = browser;
registration_ = browser.addDevToolsMessageObserver(new CefDevToolsMessageObserver() {
@Override
public void onDevToolsMethodResult(
CefBrowser browser, int messageId, boolean success, String result) {
CompletableFuture<String> future = getQueuedCommand(messageId);
if (success) {
future.complete(result);
} else {
future.completeExceptionally(
new DevToolsException("DevTools method failed", result));
}
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<String> 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 <a
* href=https://chromedevtools.github.io/devtools-protocol/> DevTools protocol documentation</a>
* for details of supported methods and the expected syntax for parameters.
*
* <p>If an error occurs the returned future is completed exceptionally, otherwise its value is
* asynchronously set to the method result.
*
* <p>Call {@link #addEventListener(String, EventListener)} to subscribe to events.
*
* @param method the method name
* @return return a future with the method result if the method was executed successfully
*/
public CompletableFuture<String> executeDevToolsMethod(String method) {
return executeDevToolsMethod(method, null);
}
/**
* Execute a method call over the DevTools protocol. See the <a
* href=https://chromedevtools.github.io/devtools-protocol/> DevTools protocol documentation</a>
* for details of supported methods and the expected syntax for parameters.
*
* <p>If an error occurs the returned future is completed exceptionally, otherwise its value is
* asynchronously set to the method result.
*
* <p>Call {@link #addEventListener(String, EventListener)} to subscribe to events.
*
* @param method the method name
* @param parametersAsJson JSON object with parameters, or null if no parameters are needed
* @return return a future with the method result if the method was executed successfully
*/
public CompletableFuture<String> executeDevToolsMethod(String method, String parametersAsJson) {
if (isClosed()) {
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new DevToolsException("Client is closed"));
return future;
}
return browser_.executeDevToolsMethod(method, parametersAsJson)
.thenCompose(this::getQueuedCommand);
}
/**
* Add an event listener for DevTools protocol events. Events by default are disabled
* and need to be enabled on a per domain basis, e.g. by sending Network.enable to enable
* network related events.
*
* @param eventListener the listener to add
*/
public void addEventListener(EventListener eventListener) {
eventListeners_.add(eventListener);
}
/**
* Remove an event listener for DevTools protocol events.
*
* @param eventListener the listener to remove
*/
public void removeEventListener(EventListener eventListener) {
eventListeners_.remove(eventListener);
}
public interface EventListener {
/**
* Method that will be called on receipt of an event.
* @param eventName the event name
* @param messageAsJson JSON object with the event message
*/
void onEvent(String eventName, String messageAsJson);
}
public static final class DevToolsException extends Exception {
private static final long serialVersionUID = 3952948449841375372L;
private final String json_;
public DevToolsException(String message) {
this(message, null);
}
public DevToolsException(String message, String json) {
super(message);
this.json_ = json;
}
@Override
public String getMessage() {
String message = super.getMessage();
if (json_ != null) message += ": " + json_;
return message;
}
/**
* JSON object with the error details that were passed back by the DevTools
* host, or null if no further details are available.
*/
public String getJson() {
return json_;
}
}
}

View File

@ -0,0 +1,34 @@
// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
package org.cef.browser;
/**
* Used internally by {@link CefDevToolsClient}.
* <p>
* Callback interface for {@link CefBrowser#addDevToolsMessageObserver(CefDevToolsMessageObserver)}.
* The methods of this class will be called on the CEF UI thread.
*/
interface CefDevToolsMessageObserver {
/**
* Method that will be called after attempted execution of a DevTools protocol method.
*
* @param browser the originating browser instance
* @param messageId the ID that identifies the originating method call
* @param success if the method succeeded, |success| will be true and |result| will be a JSON
* object containing the method call result. If the method call failed, |success| will
* be false and |result| will be a JSON object describing the error.
* @param result method call result or an error
*/
void onDevToolsMethodResult(CefBrowser browser, int messageId, boolean success, String result);
/**
* Method that will be called on receipt of a DevTools protocol event.
*
* @param browser the originating browser instance
* @param method the method name
* @param parameters the event data
*/
void onDevToolsEvent(CefBrowser browser, String method, String parameters);
}

View File

@ -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<File> files = (List<File>) 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;
}
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
package org.cef.browser;
/**
* Used internally by {@link CefDevToolsClient}.
* <p>
* Handle to observer registration, As long as this object is alive, the observer will stay
* registered.
*/
abstract class CefRegistration {
/**
* Removes the native reference from an unused object.
*/
public abstract void dispose();
@Override
public void finalize() throws Throwable {
dispose();
super.finalize();
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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.
* <p>
* 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<String, Object> 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);
}

View File

@ -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<String, Object> getAllPreferences(boolean includeDefaults) {
try {
return N_GetAllPreferences(includeDefaults);
} catch (UnsatisfiedLinkError ule) {
ule.printStackTrace();
}
return new HashMap<String, Object>();
}
@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<String, Object> 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();
}

View File

@ -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];
}
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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<String, String> 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<String> getArguments();
/**
* Add an argument to the end of the command line.
* @param argument name of the argument.
*/
public void appendArgument(String argument);
}

View File

@ -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<String, String> 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<String> 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<String, String> switches = getSwitches();
result += ", switches=" + switches;
}
if (hasArguments()) {
Vector<String> 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<String, String> 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<String> N_GetArguments(long self);
private final native void N_AppendArgument(long self, String argument);
}

View File

@ -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();
}

View File

@ -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<String> 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();
}

View File

@ -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<String> 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<String> 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);
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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<String> names);
/**
* Retrieve the list of file paths that are being dragged into the browser
* window.
*/
public abstract boolean getFilePaths(Vector<String> 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() + "]";
}
}

View File

@ -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<String> names) {
try {
return N_GetFileNames(N_CefHandle, names);
} catch (UnsatisfiedLinkError ule) {
ule.printStackTrace();
}
return false;
}
@Override
public boolean getFilePaths(Vector<String> 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<String> names);
private final native boolean N_GetFilePaths(long self, Vector<String> 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<String> 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
+ "]";
}
}

View File

@ -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<String> filePaths);
/**
* Cancel the file selection.
*/
public void Cancel();
}

View File

@ -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<String> 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<String> filePaths);
private final native void N_Cancel(long self);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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<String> filePaths);
}

View File

@ -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);
}

View File

@ -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:
* <pre>
* [scheme]://[username]:[password]@[host]:[port]/[url-path]
* </pre>
* 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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

Some files were not shown because too many files have changed in this diff Show More