From 8ff2de3ee62a37d317dca711c7de48cbe329004f Mon Sep 17 00:00:00 2001 From: Rene Schneider Date: Mon, 27 Nov 2023 18:19:27 +0000 Subject: [PATCH 01/12] Update to CEF version 119.4.3+gc76a3b9+chromium-119.0.6045.159 --- CMakeLists.txt | 2 +- java/org/cef/handler/CefLoadHandler.java | 4 ---- native/jni_util.cpp | 8 -------- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d3db080..8895daa8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,7 +130,7 @@ set_property(GLOBAL PROPERTY OS_FOLDERS ON) # Specify the CEF distribution version. if(NOT DEFINED CEF_VERSION) - set(CEF_VERSION "116.0.19+gc6a20bc+chromium-116.0.5845.141") + set(CEF_VERSION "119.4.3+gc76a3b9+chromium-119.0.6045.159") endif() # Determine the platform. diff --git a/java/org/cef/handler/CefLoadHandler.java b/java/org/cef/handler/CefLoadHandler.java index 37d5a3e8..af50686e 100644 --- a/java/org/cef/handler/CefLoadHandler.java +++ b/java/org/cef/handler/CefLoadHandler.java @@ -187,12 +187,8 @@ enum ErrorCode { ERR_INVALID_HTTP_RESPONSE(-370), ERR_CONTENT_DECODING_INIT_FAILED(-371), ERR_HTTP2_RST_STREAM_NO_ERROR_RECEIVED(-372), - ERR_HTTP2_PUSHED_STREAM_NOT_AVAILABLE(-373), - ERR_HTTP2_CLAIMED_PUSHED_STREAM_RESET_BY_SERVER(-374), ERR_TOO_MANY_RETRIES(-375), ERR_HTTP2_STREAM_CLOSED(-376), - ERR_HTTP2_CLIENT_REFUSED_STREAM(-377), - ERR_HTTP2_PUSHED_RESPONSE_DOES_NOT_MATCH(-378), ERR_HTTP_RESPONSE_CODE_FAILURE(-379), ERR_QUIC_CERT_ROOT_NOT_KNOWN(-380), ERR_QUIC_GOAWAY_REQUEST_CAN_BE_RETRIED(-381), diff --git a/native/jni_util.cpp b/native/jni_util.cpp index b71fc29e..d2c2488e 100644 --- a/native/jni_util.cpp +++ b/native/jni_util.cpp @@ -633,18 +633,10 @@ jobject NewJNIErrorCode(JNIEnv* env, cef_errorcode_t errorCode) { ERR_CONTENT_DECODING_INIT_FAILED, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_HTTP2_RST_STREAM_NO_ERROR_RECEIVED, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_HTTP2_PUSHED_STREAM_NOT_AVAILABLE, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_HTTP2_CLAIMED_PUSHED_STREAM_RESET_BY_SERVER, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_TOO_MANY_RETRIES, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_HTTP2_STREAM_CLOSED, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_HTTP2_CLIENT_REFUSED_STREAM, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_HTTP2_PUSHED_RESPONSE_DOES_NOT_MATCH, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_HTTP_RESPONSE_CODE_FAILURE, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", From 1fdf12d7599d124d2c9509666bc9b4caf45f4d46 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Fri, 5 Jan 2024 17:26:17 +0000 Subject: [PATCH 02/12] Update to CEF version 119.4.7+g55e15c8+chromium-119.0.6045.199 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8895daa8..54d592b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,7 +130,7 @@ set_property(GLOBAL PROPERTY OS_FOLDERS ON) # Specify the CEF distribution version. if(NOT DEFINED CEF_VERSION) - set(CEF_VERSION "119.4.3+gc76a3b9+chromium-119.0.6045.159") + set(CEF_VERSION "119.4.7+g55e15c8+chromium-119.0.6045.199") endif() # Determine the platform. From beb93367c934e4dc62b31ee11a836331b4401961 Mon Sep 17 00:00:00 2001 From: Rene Schneider Date: Tue, 9 Jan 2024 18:19:20 +0000 Subject: [PATCH 03/12] Fix HTTP auth credential request forwarding of realm and scheme params --- native/request_handler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/native/request_handler.cpp b/native/request_handler.cpp index 9d6b89e3..26d50dbd 100644 --- a/native/request_handler.cpp +++ b/native/request_handler.cpp @@ -120,8 +120,8 @@ bool RequestHandler::GetAuthCredentials(CefRefPtr browser, ScopedJNIBrowser jbrowser(env, browser); ScopedJNIString joriginUrl(env, origin_url); ScopedJNIString jhost(env, host); - ScopedJNIString jrealm(env, host); - ScopedJNIString jscheme(env, host); + ScopedJNIString jrealm(env, realm); + ScopedJNIString jscheme(env, scheme); ScopedJNIAuthCallback jcallback(env, callback); jboolean jresult = JNI_FALSE; From 812891babd55b482c5b4bc318ad10117057c1c61 Mon Sep 17 00:00:00 2001 From: Antoine Veldhoven Date: Tue, 9 Jan 2024 19:56:22 +0000 Subject: [PATCH 04/12] Add CefFrame.selectAll (fixes #428) Also implements common keyboard shortcuts on Mac. --- java/org/cef/browser/CefFrame.java | 7 ++++- java/org/cef/browser/CefFrame_N.java | 9 +++++++ .../detailed/handler/KeyboardHandler.java | 26 +++++++++++++++++++ native/CefFrame_N.cpp | 11 ++++++++ native/CefFrame_N.h | 9 +++++++ 5 files changed, 61 insertions(+), 1 deletion(-) diff --git a/java/org/cef/browser/CefFrame.java b/java/org/cef/browser/CefFrame.java index 3a2393fb..280f1e35 100644 --- a/java/org/cef/browser/CefFrame.java +++ b/java/org/cef/browser/CefFrame.java @@ -98,4 +98,9 @@ public interface CefFrame { * Execute paste in this frame. */ public void paste(); -} \ No newline at end of file + + /** + * Execute selectAll in this frame. + */ + public void selectAll(); +} diff --git a/java/org/cef/browser/CefFrame_N.java b/java/org/cef/browser/CefFrame_N.java index 8e129f1a..c68e1fbf 100644 --- a/java/org/cef/browser/CefFrame_N.java +++ b/java/org/cef/browser/CefFrame_N.java @@ -148,6 +148,14 @@ public void paste() { } } + public void selectAll() { + try { + N_SelectAll(getNativeRef(null)); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + private final native void N_Dispose(long self); private final native long N_GetIdentifier(long self); private final native String N_GetURL(long self); @@ -162,4 +170,5 @@ public void paste() { private final native void N_Cut(long self); private final native void N_Copy(long self); private final native void N_Paste(long self); + private final native void N_SelectAll(long self); } diff --git a/java/tests/detailed/handler/KeyboardHandler.java b/java/tests/detailed/handler/KeyboardHandler.java index 350d0f3b..6785b550 100644 --- a/java/tests/detailed/handler/KeyboardHandler.java +++ b/java/tests/detailed/handler/KeyboardHandler.java @@ -20,6 +20,32 @@ public boolean onKeyEvent(CefBrowser browser, CefKeyEvent event) { browser.executeJavaScript("alert('You pressed the space bar!');", "", 0); } return true; + } else if (event.type == CefKeyEvent.EventType.KEYEVENT_RAWKEYDOWN && event.is_system_key) { + // CMD+[key] is not working on a Mac. + // This switch statement delegates the common keyboard shortcuts to the browser + switch (event.unmodified_character) { + case 'a': + browser.getFocusedFrame().selectAll(); + break; + case 'c': + browser.getFocusedFrame().copy(); + break; + case 'v': + browser.getFocusedFrame().paste(); + break; + case 'x': + browser.getFocusedFrame().cut(); + break; + case 'z': + browser.getFocusedFrame().undo(); + break; + case 'Z': + browser.getFocusedFrame().redo(); + break; + default: + return false; + } + return true; } return false; } diff --git a/native/CefFrame_N.cpp b/native/CefFrame_N.cpp index 3fc93790..46f039fb 100644 --- a/native/CefFrame_N.cpp +++ b/native/CefFrame_N.cpp @@ -164,3 +164,14 @@ JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Paste(JNIEnv* env, frame->Paste(); } + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefFrame_1N_N_1SelectAll(JNIEnv* env, + jobject obj, + jlong self) { + CefRefPtr frame = GetSelf(self); + if (!frame) + return; + + frame->SelectAll(); +} diff --git a/native/CefFrame_N.h b/native/CefFrame_N.h index e1f6b459..c184d384 100644 --- a/native/CefFrame_N.h +++ b/native/CefFrame_N.h @@ -135,6 +135,15 @@ JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Paste(JNIEnv*, jobject, jlong); +/* + * Class: org_cef_browser_CefFrame_N + * Method: N_SelectAll + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1SelectAll(JNIEnv*, + jobject, + jlong); + #ifdef __cplusplus } #endif From 566dc4e166383559f781d2f7b4672633345bb496 Mon Sep 17 00:00:00 2001 From: Sander van den Berg Date: Thu, 11 Jan 2024 16:53:23 +0000 Subject: [PATCH 05/12] Add CefDevToolsClient --- java/org/cef/browser/CefBrowser.java | 14 +- java/org/cef/browser/CefBrowser_N.java | 50 +++++- java/org/cef/browser/CefDevToolsClient.java | 165 ++++++++++++++++++ .../browser/CefDevToolsMessageObserver.java | 34 ++++ java/org/cef/browser/CefRegistration.java | 24 +++ java/org/cef/browser/CefRegistration_N.java | 33 ++++ java/tests/detailed/ui/MenuBar.java | 59 ++++++- native/CMakeLists.txt | 6 + native/CefBrowser_N.cpp | 80 +++++++++ native/CefBrowser_N.h | 37 +++- native/CefFileDialogCallback_N.h | 3 +- native/CefRegistration_N.cpp | 14 ++ native/CefRegistration_N.h | 22 +++ native/devtools_message_observer.cpp | 44 +++++ native/devtools_message_observer.h | 37 ++++ native/devtools_method_callback.cpp | 21 +++ native/devtools_method_callback.h | 31 ++++ tools/make_all_jni_headers.bat | 1 + 18 files changed, 663 insertions(+), 12 deletions(-) create mode 100644 java/org/cef/browser/CefDevToolsClient.java create mode 100644 java/org/cef/browser/CefDevToolsMessageObserver.java create mode 100644 java/org/cef/browser/CefRegistration.java create mode 100644 java/org/cef/browser/CefRegistration_N.java create mode 100644 native/CefRegistration_N.cpp create mode 100644 native/CefRegistration_N.h create mode 100644 native/devtools_message_observer.cpp create mode 100644 native/devtools_message_observer.h create mode 100644 native/devtools_method_callback.cpp create mode 100644 native/devtools_method_callback.h diff --git a/java/org/cef/browser/CefBrowser.java b/java/org/cef/browser/CefBrowser.java index 43ae8f60..de0b2268 100644 --- a/java/org/cef/browser/CefBrowser.java +++ b/java/org/cef/browser/CefBrowser.java @@ -337,19 +337,29 @@ public void runFileDialog(FileDialogMode mode, String title, String defaultFileP public void stopFinding(boolean clearSelection); /** - * Get an instance of the dev tools to be displayed in its own window or to be + * Get an instance of the DevTools to be displayed in its own window or to be * embedded within your UI. Only one instance per browser is available. */ public CefBrowser getDevTools(); /** - * Get an instance of the dev tools to be displayed in its own window or to be + * Get an instance of the DevTools to be displayed in its own window or to be * embedded within your UI. Only one instance per browser is available. * * @param inspectAt a position in the UI which should be inspected. */ public CefBrowser getDevTools(Point inspectAt); + /** + * Get an instance of a client that can be used to leverage the DevTools + * protocol. Only one instance per browser is available. + * + * @see {@link CefDevToolsClient} + * @return DevTools client, or null if this browser is not yet created + * or if it is closed or closing + */ + public CefDevToolsClient getDevToolsClient(); + /** * If a misspelled word is currently selected in an editable node calling * this method will replace it with the specified |word|. diff --git a/java/org/cef/browser/CefBrowser_N.java b/java/org/cef/browser/CefBrowser_N.java index 406d0256..a5685bc5 100644 --- a/java/org/cef/browser/CefBrowser_N.java +++ b/java/org/cef/browser/CefBrowser_N.java @@ -5,7 +5,7 @@ package org.cef.browser; import org.cef.CefClient; -import org.cef.browser.CefRequestContext; +import org.cef.browser.CefDevToolsClient.DevToolsException; import org.cef.callback.CefDragData; import org.cef.callback.CefNativeAdapter; import org.cef.callback.CefPdfPrintCallback; @@ -18,7 +18,6 @@ import org.cef.misc.CefPdfPrintSettings; import org.cef.network.CefRequest; -import java.awt.Canvas; import java.awt.Component; import java.awt.Point; import java.awt.Rectangle; @@ -28,6 +27,7 @@ import java.awt.event.MouseWheelEvent; import java.awt.event.WindowEvent; import java.util.Vector; +import java.util.concurrent.CompletableFuture; import javax.swing.SwingUtilities; @@ -45,6 +45,7 @@ abstract class CefBrowser_N extends CefNativeAdapter implements CefBrowser { private volatile CefBrowser_N parent_ = null; private volatile Point inspectAt_ = null; private volatile CefBrowser_N devTools_ = null; + private volatile CefDevToolsClient devToolsClient_ = null; private boolean closeAllowed_ = false; private volatile boolean isClosed_ = false; private volatile boolean isClosing_ = false; @@ -130,6 +131,9 @@ public synchronized void onBeforeClose() { parent_.devTools_ = null; parent_ = null; } + if (devToolsClient_ != null) { + devToolsClient_.close(); + } } @Override @@ -145,6 +149,37 @@ public synchronized CefBrowser getDevTools(Point inspectAt) { return devTools_; } + @Override + public synchronized CefDevToolsClient getDevToolsClient() { + if (!isPending_ || isClosing_ || isClosed_) { + return null; + } + if (devToolsClient_ == null || devToolsClient_.isClosed()) { + devToolsClient_ = new CefDevToolsClient(this); + } + return devToolsClient_; + } + + CompletableFuture executeDevToolsMethod(String method, String parametersAsJson) { + CompletableFuture future = new CompletableFuture<>(); + N_ExecuteDevToolsMethod(method, parametersAsJson, new DevToolsMethodCallback() { + @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); @@ -379,6 +414,7 @@ public boolean hasDocument() { return false; } + @Override public void viewSource() { try { N_ViewSource(); @@ -387,6 +423,7 @@ public void viewSource() { } } + @Override public void getSource(CefStringVisitor visitor) { try { N_GetSource(visitor); @@ -395,6 +432,7 @@ public void getSource(CefStringVisitor visitor) { } } + @Override public void getText(CefStringVisitor visitor) { try { N_GetText(visitor); @@ -751,11 +789,19 @@ protected final void notifyMoveOrResizeStarted() { } } + private interface DevToolsMethodCallback { + void onComplete(int generatedMessageId); + } + private final native boolean N_CreateBrowser(CefClientHandler clientHandler, long windowHandle, String url, boolean osr, boolean transparent, Component canvas, CefRequestContext context); 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, DevToolsMethodCallback 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(); diff --git a/java/org/cef/browser/CefDevToolsClient.java b/java/org/cef/browser/CefDevToolsClient.java new file mode 100644 index 00000000..ee119469 --- /dev/null +++ b/java/org/cef/browser/CefDevToolsClient.java @@ -0,0 +1,165 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.browser; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +public class CefDevToolsClient implements AutoCloseable { + private final Map> queuedCommands_ = + Collections.synchronizedMap(new HashMap<>()); + private final Set eventListeners_ = + Collections.synchronizedSet(new LinkedHashSet<>()); + private CefRegistration registration_; + private final CefBrowser_N browser_; + + /** + * Use {@link CefBrowser#getDevToolsClient()} to get an instance of this class. + */ + CefDevToolsClient(CefBrowser_N browser) { + this.browser_ = browser; + + registration_ = browser.addDevToolsMessageObserver(new CefDevToolsMessageObserver() { + @Override + public void onDevToolsMethodResult( + CefBrowser browser, int messageId, boolean success, String result) { + CompletableFuture future = getQueuedCommand(messageId); + if (success) { + future.complete(result); + } else { + future.completeExceptionally( + new DevToolsException("DevTools method failed", result)); + } + } + + @Override + public void onDevToolsEvent(CefBrowser browser, String method, String parameters) { + for (EventListener eventListener : eventListeners_) { + eventListener.onEvent(method, parameters); + } + } + }); + } + + @Override + public void close() { + queuedCommands_.clear(); + eventListeners_.clear(); + registration_ = null; + } + + public boolean isClosed() { + return registration_ == null; + } + + private CompletableFuture getQueuedCommand(Integer messageId) { + return queuedCommands_.computeIfAbsent(messageId, key -> new CompletableFuture<>()); + } + + /** + * Execute a method call over the DevTools protocol. See the DevTools protocol documentation + * for details of supported methods and the expected syntax for parameters. + * + *

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

Call {@link #addEventListener(String, EventListener)} to subscribe to events. + * + * @param method the method name + * @return return a future with the method result if the method was executed successfully + */ + public CompletableFuture executeDevToolsMethod(String method) { + return executeDevToolsMethod(method, null); + } + + /** + * Execute a method call over the DevTools protocol. See the DevTools protocol documentation + * for details of supported methods and the expected syntax for parameters. + * + *

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

Call {@link #addEventListener(String, EventListener)} to subscribe to events. + * + * @param method the method name + * @param parametersAsJson JSON object with parameters, or null if no parameters are needed + * @return return a future with the method result if the method was executed successfully + */ + public CompletableFuture executeDevToolsMethod(String method, String parametersAsJson) { + if (isClosed()) { + CompletableFuture future = new CompletableFuture<>(); + future.completeExceptionally(new DevToolsException("Client is closed")); + return future; + } + + return browser_.executeDevToolsMethod(method, parametersAsJson) + .thenCompose(this::getQueuedCommand); + } + + /** + * Add an event listener for DevTools protocol events. Events by default are disabled + * and need to be enabled on a per domain basis, e.g. by sending Network.enable to enable + * network related events. + * + * @param eventListener the listener to add + */ + public void addEventListener(EventListener eventListener) { + eventListeners_.add(eventListener); + } + + /** + * Remove an event listener for DevTools protocol events. + * + * @param eventListener the listener to remove + */ + public void removeEventListener(EventListener eventListener) { + eventListeners_.remove(eventListener); + } + + public interface EventListener { + /** + * Method that will be called on receipt of an event. + * @param eventName the event name + * @param messageAsJson JSON object with the event message + */ + void onEvent(String eventName, String messageAsJson); + } + + public static final class DevToolsException extends Exception { + private static final long serialVersionUID = 3952948449841375372L; + + private final String json_; + + public DevToolsException(String message) { + this(message, null); + } + + public DevToolsException(String message, String json) { + super(message); + this.json_ = json; + } + + @Override + public String getMessage() { + String message = super.getMessage(); + if (json_ != null) message += ": " + json_; + return message; + } + + /** + * JSON object with the error details that were passed back by the DevTools + * host, or null if no further details are available. + */ + public String getJson() { + return json_; + } + } +} diff --git a/java/org/cef/browser/CefDevToolsMessageObserver.java b/java/org/cef/browser/CefDevToolsMessageObserver.java new file mode 100644 index 00000000..3a851356 --- /dev/null +++ b/java/org/cef/browser/CefDevToolsMessageObserver.java @@ -0,0 +1,34 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.browser; + +/** + * Used internally by {@link CefDevToolsClient}. + *

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

+ * Handle to observer registration, As long as this object is alive, the observer will stay + * registered. + */ +abstract class CefRegistration { + /** + * Removes the native reference from an unused object. + */ + public abstract void dispose(); + + @Override + public void finalize() throws Throwable { + dispose(); + super.finalize(); + } +} diff --git a/java/org/cef/browser/CefRegistration_N.java b/java/org/cef/browser/CefRegistration_N.java new file mode 100644 index 00000000..a7defd13 --- /dev/null +++ b/java/org/cef/browser/CefRegistration_N.java @@ -0,0 +1,33 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.browser; + +import org.cef.callback.CefNative; + +class CefRegistration_N extends CefRegistration implements CefNative { + // Used internally to store a pointer to the CEF object. + private long N_CefHandle = 0; + + @Override + public void setNativeRef(String identifier, long nativeRef) { + N_CefHandle = nativeRef; + } + + @Override + public long getNativeRef(String identifier) { + return N_CefHandle; + } + + @Override + public void dispose() { + try { + N_Dispose(N_CefHandle); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + private final native void N_Dispose(long self); +} diff --git a/java/tests/detailed/ui/MenuBar.java b/java/tests/detailed/ui/MenuBar.java index c69ae215..850e2104 100644 --- a/java/tests/detailed/ui/MenuBar.java +++ b/java/tests/detailed/ui/MenuBar.java @@ -4,10 +4,9 @@ package tests.detailed.ui; -import org.cef.CefApp; -import org.cef.CefClient; import org.cef.OS; import org.cef.browser.CefBrowser; +import org.cef.browser.CefDevToolsClient; import org.cef.callback.CefPdfPrintCallback; import org.cef.callback.CefRunFileDialogCallback; import org.cef.callback.CefStringVisitor; @@ -21,12 +20,10 @@ import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; -import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; -import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.io.File; @@ -40,10 +37,10 @@ import javax.swing.ImageIcon; import javax.swing.JButton; +import javax.swing.JCheckBoxMenuItem; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; -import javax.swing.JLayeredPane; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; @@ -86,6 +83,7 @@ public void visit(String string) { private final DownloadDialog downloadDialog_; private final CefCookieManager cookieManager_; private boolean reparentPending_ = false; + private CefDevToolsClient devToolsClient_; public MenuBar(MainFrame owner, CefBrowser browser, ControlPanel control_pane, DownloadDialog downloadDialog, CefCookieManager cookieManager) { @@ -382,6 +380,37 @@ public void componentHidden(ComponentEvent e) { }); testMenu.add(showDevTools); + JMenu devToolsProtocolMenu = new JMenu("DevTools Protocol"); + JMenuItem autoDarkMode = devToolsProtocolMenu.add(new JCheckBoxMenuItem("Auto Dark Mode")); + autoDarkMode.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Toggle the auto dark mode override + String params = String.format("{ \"enabled\": %s }", autoDarkMode.isSelected()); + executeDevToolsMethod("Emulation.setAutoDarkModeOverride", params); + } + }); + JMenuItem checkContrast = devToolsProtocolMenu.add(new JMenuItem("Check Contrast")); + checkContrast.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Check contrast, which usually triggers a series of Audits.issueAdded events + executeDevToolsMethod("Audits.checkContrast"); + } + }); + JMenuItem enableCSS = devToolsProtocolMenu.add(new JMenuItem("Enable CSS Agent")); + enableCSS.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Enable the CSS agent, which usually triggers a series of CSS.styleSheetAdded + // events. We can only enable the CSS agent if the DOM agent is enabled first, so we + // need to chain the two commands. + executeDevToolsMethod("DOM.enable") + .thenCompose(unused -> executeDevToolsMethod("CSS.enable")); + } + }); + testMenu.add(devToolsProtocolMenu); + JMenuItem testURLRequest = new JMenuItem("URL Request"); testURLRequest.addActionListener(new ActionListener() { @Override @@ -549,6 +578,26 @@ private void displayScreenshot(BufferedImage aScreenshot) { frame.pack(); } + private CompletableFuture executeDevToolsMethod(String methodName) { + return executeDevToolsMethod(methodName, null); + } + + private CompletableFuture executeDevToolsMethod( + String methodName, String paramsAsJson) { + if (devToolsClient_ == null) { + devToolsClient_ = browser_.getDevToolsClient(); + devToolsClient_.addEventListener( + (method, json) -> System.out.println("CDP event " + method + ": " + json)); + } + + return devToolsClient_.executeDevToolsMethod(methodName, paramsAsJson) + .handle((error, json) -> { + System.out.println( + "CDP result of " + methodName + ": " + (error != null ? error : json)); + return null; + }); + } + public void addBookmarkSeparator() { bookmarkMenu_.addSeparator(); } diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 7662405f..e3635be2 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -54,6 +54,8 @@ set(JCEF_SRCS CefPrintSettings_N.h CefQueryCallback_N.cpp CefQueryCallback_N.h + CefRegistration_N.cpp + CefRegistration_N.h CefRequest_N.cpp CefRequest_N.h CefCallback_N.cpp @@ -83,6 +85,10 @@ set(JCEF_SRCS cookie_visitor.cpp cookie_visitor.h critical_wait.h + devtools_message_observer.cpp + devtools_message_observer.h + devtools_method_callback.cpp + devtools_method_callback.h dialog_handler.cpp dialog_handler.h display_handler.cpp diff --git a/native/CefBrowser_N.cpp b/native/CefBrowser_N.cpp index c3c08813..c754c89a 100644 --- a/native/CefBrowser_N.cpp +++ b/native/CefBrowser_N.cpp @@ -6,12 +6,15 @@ #include "include/base/cef_callback.h" #include "include/cef_browser.h" +#include "include/cef_parser.h" #include "include/cef_task.h" #include "include/wrapper/cef_closure_task.h" #include "browser_process_handler.h" #include "client_handler.h" #include "critical_wait.h" +#include "devtools_message_observer.h" +#include "devtools_method_callback.h" #include "jni_util.h" #include "life_span_handler.h" #include "pdf_print_callback.h" @@ -1035,6 +1038,26 @@ void getZoomLevel(CefRefPtr host, } } +void executeDevToolsMethod(CefRefPtr host, + const CefString& method, + const CefString& parametersAsJson, + CefRefPtr callback) { + CefRefPtr parameters = nullptr; + if (!parametersAsJson.empty()) { + CefRefPtr value = CefParseJSON( + parametersAsJson, cef_json_parser_options_t::JSON_PARSER_RFC); + + if (!value || value->GetType() != VTYPE_DICTIONARY) { + callback->onComplete(0); + return; + } + + parameters = value->GetDictionary(); + } + + callback->onComplete(host->ExecuteDevToolsMethod(0, method, parameters)); +} + void OnAfterParentChanged(CefRefPtr browser) { if (!CefCurrentlyOn(TID_UI)) { CefPostTask(TID_UI, base::BindOnce(&OnAfterParentChanged, browser)); @@ -1138,6 +1161,16 @@ CefPdfPrintSettings GetJNIPdfPrintSettings(JNIEnv* env, jobject obj) { return settings; } +// JNI CefRegistration object. +class ScopedJNIRegistration : public ScopedJNIObject { + public: + ScopedJNIRegistration(JNIEnv* env, CefRefPtr obj) + : ScopedJNIObject(env, + obj, + "org/cef/misc/CefRegistration_N", + "CefRegistration") {} +}; + } // namespace JNIEXPORT jboolean JNICALL @@ -1183,6 +1216,53 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv* env, return JNI_FALSE; // set asynchronously } +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1ExecuteDevToolsMethod( + JNIEnv* env, + jobject jbrowser, + jstring method, + jstring parametersAsJson, + jobject jcallback) { + CefRefPtr callback = + new DevToolsMethodCallback(env, jcallback); + + CefRefPtr browser = GetJNIBrowser(env, jbrowser); + if (!browser.get()) { + callback->onComplete(0); + return; + } + + CefString strMethod = GetJNIString(env, method); + CefString strParametersAsJson = GetJNIString(env, parametersAsJson); + + if (CefCurrentlyOn(TID_UI)) { + executeDevToolsMethod(browser->GetHost(), strMethod, strParametersAsJson, + callback); + } else { + CefPostTask(TID_UI, + base::BindOnce(executeDevToolsMethod, browser->GetHost(), + strMethod, strParametersAsJson, callback)); + } +} + +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1AddDevToolsMessageObserver( + JNIEnv* env, + jobject jbrowser, + jobject jobserver) { + CefRefPtr browser = + JNI_GET_BROWSER_OR_RETURN(env, jbrowser, NULL); + + CefRefPtr observer = + new DevToolsMessageObserver(env, jobserver); + + CefRefPtr registration = + browser->GetHost()->AddDevToolsMessageObserver(observer); + + ScopedJNIRegistration jregistration(env, registration); + return jregistration.Release(); +} + JNIEXPORT jlong JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetWindowHandle(JNIEnv* env, jobject obj, diff --git a/native/CefBrowser_N.h b/native/CefBrowser_N.h index 9e03d8ca..85176735 100644 --- a/native/CefBrowser_N.h +++ b/native/CefBrowser_N.h @@ -41,6 +41,30 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv*, jobject, jobject); +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_ExecuteDevToolsMethod + * Signature: + * (Ljava/lang/String;Ljava/lang/String;Lorg/cef/browser/CefBrowser_N/DevToolsMethodCallback;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1ExecuteDevToolsMethod(JNIEnv*, + jobject, + jstring, + jstring, + jobject); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_AddDevToolsMessageObserver + * Signature: + * (Lorg/cef/browser/CefDevToolsMessageObserver;)Lorg/cef/browser/CefRegistration; + */ +JNIEXPORT jobject JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1AddDevToolsMessageObserver(JNIEnv*, + jobject, + jobject); + /* * Class: org_cef_browser_CefBrowser_N * Method: N_GetWindowHandle @@ -348,7 +372,7 @@ Java_org_cef_browser_CefBrowser_1N_N_1PrintToPDF(JNIEnv*, /* * Class: org_cef_browser_CefBrowser_N * Method: N_Find - * Signature: (ILjava/lang/String;ZZZ)V + * Signature: (Ljava/lang/String;ZZZ)V */ JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1Find(JNIEnv*, jobject, @@ -524,3 +548,14 @@ Java_org_cef_browser_CefBrowser_1N_N_1NotifyMoveOrResizeStarted(JNIEnv*, } #endif #endif +/* Header for class org_cef_browser_CefBrowser_N_DevToolsMethodCallback */ + +#ifndef _Included_org_cef_browser_CefBrowser_N_DevToolsMethodCallback +#define _Included_org_cef_browser_CefBrowser_N_DevToolsMethodCallback +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif diff --git a/native/CefFileDialogCallback_N.h b/native/CefFileDialogCallback_N.h index 1f11dae9..1da3ded8 100644 --- a/native/CefFileDialogCallback_N.h +++ b/native/CefFileDialogCallback_N.h @@ -10,13 +10,12 @@ extern "C" { /* * Class: org_cef_callback_CefFileDialogCallback_N * Method: N_Continue - * Signature: (JILjava/util/Vector;)V + * Signature: (JLjava/util/Vector;)V */ JNIEXPORT void JNICALL Java_org_cef_callback_CefFileDialogCallback_1N_N_1Continue(JNIEnv*, jobject, jlong, - jint, jobject); /* diff --git a/native/CefRegistration_N.cpp b/native/CefRegistration_N.cpp new file mode 100644 index 00000000..295002d3 --- /dev/null +++ b/native/CefRegistration_N.cpp @@ -0,0 +1,14 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "CefRegistration_N.h" +#include "include/cef_registration.h" +#include "jni_scoped_helpers.h" + +JNIEXPORT void JNICALL +Java_org_cef_misc_CefRegistration_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { + SetCefForJNIObject(env, obj, NULL, "CefRegistration"); +} diff --git a/native/CefRegistration_N.h b/native/CefRegistration_N.h new file mode 100644 index 00000000..3c48c7bc --- /dev/null +++ b/native/CefRegistration_N.h @@ -0,0 +1,22 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_cef_misc_CefRegistration_N */ + +#ifndef _Included_org_cef_misc_CefRegistration_N +#define _Included_org_cef_misc_CefRegistration_N +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_cef_misc_CefRegistration_N + * Method: N_Dispose + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_cef_misc_CefRegistration_1N_N_1Dispose(JNIEnv*, + jobject, + jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/native/devtools_message_observer.cpp b/native/devtools_message_observer.cpp new file mode 100644 index 00000000..84a47fbf --- /dev/null +++ b/native/devtools_message_observer.cpp @@ -0,0 +1,44 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "devtools_message_observer.h" + +#include "jni_util.h" + +DevToolsMessageObserver::DevToolsMessageObserver(JNIEnv* env, jobject observer) + : handle_(env, observer) {} + +void DevToolsMessageObserver::OnDevToolsMethodResult( + CefRefPtr browser, + int message_id, + bool success, + const void* result, + size_t result_size) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + std::string strResult(static_cast(result), result_size); + JNI_CALL_VOID_METHOD( + env, handle_, "onDevToolsMethodResult", + "(Lorg/cef/browser/CefBrowser;IZLjava/lang/String;)V", jbrowser.get(), + message_id, success ? JNI_TRUE : JNI_FALSE, NewJNIString(env, strResult)); +} + +void DevToolsMessageObserver::OnDevToolsEvent(CefRefPtr browser, + const CefString& method, + const void* params, + size_t params_size) { + ScopedJNIEnv env; + if (!env) + return; + ScopedJNIBrowser jbrowser(env, browser); + + std::string strParams(static_cast(params), params_size); + JNI_CALL_VOID_METHOD( + env, handle_, "onDevToolsEvent", + "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;Ljava/lang/String;)V", + jbrowser.get(), NewJNIString(env, method), NewJNIString(env, strParams)); +} diff --git a/native/devtools_message_observer.h b/native/devtools_message_observer.h new file mode 100644 index 00000000..19e34bb9 --- /dev/null +++ b/native/devtools_message_observer.h @@ -0,0 +1,37 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef JCEF_NATIVE_DEVTOOLS_MESSAGE_OBSERVER_H_ +#define JCEF_NATIVE_DEVTOOLS_MESSAGE_OBSERVER_H_ +#pragma once + +#include +#include "include/cef_devtools_message_observer.h" + +#include "jni_scoped_helpers.h" + +// DevToolsMessageObserver implementation. +class DevToolsMessageObserver : public CefDevToolsMessageObserver { + public: + DevToolsMessageObserver(JNIEnv* env, jobject observer); + + // CefDevToolsMessageObserver methods + virtual void OnDevToolsMethodResult(CefRefPtr browser, + int message_id, + bool success, + const void* result, + size_t result_size) override; + virtual void OnDevToolsEvent(CefRefPtr browser, + const CefString& method, + const void* params, + size_t params_size) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(DevToolsMessageObserver); +}; + +#endif // JCEF_NATIVE_DEVTOOLS_MESSAGE_OBSERVER_H_ diff --git a/native/devtools_method_callback.cpp b/native/devtools_method_callback.cpp new file mode 100644 index 00000000..b8057d52 --- /dev/null +++ b/native/devtools_method_callback.cpp @@ -0,0 +1,21 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "devtools_method_callback.h" + +#include "jni_scoped_helpers.h" +#include "jni_util.h" +#include "util.h" + +DevToolsMethodCallback::DevToolsMethodCallback(JNIEnv* env, jobject jcallback) + : handle_(env, jcallback) {} + +void DevToolsMethodCallback::onComplete(int generatedMessageId) { + ScopedJNIEnv env; + if (!env) + return; + + JNI_CALL_VOID_METHOD(env, handle_, "onComplete", "(I)V", + (jint)generatedMessageId); +} diff --git a/native/devtools_method_callback.h b/native/devtools_method_callback.h new file mode 100644 index 00000000..1c219f90 --- /dev/null +++ b/native/devtools_method_callback.h @@ -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. + +#ifndef JCEF_NATIVE_DEVTOOLS_METHOD_CALLBACK_H_ +#define JCEF_NATIVE_DEVTOOLS_METHOD_CALLBACK_H_ +#pragma once + +#include + +#include "jni_scoped_helpers.h" + +// Callback for CefBrowserHost::ExecuteDevToolsMethod. The methods of +// this class will be called on the browser process UI thread. +class DevToolsMethodCallback : public virtual CefBaseRefCounted { + public: + DevToolsMethodCallback(JNIEnv* env, jobject jcallback); + + // Method that will be called when the DevTools method has been executed. + // |generatedMessageId| is the generated message ID, or 0 if an error + // occurred. + virtual void onComplete(int generatedMessageId); + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(DevToolsMethodCallback); +}; + +#endif // JCEF_NATIVE_DEVTOOLS_METHOD_CALLBACK_H_ diff --git a/tools/make_all_jni_headers.bat b/tools/make_all_jni_headers.bat index 3f101d3a..9c463161 100644 --- a/tools/make_all_jni_headers.bat +++ b/tools/make_all_jni_headers.bat @@ -37,6 +37,7 @@ call make_jni_header.bat %1 org.cef.callback.CefQueryCallback_N call make_jni_header.bat %1 org.cef.callback.CefSchemeRegistrar_N call make_jni_header.bat %1 org.cef.handler.CefClientHandler call make_jni_header.bat %1 org.cef.misc.CefPrintSettings_N +call make_jni_header.bat %1 org.cef.misc.CefRegistration_N call make_jni_header.bat %1 org.cef.network.CefCookieManager_N call make_jni_header.bat %1 org.cef.network.CefPostData_N call make_jni_header.bat %1 org.cef.network.CefPostDataElement_N From ade64c361b98671924d198e958e2cde4976e55d3 Mon Sep 17 00:00:00 2001 From: Osiris Team Date: Thu, 11 Jan 2024 16:59:07 +0000 Subject: [PATCH 06/12] Add rendered image callback for CefBrowserOsr/CefRenderer (fixes #432) --- java/org/cef/SystemBootstrap.java | 4 +- java/org/cef/browser/CefBrowserOsr.java | 28 ++++++++++ java/org/cef/browser/CefPaintEvent.java | 51 +++++++++++++++++++ .../org/cef/handler/CefAppHandlerAdapter.java | 7 +-- java/org/cef/handler/CefRenderHandler.java | 20 ++++++++ 5 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 java/org/cef/browser/CefPaintEvent.java diff --git a/java/org/cef/SystemBootstrap.java b/java/org/cef/SystemBootstrap.java index 0a217ac4..342aaa82 100644 --- a/java/org/cef/SystemBootstrap.java +++ b/java/org/cef/SystemBootstrap.java @@ -13,7 +13,9 @@ public class SystemBootstrap { /** * Simple interface for how a library by name should be loaded. */ - static public interface Loader { public void loadLibrary(String libname); } + static public interface Loader { + public void loadLibrary(String libname); + } /** * Default implementation is to call System.loadLibrary diff --git a/java/org/cef/browser/CefBrowserOsr.java b/java/org/cef/browser/CefBrowserOsr.java index 902bc862..506f6e63 100644 --- a/java/org/cef/browser/CefBrowserOsr.java +++ b/java/org/cef/browser/CefBrowserOsr.java @@ -60,9 +60,11 @@ import java.util.Arrays; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; import javax.swing.MenuSelectionManager; import javax.swing.SwingUtilities; @@ -84,6 +86,9 @@ class CefBrowserOsr extends CefBrowser_N implements CefRenderHandler { private int depth_per_component = 8; private boolean isTransparent_; + private CopyOnWriteArrayList> onPaintListeners = + new CopyOnWriteArrayList<>(); + CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context) { this(client, url, transparent, context, null, null); } @@ -354,6 +359,22 @@ public void onPopupSize(CefBrowser browser, Rectangle size) { renderer_.onPopupSize(size); } + @Override + public void addOnPaintListener(Consumer listener) { + onPaintListeners.add(listener); + } + + @Override + public void setOnPaintListener(Consumer listener) { + onPaintListeners.clear(); + onPaintListeners.add(listener); + } + + @Override + public void removeOnPaintListener(Consumer listener) { + onPaintListeners.remove(listener); + } + @Override public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height) { @@ -376,6 +397,13 @@ public void run() { canvas_.display(); } }); + if (!onPaintListeners.isEmpty()) { + CefPaintEvent paintEvent = + new CefPaintEvent(browser, popup, dirtyRects, buffer, width, height); + for (Consumer l : onPaintListeners) { + l.accept(paintEvent); + } + } } @Override diff --git a/java/org/cef/browser/CefPaintEvent.java b/java/org/cef/browser/CefPaintEvent.java new file mode 100644 index 00000000..aed9af31 --- /dev/null +++ b/java/org/cef/browser/CefPaintEvent.java @@ -0,0 +1,51 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.browser; + +import java.awt.*; +import java.nio.ByteBuffer; + +public class CefPaintEvent { + private final CefBrowser browser; + private final boolean popup; + private final Rectangle[] dirtyRects; + private final ByteBuffer renderedFrame; + private final int width; + private final int height; + + public CefPaintEvent(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, + ByteBuffer renderedFrame, int width, int height) { + this.browser = browser; + this.popup = popup; + this.dirtyRects = dirtyRects; + this.renderedFrame = renderedFrame; + this.width = width; + this.height = height; + } + + public CefBrowser getBrowser() { + return browser; + } + + public boolean getPopup() { + return popup; + } + + public Rectangle[] getDirtyRects() { + return dirtyRects; + } + + public ByteBuffer getRenderedFrame() { + return renderedFrame; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } +} \ No newline at end of file diff --git a/java/org/cef/handler/CefAppHandlerAdapter.java b/java/org/cef/handler/CefAppHandlerAdapter.java index d74eee48..47f7ae53 100644 --- a/java/org/cef/handler/CefAppHandlerAdapter.java +++ b/java/org/cef/handler/CefAppHandlerAdapter.java @@ -32,9 +32,10 @@ public void onBeforeCommandLineProcessing(String process_type, CefCommandLine co continue; } // Arguments with '--', '-' and, on Windows, '/' prefixes are considered switches. - int switchCnt = arg.startsWith("--") - ? 2 - : arg.startsWith("/") ? 1 : arg.startsWith("-") ? 1 : 0; + int switchCnt = arg.startsWith("--") ? 2 + : arg.startsWith("/") ? 1 + : arg.startsWith("-") ? 1 + : 0; switch (switchCnt) { case 2: // An argument of "--" will terminate switch parsing with all subsequent diff --git a/java/org/cef/handler/CefRenderHandler.java b/java/org/cef/handler/CefRenderHandler.java index 0a94bb2f..258df884 100644 --- a/java/org/cef/handler/CefRenderHandler.java +++ b/java/org/cef/handler/CefRenderHandler.java @@ -5,11 +5,13 @@ package org.cef.handler; import org.cef.browser.CefBrowser; +import org.cef.browser.CefPaintEvent; import org.cef.callback.CefDragData; import java.awt.Point; import java.awt.Rectangle; import java.nio.ByteBuffer; +import java.util.function.Consumer; /** * Implement this interface to handle events when window rendering is disabled. @@ -65,6 +67,24 @@ public interface CefRenderHandler { public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height); + /** + * Add provided listener. + * @param listener Code that gets executed after a frame was rendered. + */ + public void addOnPaintListener(Consumer listener); + + /** + * Remove existing listeners and replace with provided listener. + * @param listener Code that gets executed after a frame was rendered. + */ + public void setOnPaintListener(Consumer listener); + + /** + * Remove provided listener. + * @param listener Code that gets executed after a frame was rendered. + */ + public void removeOnPaintListener(Consumer listener); + /** * Handle cursor changes. * @param browser The browser generating the event. From 423f5b8e9663c6718f954a9be5154a1e1be3a8fb Mon Sep 17 00:00:00 2001 From: Filip Date: Thu, 11 Jan 2024 18:25:25 +0000 Subject: [PATCH 07/12] Add CefBrowserSettings.windowless_frame_rate (see #459) Also adds methods to dynamically set/get the frame rate and fixes some pre-existing compile issues. --- java/org/cef/CefBrowserSettings.java | 31 +++++++++ java/org/cef/CefClient.java | 27 ++++++-- java/org/cef/browser/CefBrowser.java | 22 ++++++ java/org/cef/browser/CefBrowserFactory.java | 8 ++- java/org/cef/browser/CefBrowserOsr.java | 13 ++-- java/org/cef/browser/CefBrowserWr.java | 24 +++++-- java/org/cef/browser/CefBrowser_N.java | 43 +++++++++--- java/tests/detailed/MainFrame.java | 28 ++++++-- java/tests/detailed/ui/MenuBar.java | 2 +- native/CMakeLists.txt | 4 +- native/CefBrowser_N.cpp | 68 ++++++++++++++++--- native/CefBrowser_N.h | 25 ++++++- native/devtools_method_callback.h | 31 --------- ...s_method_callback.cpp => int_callback.cpp} | 9 ++- native/int_callback.h | 28 ++++++++ 15 files changed, 279 insertions(+), 84 deletions(-) create mode 100644 java/org/cef/CefBrowserSettings.java delete mode 100644 native/devtools_method_callback.h rename native/{devtools_method_callback.cpp => int_callback.cpp} (54%) create mode 100644 native/int_callback.h diff --git a/java/org/cef/CefBrowserSettings.java b/java/org/cef/CefBrowserSettings.java new file mode 100644 index 00000000..8733a418 --- /dev/null +++ b/java/org/cef/CefBrowserSettings.java @@ -0,0 +1,31 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef; + +/** + * Browser initialization settings. Specify NULL or 0 to get the recommended + * default values. The consequences of using custom values may not be well + * tested. Many of these and other settings can also configured using command- + * line switches. + */ +public class CefBrowserSettings { + /** + * The maximum rate in frames per second (fps) that CefRenderHandler::OnPaint + * will be called for a windowless browser. The actual fps may be lower if + * the browser cannot generate frames at the requested rate. The minimum + * value is 1 and the maximum value is 60 (default 30). This value can also + * be changed dynamically via {@code CefBrowser#setWindowlessFrameRate} + */ + public int windowless_frame_rate = 0; + + public CefBrowserSettings() {} + + @Override + public CefBrowserSettings clone() { + CefBrowserSettings tmp = new CefBrowserSettings(); + tmp.windowless_frame_rate = windowless_frame_rate; + return tmp; + } +} diff --git a/java/org/cef/CefClient.java b/java/org/cef/CefClient.java index 7f87bc5c..90122936 100644 --- a/java/org/cef/CefClient.java +++ b/java/org/cef/CefClient.java @@ -4,11 +4,7 @@ package org.cef; -import org.cef.browser.CefBrowser; -import org.cef.browser.CefBrowserFactory; -import org.cef.browser.CefFrame; -import org.cef.browser.CefMessageRouter; -import org.cef.browser.CefRequestContext; +import org.cef.browser.*; import org.cef.callback.CefAuthCallback; import org.cef.callback.CefBeforeDownloadCallback; import org.cef.callback.CefCallback; @@ -60,6 +56,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Vector; +import java.util.function.Consumer; import javax.swing.SwingUtilities; @@ -141,7 +138,16 @@ public CefBrowser createBrowser(String url, boolean isOffscreenRendered, boolean CefRequestContext context) { if (isDisposed_) throw new IllegalStateException("Can't create browser. CefClient is disposed"); - return CefBrowserFactory.create(this, url, isOffscreenRendered, isTransparent, context); + return CefBrowserFactory.create( + this, url, isOffscreenRendered, isTransparent, context, null); + } + + public CefBrowser createBrowser(String url, boolean isOffscreenRendered, boolean isTransparent, + CefRequestContext context, CefBrowserSettings settings) { + if (isDisposed_) + throw new IllegalStateException("Can't create browser. CefClient is disposed"); + return CefBrowserFactory.create( + this, url, isOffscreenRendered, isTransparent, context, settings); } @Override @@ -753,6 +759,15 @@ public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, realHandler.onPaint(browser, popup, dirtyRects, buffer, width, height); } + @Override + public void addOnPaintListener(Consumer listener) {} + + @Override + public void setOnPaintListener(Consumer listener) {} + + @Override + public void removeOnPaintListener(Consumer listener) {} + @Override public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y) { if (browser == null) return false; diff --git a/java/org/cef/browser/CefBrowser.java b/java/org/cef/browser/CefBrowser.java index de0b2268..f6c72ee5 100644 --- a/java/org/cef/browser/CefBrowser.java +++ b/java/org/cef/browser/CefBrowser.java @@ -390,4 +390,26 @@ public void runFileDialog(FileDialogMode mode, String title, String defaultFileP * @throws UnsupportedOperationException if not supported */ public CompletableFuture createScreenshot(boolean nativeResolution); + + /** + * Set the maximum rate in frames per second (fps) that {@code CefRenderHandler::onPaint} + * will be called for a windowless browser. The actual fps may be + * lower if the browser cannot generate frames at the requested rate. The + * minimum value is 1, and the maximum value is 60 (default 30). + * + * @param frameRate the maximum frame rate + * @throws UnsupportedOperationException if not supported + */ + public void setWindowlessFrameRate(int frameRate); + + /** + * Returns the maximum rate in frames per second (fps) that {@code CefRenderHandler::onPaint} + * will be called for a windowless browser. The actual fps may be lower if the browser cannot + * generate frames at the requested rate. The minimum value is 1, and the maximum value is 60 + * (default 30). + * + * @return the framerate, 0 if an error occurs + * @throws UnsupportedOperationException if not supported + */ + public CompletableFuture getWindowlessFrameRate(); } diff --git a/java/org/cef/browser/CefBrowserFactory.java b/java/org/cef/browser/CefBrowserFactory.java index 708d0f24..299dfcfb 100644 --- a/java/org/cef/browser/CefBrowserFactory.java +++ b/java/org/cef/browser/CefBrowserFactory.java @@ -4,6 +4,7 @@ package org.cef.browser; +import org.cef.CefBrowserSettings; import org.cef.CefClient; /** @@ -11,8 +12,9 @@ */ public class CefBrowserFactory { public static CefBrowser create(CefClient client, String url, boolean isOffscreenRendered, - boolean isTransparent, CefRequestContext context) { - if (isOffscreenRendered) return new CefBrowserOsr(client, url, isTransparent, context); - return new CefBrowserWr(client, url, context); + boolean isTransparent, CefRequestContext context, CefBrowserSettings settings) { + if (isOffscreenRendered) + return new CefBrowserOsr(client, url, isTransparent, context, settings); + return new CefBrowserWr(client, url, context, settings); } } diff --git a/java/org/cef/browser/CefBrowserOsr.java b/java/org/cef/browser/CefBrowserOsr.java index 506f6e63..b999b6ba 100644 --- a/java/org/cef/browser/CefBrowserOsr.java +++ b/java/org/cef/browser/CefBrowserOsr.java @@ -15,6 +15,7 @@ import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.util.GLBuffers; +import org.cef.CefBrowserSettings; import org.cef.CefClient; import org.cef.OS; import org.cef.callback.CefDragData; @@ -89,13 +90,15 @@ class CefBrowserOsr extends CefBrowser_N implements CefRenderHandler { private CopyOnWriteArrayList> onPaintListeners = new CopyOnWriteArrayList<>(); - CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context) { - this(client, url, transparent, context, null, null); + CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context, + CefBrowserSettings settings) { + this(client, url, transparent, context, null, null, settings); } private CefBrowserOsr(CefClient client, String url, boolean transparent, - CefRequestContext context, CefBrowserOsr parent, Point inspectAt) { - super(client, url, context, parent, inspectAt); + CefRequestContext context, CefBrowserOsr parent, Point inspectAt, + CefBrowserSettings settings) { + super(client, url, context, parent, inspectAt, settings); isTransparent_ = transparent; renderer_ = new CefRenderer(transparent); createGLCanvas(); @@ -122,7 +125,7 @@ public CefRenderHandler getRenderHandler() { protected CefBrowser_N createDevToolsBrowser(CefClient client, String url, CefRequestContext context, CefBrowser_N parent, Point inspectAt) { return new CefBrowserOsr( - client, url, isTransparent_, context, (CefBrowserOsr) this, inspectAt); + client, url, isTransparent_, context, (CefBrowserOsr) this, inspectAt, null); } private synchronized long getWindowHandle() { diff --git a/java/org/cef/browser/CefBrowserWr.java b/java/org/cef/browser/CefBrowserWr.java index 583c4f41..677ddce7 100644 --- a/java/org/cef/browser/CefBrowserWr.java +++ b/java/org/cef/browser/CefBrowserWr.java @@ -4,6 +4,7 @@ package org.cef.browser; +import org.cef.CefBrowserSettings; import org.cef.CefClient; import org.cef.OS; import org.cef.handler.CefWindowHandler; @@ -166,14 +167,15 @@ public int getClickCount(int event, int button) { } }; - CefBrowserWr(CefClient client, String url, CefRequestContext context) { - this(client, url, context, null, null); + CefBrowserWr( + CefClient client, String url, CefRequestContext context, CefBrowserSettings settings) { + this(client, url, context, null, null, settings); } @SuppressWarnings("serial") private CefBrowserWr(CefClient client, String url, CefRequestContext context, - CefBrowserWr parent, Point inspectAt) { - super(client, url, context, parent, inspectAt); + CefBrowserWr parent, Point inspectAt, CefBrowserSettings settings) { + super(client, url, context, parent, inspectAt, settings); delayedUpdate_.setRepeats(false); // Disabling lightweight of popup menu is required because @@ -318,7 +320,7 @@ public CefWindowHandler getWindowHandler() { @Override protected CefBrowser_N createDevToolsBrowser(CefClient client, String url, CefRequestContext context, CefBrowser_N parent, Point inspectAt) { - return new CefBrowserWr(client, url, context, (CefBrowserWr) this, inspectAt); + return new CefBrowserWr(client, url, context, (CefBrowserWr) this, inspectAt, null); } private synchronized long getWindowHandle() { @@ -421,4 +423,16 @@ private boolean createBrowserIfRequired(boolean hasParent) { public CompletableFuture createScreenshot(boolean nativeResolution) { throw new UnsupportedOperationException("Unsupported for windowed rendering"); } + + @Override + public void setWindowlessFrameRate(int frameRate) { + throw new UnsupportedOperationException( + "You can only set windowless framerate on OSR browser"); + } + + @Override + public CompletableFuture getWindowlessFrameRate() { + throw new UnsupportedOperationException( + "You can only get windowless framerate on OSR browser"); + } } diff --git a/java/org/cef/browser/CefBrowser_N.java b/java/org/cef/browser/CefBrowser_N.java index a5685bc5..d7c62e0f 100644 --- a/java/org/cef/browser/CefBrowser_N.java +++ b/java/org/cef/browser/CefBrowser_N.java @@ -4,6 +4,7 @@ package org.cef.browser; +import org.cef.CefBrowserSettings; import org.cef.CefClient; import org.cef.browser.CefDevToolsClient.DevToolsException; import org.cef.callback.CefDragData; @@ -49,14 +50,19 @@ abstract class CefBrowser_N extends CefNativeAdapter implements CefBrowser { private boolean closeAllowed_ = false; private volatile boolean isClosed_ = false; private volatile boolean isClosing_ = false; + private final CefBrowserSettings settings_; protected CefBrowser_N(CefClient client, String url, CefRequestContext context, - CefBrowser_N parent, Point inspectAt) { + CefBrowser_N parent, Point inspectAt, CefBrowserSettings settings) { client_ = client; url_ = url; request_context_ = context; parent_ = parent; inspectAt_ = inspectAt; + if (settings != null) + settings_ = settings.clone(); + else + settings_ = new CefBrowserSettings(); } protected String getUrl() { @@ -162,7 +168,7 @@ public synchronized CefDevToolsClient getDevToolsClient() { CompletableFuture executeDevToolsMethod(String method, String parametersAsJson) { CompletableFuture future = new CompletableFuture<>(); - N_ExecuteDevToolsMethod(method, parametersAsJson, new DevToolsMethodCallback() { + N_ExecuteDevToolsMethod(method, parametersAsJson, new IntCallback() { @Override public void onComplete(int generatedMessageId) { if (generatedMessageId <= 0) { @@ -190,8 +196,8 @@ protected void createBrowser(CefClientHandler clientHandler, long windowHandle, boolean osr, boolean transparent, Component canvas, CefRequestContext context) { if (getNativeRef("CefBrowser") == 0 && !isPending_) { try { - N_CreateBrowser( - clientHandler, windowHandle, url, osr, transparent, canvas, context); + N_CreateBrowser(clientHandler, windowHandle, url, osr, transparent, canvas, context, + settings_); } catch (UnsatisfiedLinkError err) { err.printStackTrace(); } @@ -789,17 +795,36 @@ protected final void notifyMoveOrResizeStarted() { } } - private interface DevToolsMethodCallback { - void onComplete(int generatedMessageId); + public void setWindowlessFrameRate(int frameRate) { + try { + N_SetWindowlessFrameRate(frameRate); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + public CompletableFuture getWindowlessFrameRate() { + final CompletableFuture future = new CompletableFuture<>(); + try { + N_GetWindowlessFrameRate(future::complete); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + future.complete(0); + } + return future; + } + + private interface IntCallback { + void onComplete(int value); } private final native boolean N_CreateBrowser(CefClientHandler clientHandler, long windowHandle, String url, boolean osr, boolean transparent, Component canvas, - CefRequestContext context); + CefRequestContext context, CefBrowserSettings settings); private final native boolean N_CreateDevTools(CefBrowser parent, CefClientHandler clientHandler, long windowHandle, boolean osr, boolean transparent, Component canvas, Point inspectAt); private final native void N_ExecuteDevToolsMethod( - String method, String parametersAsJson, DevToolsMethodCallback callback); + String method, String parametersAsJson, IntCallback callback); private final native CefRegistration N_AddDevToolsMessageObserver( CefDevToolsMessageObserver observer); private final native long N_GetWindowHandle(long surfaceHandle); @@ -860,4 +885,6 @@ private final native void N_DragTargetDragEnter( private final native void N_UpdateUI(Rectangle contentRect, Rectangle browserRect); private final native void N_SetParent(long windowHandle, Component canvas); private final native void N_NotifyMoveOrResizeStarted(); + private final native void N_SetWindowlessFrameRate(int frameRate); + private final native void N_GetWindowlessFrameRate(IntCallback frameRateCallback); } diff --git a/java/tests/detailed/MainFrame.java b/java/tests/detailed/MainFrame.java index f13b321d..85eb3cdb 100644 --- a/java/tests/detailed/MainFrame.java +++ b/java/tests/detailed/MainFrame.java @@ -6,6 +6,7 @@ import org.cef.CefApp; import org.cef.CefApp.CefVersion; +import org.cef.CefBrowserSettings; import org.cef.CefClient; import org.cef.CefSettings; import org.cef.CefSettings.ColorType; @@ -58,6 +59,7 @@ public static void main(String[] args) { boolean osrEnabledArg = false; boolean transparentPaintingEnabledArg = false; boolean createImmediately = false; + int windowless_frame_rate = 0; for (String arg : args) { arg = arg.toLowerCase(); if (arg.equals("--off-screen-rendering-enabled")) { @@ -66,6 +68,8 @@ public static void main(String[] args) { transparentPaintingEnabledArg = true; } else if (arg.equals("--create-immediately")) { createImmediately = true; + } else if (arg.equals("--windowless-frame-rate-60")) { + windowless_frame_rate = 60; } } @@ -73,10 +77,21 @@ public static void main(String[] args) { // MainFrame keeps all the knowledge to display the embedded browser // frame. - final MainFrame frame = new MainFrame( - osrEnabledArg, transparentPaintingEnabledArg, createImmediately, args); + final MainFrame frame = new MainFrame(osrEnabledArg, transparentPaintingEnabledArg, + createImmediately, windowless_frame_rate, args); frame.setSize(800, 600); frame.setVisible(true); + + if (osrEnabledArg && windowless_frame_rate != 0) { + frame.getBrowser().getWindowlessFrameRate().thenAccept( + framerate -> System.out.println("Framerate is:" + framerate)); + + frame.getBrowser().setWindowlessFrameRate(2); + frame.getBrowser().getWindowlessFrameRate().thenAccept( + framerate -> System.out.println("Framerate is:" + framerate)); + + frame.getBrowser().setWindowlessFrameRate(windowless_frame_rate); + } } private final CefClient client_; @@ -88,7 +103,7 @@ public static void main(String[] args) { private boolean transparent_painting_enabled_; public MainFrame(boolean osrEnabled, boolean transparentPaintingEnabled, - boolean createImmediately, String[] args) { + boolean createImmediately, int windowless_frame_rate, String[] args) { this.osr_enabled_ = osrEnabled; this.transparent_painting_enabled_ = transparentPaintingEnabled; @@ -200,9 +215,12 @@ public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, } }); + CefBrowserSettings browserSettings = new CefBrowserSettings(); + browserSettings.windowless_frame_rate = windowless_frame_rate; + // Create the browser. - CefBrowser browser = client_.createBrowser( - "http://www.google.com", osrEnabled, transparentPaintingEnabled, null); + CefBrowser browser = client_.createBrowser("http://www.google.com", osrEnabled, + transparentPaintingEnabled, null, browserSettings); setBrowser(browser); // Set up the UI for this example implementation. diff --git a/java/tests/detailed/ui/MenuBar.java b/java/tests/detailed/ui/MenuBar.java index 850e2104..0ed8bf1a 100644 --- a/java/tests/detailed/ui/MenuBar.java +++ b/java/tests/detailed/ui/MenuBar.java @@ -470,7 +470,7 @@ public void run() { newwindow.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - final MainFrame frame = new MainFrame(OS.isLinux(), false, false, null); + final MainFrame frame = new MainFrame(OS.isLinux(), false, false, 0, null); frame.setSize(800, 600); frame.setVisible(true); } diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index e3635be2..257bd60a 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -87,8 +87,6 @@ set(JCEF_SRCS critical_wait.h devtools_message_observer.cpp devtools_message_observer.h - devtools_method_callback.cpp - devtools_method_callback.h dialog_handler.cpp dialog_handler.h display_handler.cpp @@ -99,6 +97,8 @@ set(JCEF_SRCS drag_handler.h focus_handler.cpp focus_handler.h + int_callback.cpp + int_callback.h jcef_version.h jni_scoped_helpers.h jni_scoped_helpers.cpp diff --git a/native/CefBrowser_N.cpp b/native/CefBrowser_N.cpp index c754c89a..92c43636 100644 --- a/native/CefBrowser_N.cpp +++ b/native/CefBrowser_N.cpp @@ -14,7 +14,7 @@ #include "client_handler.h" #include "critical_wait.h" #include "devtools_message_observer.h" -#include "devtools_method_callback.h" +#include "int_callback.h" #include "jni_util.h" #include "life_span_handler.h" #include "pdf_print_callback.h" @@ -902,6 +902,7 @@ struct JNIObjectsForCreate { ScopedJNIObjectGlobal canvas; ScopedJNIObjectGlobal jcontext; ScopedJNIObjectGlobal jinspectAt; + ScopedJNIObjectGlobal jbrowserSettings; JNIObjectsForCreate(JNIEnv* env, jobject _jbrowser, @@ -910,7 +911,8 @@ struct JNIObjectsForCreate { jstring _url, jobject _canvas, jobject _jcontext, - jobject _jinspectAt) + jobject _jinspectAt, + jobject _browserSettings) : jbrowser(env, _jbrowser), @@ -919,7 +921,8 @@ struct JNIObjectsForCreate { url(env, _url), canvas(env, _canvas), jcontext(env, _jcontext), - jinspectAt(env, _jinspectAt) {} + jinspectAt(env, _jinspectAt), + jbrowserSettings(env, _browserSettings) {} }; void create(std::shared_ptr objs, @@ -982,6 +985,13 @@ void create(std::shared_ptr objs, settings.background_color = CefColorSetARGB(255, 255, 255, 255); } + ScopedJNIClass cefBrowserSettings(env, "org/cef/CefBrowserSettings"); + if (cefBrowserSettings != nullptr && + objs->jbrowserSettings != nullptr) { // Dev-tools settings are null + GetJNIFieldInt(env, cefBrowserSettings, objs->jbrowserSettings, + "windowless_frame_rate", &settings.windowless_frame_rate); + } + CefRefPtr browserObj; CefString strUrl = GetJNIString(env, static_cast(objs->url.get())); @@ -1041,7 +1051,7 @@ void getZoomLevel(CefRefPtr host, void executeDevToolsMethod(CefRefPtr host, const CefString& method, const CefString& parametersAsJson, - CefRefPtr callback) { + CefRefPtr callback) { CefRefPtr parameters = nullptr; if (!parametersAsJson.empty()) { CefRefPtr value = CefParseJSON( @@ -1167,7 +1177,7 @@ class ScopedJNIRegistration : public ScopedJNIObject { ScopedJNIRegistration(JNIEnv* env, CefRefPtr obj) : ScopedJNIObject(env, obj, - "org/cef/misc/CefRegistration_N", + "org/cef/browser/CefRegistration_N", "CefRegistration") {} }; @@ -1182,9 +1192,11 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv* env, jboolean osr, jboolean transparent, jobject canvas, - jobject jcontext) { - std::shared_ptr objs(new JNIObjectsForCreate( - env, jbrowser, nullptr, jclientHandler, url, canvas, jcontext, nullptr)); + jobject jcontext, + jobject browserSettings) { + std::shared_ptr objs( + new JNIObjectsForCreate(env, jbrowser, nullptr, jclientHandler, url, + canvas, jcontext, nullptr, browserSettings)); if (CefCurrentlyOn(TID_UI)) { create(objs, windowHandle, osr, transparent); } else { @@ -1206,7 +1218,7 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv* env, jobject inspect) { std::shared_ptr objs( new JNIObjectsForCreate(env, jbrowser, jparent, jclientHandler, nullptr, - canvas, nullptr, inspect)); + canvas, nullptr, inspect, nullptr)); if (CefCurrentlyOn(TID_UI)) { create(objs, windowHandle, osr, transparent); } else { @@ -1223,8 +1235,7 @@ Java_org_cef_browser_CefBrowser_1N_N_1ExecuteDevToolsMethod( jstring method, jstring parametersAsJson, jobject jcallback) { - CefRefPtr callback = - new DevToolsMethodCallback(env, jcallback); + CefRefPtr callback = new IntCallback(env, jcallback); CefRefPtr browser = GetJNIBrowser(env, jbrowser); if (!browser.get()) { @@ -2151,3 +2162,38 @@ Java_org_cef_browser_CefBrowser_1N_N_1NotifyMoveOrResizeStarted(JNIEnv* env, } #endif } + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SetWindowlessFrameRate(JNIEnv* env, + jobject jbrowser, + jint frameRate) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, jbrowser); + CefRefPtr host = browser->GetHost(); + host->SetWindowlessFrameRate(frameRate); +} + +void getWindowlessFrameRate(CefRefPtr host, + CefRefPtr callback) { + callback->onComplete((jint)host->GetWindowlessFrameRate()); +} + +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetWindowlessFrameRate( + JNIEnv* env, + jobject jbrowser, + jobject jintCallback) { + CefRefPtr callback = new IntCallback(env, jintCallback); + + CefRefPtr browser = GetJNIBrowser(env, jbrowser); + if (!browser.get()) { + callback->onComplete(0); + return; + } + + CefRefPtr host = browser->GetHost(); + if (CefCurrentlyOn(TID_UI)) { + getWindowlessFrameRate(host, callback); + } else { + CefPostTask(TID_UI, base::BindOnce(getWindowlessFrameRate, host, callback)); + } +} diff --git a/native/CefBrowser_N.h b/native/CefBrowser_N.h index 85176735..ae103a9b 100644 --- a/native/CefBrowser_N.h +++ b/native/CefBrowser_N.h @@ -11,7 +11,7 @@ extern "C" { * Class: org_cef_browser_CefBrowser_N * Method: N_CreateBrowser * Signature: - * (Lorg/cef/handler/CefClientHandler;JLjava/lang/String;ZZLjava/awt/Component;Lorg/cef/browser/CefRequestContext;)Z + * (Lorg/cef/handler/CefClientHandler;JLjava/lang/String;ZZLjava/awt/Component;Lorg/cef/browser/CefRequestContext;Lorg/cef/CefBrowserSettings;)Z */ JNIEXPORT jboolean JNICALL Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv*, @@ -22,6 +22,7 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv*, jboolean, jboolean, jobject, + jobject, jobject); /* @@ -45,7 +46,7 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv*, * Class: org_cef_browser_CefBrowser_N * Method: N_ExecuteDevToolsMethod * Signature: - * (Ljava/lang/String;Ljava/lang/String;Lorg/cef/browser/CefBrowser_N/DevToolsMethodCallback;)V + * (Ljava/lang/String;Ljava/lang/String;Lorg/cef/browser/CefBrowser_N/IntCallback;)V */ JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1ExecuteDevToolsMethod(JNIEnv*, @@ -544,6 +545,26 @@ JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1NotifyMoveOrResizeStarted(JNIEnv*, jobject); +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_SetWindowlessFrameRate + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SetWindowlessFrameRate(JNIEnv*, + jobject, + jint); + +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_GetWindowlessFrameRate + * Signature: (Lorg/cef/browser/CefBrowser_N/IntCallback;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1GetWindowlessFrameRate(JNIEnv*, + jobject, + jobject); + #ifdef __cplusplus } #endif diff --git a/native/devtools_method_callback.h b/native/devtools_method_callback.h deleted file mode 100644 index 1c219f90..00000000 --- a/native/devtools_method_callback.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -#ifndef JCEF_NATIVE_DEVTOOLS_METHOD_CALLBACK_H_ -#define JCEF_NATIVE_DEVTOOLS_METHOD_CALLBACK_H_ -#pragma once - -#include - -#include "jni_scoped_helpers.h" - -// Callback for CefBrowserHost::ExecuteDevToolsMethod. The methods of -// this class will be called on the browser process UI thread. -class DevToolsMethodCallback : public virtual CefBaseRefCounted { - public: - DevToolsMethodCallback(JNIEnv* env, jobject jcallback); - - // Method that will be called when the DevTools method has been executed. - // |generatedMessageId| is the generated message ID, or 0 if an error - // occurred. - virtual void onComplete(int generatedMessageId); - - protected: - ScopedJNIObjectGlobal handle_; - - // Include the default reference counting implementation. - IMPLEMENT_REFCOUNTING(DevToolsMethodCallback); -}; - -#endif // JCEF_NATIVE_DEVTOOLS_METHOD_CALLBACK_H_ diff --git a/native/devtools_method_callback.cpp b/native/int_callback.cpp similarity index 54% rename from native/devtools_method_callback.cpp rename to native/int_callback.cpp index b8057d52..a45471a4 100644 --- a/native/devtools_method_callback.cpp +++ b/native/int_callback.cpp @@ -2,20 +2,19 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. -#include "devtools_method_callback.h" +#include "int_callback.h" #include "jni_scoped_helpers.h" #include "jni_util.h" #include "util.h" -DevToolsMethodCallback::DevToolsMethodCallback(JNIEnv* env, jobject jcallback) +IntCallback::IntCallback(JNIEnv* env, jobject jcallback) : handle_(env, jcallback) {} -void DevToolsMethodCallback::onComplete(int generatedMessageId) { +void IntCallback::onComplete(int value) { ScopedJNIEnv env; if (!env) return; - JNI_CALL_VOID_METHOD(env, handle_, "onComplete", "(I)V", - (jint)generatedMessageId); + JNI_CALL_VOID_METHOD(env, handle_, "onComplete", "(I)V", (jint)value); } diff --git a/native/int_callback.h b/native/int_callback.h new file mode 100644 index 00000000..6437479c --- /dev/null +++ b/native/int_callback.h @@ -0,0 +1,28 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef JCEF_NATIVE_INT_CALLBACK_H_ +#define JCEF_NATIVE_INT_CALLBACK_H_ +#pragma once + +#include + +#include "jni_scoped_helpers.h" + +// Callback for returning int primatives. The methods of +// this class will be called on the browser process UI thread. +class IntCallback : public virtual CefBaseRefCounted { + public: + IntCallback(JNIEnv* env, jobject jcallback); + + virtual void onComplete(int value); + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(IntCallback); +}; + +#endif // JCEF_NATIVE_INT_CALLBACK_H_ From b5612ba49821008c7e7b1d3bc069f30eb545d39c Mon Sep 17 00:00:00 2001 From: Sander van den Berg Date: Mon, 15 Jan 2024 18:30:13 +0000 Subject: [PATCH 08/12] Fix UnsatisfiedLinkError with CefRegistration_N --- native/CefBrowser_N.h | 6 +++--- native/CefRegistration_N.cpp | 6 +++--- native/CefRegistration_N.h | 13 ++++++------- tools/make_all_jni_headers.bat | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/native/CefBrowser_N.h b/native/CefBrowser_N.h index ae103a9b..f01e1f5a 100644 --- a/native/CefBrowser_N.h +++ b/native/CefBrowser_N.h @@ -569,10 +569,10 @@ Java_org_cef_browser_CefBrowser_1N_N_1GetWindowlessFrameRate(JNIEnv*, } #endif #endif -/* Header for class org_cef_browser_CefBrowser_N_DevToolsMethodCallback */ +/* Header for class org_cef_browser_CefBrowser_N_IntCallback */ -#ifndef _Included_org_cef_browser_CefBrowser_N_DevToolsMethodCallback -#define _Included_org_cef_browser_CefBrowser_N_DevToolsMethodCallback +#ifndef _Included_org_cef_browser_CefBrowser_N_IntCallback +#define _Included_org_cef_browser_CefBrowser_N_IntCallback #ifdef __cplusplus extern "C" { #endif diff --git a/native/CefRegistration_N.cpp b/native/CefRegistration_N.cpp index 295002d3..dc23751d 100644 --- a/native/CefRegistration_N.cpp +++ b/native/CefRegistration_N.cpp @@ -7,8 +7,8 @@ #include "jni_scoped_helpers.h" JNIEXPORT void JNICALL -Java_org_cef_misc_CefRegistration_1N_N_1Dispose(JNIEnv* env, - jobject obj, - jlong self) { +Java_org_cef_browser_CefRegistration_1N_N_1Dispose(JNIEnv* env, + jobject obj, + jlong self) { SetCefForJNIObject(env, obj, NULL, "CefRegistration"); } diff --git a/native/CefRegistration_N.h b/native/CefRegistration_N.h index 3c48c7bc..9747b04b 100644 --- a/native/CefRegistration_N.h +++ b/native/CefRegistration_N.h @@ -1,20 +1,19 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ #include -/* Header for class org_cef_misc_CefRegistration_N */ +/* Header for class org_cef_browser_CefRegistration_N */ -#ifndef _Included_org_cef_misc_CefRegistration_N -#define _Included_org_cef_misc_CefRegistration_N +#ifndef _Included_org_cef_browser_CefRegistration_N +#define _Included_org_cef_browser_CefRegistration_N #ifdef __cplusplus extern "C" { #endif /* - * Class: org_cef_misc_CefRegistration_N + * Class: org_cef_browser_CefRegistration_N * Method: N_Dispose * Signature: (J)V */ -JNIEXPORT void JNICALL Java_org_cef_misc_CefRegistration_1N_N_1Dispose(JNIEnv*, - jobject, - jlong); +JNIEXPORT void JNICALL +Java_org_cef_browser_CefRegistration_1N_N_1Dispose(JNIEnv*, jobject, jlong); #ifdef __cplusplus } diff --git a/tools/make_all_jni_headers.bat b/tools/make_all_jni_headers.bat index 9c463161..ecb1dee0 100644 --- a/tools/make_all_jni_headers.bat +++ b/tools/make_all_jni_headers.bat @@ -37,7 +37,7 @@ call make_jni_header.bat %1 org.cef.callback.CefQueryCallback_N call make_jni_header.bat %1 org.cef.callback.CefSchemeRegistrar_N call make_jni_header.bat %1 org.cef.handler.CefClientHandler call make_jni_header.bat %1 org.cef.misc.CefPrintSettings_N -call make_jni_header.bat %1 org.cef.misc.CefRegistration_N +call make_jni_header.bat %1 org.cef.browser.CefRegistration_N call make_jni_header.bat %1 org.cef.network.CefCookieManager_N call make_jni_header.bat %1 org.cef.network.CefPostData_N call make_jni_header.bat %1 org.cef.network.CefPostDataElement_N From 3df5f071df9a5f080cfa7d606f75189d3850706b Mon Sep 17 00:00:00 2001 From: Milos Ratkovic Date: Fri, 19 Jan 2024 20:42:12 +0000 Subject: [PATCH 09/12] Add CefDisplayHandler.onFullscreenModeChange callback (fixes #239) - Detailed test: Don't display error for frames other than main frame --- java/org/cef/CefClient.java | 6 ++ java/org/cef/handler/CefDisplayHandler.java | 7 ++ .../cef/handler/CefDisplayHandlerAdapter.java | 5 ++ java/tests/detailed/MainFrame.java | 68 ++++++++++++++++--- java/tests/simple/MainFrame.java | 42 +++++++++++- native/display_handler.cpp | 12 ++++ native/display_handler.h | 2 + 7 files changed, 128 insertions(+), 14 deletions(-) diff --git a/java/org/cef/CefClient.java b/java/org/cef/CefClient.java index 90122936..7fa5fdaf 100644 --- a/java/org/cef/CefClient.java +++ b/java/org/cef/CefClient.java @@ -311,6 +311,12 @@ public void onTitleChange(CefBrowser browser, String title) { displayHandler_.onTitleChange(browser, title); } + @Override + public void OnFullscreenModeChange(CefBrowser browser, boolean fullscreen) { + if (displayHandler_ != null && browser != null) + displayHandler_.OnFullscreenModeChange(browser, fullscreen); + } + @Override public boolean onTooltip(CefBrowser browser, String text) { if (displayHandler_ != null && browser != null) { diff --git a/java/org/cef/handler/CefDisplayHandler.java b/java/org/cef/handler/CefDisplayHandler.java index 0affefc5..5913794e 100644 --- a/java/org/cef/handler/CefDisplayHandler.java +++ b/java/org/cef/handler/CefDisplayHandler.java @@ -28,6 +28,13 @@ public interface CefDisplayHandler { */ public void onTitleChange(CefBrowser browser, String title); + /** + * Browser fullscreen mode changed. + * @param browser The browser generating the event. + * @param fullscreen True if fullscreen mode is on. + */ + public void OnFullscreenModeChange(CefBrowser browser, boolean fullscreen); + /** * About to display a tooltip. * @param browser The browser generating the event. diff --git a/java/org/cef/handler/CefDisplayHandlerAdapter.java b/java/org/cef/handler/CefDisplayHandlerAdapter.java index 80ab96b6..302ae6b0 100644 --- a/java/org/cef/handler/CefDisplayHandlerAdapter.java +++ b/java/org/cef/handler/CefDisplayHandlerAdapter.java @@ -24,6 +24,11 @@ public void onTitleChange(CefBrowser browser, String title) { return; } + @Override + public void OnFullscreenModeChange(CefBrowser browser, boolean fullscreen) { + return; + } + @Override public boolean onTooltip(CefBrowser browser, String text) { return false; diff --git a/java/tests/detailed/MainFrame.java b/java/tests/detailed/MainFrame.java index 85eb3cdb..afa9d823 100644 --- a/java/tests/detailed/MainFrame.java +++ b/java/tests/detailed/MainFrame.java @@ -22,6 +22,8 @@ import org.cef.network.CefCookieManager; import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.GraphicsConfiguration; import java.awt.KeyboardFocusManager; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; @@ -30,6 +32,7 @@ import javax.swing.JFrame; import javax.swing.JPanel; +import javax.swing.SwingUtilities; import tests.detailed.dialog.DownloadDialog; import tests.detailed.handler.AppHandler; @@ -101,6 +104,8 @@ public static void main(String[] args) { private boolean browserFocus_ = true; private boolean osr_enabled_; private boolean transparent_painting_enabled_; + private JPanel contentPanel_; + private JFrame fullscreenFrame_; public MainFrame(boolean osrEnabled, boolean transparentPaintingEnabled, boolean createImmediately, int windowless_frame_rate, String[] args) { @@ -178,6 +183,10 @@ public void onTitleChange(CefBrowser browser, String title) { public void onStatusMessage(CefBrowser browser, String value) { status_panel_.setStatusText(value); } + @Override + public void OnFullscreenModeChange(CefBrowser browser, boolean fullscreen) { + setBrowserFullscreen(fullscreen); + } }); // 2.2) To disable/enable navigation buttons and to display a prgress bar @@ -190,19 +199,25 @@ public void onStatusMessage(CefBrowser browser, String value) { @Override public void onLoadingStateChange(CefBrowser browser, boolean isLoading, boolean canGoBack, boolean canGoForward) { - control_pane_.update(browser, isLoading, canGoBack, canGoForward); - status_panel_.setIsInProgress(isLoading); - - if (!isLoading && !errorMsg_.isEmpty()) { - browser.loadURL(DataUri.create("text/html", errorMsg_)); - errorMsg_ = ""; - } + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + control_pane_.update(browser, isLoading, canGoBack, canGoForward); + status_panel_.setIsInProgress(isLoading); + + if (!isLoading && !errorMsg_.isEmpty()) { + browser.loadURL(DataUri.create("text/html", errorMsg_)); + errorMsg_ = ""; + } + } + }); } @Override public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, String errorText, String failedUrl) { - if (errorCode != ErrorCode.ERR_NONE && errorCode != ErrorCode.ERR_ABORTED) { + if (errorCode != ErrorCode.ERR_NONE && errorCode != ErrorCode.ERR_ABORTED + && frame == browser.getMainFrame()) { errorMsg_ = ""; errorMsg_ += "Error while loading"; errorMsg_ += ""; @@ -224,8 +239,8 @@ public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, setBrowser(browser); // Set up the UI for this example implementation. - JPanel contentPanel = createContentPanel(); - getContentPane().add(contentPanel, BorderLayout.CENTER); + contentPanel_ = createContentPanel(); + getContentPane().add(contentPanel_, BorderLayout.CENTER); // Clear focus from the browser when the address field gains focus. control_pane_.getAddressField().addFocusListener(new FocusAdapter() { @@ -257,7 +272,7 @@ public void onTakeFocus(CefBrowser browser, boolean next) { if (createImmediately) browser.createImmediately(); // Add the browser to the UI. - contentPanel.add(getBrowser().getUIComponent(), BorderLayout.CENTER); + contentPanel_.add(getBrowser().getUIComponent(), BorderLayout.CENTER); MenuBar menuBar = new MenuBar( this, browser, control_pane_, downloadDialog, CefCookieManager.getGlobalManager()); @@ -277,6 +292,8 @@ public void onTakeFocus(CefBrowser browser, boolean next) { menuBar.addBookmark("Spellcheck Test", "client://tests/spellcheck.html"); menuBar.addBookmark("LocalStorage Test", "client://tests/localstorage.html"); menuBar.addBookmark("Transparency Test", "client://tests/transparency.html"); + menuBar.addBookmark("Fullscreen Test", + "https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_fullscreen2"); menuBar.addBookmarkSeparator(); menuBar.addBookmark( "javachromiumembedded", "https://bitbucket.org/chromiumembedded/java-cef"); @@ -300,4 +317,33 @@ public boolean isOsrEnabled() { public boolean isTransparentPaintingEnabled() { return transparent_painting_enabled_; } + + public void setBrowserFullscreen(boolean fullscreen) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + Component browserUI = getBrowser().getUIComponent(); + if (fullscreen) { + if (fullscreenFrame_ == null) { + fullscreenFrame_ = new JFrame(); + fullscreenFrame_.setUndecorated(true); + fullscreenFrame_.setResizable(true); + } + GraphicsConfiguration gc = MainFrame.this.getGraphicsConfiguration(); + fullscreenFrame_.setBounds(gc.getBounds()); + gc.getDevice().setFullScreenWindow(fullscreenFrame_); + + contentPanel_.remove(browserUI); + fullscreenFrame_.add(browserUI); + fullscreenFrame_.setVisible(true); + fullscreenFrame_.validate(); + } else { + fullscreenFrame_.remove(browserUI); + fullscreenFrame_.setVisible(false); + contentPanel_.add(browserUI, BorderLayout.CENTER); + contentPanel_.validate(); + } + } + }); + } } diff --git a/java/tests/simple/MainFrame.java b/java/tests/simple/MainFrame.java index 7b2b21ab..109ccb2a 100644 --- a/java/tests/simple/MainFrame.java +++ b/java/tests/simple/MainFrame.java @@ -17,6 +17,7 @@ import java.awt.BorderLayout; import java.awt.Component; +import java.awt.GraphicsConfiguration; import java.awt.KeyboardFocusManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -26,7 +27,9 @@ import java.awt.event.WindowEvent; import javax.swing.JFrame; +import javax.swing.JPanel; import javax.swing.JTextField; +import javax.swing.SwingUtilities; /** * This is a simple example application using JCEF. @@ -46,8 +49,9 @@ public class MainFrame extends JFrame { private final CefApp cefApp_; private final CefClient client_; private final CefBrowser browser_; - private final Component browerUI_; + private final Component browserUI_; private boolean browserFocus_ = true; + private JFrame fullscreenFrame_; /** * To display a simple browser window, it suffices completely to create an @@ -105,7 +109,7 @@ public void stateHasChanged(org.cef.CefApp.CefAppState state) { // The UI component is inherited from a java.awt.Component and therefore // it can be embedded into any AWT UI. browser_ = client_.createBrowser(startURL, useOSR, isTransparent); - browerUI_ = browser_.getUIComponent(); + browserUI_ = browser_.getUIComponent(); // (4) For this minimal browser, we need only a text field to enter an URL // we want to navigate to and a CefBrowser window to display the content @@ -128,6 +132,10 @@ public void actionPerformed(ActionEvent e) { public void onAddressChange(CefBrowser browser, CefFrame frame, String url) { address_.setText(url); } + @Override + public void OnFullscreenModeChange(CefBrowser browser, boolean fullscreen) { + setBrowserFullscreen(fullscreen); + } }); // Clear focus from the browser when the address field gains focus. @@ -160,7 +168,7 @@ public void onTakeFocus(CefBrowser browser, boolean next) { // (5) All UI components are assigned to the default content pane of this // JFrame and afterwards the frame is made visible to the user. getContentPane().add(address_, BorderLayout.NORTH); - getContentPane().add(browerUI_, BorderLayout.CENTER); + getContentPane().add(browserUI_, BorderLayout.CENTER); pack(); setSize(800, 600); setVisible(true); @@ -177,6 +185,34 @@ public void windowClosing(WindowEvent e) { }); } + public void setBrowserFullscreen(boolean fullscreen) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (fullscreen) { + if (fullscreenFrame_ == null) { + fullscreenFrame_ = new JFrame(); + fullscreenFrame_.setUndecorated(true); + fullscreenFrame_.setResizable(true); + } + GraphicsConfiguration gc = MainFrame.this.getGraphicsConfiguration(); + fullscreenFrame_.setBounds(gc.getBounds()); + gc.getDevice().setFullScreenWindow(fullscreenFrame_); + + getContentPane().remove(browserUI_); + fullscreenFrame_.add(browserUI_); + fullscreenFrame_.setVisible(true); + fullscreenFrame_.validate(); + } else { + fullscreenFrame_.remove(browserUI_); + fullscreenFrame_.setVisible(false); + getContentPane().add(browserUI_, BorderLayout.CENTER); + getContentPane().validate(); + } + } + }); + } + public static void main(String[] args) { // Perform startup initialization on platforms that require it. if (!CefApp.startup(args)) { diff --git a/native/display_handler.cpp b/native/display_handler.cpp index cf088682..33f9e17e 100644 --- a/native/display_handler.cpp +++ b/native/display_handler.cpp @@ -112,6 +112,18 @@ void DisplayHandler::OnTitleChange(CefRefPtr browser, jbrowser.get(), jtitle.get()); } +void DisplayHandler::OnFullscreenModeChange(CefRefPtr browser, + bool fullscreen) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + JNI_CALL_VOID_METHOD(env, handle_, "OnFullscreenModeChange", + "(Lorg/cef/browser/CefBrowser;Z)V", jbrowser.get(), + (jboolean)fullscreen); +} + bool DisplayHandler::OnTooltip(CefRefPtr browser, CefString& text) { ScopedJNIEnv env; if (!env) diff --git a/native/display_handler.h b/native/display_handler.h index 3b015b62..30615fdb 100644 --- a/native/display_handler.h +++ b/native/display_handler.h @@ -23,6 +23,8 @@ class DisplayHandler : public CefDisplayHandler { const CefString& url) override; void OnTitleChange(CefRefPtr browser, const CefString& title) override; + void OnFullscreenModeChange(CefRefPtr browser, + bool fullscreen) override; bool OnTooltip(CefRefPtr browser, CefString& text) override; void OnStatusMessage(CefRefPtr browser, const CefString& value) override; From e75a3c050cc6891fabce9a3918a6c06558a0c045 Mon Sep 17 00:00:00 2001 From: Rene Schneider Date: Mon, 4 Mar 2024 18:43:25 +0000 Subject: [PATCH 10/12] Update to CEF 121.3.9+g1e0a38f+chromium-121.0.6167.184 Added root_cache_path setting and onAlreadyRunningAppRelaunch event to deal with new CEF restrictions regarding parallel use of root_cache_path dir starting with CEF 120. --- CMakeLists.txt | 2 +- java/org/cef/CefApp.java | 12 ++++++- java/org/cef/CefSettings.java | 32 ++++++++++++++++++- java/org/cef/handler/CefAppHandler.java | 19 +++++++++++ .../org/cef/handler/CefAppHandlerAdapter.java | 7 ++++ native/browser_process_handler.cpp | 25 +++++++++++++++ native/browser_process_handler.h | 2 ++ native/context.cpp | 5 +++ 8 files changed, 101 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54d592b3..4d198bdf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,7 +130,7 @@ set_property(GLOBAL PROPERTY OS_FOLDERS ON) # Specify the CEF distribution version. if(NOT DEFINED CEF_VERSION) - set(CEF_VERSION "119.4.7+g55e15c8+chromium-119.0.6045.199") + set(CEF_VERSION "121.3.9+g1e0a38f+chromium-121.0.6167.184") endif() # Determine the platform. diff --git a/java/org/cef/CefApp.java b/java/org/cef/CefApp.java index afd10f04..e623b834 100644 --- a/java/org/cef/CefApp.java +++ b/java/org/cef/CefApp.java @@ -102,6 +102,12 @@ public enum CefAppState { */ INITIALIZED, + /** + * CEF initialization has failed (for example due to a second process using + * the same root_cache_path). + */ + INITIALIZATION_FAILED, + /** * CefApp is in its shutdown process. All CefClients and CefBrowser * instances will be disposed. No new CefClient or CefBrowser is allowed to @@ -424,7 +430,11 @@ public void run() { } } - if (N_Initialize(appHandler_, settings)) setState(CefAppState.INITIALIZED); + if (N_Initialize(appHandler_, settings)) { + setState(CefAppState.INITIALIZED); + } else { + setState(CefAppState.INITIALIZATION_FAILED); + } } }; if (SwingUtilities.isEventDispatchThread()) diff --git a/java/org/cef/CefSettings.java b/java/org/cef/CefSettings.java index 5d756d99..577a96ea 100644 --- a/java/org/cef/CefSettings.java +++ b/java/org/cef/CefSettings.java @@ -102,10 +102,39 @@ public ColorType clone() { * The location where cache data will be stored on disk. If empty an in-memory * cache will be used for some features and a temporary disk cache for others. * HTML5 databases such as localStorage will only persist across sessions if a - * cache path is specified. + * cache path is specified. If this is set and root_cache_path is also set, the cache_path + * directory must reside within root_cache_path. */ public String cache_path = null; + /** + * The root directory for installation-specific data and the parent directory + * for profile-specific data. All CefSettings.cache_path and + * CefRequestContextSettings.cache_path values must have this parent + * directory in common. If this value is empty and CefSettings.cache_path is + * non-empty then it will default to the CefSettings.cache_path value. Any + * non-empty value must be an absolute path. If both values are empty then + * the default platform-specific directory will be used + * ("~/.config/cef_user_data" directory on Linux, "~/Library/Application + * Support/CEF/User Data" directory on MacOS, "AppData\Local\CEF\User Data" + * directory under the user profile directory on Windows). Use of the default + * directory is not recommended in production applications (see below). + * + * Multiple application instances writing to the same root_cache_path + * directory could result in data corruption. A process singleton lock based + * on the root_cache_path value is therefore used to protect against this. + * This singleton behavior applies to all CEF-based applications using + * version 120 or newer. You should customize root_cache_path for your + * application and implement CefAppHandler:: + * onAlreadyRunningAppRelaunch, which will then be called on any app relaunch + * with the same root_cache_path value. + * + * Failure to set the root_cache_path value correctly may result in startup + * crashes or other unexpected behaviors (for example, the sandbox blocking + * read/write access to certain files). + */ + public String root_cache_path = null; + /** * To persist session cookies (cookies without an expiry date or validity * interval) by default when using the global cookie manager set this value to @@ -239,6 +268,7 @@ public CefSettings clone() { tmp.windowless_rendering_enabled = windowless_rendering_enabled; tmp.command_line_args_disabled = command_line_args_disabled; tmp.cache_path = cache_path; + tmp.root_cache_path = root_cache_path; tmp.persist_session_cookies = persist_session_cookies; tmp.user_agent = user_agent; tmp.user_agent_product = user_agent_product; diff --git a/java/org/cef/handler/CefAppHandler.java b/java/org/cef/handler/CefAppHandler.java index 095e4747..b6ede710 100644 --- a/java/org/cef/handler/CefAppHandler.java +++ b/java/org/cef/handler/CefAppHandler.java @@ -72,4 +72,23 @@ public interface CefAppHandler { * currently pending scheduled call should be cancelled. */ public void onScheduleMessagePumpWork(long delay_ms); + + /** + * Implement this method to provide app-specific behavior when an already + * running app is relaunched with the same CefSettings.root_cache_path value. + * For example, activate an existing app window or create a new app window. + * |command_line| will be read-only. Do not keep a reference to + * |command_line| outside of this method. Return true if the relaunch is + * handled or false for default relaunch behavior. Default behavior will + * create a new default styled Chrome window. + * + * To avoid cache corruption only a single app instance is allowed to run for + * a given CefSettings.root_cache_path value. On relaunch the app checks a + * process singleton lock and then forwards the new launch arguments to the + * already running app process before exiting early. Client apps should + * therefore check the CefInitialize() return value for early exit before + * proceeding. + */ + public boolean onAlreadyRunningAppRelaunch( + CefCommandLine command_line, String current_directory); } diff --git a/java/org/cef/handler/CefAppHandlerAdapter.java b/java/org/cef/handler/CefAppHandlerAdapter.java index 47f7ae53..1d0bc15b 100644 --- a/java/org/cef/handler/CefAppHandlerAdapter.java +++ b/java/org/cef/handler/CefAppHandlerAdapter.java @@ -89,4 +89,11 @@ public void onContextInitialized() { public void onScheduleMessagePumpWork(long delay_ms) { CefApp.getInstance().doMessageLoopWork(delay_ms); } + + @Override + public boolean onAlreadyRunningAppRelaunch( + CefCommandLine command_line, String current_directory) { + // The default implementation does nothing + return false; + } } diff --git a/native/browser_process_handler.cpp b/native/browser_process_handler.cpp index 38c8fdca..ad583e87 100644 --- a/native/browser_process_handler.cpp +++ b/native/browser_process_handler.cpp @@ -50,6 +50,31 @@ void BrowserProcessHandler::OnScheduleMessagePumpWork(int64_t delay_ms) { delay_ms); } +bool BrowserProcessHandler::OnAlreadyRunningAppRelaunch( + CefRefPtr command_line, + const CefString& current_directory) { + if (!handle_) + return false; + + ScopedJNIEnv env; + if (!env) + return false; + + ScopedJNIObject jcommandLine( + env, command_line, "org/cef/callback/CefCommandLine_N", "CefCommandLine"); + jcommandLine.SetTemporary(); + ScopedJNIString jcurrentDirectory(env, current_directory); + + jboolean jresult = 0; + + JNI_CALL_BOOLEAN_METHOD( + jresult, env, handle_, "onAlreadyRunningAppRelaunch", + "(Lorg/cef/callback/CefCommandLine;Ljava/lang/String;)Z", + jcommandLine.get(), jcurrentDirectory.get()); + + return jresult; +} + // static CefRefPtr BrowserProcessHandler::GetMessageRouterConfigs() { int idx = 0; diff --git a/native/browser_process_handler.h b/native/browser_process_handler.h index 260ebd66..8bbf29e3 100644 --- a/native/browser_process_handler.h +++ b/native/browser_process_handler.h @@ -34,6 +34,8 @@ class BrowserProcessHandler : public CefBrowserProcessHandler { void OnContextInitialized() override; void OnScheduleMessagePumpWork(int64_t delay_ms) override; + bool OnAlreadyRunningAppRelaunch(CefRefPtr command_line, + const CefString& current_directory) override; static CefRefPtr GetMessageRouterConfigs(); static void AddMessageRouterConfig(const CefMessageRouterConfig& cfg); diff --git a/native/context.cpp b/native/context.cpp index 7f894ad9..a9fd67ae 100644 --- a/native/context.cpp +++ b/native/context.cpp @@ -44,6 +44,11 @@ CefSettings GetJNISettings(JNIEnv* env, jobject obj) { CefString(&settings.cache_path) = tmp; tmp.clear(); } + if (GetJNIFieldString(env, cls, obj, "root_cache_path", &tmp) && + !tmp.empty()) { + CefString(&settings.root_cache_path) = tmp; + tmp.clear(); + } GetJNIFieldBoolean(env, cls, obj, "persist_session_cookies", &settings.persist_session_cookies); if (GetJNIFieldString(env, cls, obj, "user_agent", &tmp) && !tmp.empty()) { From 0b8e42e52acf707e84b4a0e92124b1d012ffdda0 Mon Sep 17 00:00:00 2001 From: Rene Schneider Date: Thu, 7 Mar 2024 17:26:56 +0000 Subject: [PATCH 11/12] Update to CEF 122.1.10+gc902316+chromium-122.0.6261.112 Frame identifiers change from long to String. --- CMakeLists.txt | 2 +- java/org/cef/browser/CefBrowser.java | 6 ++--- java/org/cef/browser/CefBrowser_N.java | 16 ++++++------ java/org/cef/browser/CefFrame.java | 4 +-- java/org/cef/browser/CefFrame_N.java | 6 ++--- native/CefBrowser_N.cpp | 36 ++++++++------------------ native/CefBrowser_N.h | 12 +++++---- native/CefFrame_N.cpp | 6 ++--- native/CefFrame_N.h | 4 +-- 9 files changed, 40 insertions(+), 52 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d198bdf..8efab352 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,7 +130,7 @@ set_property(GLOBAL PROPERTY OS_FOLDERS ON) # Specify the CEF distribution version. if(NOT DEFINED CEF_VERSION) - set(CEF_VERSION "121.3.9+g1e0a38f+chromium-121.0.6167.184") + set(CEF_VERSION "122.1.10+gc902316+chromium-122.0.6261.112") endif() # Determine the platform. diff --git a/java/org/cef/browser/CefBrowser.java b/java/org/cef/browser/CefBrowser.java index f6c72ee5..437a0192 100644 --- a/java/org/cef/browser/CefBrowser.java +++ b/java/org/cef/browser/CefBrowser.java @@ -125,20 +125,20 @@ public interface CefBrowser { * @param identifier The unique frame identifier * @return The frame or NULL if not found */ - public CefFrame getFrame(long identifier); + public CefFrame getFrameByIdentifier(String identifier); /** * Returns the frame with the specified name, or NULL if not found. * @param name The specified name * @return The frame or NULL if not found */ - public CefFrame getFrame(String name); + public CefFrame getFrameByName(String name); /** * Returns the identifiers of all existing frames. * @return All identifiers of existing frames. */ - public Vector getFrameIdentifiers(); + public Vector getFrameIdentifiers(); /** * Returns the names of all existing frames. diff --git a/java/org/cef/browser/CefBrowser_N.java b/java/org/cef/browser/CefBrowser_N.java index d7c62e0f..94530dab 100644 --- a/java/org/cef/browser/CefBrowser_N.java +++ b/java/org/cef/browser/CefBrowser_N.java @@ -351,9 +351,9 @@ public CefFrame getFocusedFrame() { } @Override - public CefFrame getFrame(long identifier) { + public CefFrame getFrameByIdentifier(String identifier) { try { - return N_GetFrame(identifier); + return N_GetFrameByIdentifier(identifier); } catch (UnsatisfiedLinkError ule) { ule.printStackTrace(); return null; @@ -361,9 +361,9 @@ public CefFrame getFrame(long identifier) { } @Override - public CefFrame getFrame(String name) { + public CefFrame getFrameByName(String name) { try { - return N_GetFrame2(name); + return N_GetFrameByName(name); } catch (UnsatisfiedLinkError ule) { ule.printStackTrace(); return null; @@ -371,7 +371,7 @@ public CefFrame getFrame(String name) { } @Override - public Vector getFrameIdentifiers() { + public Vector getFrameIdentifiers() { try { return N_GetFrameIdentifiers(); } catch (UnsatisfiedLinkError ule) { @@ -839,9 +839,9 @@ private final native CefRegistration N_AddDevToolsMessageObserver( private final native int N_GetIdentifier(); private final native CefFrame N_GetMainFrame(); private final native CefFrame N_GetFocusedFrame(); - private final native CefFrame N_GetFrame(long identifier); - private final native CefFrame N_GetFrame2(String name); - private final native Vector N_GetFrameIdentifiers(); + private final native CefFrame N_GetFrameByIdentifier(String identifier); + private final native CefFrame N_GetFrameByName(String name); + private final native Vector N_GetFrameIdentifiers(); private final native Vector N_GetFrameNames(); private final native int N_GetFrameCount(); private final native boolean N_IsPopup(); diff --git a/java/org/cef/browser/CefFrame.java b/java/org/cef/browser/CefFrame.java index 280f1e35..a64b4ed9 100644 --- a/java/org/cef/browser/CefFrame.java +++ b/java/org/cef/browser/CefFrame.java @@ -14,11 +14,11 @@ public interface CefFrame { void dispose(); /** - * Returns the globally unique identifier for this frame or < 0 if the + * Returns the globally unique identifier for this frame or an empty string if the * underlying frame does not yet exist. * @return The frame identifier */ - long getIdentifier(); + String getIdentifier(); /** * Emits the URL currently loaded in this frame. diff --git a/java/org/cef/browser/CefFrame_N.java b/java/org/cef/browser/CefFrame_N.java index c68e1fbf..0bd1c6af 100644 --- a/java/org/cef/browser/CefFrame_N.java +++ b/java/org/cef/browser/CefFrame_N.java @@ -30,12 +30,12 @@ public void dispose() { } @Override - public long getIdentifier() { + public String getIdentifier() { try { return N_GetIdentifier(getNativeRef(null)); } catch (UnsatisfiedLinkError ule) { ule.printStackTrace(); - return -1; + return null; } } @@ -157,7 +157,7 @@ public void selectAll() { } private final native void N_Dispose(long self); - private final native long N_GetIdentifier(long self); + private final native String N_GetIdentifier(long self); private final native String N_GetURL(long self); private final native String N_GetName(long self); private final native boolean N_IsMain(long self); diff --git a/native/CefBrowser_N.cpp b/native/CefBrowser_N.cpp index 92c43636..e00f5b88 100644 --- a/native/CefBrowser_N.cpp +++ b/native/CefBrowser_N.cpp @@ -1086,21 +1086,6 @@ void OnAfterParentChanged(CefRefPtr browser) { } } -jobject NewJNILongVector(JNIEnv* env, const std::vector& vals) { - ScopedJNIObjectLocal jvector(env, "java/util/Vector"); - if (!jvector) - return nullptr; - - std::vector::const_iterator iter; - for (iter = vals.begin(); iter != vals.end(); ++iter) { - ScopedJNIObjectLocal argument( - env, NewJNIObject(env, "java/lang/Long", "(J)V", (jlong)*iter)); - JNI_CALL_VOID_METHOD(env, jvector, "addElement", "(Ljava/lang/Object;)V", - argument.get()); - } - return jvector.Release(); -} - CefPdfPrintSettings GetJNIPdfPrintSettings(JNIEnv* env, jobject obj) { CefString tmp; CefPdfPrintSettings settings; @@ -1369,11 +1354,12 @@ Java_org_cef_browser_CefBrowser_1N_N_1GetFocusedFrame(JNIEnv* env, } JNIEXPORT jobject JNICALL -Java_org_cef_browser_CefBrowser_1N_N_1GetFrame(JNIEnv* env, - jobject obj, - jlong identifier) { +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByIdentifier(JNIEnv* env, + jobject obj, + jstring identifier) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr); - CefRefPtr frame = browser->GetFrame(identifier); + CefRefPtr frame = + browser->GetFrameByIdentifier(GetJNIString(env, identifier)); if (!frame) return nullptr; ScopedJNIFrame jframe(env, frame); @@ -1381,11 +1367,11 @@ Java_org_cef_browser_CefBrowser_1N_N_1GetFrame(JNIEnv* env, } JNIEXPORT jobject JNICALL -Java_org_cef_browser_CefBrowser_1N_N_1GetFrame2(JNIEnv* env, - jobject obj, - jstring name) { +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByName(JNIEnv* env, + jobject obj, + jstring name) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr); - CefRefPtr frame = browser->GetFrame(GetJNIString(env, name)); + CefRefPtr frame = browser->GetFrameByName(GetJNIString(env, name)); if (!frame) return nullptr; ScopedJNIFrame jframe(env, frame); @@ -1402,9 +1388,9 @@ JNIEXPORT jobject JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetFrameIdentifiers(JNIEnv* env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr); - std::vector identifiers; + std::vector identifiers; browser->GetFrameIdentifiers(identifiers); - return NewJNILongVector(env, identifiers); + return NewJNIStringVector(env, identifiers); } JNIEXPORT jobject JNICALL diff --git a/native/CefBrowser_N.h b/native/CefBrowser_N.h index f01e1f5a..b0348d5d 100644 --- a/native/CefBrowser_N.h +++ b/native/CefBrowser_N.h @@ -164,19 +164,21 @@ Java_org_cef_browser_CefBrowser_1N_N_1GetFocusedFrame(JNIEnv*, jobject); /* * Class: org_cef_browser_CefBrowser_N - * Method: N_GetFrame - * Signature: (J)Lorg/cef/browser/CefFrame; + * Method: N_GetFrameByIdentifier + * Signature: (Ljava/lang/String;)Lorg/cef/browser/CefFrame; */ JNIEXPORT jobject JNICALL -Java_org_cef_browser_CefBrowser_1N_N_1GetFrame(JNIEnv*, jobject, jlong); +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByIdentifier(JNIEnv*, + jobject, + jstring); /* * Class: org_cef_browser_CefBrowser_N - * Method: N_GetFrame2 + * Method: N_GetFrameByName * Signature: (Ljava/lang/String;)Lorg/cef/browser/CefFrame; */ JNIEXPORT jobject JNICALL -Java_org_cef_browser_CefBrowser_1N_N_1GetFrame2(JNIEnv*, jobject, jstring); +Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByName(JNIEnv*, jobject, jstring); /* * Class: org_cef_browser_CefBrowser_N diff --git a/native/CefFrame_N.cpp b/native/CefFrame_N.cpp index 46f039fb..cab338ed 100644 --- a/native/CefFrame_N.cpp +++ b/native/CefFrame_N.cpp @@ -27,14 +27,14 @@ JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Dispose(JNIEnv* env, ClearSelf(env, obj); } -JNIEXPORT jlong JNICALL +JNIEXPORT jstring JNICALL Java_org_cef_browser_CefFrame_1N_N_1GetIdentifier(JNIEnv* env, jobject obj, jlong self) { CefRefPtr frame = GetSelf(self); if (!frame) - return (jlong)-1; - return (jlong)frame->GetIdentifier(); + return nullptr; + return NewJNIString(env, frame->GetIdentifier()); } JNIEXPORT jstring JNICALL diff --git a/native/CefFrame_N.h b/native/CefFrame_N.h index c184d384..a1568181 100644 --- a/native/CefFrame_N.h +++ b/native/CefFrame_N.h @@ -19,9 +19,9 @@ JNIEXPORT void JNICALL Java_org_cef_browser_CefFrame_1N_N_1Dispose(JNIEnv*, /* * Class: org_cef_browser_CefFrame_N * Method: N_GetIdentifier - * Signature: (J)J + * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jlong JNICALL +JNIEXPORT jstring JNICALL Java_org_cef_browser_CefFrame_1N_N_1GetIdentifier(JNIEnv*, jobject, jlong); /* From 2d43af00da840e382ed8e302cc72e6b1b235013b Mon Sep 17 00:00:00 2001 From: 1zuna Date: Tue, 12 Mar 2024 07:16:42 +0100 Subject: [PATCH 12/12] feat: JCEF w/ CEF 122.1.10+gc902316+chromium-122.0.6261.112 - Fixed merge issues - Fixed macOS building - Removal of tests (not required for our use-case) - Fix JCEF CMAKE download --- .github/workflows/build-jcef.yml | 36 +- build.xml | 7 - cmake/DownloadCEF.cmake | 12 +- java/org/cef/CefClient.java | 32 +- java/org/cef/browser/CefBrowserFactory.java | 4 +- java/org/cef/browser/CefBrowserOsr.java | 12 +- java/org/cef/browser/CefBrowser_N.java | 45 +- java/tests/detailed/BrowserFrame.java | 136 ---- java/tests/detailed/MainFrame.java | 284 --------- .../detailed/dialog/CertErrorDialog.java | 40 -- .../detailed/dialog/CookieManagerDialog.java | 148 ----- .../tests/detailed/dialog/DevToolsDialog.java | 46 -- .../tests/detailed/dialog/DownloadDialog.java | 162 ----- .../tests/detailed/dialog/PasswordDialog.java | 65 -- java/tests/detailed/dialog/SearchDialog.java | 107 ---- .../tests/detailed/dialog/ShowTextDialog.java | 53 -- .../detailed/dialog/UrlRequestDialog.java | 395 ------------ .../dialog/UrlRequestDialogReply.java | 188 ------ java/tests/detailed/handler/AppHandler.java | 80 --- .../detailed/handler/ClientSchemeHandler.java | 134 ---- .../detailed/handler/ContextMenuHandler.java | 101 --- java/tests/detailed/handler/DragHandler.java | 31 - .../detailed/handler/JSDialogHandler.java | 26 - .../detailed/handler/KeyboardHandler.java | 52 -- .../handler/MessageRouterHandler.java | 25 - .../handler/MessageRouterHandlerEx.java | 68 -- .../detailed/handler/RequestHandler.java | 167 ----- .../detailed/handler/ResourceHandler.java | 72 --- .../handler/ResourceSetErrorHandler.java | 25 - .../detailed/handler/SearchSchemeHandler.java | 48 -- java/tests/detailed/handler/binding_test.html | 28 - .../tests/detailed/handler/binding_test2.html | 81 --- java/tests/detailed/handler/localstorage.html | 24 - java/tests/detailed/handler/logo.png | Bin 24025 -> 0 bytes java/tests/detailed/handler/spellcheck.html | 14 - java/tests/detailed/handler/transparency.html | 63 -- java/tests/detailed/ui/ControlPanel.java | 182 ------ java/tests/detailed/ui/MenuBar.java | 602 ------------------ java/tests/detailed/ui/StatusPanel.java | 48 -- java/tests/detailed/util/DataUri.java | 15 - java/tests/junittests/DisplayHandlerTest.java | 81 --- java/tests/junittests/DragDataTest.java | 165 ----- java/tests/junittests/TestFrame.java | 297 --------- java/tests/junittests/TestFrameTest.java | 63 -- .../tests/junittests/TestResourceHandler.java | 69 -- java/tests/junittests/TestSetupContext.java | 27 - java/tests/junittests/TestSetupExtension.java | 90 --- java/tests/simple/MainFrame.java | 190 ------ native/CefBrowser_N.cpp | 45 -- 49 files changed, 56 insertions(+), 4629 deletions(-) delete mode 100644 java/tests/detailed/BrowserFrame.java delete mode 100644 java/tests/detailed/MainFrame.java delete mode 100644 java/tests/detailed/dialog/CertErrorDialog.java delete mode 100644 java/tests/detailed/dialog/CookieManagerDialog.java delete mode 100644 java/tests/detailed/dialog/DevToolsDialog.java delete mode 100644 java/tests/detailed/dialog/DownloadDialog.java delete mode 100644 java/tests/detailed/dialog/PasswordDialog.java delete mode 100644 java/tests/detailed/dialog/SearchDialog.java delete mode 100644 java/tests/detailed/dialog/ShowTextDialog.java delete mode 100644 java/tests/detailed/dialog/UrlRequestDialog.java delete mode 100644 java/tests/detailed/dialog/UrlRequestDialogReply.java delete mode 100644 java/tests/detailed/handler/AppHandler.java delete mode 100644 java/tests/detailed/handler/ClientSchemeHandler.java delete mode 100644 java/tests/detailed/handler/ContextMenuHandler.java delete mode 100644 java/tests/detailed/handler/DragHandler.java delete mode 100644 java/tests/detailed/handler/JSDialogHandler.java delete mode 100644 java/tests/detailed/handler/KeyboardHandler.java delete mode 100644 java/tests/detailed/handler/MessageRouterHandler.java delete mode 100644 java/tests/detailed/handler/MessageRouterHandlerEx.java delete mode 100644 java/tests/detailed/handler/RequestHandler.java delete mode 100644 java/tests/detailed/handler/ResourceHandler.java delete mode 100644 java/tests/detailed/handler/ResourceSetErrorHandler.java delete mode 100644 java/tests/detailed/handler/SearchSchemeHandler.java delete mode 100644 java/tests/detailed/handler/binding_test.html delete mode 100644 java/tests/detailed/handler/binding_test2.html delete mode 100644 java/tests/detailed/handler/localstorage.html delete mode 100644 java/tests/detailed/handler/logo.png delete mode 100644 java/tests/detailed/handler/spellcheck.html delete mode 100644 java/tests/detailed/handler/transparency.html delete mode 100644 java/tests/detailed/ui/ControlPanel.java delete mode 100644 java/tests/detailed/ui/MenuBar.java delete mode 100644 java/tests/detailed/ui/StatusPanel.java delete mode 100644 java/tests/detailed/util/DataUri.java delete mode 100644 java/tests/junittests/DisplayHandlerTest.java delete mode 100644 java/tests/junittests/DragDataTest.java delete mode 100644 java/tests/junittests/TestFrame.java delete mode 100644 java/tests/junittests/TestFrameTest.java delete mode 100644 java/tests/junittests/TestResourceHandler.java delete mode 100644 java/tests/junittests/TestSetupContext.java delete mode 100644 java/tests/junittests/TestSetupExtension.java delete mode 100644 java/tests/simple/MainFrame.java diff --git a/.github/workflows/build-jcef.yml b/.github/workflows/build-jcef.yml index c6f849d5..7c2c63c4 100644 --- a/.github/workflows/build-jcef.yml +++ b/.github/workflows/build-jcef.yml @@ -11,7 +11,7 @@ jobs: matrix: platform: [amd64, arm64] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install deps and build run: | sudo apt update @@ -40,7 +40,7 @@ jobs: matrix: platform: [amd64, arm64] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ilammy/msvc-dev-cmd@v1 - name: Build run: | @@ -61,3 +61,35 @@ jobs: jcef_build/windows_${{ matrix.platform }}.tar.gz jcef_build/windows_${{ matrix.platform }}.tar.gz.sha256 if-no-files-found: error + + java-cef-macos: + runs-on: [macos-12] + strategy: + matrix: + platform: [amd64, arm64] + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.9 + uses: actions/setup-python@v4 + with: + python-version: '3.9' + - run: | + brew install ninja + brew install python + brew install coreutils + sudo xcode-select --switch /Applications/Xcode_13.1.app + mkdir jcef_build && cd jcef_build + cmake -G "Ninja" -DPROJECT_ARCH=${{ matrix.platform }} -DCMAKE_BUILD_TYPE=Release .. + ninja -j4 + mv native/Release macos_${{ matrix.platform }} + tar -czf macos_${{ matrix.platform }}.tar.gz macos_${{ matrix.platform }} + sha256sum macos_${{ matrix.platform }}.tar.gz > macos_${{ matrix.platform }}.tar.gz.sha256 + + - uses: actions/upload-artifact@v3 + if: ${{ github.ref == 'refs/heads/master' }} + with: + name: 'macos_${{ matrix.platform }}' + path: | + jcef_build/macos_${{ matrix.platform }}.tar.gz + jcef_build/macos_${{ matrix.platform }}.tar.gz.sha256 + if-no-files-found: error diff --git a/build.xml b/build.xml index 010b5c57..a9227e30 100644 --- a/build.xml +++ b/build.xml @@ -30,7 +30,6 @@ - @@ -47,11 +46,6 @@ - - - - - @@ -64,7 +58,6 @@ icon="third_party/cef/res/CefIcon.icns"> - diff --git a/cmake/DownloadCEF.cmake b/cmake/DownloadCEF.cmake index b2d11930..a64592bc 100644 --- a/cmake/DownloadCEF.cmake +++ b/cmake/DownloadCEF.cmake @@ -8,7 +8,7 @@ # Visit https://cef-builds.spotifycdn.com/index.html for the list of # supported platforms and versions. -function(DownloadCEF platform branch version download_dir) +function(DownloadCEF platform version download_dir) # Specify the binary distribution type and download directory. set(CEF_DISTRIBUTION "cef_binary_${version}_${platform}") set(CEF_DOWNLOAD_DIR "${download_dir}") @@ -21,19 +21,19 @@ function(DownloadCEF platform branch version download_dir) set(CEF_DOWNLOAD_FILENAME "${CEF_DISTRIBUTION}.tar.bz2") set(CEF_DOWNLOAD_PATH "${CEF_DOWNLOAD_DIR}/${CEF_DOWNLOAD_FILENAME}") if(NOT EXISTS "${CEF_DOWNLOAD_PATH}") - set(CEF_DOWNLOAD_URL "https://mcef-download.cinemamod.com/cef-builds/${branch}/${CEF_DOWNLOAD_FILENAME}") + set(CEF_DOWNLOAD_URL "https://cef-builds.spotifycdn.com/${CEF_DOWNLOAD_FILENAME}") string(REPLACE "+" "%2B" CEF_DOWNLOAD_URL_ESCAPED ${CEF_DOWNLOAD_URL}) # Download the SHA1 hash for the binary distribution. - # message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}.sha1 from ${CEF_DOWNLOAD_URL_ESCAPED}...") - # file(DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}.sha1" "${CEF_DOWNLOAD_PATH}.sha1") - # file(READ "${CEF_DOWNLOAD_PATH}.sha1" CEF_SHA1) + message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}.sha1 from ${CEF_DOWNLOAD_URL_ESCAPED}...") + file(DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}.sha1" "${CEF_DOWNLOAD_PATH}.sha1") + file(READ "${CEF_DOWNLOAD_PATH}.sha1" CEF_SHA1) # Download the binary distribution and verify the hash. message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}...") file( DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}" "${CEF_DOWNLOAD_PATH}" - # EXPECTED_HASH SHA1=${CEF_SHA1} + EXPECTED_HASH SHA1=${CEF_SHA1} SHOW_PROGRESS ) endif() diff --git a/java/org/cef/CefClient.java b/java/org/cef/CefClient.java index 0c88e8dc..39034ea6 100644 --- a/java/org/cef/CefClient.java +++ b/java/org/cef/CefClient.java @@ -4,46 +4,22 @@ package org.cef; -import org.cef.browser.CefBrowser; -import org.cef.browser.CefBrowserFactory; -import org.cef.browser.CefFrame; -import org.cef.browser.CefMessageRouter; -import org.cef.browser.CefRequestContext; -import org.cef.callback.CefAuthCallback; -import org.cef.callback.CefBeforeDownloadCallback; -import org.cef.callback.CefCallback; -import org.cef.callback.CefContextMenuParams; -import org.cef.callback.CefDownloadItem; -import org.cef.callback.CefDownloadItemCallback; -import org.cef.callback.CefDragData; -import org.cef.callback.CefFileDialogCallback; -import org.cef.callback.CefJSDialogCallback; -import org.cef.callback.CefMenuModel; -import org.cef.callback.CefPrintDialogCallback; -import org.cef.callback.CefPrintJobCallback; +import org.cef.browser.*; +import org.cef.callback.*; import org.cef.handler.*; import org.cef.misc.BoolRef; import org.cef.misc.CefAudioParameters; import org.cef.misc.CefPrintSettings; -import org.cef.misc.StringRef; import org.cef.network.CefRequest; import org.cef.network.CefRequest.TransitionType; -import org.cef.network.CefResponse; -import org.cef.network.CefURLRequest; - -import java.awt.Dimension; -import java.awt.Point; -import java.awt.Rectangle; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; + +import java.awt.*; import java.nio.ByteBuffer; import java.util.Collection; import java.util.HashMap; import java.util.Vector; import java.util.function.Consumer; -import javax.swing.SwingUtilities; - /** * Client that owns a browser and renderer. */ diff --git a/java/org/cef/browser/CefBrowserFactory.java b/java/org/cef/browser/CefBrowserFactory.java index 38bfd596..853ce9b2 100644 --- a/java/org/cef/browser/CefBrowserFactory.java +++ b/java/org/cef/browser/CefBrowserFactory.java @@ -13,8 +13,6 @@ 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); + return new CefBrowserOsr(client, url, isTransparent, context, settings); } } diff --git a/java/org/cef/browser/CefBrowserOsr.java b/java/org/cef/browser/CefBrowserOsr.java index 335bd8db..2fd33b1b 100644 --- a/java/org/cef/browser/CefBrowserOsr.java +++ b/java/org/cef/browser/CefBrowserOsr.java @@ -4,6 +4,7 @@ package org.cef.browser; +import org.cef.CefBrowserSettings; import org.cef.CefClient; import org.cef.callback.CefDragData; import org.cef.handler.CefRenderHandler; @@ -18,9 +19,6 @@ import java.nio.ByteBuffer; 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; /** @@ -40,8 +38,8 @@ public class CefBrowserOsr extends CefBrowser_N implements CefRenderHandler { private CopyOnWriteArrayList> onPaintListeners = new CopyOnWriteArrayList<>(); - CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context, - CefBrowserSettings settings) { + protected CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context, + CefBrowserSettings settings) { this(client, url, transparent, context, null, null, settings); } @@ -50,8 +48,6 @@ private CefBrowserOsr(CefClient client, String url, boolean transparent, CefBrowserSettings settings) { super(client, url, context, parent, inspectAt, settings); isTransparent_ = transparent; - renderer_ = new CefRenderer(transparent); - createGLCanvas(); } @Override @@ -160,7 +156,7 @@ private void createBrowserIfRequired(boolean hasParent) { getInspectAt()); } else { createBrowser(getClient(), windowHandle, getUrl(), true, isTransparent_, - getRequestContext()); + null, getRequestContext()); } } else if (hasParent && justCreated_) { notifyAfterParentChanged(); diff --git a/java/org/cef/browser/CefBrowser_N.java b/java/org/cef/browser/CefBrowser_N.java index ed60c2be..72502f64 100644 --- a/java/org/cef/browser/CefBrowser_N.java +++ b/java/org/cef/browser/CefBrowser_N.java @@ -7,12 +7,7 @@ import org.cef.CefBrowserSettings; import org.cef.CefClient; import org.cef.browser.CefDevToolsClient.DevToolsException; -import org.cef.browser.CefRequestContext; -import org.cef.callback.CefDragData; -import org.cef.callback.CefNativeAdapter; -import org.cef.callback.CefPdfPrintCallback; -import org.cef.callback.CefRunFileDialogCallback; -import org.cef.callback.CefStringVisitor; +import org.cef.callback.*; import org.cef.event.CefKeyEvent; import org.cef.event.CefMouseEvent; import org.cef.event.CefMouseWheelEvent; @@ -22,16 +17,10 @@ import org.cef.handler.CefWindowHandler; import org.cef.misc.CefPdfPrintSettings; import org.cef.network.CefRequest; -import java.util.concurrent.CompletableFuture; -import java.awt.Component; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Window; -import java.awt.event.WindowEvent; +import java.awt.*; import java.util.Vector; - -import javax.swing.SwingUtilities; +import java.util.concurrent.CompletableFuture; /** * This class represents all methods which are connected to the @@ -209,7 +198,7 @@ protected final void createDevTools(CefBrowser_N parent, CefClientHandler client if (getNativeRef("CefBrowser") == 0 && !isPending_) { try { isPending_ = N_CreateDevTools( - parent, clientHandler, windowHandle, osr, transparent, inspectAt); + parent, clientHandler, windowHandle, osr, transparent, null, inspectAt); } catch (UnsatisfiedLinkError err) { err.printStackTrace(); } @@ -339,26 +328,6 @@ public CefFrame getFocusedFrame() { } } - @Override - public CefFrame getFrame(long identifier) { - try { - return N_GetFrame(identifier); - } catch (UnsatisfiedLinkError ule) { - ule.printStackTrace(); - return null; - } - } - - @Override - public CefFrame getFrame(String name) { - try { - return N_GetFrame2(name); - } catch (UnsatisfiedLinkError ule) { - ule.printStackTrace(); - return null; - } - } - @Override public CefFrame getFrameByIdentifier(String identifier) { try { @@ -871,9 +840,9 @@ private final native void N_Find( 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_SendKeyEvent(CefKeyEvent e); + private final native void N_SendMouseEvent(CefMouseEvent e); + private final native void N_SendMouseWheelEvent(CefMouseWheelEvent 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); diff --git a/java/tests/detailed/BrowserFrame.java b/java/tests/detailed/BrowserFrame.java deleted file mode 100644 index 25beacf3..00000000 --- a/java/tests/detailed/BrowserFrame.java +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) 2018 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed; - -import org.cef.CefApp; -import org.cef.browser.CefBrowser; -import org.cef.handler.CefLifeSpanHandlerAdapter; - -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -import javax.swing.JFrame; -import javax.swing.SwingUtilities; - -public class BrowserFrame extends JFrame { - private volatile boolean isClosed_ = false; - private CefBrowser browser_ = null; - private static int browserCount_ = 0; - private Runnable afterParentChangedAction_ = null; - - public BrowserFrame() { - this(null); - } - - public BrowserFrame(String title) { - super(title); - - // Browser window closing works as follows: - // 1. Clicking the window X button calls WindowAdapter.windowClosing. - // 2. WindowAdapter.windowClosing calls CefBrowser.close(false). - // 3. CEF calls CefLifeSpanHandler.doClose() which calls CefBrowser.doClose() - // which returns true (canceling the close). - // 4. CefBrowser.doClose() triggers another call to WindowAdapter.windowClosing. - // 5. WindowAdapter.windowClosing calls CefBrowser.close(true). - // 6. For windowed browsers CEF destroys the native window handle. For OSR - // browsers CEF calls CefLifeSpanHandler.doClose() which calls - // CefBrowser.doClose() again which returns false (allowing the close). - // 7. CEF calls CefLifeSpanHandler.onBeforeClose and the browser is destroyed. - // - // On macOS pressing Cmd+Q results in a call to CefApp.handleBeforeTerminate - // which calls CefBrowser.close(true) for each existing browser. CEF then calls - // CefLifeSpanHandler.onBeforeClose and the browser is destroyed. - // - // Application shutdown works as follows: - // 1. CefLifeSpanHandler.onBeforeClose calls CefApp.getInstance().dispose() - // when the last browser window is destroyed. - // 2. CefAppHandler.stateHasChanged terminates the application by calling - // System.exit(0) when the state changes to CefAppState.TERMINATED. - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - if (browser_ == null) { - // If there's no browser we can dispose immediately. - isClosed_ = true; - System.out.println("BrowserFrame.windowClosing Frame.dispose"); - dispose(); - return; - } - - boolean isClosed = isClosed_; - - if (isClosed) { - // Cause browser.doClose() to return false so that OSR browsers - // can close. - browser_.setCloseAllowed(); - } - - // Results in another call to this method. - System.out.println("BrowserFrame.windowClosing CefBrowser.close(" + isClosed + ")"); - browser_.close(isClosed); - if (!isClosed_) { - isClosed_ = true; - } - if (isClosed) { - // Dispose after the 2nd call to this method. - System.out.println("BrowserFrame.windowClosing Frame.dispose"); - dispose(); - } - } - }); - } - - public void setBrowser(CefBrowser browser) { - if (browser_ == null) browser_ = browser; - - browser_.getClient().removeLifeSpanHandler(); - browser_.getClient().addLifeSpanHandler(new CefLifeSpanHandlerAdapter() { - @Override - public void onAfterCreated(CefBrowser browser) { - System.out.println("BrowserFrame.onAfterCreated id=" + browser.getIdentifier()); - browserCount_++; - } - - @Override - public void onAfterParentChanged(CefBrowser browser) { - System.out.println( - "BrowserFrame.onAfterParentChanged id=" + browser.getIdentifier()); - if (afterParentChangedAction_ != null) { - SwingUtilities.invokeLater(afterParentChangedAction_); - afterParentChangedAction_ = null; - } - } - - @Override - public boolean doClose(CefBrowser browser) { - boolean result = browser.doClose(); - System.out.println("BrowserFrame.doClose id=" + browser.getIdentifier() - + " CefBrowser.doClose=" + result); - return result; - } - - @Override - public void onBeforeClose(CefBrowser browser) { - System.out.println("BrowserFrame.onBeforeClose id=" + browser.getIdentifier()); - if (--browserCount_ == 0) { - System.out.println("BrowserFrame.onBeforeClose CefApp.dispose"); - CefApp.getInstance().dispose(); - } - } - }); - } - - public void removeBrowser(Runnable r) { - System.out.println("BrowserFrame.removeBrowser"); - afterParentChangedAction_ = r; - // The removeNotify() notification should be sent as a result of calling remove(). - // However, it isn't in all cases so we do it manually here. - browser_ = null; - } - - public CefBrowser getBrowser() { - return browser_; - } -} diff --git a/java/tests/detailed/MainFrame.java b/java/tests/detailed/MainFrame.java deleted file mode 100644 index 5b1efeb5..00000000 --- a/java/tests/detailed/MainFrame.java +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed; - -import org.cef.CefApp; -import org.cef.CefApp.CefVersion; -import org.cef.CefClient; -import org.cef.CefSettings; -import org.cef.CefSettings.ColorType; -import org.cef.OS; -import org.cef.browser.CefBrowser; -import org.cef.browser.CefFrame; -import org.cef.browser.CefMessageRouter; -import org.cef.browser.CefRequestContext; -import org.cef.handler.CefDisplayHandlerAdapter; -import org.cef.handler.CefFocusHandlerAdapter; -import org.cef.handler.CefLoadHandlerAdapter; -import org.cef.handler.CefRequestContextHandlerAdapter; -import org.cef.network.CefCookieManager; - -import java.awt.BorderLayout; -import java.awt.KeyboardFocusManager; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.io.File; -import java.lang.Thread.UncaughtExceptionHandler; - -import javax.swing.JFrame; -import javax.swing.JPanel; - -import tests.detailed.dialog.DownloadDialog; -import tests.detailed.handler.AppHandler; -import tests.detailed.handler.ContextMenuHandler; -import tests.detailed.handler.DragHandler; -import tests.detailed.handler.JSDialogHandler; -import tests.detailed.handler.KeyboardHandler; -import tests.detailed.handler.MessageRouterHandler; -import tests.detailed.handler.MessageRouterHandlerEx; -import tests.detailed.handler.RequestHandler; -import tests.detailed.ui.ControlPanel; -import tests.detailed.ui.MenuBar; -import tests.detailed.ui.StatusPanel; -import tests.detailed.util.DataUri; - -public class MainFrame extends BrowserFrame { - private static final long serialVersionUID = -2295538706810864538L; - public static void main(String[] args) { - // Perform startup initialization on platforms that require it. - if (!CefApp.startup(args)) { - System.out.println("Startup initialization failed!"); - return; - } - - // OSR mode is enabled by default on Linux. - // and disabled by default on Windows and Mac OS X. - boolean osrEnabledArg = false; - boolean transparentPaintingEnabledArg = false; - boolean createImmediately = false; - for (String arg : args) { - arg = arg.toLowerCase(); - if (arg.equals("--off-screen-rendering-enabled")) { - osrEnabledArg = true; - } else if (arg.equals("--transparent-painting-enabled")) { - transparentPaintingEnabledArg = true; - } else if (arg.equals("--create-immediately")) { - createImmediately = true; - } - } - - System.out.println("Offscreen rendering " + (osrEnabledArg ? "enabled" : "disabled")); - - // MainFrame keeps all the knowledge to display the embedded browser - // frame. - final MainFrame frame = new MainFrame( - osrEnabledArg, transparentPaintingEnabledArg, createImmediately, args); - frame.setSize(800, 600); - frame.setVisible(true); - } - - private final CefClient client_; - private String errorMsg_ = ""; - private ControlPanel control_pane_; - private StatusPanel status_panel_; - private boolean browserFocus_ = true; - private boolean osr_enabled_; - private boolean transparent_painting_enabled_; - - public MainFrame(boolean osrEnabled, boolean transparentPaintingEnabled, - boolean createImmediately, String[] args) { - this.osr_enabled_ = osrEnabled; - this.transparent_painting_enabled_ = transparentPaintingEnabled; - - CefApp myApp; - if (CefApp.getState() != CefApp.CefAppState.INITIALIZED) { - // 1) CefApp is the entry point for JCEF. You can pass - // application arguments to it, if you want to handle any - // chromium or CEF related switches/attributes in - // the native world. - CefSettings settings = new CefSettings(); - settings.windowless_rendering_enabled = osrEnabled; - // try to load URL "about:blank" to see the background color - settings.background_color = settings.new ColorType(100, 255, 242, 211); - myApp = CefApp.getInstance(args, settings); - - CefVersion version = myApp.getVersion(); - System.out.println("Using:\n" + version); - - // We're registering our own AppHandler because we want to - // add an own schemes (search:// and client://) and its corresponding - // protocol handlers. So if you enter "search:something on the web", your - // search request "something on the web" is forwarded to www.google.com - CefApp.addAppHandler(new AppHandler(args)); - } else { - myApp = CefApp.getInstance(); - } - - // By calling the method createClient() the native part - // of JCEF/CEF will be initialized and an instance of - // CefClient will be created. You can create one to many - // instances of CefClient. - client_ = myApp.createClient(); - - // 2) You have the ability to pass different handlers to your - // instance of CefClient. Each handler is responsible to - // deal with different informations (e.g. keyboard input). - // - // For each handler (with more than one method) adapter - // classes exists. So you don't need to override methods - // you're not interested in. - DownloadDialog downloadDialog = new DownloadDialog(this); - client_.addContextMenuHandler(new ContextMenuHandler(this)); - client_.addDownloadHandler(downloadDialog); - client_.addDragHandler(new DragHandler()); - client_.addJSDialogHandler(new JSDialogHandler()); - client_.addKeyboardHandler(new KeyboardHandler()); - client_.addRequestHandler(new RequestHandler(this)); - - // Beside the normal handler instances, we're registering a MessageRouter - // as well. That gives us the opportunity to reply to JavaScript method - // calls (JavaScript binding). We're using the default configuration, so - // that the JavaScript binding methods "cefQuery" and "cefQueryCancel" - // are used. - CefMessageRouter msgRouter = CefMessageRouter.create(); - msgRouter.addHandler(new MessageRouterHandler(), true); - msgRouter.addHandler(new MessageRouterHandlerEx(client_), false); - client_.addMessageRouter(msgRouter); - - // 2.1) We're overriding CefDisplayHandler as nested anonymous class - // to update our address-field, the title of the panel as well - // as for updating the status-bar on the bottom of the browser - client_.addDisplayHandler(new CefDisplayHandlerAdapter() { - @Override - public void onAddressChange(CefBrowser browser, CefFrame frame, String url) { - control_pane_.setAddress(browser, url); - } - @Override - public void onTitleChange(CefBrowser browser, String title) { - setTitle(title); - } - @Override - public void onStatusMessage(CefBrowser browser, String value) { - status_panel_.setStatusText(value); - } - }); - - // 2.2) To disable/enable navigation buttons and to display a prgress bar - // which indicates the load state of our website, we're overloading - // the CefLoadHandler as nested anonymous class. Beside this, the - // load handler is responsible to deal with (load) errors as well. - // For example if you navigate to a URL which does not exist, the - // browser will show up an error message. - client_.addLoadHandler(new CefLoadHandlerAdapter() { - @Override - public void onLoadingStateChange(CefBrowser browser, boolean isLoading, - boolean canGoBack, boolean canGoForward) { - control_pane_.update(browser, isLoading, canGoBack, canGoForward); - status_panel_.setIsInProgress(isLoading); - - if (!isLoading && !errorMsg_.isEmpty()) { - browser.loadURL(DataUri.create("text/html", errorMsg_)); - errorMsg_ = ""; - } - } - - @Override - public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, - String errorText, String failedUrl) { - if (errorCode != ErrorCode.ERR_NONE && errorCode != ErrorCode.ERR_ABORTED) { - errorMsg_ = ""; - errorMsg_ += "Error while loading"; - errorMsg_ += ""; - errorMsg_ += "

" + errorCode + "

"; - errorMsg_ += "

Failed to load " + failedUrl + "

"; - errorMsg_ += "

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

"; - errorMsg_ += ""; - browser.stopLoad(); - } - } - }); - - // Create the browser. - CefBrowser browser = client_.createBrowser( - "http://www.google.com", osrEnabled, null); - setBrowser(browser); - - // Set up the UI for this example implementation. - JPanel contentPanel = createContentPanel(); - getContentPane().add(contentPanel, BorderLayout.CENTER); - - // Clear focus from the browser when the address field gains focus. - control_pane_.getAddressField().addFocusListener(new FocusAdapter() { - @Override - public void focusGained(FocusEvent e) { - if (!browserFocus_) return; - browserFocus_ = false; - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); - control_pane_.getAddressField().requestFocus(); - } - }); - - // Clear focus from the address field when the browser gains focus. - client_.addFocusHandler(new CefFocusHandlerAdapter() { - @Override - public void onGotFocus(CefBrowser browser) { - if (browserFocus_) return; - browserFocus_ = true; - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); - browser.setFocus(true); - } - - @Override - public void onTakeFocus(CefBrowser browser, boolean next) { - browserFocus_ = false; - } - }); - - if (createImmediately) browser.createImmediately(); - - // Add the browser to the UI. - - MenuBar menuBar = new MenuBar( - this, browser, control_pane_, downloadDialog, CefCookieManager.getGlobalManager()); - - menuBar.addBookmark("Binding Test", "client://tests/binding_test.html"); - menuBar.addBookmark("Binding Test 2", "client://tests/binding_test2.html"); - menuBar.addBookmark("Download Test", "https://cef-builds.spotifycdn.com/index.html"); - menuBar.addBookmark("Login Test (username:pumpkin, password:pie)", - "http://www.colostate.edu/~ric/protect/your.html"); - menuBar.addBookmark("Certificate-error Test", "https://www.k2go.de"); - menuBar.addBookmark("Resource-Handler Test", "http://www.foo.bar/"); - menuBar.addBookmark("Resource-Handler Set Error Test", "http://seterror.test/"); - menuBar.addBookmark( - "Scheme-Handler Test 1: (scheme \"client\")", "client://tests/handler.html"); - menuBar.addBookmark( - "Scheme-Handler Test 2: (scheme \"search\")", "search://do a barrel roll/"); - menuBar.addBookmark("Spellcheck Test", "client://tests/spellcheck.html"); - menuBar.addBookmark("LocalStorage Test", "client://tests/localstorage.html"); - menuBar.addBookmark("Transparency Test", "client://tests/transparency.html"); - menuBar.addBookmarkSeparator(); - menuBar.addBookmark( - "javachromiumembedded", "https://bitbucket.org/chromiumembedded/java-cef"); - menuBar.addBookmark("chromiumembedded", "https://bitbucket.org/chromiumembedded/cef"); - setJMenuBar(menuBar); - } - - private JPanel createContentPanel() { - JPanel contentPanel = new JPanel(new BorderLayout()); - control_pane_ = new ControlPanel(getBrowser()); - status_panel_ = new StatusPanel(); - contentPanel.add(control_pane_, BorderLayout.NORTH); - contentPanel.add(status_panel_, BorderLayout.SOUTH); - return contentPanel; - } - - public boolean isOsrEnabled() { - return osr_enabled_; - } - - public boolean isTransparentPaintingEnabled() { - return transparent_painting_enabled_; - } -} diff --git a/java/tests/detailed/dialog/CertErrorDialog.java b/java/tests/detailed/dialog/CertErrorDialog.java deleted file mode 100644 index 4c78ea79..00000000 --- a/java/tests/detailed/dialog/CertErrorDialog.java +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.dialog; - -import org.cef.callback.CefCallback; -import org.cef.handler.CefLoadHandler.ErrorCode; - -import java.awt.Frame; - -import javax.swing.JOptionPane; - -public class CertErrorDialog implements Runnable { - private final Frame owner_; - private final ErrorCode cert_error_; - private final String request_url_; - private final CefCallback callback_; - - public CertErrorDialog( - Frame owner, ErrorCode cert_error, String request_url, CefCallback callback) { - owner_ = owner; - cert_error_ = cert_error; - request_url_ = request_url; - callback_ = callback; - } - - @Override - public void run() { - int dialogResult = JOptionPane.showConfirmDialog(owner_, - "An certificate error (" + cert_error_ + ") occurreed " - + "while requesting\n" + request_url_ + "\nDo you want to proceed anyway?", - "Certificate error", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE); - if (dialogResult == JOptionPane.YES_OPTION) { - callback_.Continue(); - } else { - callback_.cancel(); - } - } -} diff --git a/java/tests/detailed/dialog/CookieManagerDialog.java b/java/tests/detailed/dialog/CookieManagerDialog.java deleted file mode 100644 index 279ebbf2..00000000 --- a/java/tests/detailed/dialog/CookieManagerDialog.java +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.dialog; - -import org.cef.callback.CefCookieVisitor; -import org.cef.misc.BoolRef; -import org.cef.network.CefCookie; -import org.cef.network.CefCookieManager; - -import java.awt.BorderLayout; -import java.awt.Frame; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Date; -import java.util.Vector; - -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.table.AbstractTableModel; - -@SuppressWarnings("serial") -public class CookieManagerDialog extends JDialog { - private static int testCookieId = 1; - private final CefCookieManager manager; - private final CookieTableModel tblModel = new CookieTableModel(); - - public CookieManagerDialog(Frame owner, String title, CefCookieManager cookieManager) { - super(owner, title, false); - setLayout(new BorderLayout()); - setSize(800, 600); - manager = cookieManager; - - JTable cookieTable = new JTable(tblModel); - cookieTable.setFillsViewportHeight(true); - - JPanel controlPanel = new JPanel(); - controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS)); - JButton delButton = new JButton("Delete cookies"); - delButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - tblModel.removeCookies(); - } - }); - controlPanel.add(delButton); - - JButton testCreateCookie = new JButton("Add test cookie"); - testCreateCookie.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Date now = new Date(); - Date expires = new Date(now.getTime() + 86400000); - String name = "testNo" + testCookieId++; - CefCookie cookie = new CefCookie(name, "testCookie", ".test.cookie", "/", false, - true, now, now, true, expires); - if (manager.setCookie("http://my.test.cookie", cookie)) { - tblModel.visit(cookie, 1, 1, new BoolRef()); - } - } - }); - controlPanel.add(testCreateCookie); - - JButton doneButton = new JButton("Done"); - doneButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - setVisible(false); - } - }); - controlPanel.add(doneButton); - - add(new JScrollPane(cookieTable)); - add(controlPanel, BorderLayout.SOUTH); - - if (manager == null) throw new NullPointerException("Cookie manager is null"); - manager.visitAllCookies(tblModel); - } - - private class CookieTableModel extends AbstractTableModel implements CefCookieVisitor { - private final String[] columnNames; - private Vector rowData = new Vector<>(); - - public CookieTableModel() { - super(); - columnNames = new String[] {"Name", "Value", "Domain", "Path", "Secure", "HTTP only", - "Created", "Last Access", "Expires"}; - } - - // add an entry to the table - @Override - public boolean visit(CefCookie cookie, int count, int total, BoolRef delete) { - Object[] entry = {cookie.name, cookie.value, cookie.domain, cookie.path, - new Boolean(cookie.secure), new Boolean(cookie.httponly), cookie.creation, - cookie.lastAccess, cookie.expires}; - int row = rowData.size(); - rowData.addElement(entry); - fireTableRowsInserted(row, row); - - return true; - } - - public void removeCookies() { - int cnt = rowData.size(); - if (cnt > 0) { - rowData.clear(); - manager.deleteCookies("", ""); - fireTableRowsDeleted(0, cnt - 1); - } - } - - @Override - public int getRowCount() { - return rowData.size(); - } - - @Override - public int getColumnCount() { - return columnNames.length; - } - - @Override - public String getColumnName(int column) { - return columnNames[column]; - } - - @Override - public Class getColumnClass(int columnIndex) { - if (rowData.size() > 0) return rowData.get(0)[columnIndex].getClass(); - return Object.class; - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return false; - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - return rowData.get(rowIndex)[columnIndex]; - } - } -} diff --git a/java/tests/detailed/dialog/DevToolsDialog.java b/java/tests/detailed/dialog/DevToolsDialog.java deleted file mode 100644 index 74a3a766..00000000 --- a/java/tests/detailed/dialog/DevToolsDialog.java +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.dialog; - -import org.cef.browser.CefBrowser; - -import java.awt.BorderLayout; -import java.awt.Frame; -import java.awt.Point; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; - -import javax.swing.JDialog; - -@SuppressWarnings("serial") -public class DevToolsDialog extends JDialog { - private final CefBrowser devTools_; - public DevToolsDialog(Frame owner, String title, CefBrowser browser) { - this(owner, title, browser, null); - } - - public DevToolsDialog(Frame owner, String title, CefBrowser browser, Point inspectAt) { - super(owner, title, false); - - setLayout(new BorderLayout()); - setSize(800, 600); - setLocation(owner.getLocation().x + 20, owner.getLocation().y + 20); - - devTools_ = browser.getDevTools(inspectAt); - - addComponentListener(new ComponentAdapter() { - @Override - public void componentHidden(ComponentEvent e) { - dispose(); - } - }); - } - - @Override - public void dispose() { - devTools_.close(true); - super.dispose(); - } -} diff --git a/java/tests/detailed/dialog/DownloadDialog.java b/java/tests/detailed/dialog/DownloadDialog.java deleted file mode 100644 index f9717a50..00000000 --- a/java/tests/detailed/dialog/DownloadDialog.java +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.dialog; - -import org.cef.browser.CefBrowser; -import org.cef.callback.CefBeforeDownloadCallback; -import org.cef.callback.CefDownloadItem; -import org.cef.callback.CefDownloadItemCallback; -import org.cef.handler.CefDownloadHandler; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Frame; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPanel; - -@SuppressWarnings("serial") -public class DownloadDialog extends JDialog implements CefDownloadHandler { - private final Frame owner_; - private final Map downloadObjects_ = - new HashMap(); - private final JPanel downloadPanel_ = new JPanel(); - private final DownloadDialog dialog_; - - public DownloadDialog(Frame owner) { - super(owner, "Downloads", false); - setVisible(false); - setSize(400, 300); - - owner_ = owner; - dialog_ = this; - downloadPanel_.setLayout(new BoxLayout(downloadPanel_, BoxLayout.Y_AXIS)); - add(downloadPanel_); - } - - private class DownloadObject extends JPanel { - private boolean isHidden_ = true; - private final int identifier_; - private JLabel fileName_ = new JLabel(); - private JLabel status_ = new JLabel(); - private JButton dlAbort_ = new JButton(); - private JButton dlRemoveEntry_ = new JButton("x"); - private CefDownloadItemCallback callback_; - private Color bgColor_; - - DownloadObject(CefDownloadItem downloadItem, String suggestedName) { - super(); - setOpaque(true); - setLayout(new BorderLayout()); - setMaximumSize(new Dimension(dialog_.getWidth() - 10, 80)); - identifier_ = downloadItem.getId(); - bgColor_ = identifier_ % 2 == 0 ? Color.WHITE : Color.YELLOW; - setBackground(bgColor_); - - fileName_.setText(suggestedName); - add(fileName_, BorderLayout.NORTH); - - status_.setAlignmentX(LEFT_ALIGNMENT); - add(status_, BorderLayout.CENTER); - - JPanel controlPane = new JPanel(); - controlPane.setLayout(new BoxLayout(controlPane, BoxLayout.X_AXIS)); - controlPane.setOpaque(true); - controlPane.setBackground(bgColor_); - dlAbort_.setText("Abort"); - dlAbort_.setEnabled(false); - dlAbort_.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (callback_ != null) { - fileName_.setText("ABORTED - " + fileName_.getText()); - callback_.cancel(); - } - } - }); - controlPane.add(dlAbort_); - - dlRemoveEntry_.setEnabled(false); - dlRemoveEntry_.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - DownloadObject removed = downloadObjects_.remove(identifier_); - if (removed != null) { - downloadPanel_.remove(removed); - dialog_.repaint(); - } - } - }); - controlPane.add(dlRemoveEntry_); - add(controlPane, BorderLayout.SOUTH); - - update(downloadItem, null); - } - - // The method humanReadableByteCount() is based on - // http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java - String humanReadableByteCount(long bytes) { - int unit = 1024; - if (bytes < unit) return bytes + " B"; - - int exp = (int) (Math.log(bytes) / Math.log(unit)); - String pre = "" + ("kMGTPE").charAt(exp - 1); - return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); - } - - void update(CefDownloadItem downloadItem, CefDownloadItemCallback callback) { - int percentComplete = downloadItem.getPercentComplete(); - String rcvBytes = humanReadableByteCount(downloadItem.getReceivedBytes()); - String totalBytes = humanReadableByteCount(downloadItem.getTotalBytes()); - String speed = humanReadableByteCount(downloadItem.getCurrentSpeed()) + "it/s"; - - if (downloadItem.getReceivedBytes() >= 5 && isHidden_) { - dialog_.setVisible(true); - dialog_.toFront(); - owner_.toBack(); - isHidden_ = false; - } - Runtime.getRuntime().runFinalization(); - - callback_ = callback; - status_.setText(rcvBytes + " of " + totalBytes + " - " + percentComplete + "%" - + " - " + speed); - dlAbort_.setEnabled(downloadItem.isInProgress()); - dlRemoveEntry_.setEnabled(!downloadItem.isInProgress() || downloadItem.isCanceled() - || downloadItem.isComplete()); - if (!downloadItem.isInProgress() && !downloadItem.isCanceled() - && !downloadItem.isComplete()) { - fileName_.setText("FAILED - " + fileName_.getText()); - callback.cancel(); - } - } - } - - @Override - public void onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem, - String suggestedName, CefBeforeDownloadCallback callback) { - callback.Continue(suggestedName, true); - - DownloadObject dlObject = new DownloadObject(downloadItem, suggestedName); - downloadObjects_.put(downloadItem.getId(), dlObject); - downloadPanel_.add(dlObject); - } - - @Override - public void onDownloadUpdated( - CefBrowser browser, CefDownloadItem downloadItem, CefDownloadItemCallback callback) { - DownloadObject dlObject = downloadObjects_.get(downloadItem.getId()); - if (dlObject == null) return; - dlObject.update(downloadItem, callback); - } -} diff --git a/java/tests/detailed/dialog/PasswordDialog.java b/java/tests/detailed/dialog/PasswordDialog.java deleted file mode 100644 index 61662f48..00000000 --- a/java/tests/detailed/dialog/PasswordDialog.java +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.dialog; - -import org.cef.callback.CefAuthCallback; - -import java.awt.Frame; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPasswordField; -import javax.swing.JTextField; - -@SuppressWarnings("serial") -public class PasswordDialog extends JDialog implements Runnable { - private final JTextField username_ = new JTextField(20); - private final JPasswordField password_ = new JPasswordField(20); - private final CefAuthCallback callback_; - - public PasswordDialog(Frame owner, CefAuthCallback callback) { - super(owner, "Authentication required", true); - callback_ = callback; - setSize(400, 100); - setLayout(new GridLayout(0, 2)); - add(new JLabel("Username:")); - add(username_); - add(new JLabel("Password:")); - add(password_); - - JButton abortButton = new JButton("Abort"); - abortButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - callback_.cancel(); - setVisible(false); - dispose(); - } - }); - add(abortButton); - - JButton okButton = new JButton("OK"); - okButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (username_.getText().isEmpty()) return; - String password = new String(password_.getPassword()); - callback_.Continue(username_.getText(), password); - setVisible(false); - dispose(); - } - }); - add(okButton); - } - - @Override - public void run() { - setVisible(true); - } -} diff --git a/java/tests/detailed/dialog/SearchDialog.java b/java/tests/detailed/dialog/SearchDialog.java deleted file mode 100644 index 88838c36..00000000 --- a/java/tests/detailed/dialog/SearchDialog.java +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.dialog; - -import org.cef.browser.CefBrowser; - -import java.awt.BorderLayout; -import java.awt.Frame; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; - -@SuppressWarnings("serial") -public class SearchDialog extends JDialog { - private final CefBrowser browser_; - private final JTextField searchField_ = new JTextField(30); - private final JCheckBox caseCheckBox_ = new JCheckBox("Case sensitive"); - private final JButton prevButton_ = new JButton("Prev"); - private final JButton nextButton_ = new JButton("Next"); - - public SearchDialog(Frame owner, CefBrowser browser) { - super(owner, "Find...", false); - browser_ = browser; - - setLayout(new BorderLayout()); - setSize(400, 100); - - JPanel searchPanel = new JPanel(); - searchPanel.setLayout(new BoxLayout(searchPanel, BoxLayout.X_AXIS)); - searchPanel.add(Box.createHorizontalStrut(5)); - searchPanel.add(new JLabel("Search:")); - searchPanel.add(searchField_); - - JPanel controlPanel = new JPanel(); - controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS)); - controlPanel.add(Box.createHorizontalStrut(5)); - - JButton searchButton = new JButton("Search"); - searchButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (searchField_.getText() == null || searchField_.getText().isEmpty()) return; - - setTitle("Find \"" + searchField_.getText() + "\""); - boolean matchCase = caseCheckBox_.isSelected(); - browser_.find(searchField_.getText(), true, matchCase, false); - prevButton_.setEnabled(true); - nextButton_.setEnabled(true); - } - }); - controlPanel.add(searchButton); - - prevButton_.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - boolean matchCase = caseCheckBox_.isSelected(); - setTitle("Find \"" + searchField_.getText() + "\""); - browser_.find(searchField_.getText(), false, matchCase, true); - } - }); - prevButton_.setEnabled(false); - controlPanel.add(prevButton_); - - nextButton_.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - boolean matchCase = caseCheckBox_.isSelected(); - setTitle("Find \"" + searchField_.getText() + "\""); - browser_.find(searchField_.getText(), true, matchCase, true); - } - }); - nextButton_.setEnabled(false); - controlPanel.add(nextButton_); - - controlPanel.add(Box.createHorizontalStrut(50)); - - JButton doneButton = new JButton("Done"); - doneButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - setVisible(false); - dispose(); - } - }); - controlPanel.add(doneButton); - - add(searchPanel, BorderLayout.NORTH); - add(caseCheckBox_); - add(controlPanel, BorderLayout.SOUTH); - } - - @Override - public void dispose() { - browser_.stopFinding(true); - super.dispose(); - } -} diff --git a/java/tests/detailed/dialog/ShowTextDialog.java b/java/tests/detailed/dialog/ShowTextDialog.java deleted file mode 100644 index 70813046..00000000 --- a/java/tests/detailed/dialog/ShowTextDialog.java +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.dialog; - -import org.cef.callback.CefStringVisitor; - -import java.awt.BorderLayout; -import java.awt.Frame; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; - -@SuppressWarnings("serial") -public class ShowTextDialog extends JDialog implements CefStringVisitor { - private final JTextArea textArea_ = new JTextArea(); - - public ShowTextDialog(Frame owner, String title) { - super(owner, title, false); - setLayout(new BorderLayout()); - setSize(800, 600); - - JPanel controlPanel = new JPanel(); - controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS)); - JButton doneButton = new JButton("Done"); - doneButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - setVisible(false); - dispose(); - } - }); - controlPanel.add(doneButton); - - add(new JScrollPane(textArea_)); - add(controlPanel, BorderLayout.SOUTH); - } - - @Override - public void visit(String string) { - if (!isVisible()) { - setVisible(true); - } - textArea_.append(string); - } -} diff --git a/java/tests/detailed/dialog/UrlRequestDialog.java b/java/tests/detailed/dialog/UrlRequestDialog.java deleted file mode 100644 index b1cc175e..00000000 --- a/java/tests/detailed/dialog/UrlRequestDialog.java +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.dialog; - -import org.cef.network.CefPostData; -import org.cef.network.CefPostDataElement; -import org.cef.network.CefRequest; -import org.cef.network.CefRequest.CefUrlRequestFlags; - -import java.awt.BorderLayout; -import java.awt.Frame; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.Vector; - -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import javax.swing.table.AbstractTableModel; - -@SuppressWarnings("serial") -public class UrlRequestDialog extends JDialog { - private final Vector requestMethods = new Vector<>(); - private final Map requestFlags = new HashMap<>(); - private final TableModel headerTblModel = new TableModel(true); - private final TableModel postDataModel = new TableModel(false); - private final JTextField urlField; - private final JTextField cookieUrl; - private final Frame owner_; - - private CefRequest createRequest() { - String url = urlField.getText(); - if (url.isEmpty() || url.trim().equalsIgnoreCase("http://")) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JOptionPane.showMessageDialog(owner_, - "Please specify at least an URL. Otherwise the CefRequest is invalid"); - } - }); - return null; - } - - CefRequest request = CefRequest.create(); - if (request == null) return null; - - String firstPartyForCookie = cookieUrl.getText(); - if (firstPartyForCookie.isEmpty() || firstPartyForCookie.trim().equalsIgnoreCase("http://")) - firstPartyForCookie = url; - - String method = "GET"; - for (int i = 0; i < requestMethods.size(); i++) { - JRadioButton button = requestMethods.get(i); - if (button.isSelected()) { - method = button.getText(); - break; - } - } - - CefPostData postData = null; - int postDataRows = postDataModel.getRowCount(); - if (postDataRows > 0) { - postData = CefPostData.create(); - } else if (method.equalsIgnoreCase("POST") || method.equalsIgnoreCase("PUT")) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JOptionPane.showMessageDialog( - owner_, "The methods POST and PUT require at least one row of data."); - } - }); - return null; - } - - if (postData != null) { - for (int i = 0; i < postDataRows; i++) { - String value = (String) postDataModel.getValueAt(i, 0); - if (value.trim().isEmpty()) continue; - - CefPostDataElement elem = CefPostDataElement.create(); - if (elem != null) { - File f = new File(value); - if (f.isFile()) { - elem.setToFile(value); - } else { - byte[] byteStr = value.getBytes(); - elem.setToBytes(byteStr.length, byteStr); - } - postData.addElement(elem); - } - } - } - - Map headerMap = null; - int headerRows = headerTblModel.getRowCount(); - if (headerRows > 0) { - headerMap = new HashMap<>(); - for (int i = 0; i < headerRows; i++) { - String key = (String) headerTblModel.getValueAt(i, 0); - String value = (String) headerTblModel.getValueAt(i, 1); - if (key.trim().isEmpty()) continue; - - headerMap.put(key, value); - } - } - - int flags = 0; - Set> entrySet = requestFlags.entrySet(); - for (Entry entry : entrySet) { - if (entry.getKey().isSelected()) { - flags |= entry.getValue(); - } - } - - request.set(url, method, postData, headerMap); - request.setFirstPartyForCookies(firstPartyForCookie); - request.setFlags(flags); - return request; - } - - public UrlRequestDialog(Frame owner, String title) { - super(owner, title, false); - setSize(1200, 600); - setLayout(new BorderLayout()); - - owner_ = owner; - - // URL for the request - urlField = new JTextField("http://"); - JPanel urlPanel = createPanelWithTitle("Request URL", 1, 0); - urlPanel.add(urlField); - - // URL for the cookies - cookieUrl = new JTextField("http://"); - JPanel cookiePanel = createPanelWithTitle("Cookie-URL", 1, 0); - cookiePanel.add(cookieUrl); - - // Radio buttons for the request method - ButtonGroup requestModeGrp = new ButtonGroup(); - JPanel requestModePanel = createPanelWithTitle("HTTP Request Mode", 1, 0); - addRequestMode(requestModePanel, requestModeGrp, "GET", true); - addRequestMode(requestModePanel, requestModeGrp, "HEAD", false); - addRequestMode(requestModePanel, requestModeGrp, "POST", false); - addRequestMode(requestModePanel, requestModeGrp, "PUT", false); - addRequestMode(requestModePanel, requestModeGrp, "DELETE", false); - - // Checkboxes for the flags - JPanel flagsPanel = createPanelWithTitle("Flags", 0, 1); - addRequestFlag(flagsPanel, "Skip cache", CefUrlRequestFlags.UR_FLAG_SKIP_CACHE, - "If set the cache will be skipped when handling the request", false); - addRequestFlag(flagsPanel, "Allow cached credentials", - CefUrlRequestFlags.UR_FLAG_ALLOW_CACHED_CREDENTIALS, - "If set user name, password, and cookies may be sent with the request, " - + "and cookies may be saved from the response.", - false); - addRequestFlag(flagsPanel, "Report Upload Progress", - CefUrlRequestFlags.UR_FLAG_REPORT_UPLOAD_PROGRESS, - "If set upload progress events will be generated when a request has a body", false); - addRequestFlag(flagsPanel, "Report RawHeaders", - CefUrlRequestFlags.UR_FLAG_REPORT_RAW_HEADERS, - "If set the headers sent and received for the request will be recorded", false); - addRequestFlag(flagsPanel, "No download data", CefUrlRequestFlags.UR_FLAG_NO_DOWNLOAD_DATA, - "If set the CefURLRequestClient.onDownloadData method will not be called", false); - addRequestFlag(flagsPanel, "No retry on 5xx", CefUrlRequestFlags.UR_FLAG_NO_RETRY_ON_5XX, - "If set 5XX redirect errors will be propagated to the observer instead of automatically re-tried.", - false); - - // Table for header values - JPanel headerValues = createPanelWithTable("Header Values", headerTblModel); - headerTblModel.addEntry("User-Agent", "Mozilla/5.0 JCEF Example Agent"); - headerTblModel.addEntry("Accept", - "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); - - // Table for post-data - JPanel postData = createPanelWithTable("Post Data", postDataModel); - - // Create view - JPanel headerPanel = new JPanel(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 0.5; - c.gridx = 0; - c.gridy = 0; - headerPanel.add(urlPanel, c); - c.gridx = 1; - headerPanel.add(cookiePanel, c); - c.gridx = 0; - c.gridy = 1; - c.gridwidth = 2; - c.weightx = 0.0; - headerPanel.add(requestModePanel, c); - - JPanel centerPanel = new JPanel(new GridLayout(2, 0)); - centerPanel.add(headerValues); - centerPanel.add(postData); - - JButton abortButton = new JButton("Abort"); - abortButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - setVisible(false); - dispose(); - } - }); - - JButton sendButton = new JButton("Send"); - sendButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - CefRequest request = createRequest(); - if (request == null) return; - - UrlRequestDialogReply handleRequest = - new UrlRequestDialogReply(owner_, getTitle() + " - Result"); - handleRequest.send(request); - handleRequest.setVisible(true); - setVisible(false); - dispose(); - } - }); - - JPanel bottomPanel = new JPanel(new GridLayout(0, 2)); - bottomPanel.add(abortButton); - bottomPanel.add(sendButton); - - add(headerPanel, BorderLayout.PAGE_START); - add(flagsPanel, BorderLayout.LINE_START); - add(centerPanel, BorderLayout.CENTER); - add(bottomPanel, BorderLayout.PAGE_END); - } - - private void addRequestMode( - JPanel panel, ButtonGroup buttonGrp, String requestMode, boolean selected) { - JRadioButton button = new JRadioButton(requestMode, selected); - buttonGrp.add(button); - panel.add(button); - requestMethods.addElement(button); - } - - private void addRequestFlag( - JPanel panel, String flag, int value, String tooltip, boolean selected) { - JCheckBox checkBox = new JCheckBox(flag, selected); - checkBox.setToolTipText(tooltip); - panel.add(checkBox); - requestFlags.put(checkBox, value); - } - - private JPanel createPanelWithTitle(String title, int rows, int cols) { - JPanel result = new JPanel(new GridLayout(rows, cols)); - result.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(title), - BorderFactory.createEmptyBorder(10, 10, 10, 10))); - return result; - } - - private JPanel createPanelWithTable(String title, TableModel tblModel) { - final TableModel localTblModel = tblModel; - JPanel result = new JPanel(new BorderLayout()); - result.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(title), - BorderFactory.createEmptyBorder(10, 10, 10, 10))); - - JTable table = new JTable(tblModel); - table.setFillsViewportHeight(true); - JScrollPane scrollPane = new JScrollPane(table); - - JPanel buttonPane = new JPanel(new GridLayout(0, 2)); - JButton addButton = new JButton("Add entry"); - addButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - localTblModel.newDefaultEntry(); - } - }); - buttonPane.add(addButton); - - JButton delButton = new JButton("Remove entry"); - delButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - localTblModel.removeSelected(); - } - }); - buttonPane.add(delButton); - - result.add(scrollPane, BorderLayout.CENTER); - result.add(buttonPane, BorderLayout.PAGE_END); - - return result; - } - - private class TableModel extends AbstractTableModel { - private final String[] columnNames; - private Vector rowData = new Vector<>(); - private final boolean hasKeyColumn_; - - public TableModel(boolean hasKeyColumn) { - super(); - hasKeyColumn_ = hasKeyColumn; - if (hasKeyColumn) - columnNames = new String[] {"Key", "Value", ""}; - else - columnNames = new String[] {"Value", ""}; - } - - public void newDefaultEntry() { - int row = rowData.size(); - if (hasKeyColumn_) { - Object[] rowEntry = {"key", "value", new Boolean(false)}; - rowData.addElement(rowEntry); - } else { - Object[] rowEntry = {"value", new Boolean(false)}; - rowData.addElement(rowEntry); - } - fireTableRowsInserted(row, row); - } - - public void removeSelected() { - int idx = hasKeyColumn_ ? 2 : 1; - for (int i = 0; i < rowData.size(); ++i) { - if ((Boolean) rowData.get(i)[idx]) { - rowData.remove(i); - fireTableRowsDeleted(i, i); - i--; - } - } - } - - public void addEntry(String key, String value) { - int row = rowData.size(); - if (hasKeyColumn_) { - Object[] rowEntry = {key, value, new Boolean(false)}; - rowData.addElement(rowEntry); - } else { - Object[] rowEntry = {value, new Boolean(false)}; - rowData.addElement(rowEntry); - } - fireTableRowsInserted(row, row); - } - - @Override - public int getRowCount() { - return rowData.size(); - } - - @Override - public int getColumnCount() { - return columnNames.length; - } - - @Override - public String getColumnName(int column) { - return columnNames[column]; - } - - @Override - public Class getColumnClass(int columnIndex) { - if (rowData.size() > 0) return rowData.get(0)[columnIndex].getClass(); - return Object.class; - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return true; - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - return rowData.get(rowIndex)[columnIndex]; - } - - @Override - public void setValueAt(Object aValue, int rowIndex, int columnIndex) { - rowData.get(rowIndex)[columnIndex] = aValue; - fireTableCellUpdated(rowIndex, columnIndex); - } - } -} diff --git a/java/tests/detailed/dialog/UrlRequestDialogReply.java b/java/tests/detailed/dialog/UrlRequestDialogReply.java deleted file mode 100644 index 861388d3..00000000 --- a/java/tests/detailed/dialog/UrlRequestDialogReply.java +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.dialog; - -import org.cef.callback.CefAuthCallback; -import org.cef.callback.CefURLRequestClient; -import org.cef.network.CefRequest; -import org.cef.network.CefResponse; -import org.cef.network.CefURLRequest; -import org.cef.network.CefURLRequest.Status; - -import java.awt.BorderLayout; -import java.awt.Frame; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; - -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.SwingUtilities; - -@SuppressWarnings("serial") -public class UrlRequestDialogReply extends JDialog implements CefURLRequestClient { - private long nativeRef_ = 0; - private final JLabel statusLabel_ = new JLabel("HTTP-Request status: "); - private final JTextArea sentRequest_ = new JTextArea(); - private final JTextArea repliedResult_ = new JTextArea(); - private final JButton cancelButton_ = new JButton("Cancel"); - private CefURLRequest urlRequest_ = null; - private final Frame owner_; - private ByteArrayOutputStream byteStream_ = new ByteArrayOutputStream(); - - public UrlRequestDialogReply(Frame owner, String title) { - super(owner, title, false); - setLayout(new BorderLayout()); - setSize(800, 600); - - owner_ = owner; - - JPanel controlPanel = new JPanel(); - controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS)); - JButton doneButton = new JButton("Done"); - doneButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - urlRequest_.dispose(); - setVisible(false); - dispose(); - } - }); - controlPanel.add(doneButton); - - cancelButton_.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (urlRequest_ != null) { - urlRequest_.cancel(); - } - } - }); - cancelButton_.setEnabled(false); - controlPanel.add(cancelButton_); - - JPanel requestPane = createPanelWithTitle("Sent HTTP-Request", 1, 0); - requestPane.add(new JScrollPane(sentRequest_)); - - JPanel replyPane = createPanelWithTitle("Reply from the server", 1, 0); - replyPane.add(new JScrollPane(repliedResult_)); - - JPanel contentPane = new JPanel(new GridLayout(2, 0)); - contentPane.add(requestPane); - contentPane.add(replyPane); - - add(statusLabel_, BorderLayout.PAGE_START); - add(contentPane, BorderLayout.CENTER); - add(controlPanel, BorderLayout.PAGE_END); - } - - private JPanel createPanelWithTitle(String title, int rows, int cols) { - JPanel result = new JPanel(new GridLayout(rows, cols)); - result.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(title), - BorderFactory.createEmptyBorder(10, 10, 10, 10))); - return result; - } - - public void send(CefRequest request) { - if (request == null) { - statusLabel_.setText("HTTP-Request status: FAILED"); - sentRequest_.append("Can't send CefRequest because it is NULL"); - cancelButton_.setEnabled(false); - return; - } - - urlRequest_ = CefURLRequest.create(request, this); - if (urlRequest_ == null) { - statusLabel_.setText("HTTP-Request status: FAILED"); - sentRequest_.append("Can't send CefRequest because creation of CefURLRequest failed."); - repliedResult_.append( - "The native code (CEF) returned a NULL-Pointer for CefURLRequest."); - cancelButton_.setEnabled(false); - } else { - sentRequest_.append(request.toString()); - cancelButton_.setEnabled(true); - updateStatus("", false); - } - } - - private void updateStatus(final String updateMsg, final boolean printByteStream) { - final Status status = urlRequest_.getRequestStatus(); - Runnable runnable = new Runnable() { - @Override - public void run() { - statusLabel_.setText("HTTP-Request status: " + status); - if (status != Status.UR_UNKNOWN && status != Status.UR_IO_PENDING) { - cancelButton_.setEnabled(false); - } - repliedResult_.append(updateMsg); - if (printByteStream) { - try { - repliedResult_.append("\n\n" + byteStream_.toString("UTF-8")); - } catch (UnsupportedEncodingException e) { - repliedResult_.append("\n\n" + byteStream_.toString()); - } - } - } - }; - - if (SwingUtilities.isEventDispatchThread()) { - runnable.run(); - } else { - SwingUtilities.invokeLater(runnable); - } - } - - // CefURLRequestClient - - @Override - public void setNativeRef(String identifer, long nativeRef) { - nativeRef_ = nativeRef; - } - - @Override - public long getNativeRef(String identifer) { - return nativeRef_; - } - - @Override - public void onRequestComplete(CefURLRequest request) { - String updateStr = "onRequestCompleted\n\n"; - CefResponse response = request.getResponse(); - boolean isText = response.getHeaderByName("Content-Type").startsWith("text"); - updateStr += response.toString(); - updateStatus(updateStr, isText); - } - - @Override - public void onUploadProgress(CefURLRequest request, int current, int total) { - updateStatus("onUploadProgress: " + current + "/" + total + " bytes\n", false); - } - - @Override - public void onDownloadProgress(CefURLRequest request, int current, int total) { - updateStatus("onDownloadProgress: " + current + "/" + total + " bytes\n", false); - } - - @Override - public void onDownloadData(CefURLRequest request, byte[] data, int data_length) { - byteStream_.write(data, 0, data_length); - updateStatus("onDownloadData: " + data_length + " bytes\n", false); - } - - @Override - public boolean getAuthCredentials(boolean isProxy, String host, int port, String realm, - String scheme, CefAuthCallback callback) { - SwingUtilities.invokeLater(new PasswordDialog(owner_, callback)); - return true; - } -} diff --git a/java/tests/detailed/handler/AppHandler.java b/java/tests/detailed/handler/AppHandler.java deleted file mode 100644 index 45ec49bb..00000000 --- a/java/tests/detailed/handler/AppHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.handler; - -import org.cef.CefApp; -import org.cef.CefApp.CefAppState; -import org.cef.browser.CefBrowser; -import org.cef.browser.CefFrame; -import org.cef.callback.CefSchemeHandlerFactory; -import org.cef.callback.CefSchemeRegistrar; -import org.cef.handler.CefAppHandlerAdapter; -import org.cef.handler.CefResourceHandler; -import org.cef.network.CefRequest; - -public class AppHandler extends CefAppHandlerAdapter { - // We're registering our own schemes to demonstrate how to use - // CefAppHandler.onRegisterCustomSchemes() in combination with - // CefApp.registerSchemeHandlerFactory(). - public AppHandler(String[] args) { - super(args); - } - - // (1) First of all we have to register our custom schemes by implementing - // the method "onRegisterCustomSchemes. The scheme names are added by - // calling CefSchemeRegistrar.addCustomScheme. - @Override - public void onRegisterCustomSchemes(CefSchemeRegistrar registrar) { - if (registrar.addCustomScheme( - SearchSchemeHandler.scheme, true, false, false, false, true, false, false)) { - System.out.println("Added scheme " + SearchSchemeHandler.scheme + "://"); - } - if (registrar.addCustomScheme( - ClientSchemeHandler.scheme, true, false, false, false, true, false, false)) { - System.out.println("Added scheme " + ClientSchemeHandler.scheme + "://"); - } - } - - // (2) At the next step we have to register a SchemeHandlerFactory which is - // called if an user enters our registered scheme. - // - // This is done via the CefApp.registerSchemeHandlerFactory() method. - // A good place to call this function is from - // CefAppHandler.onContextInitialized(). - // - // The empty |domain_name| value will cause the factory to match all - // domain names. A set |domain_name| will only be valid for the entered - // domain. - @Override - public void onContextInitialized() { - CefApp cefApp = CefApp.getInstance(); - cefApp.registerSchemeHandlerFactory( - SearchSchemeHandler.scheme, SearchSchemeHandler.domain, new SchemeHandlerFactory()); - cefApp.registerSchemeHandlerFactory( - ClientSchemeHandler.scheme, ClientSchemeHandler.domain, new SchemeHandlerFactory()); - } - - // (3) The SchemeHandlerFactory creates a new ResourceHandler instance for each - // request the user has send to the browser. The ResourceHandler is the - // responsible class to process and return the result of a received - // request. - private class SchemeHandlerFactory implements CefSchemeHandlerFactory { - @Override - public CefResourceHandler create( - CefBrowser browser, CefFrame frame, String schemeName, CefRequest request) { - if (schemeName.equals(SearchSchemeHandler.scheme)) - return new SearchSchemeHandler(browser); - else if (schemeName.equals(ClientSchemeHandler.scheme)) - return new ClientSchemeHandler(); - return null; - } - } - - @Override - public void stateHasChanged(CefAppState state) { - System.out.println("AppHandler.stateHasChanged: " + state); - if (state == CefAppState.TERMINATED) System.exit(0); - } -} diff --git a/java/tests/detailed/handler/ClientSchemeHandler.java b/java/tests/detailed/handler/ClientSchemeHandler.java deleted file mode 100644 index 2ee156ff..00000000 --- a/java/tests/detailed/handler/ClientSchemeHandler.java +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.handler; - -import org.cef.callback.CefCallback; -import org.cef.handler.CefResourceHandlerAdapter; -import org.cef.misc.IntRef; -import org.cef.misc.StringRef; -import org.cef.network.CefRequest; -import org.cef.network.CefResponse; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * The example for the second scheme with domain handling is a more - * complex example and is taken from the parent project CEF. Please - * see CEF: "cefclient/scheme_test.cpp" for futher details - */ -public class ClientSchemeHandler extends CefResourceHandlerAdapter { - public static final String scheme = "client"; - public static final String domain = "tests"; - - private byte[] data_; - private String mime_type_; - private int offset_ = 0; - - public ClientSchemeHandler() { - super(); - } - - @Override - public synchronized boolean processRequest(CefRequest request, CefCallback callback) { - boolean handled = false; - String url = request.getURL(); - if (url.indexOf("handler.html") != -1) { - // Build the response html - String html; - html = "Client Scheme Handler" - + "" - + "This contents of this page page are served by the " - + "ClientSchemeHandler class handling the client:// protocol." - + "
You should see an image:" - + "
";
-
-            // Output a string representation of the request
-            html += request.toString();
-
-            html += "

Try the test form:" - + "
" - + "" - + "" - + "" - + "
"; - - data_ = html.getBytes(); - - handled = true; - // Set the resulting mime type - mime_type_ = "text/html"; - } else if (url.endsWith(".png")) { - handled = loadContent(url.substring(url.lastIndexOf('/') + 1)); - mime_type_ = "image/png"; - } else if (url.endsWith(".html")) { - handled = loadContent(url.substring(url.lastIndexOf('/') + 1)); - mime_type_ = "text/html"; - if (!handled) { - String html = "Error 404"; - html += "

Error 404

"; - html += "File " + url.substring(url.lastIndexOf('/') + 1) + " "; - html += "does not exist"; - data_ = html.getBytes(); - handled = true; - } - } - - if (handled) { - // Indicate the headers are available. - callback.Continue(); - return true; - } - - return false; - } - - @Override - public void getResponseHeaders( - CefResponse response, IntRef response_length, StringRef redirectUrl) { - response.setMimeType(mime_type_); - response.setStatus(200); - - // Set the resulting response length - response_length.set(data_.length); - } - - @Override - public synchronized boolean readResponse( - byte[] data_out, int bytes_to_read, IntRef bytes_read, CefCallback callback) { - boolean has_data = false; - - if (offset_ < data_.length) { - // Copy the next block of data into the buffer. - int transfer_size = Math.min(bytes_to_read, (data_.length - offset_)); - System.arraycopy(data_, offset_, data_out, 0, transfer_size); - offset_ += transfer_size; - - bytes_read.set(transfer_size); - has_data = true; - } else { - offset_ = 0; - bytes_read.set(0); - } - - return has_data; - } - - private boolean loadContent(String resName) { - InputStream inStream = getClass().getResourceAsStream(resName); - if (inStream != null) { - try { - ByteArrayOutputStream outFile = new ByteArrayOutputStream(); - int readByte = -1; - while ((readByte = inStream.read()) >= 0) outFile.write(readByte); - data_ = outFile.toByteArray(); - return true; - } catch (IOException e) { - } - } - return false; - } -} diff --git a/java/tests/detailed/handler/ContextMenuHandler.java b/java/tests/detailed/handler/ContextMenuHandler.java deleted file mode 100644 index c18c76b8..00000000 --- a/java/tests/detailed/handler/ContextMenuHandler.java +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.handler; - -import org.cef.browser.CefBrowser; -import org.cef.browser.CefFrame; -import org.cef.callback.CefContextMenuParams; -import org.cef.callback.CefMenuModel; -import org.cef.callback.CefMenuModel.MenuId; -import org.cef.handler.CefContextMenuHandler; - -import java.awt.Frame; -import java.util.HashMap; -import java.util.Map; -import java.util.Vector; - -import tests.detailed.dialog.SearchDialog; -import tests.detailed.dialog.ShowTextDialog; - -public class ContextMenuHandler implements CefContextMenuHandler { - private final Frame owner_; - private Map suggestions_ = new HashMap(); - - public ContextMenuHandler(Frame owner) { - owner_ = owner; - } - - @Override - public void onBeforeContextMenu( - CefBrowser browser, CefFrame frame, CefContextMenuParams params, CefMenuModel model) { - model.clear(); - - // Navigation menu - model.addItem(MenuId.MENU_ID_BACK, "Back"); - model.setEnabled(MenuId.MENU_ID_BACK, browser.canGoBack()); - - model.addItem(MenuId.MENU_ID_FORWARD, "Forward"); - model.setEnabled(MenuId.MENU_ID_FORWARD, browser.canGoForward()); - - model.addSeparator(); - model.addItem(MenuId.MENU_ID_FIND, "Find..."); - if (params.hasImageContents() && params.getSourceUrl() != null) - model.addItem(MenuId.MENU_ID_USER_FIRST, "Download Image..."); - model.addItem(MenuId.MENU_ID_VIEW_SOURCE, "View Source..."); - - Vector suggestions = new Vector(); - params.getDictionarySuggestions(suggestions); - - // Spell checking menu - model.addSeparator(); - if (suggestions.size() == 0) { - model.addItem(MenuId.MENU_ID_NO_SPELLING_SUGGESTIONS, "No suggestions"); - model.setEnabled(MenuId.MENU_ID_NO_SPELLING_SUGGESTIONS, false); - return; - } - - int id = MenuId.MENU_ID_SPELLCHECK_SUGGESTION_0; - for (String suggestedWord : suggestions) { - model.addItem(id, suggestedWord); - suggestions_.put(id, suggestedWord); - if (++id > MenuId.MENU_ID_SPELLCHECK_SUGGESTION_LAST) break; - } - } - - @Override - public boolean onContextMenuCommand(CefBrowser browser, CefFrame frame, - CefContextMenuParams params, int commandId, int eventFlags) { - switch (commandId) { - case MenuId.MENU_ID_VIEW_SOURCE: - ShowTextDialog visitor = - new ShowTextDialog(owner_, "Source of \"" + browser.getURL() + "\""); - browser.getSource(visitor); - return true; - case MenuId.MENU_ID_FIND: - SearchDialog search = new SearchDialog(owner_, browser); - search.setVisible(true); - return true; - case MenuId.MENU_ID_USER_FIRST: - browser.startDownload(params.getSourceUrl()); - return true; - default: - if (commandId >= MenuId.MENU_ID_SPELLCHECK_SUGGESTION_0) { - String newWord = suggestions_.get(commandId); - if (newWord != null) { - System.err.println( - "replacing " + params.getMisspelledWord() + " with " + newWord); - browser.replaceMisspelling(newWord); - return true; - } - } - return false; - } - } - - @Override - public void onContextMenuDismissed(CefBrowser browser, CefFrame frame) { - suggestions_.clear(); - } -} diff --git a/java/tests/detailed/handler/DragHandler.java b/java/tests/detailed/handler/DragHandler.java deleted file mode 100644 index ee7d36aa..00000000 --- a/java/tests/detailed/handler/DragHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.handler; - -import org.cef.browser.CefBrowser; -import org.cef.callback.CefDragData; -import org.cef.handler.CefDragHandler; - -public class DragHandler implements CefDragHandler { - @Override - public boolean onDragEnter(CefBrowser browser, CefDragData dragData, int mask) { - System.out.println("DRAG:"); - System.out.print(" flags:"); - if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_COPY) != 0) - System.out.print(" COPY"); - if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_LINK) != 0) - System.out.print(" LINK"); - if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_GENERIC) != 0) - System.out.print(" GENERIC"); - if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_PRIVATE) != 0) - System.out.print(" PRIVATE"); - if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_MOVE) != 0) - System.out.print(" MOVE"); - if ((mask & CefDragHandler.DragOperationMask.DRAG_OPERATION_DELETE) != 0) - System.out.print(" DELETE"); - System.out.println("\n " + dragData); - return false; - } -} diff --git a/java/tests/detailed/handler/JSDialogHandler.java b/java/tests/detailed/handler/JSDialogHandler.java deleted file mode 100644 index 417a55fb..00000000 --- a/java/tests/detailed/handler/JSDialogHandler.java +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.handler; - -import org.cef.browser.CefBrowser; -import org.cef.callback.CefJSDialogCallback; -import org.cef.handler.CefJSDialogHandlerAdapter; -import org.cef.misc.BoolRef; - -public class JSDialogHandler extends CefJSDialogHandlerAdapter { - @Override - public boolean onJSDialog(CefBrowser browser, String origin_url, JSDialogType dialog_type, - String message_text, String default_prompt_text, CefJSDialogCallback callback, - BoolRef suppress_message) { - if (message_text.equalsIgnoreCase("Never displayed")) { - suppress_message.set(true); - System.out.println( - "The " + dialog_type + " from origin \"" + origin_url + "\" was suppressed."); - System.out.println( - " The content of the suppressed dialog was: \"" + message_text + "\""); - } - return false; - } -} diff --git a/java/tests/detailed/handler/KeyboardHandler.java b/java/tests/detailed/handler/KeyboardHandler.java deleted file mode 100644 index 6785b550..00000000 --- a/java/tests/detailed/handler/KeyboardHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.handler; - -import org.cef.browser.CefBrowser; -import org.cef.handler.CefKeyboardHandlerAdapter; - -public class KeyboardHandler extends CefKeyboardHandlerAdapter { - @Override - public boolean onKeyEvent(CefBrowser browser, CefKeyEvent event) { - if (!event.focus_on_editable_field && event.windows_key_code == 0x20) { - // Special handling for the space character when an input element does not - // have focus. Handling the event in OnPreKeyEvent() keeps the event from - // being processed in the renderer. If we instead handled the event in the - // OnKeyEvent() method the space key would cause the window to scroll in - // addition to showing the alert box. - if (event.type == CefKeyEvent.EventType.KEYEVENT_RAWKEYDOWN) { - browser.executeJavaScript("alert('You pressed the space bar!');", "", 0); - } - return true; - } else if (event.type == CefKeyEvent.EventType.KEYEVENT_RAWKEYDOWN && event.is_system_key) { - // CMD+[key] is not working on a Mac. - // This switch statement delegates the common keyboard shortcuts to the browser - switch (event.unmodified_character) { - case 'a': - browser.getFocusedFrame().selectAll(); - break; - case 'c': - browser.getFocusedFrame().copy(); - break; - case 'v': - browser.getFocusedFrame().paste(); - break; - case 'x': - browser.getFocusedFrame().cut(); - break; - case 'z': - browser.getFocusedFrame().undo(); - break; - case 'Z': - browser.getFocusedFrame().redo(); - break; - default: - return false; - } - return true; - } - return false; - } -} diff --git a/java/tests/detailed/handler/MessageRouterHandler.java b/java/tests/detailed/handler/MessageRouterHandler.java deleted file mode 100644 index 1d37c85a..00000000 --- a/java/tests/detailed/handler/MessageRouterHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.handler; - -import org.cef.browser.CefBrowser; -import org.cef.browser.CefFrame; -import org.cef.callback.CefQueryCallback; -import org.cef.handler.CefMessageRouterHandlerAdapter; - -public class MessageRouterHandler extends CefMessageRouterHandlerAdapter { - @Override - public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String request, - boolean persistent, CefQueryCallback callback) { - if (request.indexOf("BindingTest:") == 0) { - // Reverse the message and return it to the JavaScript caller. - String msg = request.substring(12); - callback.success(new StringBuilder(msg).reverse().toString()); - return true; - } - // Not handled. - return false; - } -} diff --git a/java/tests/detailed/handler/MessageRouterHandlerEx.java b/java/tests/detailed/handler/MessageRouterHandlerEx.java deleted file mode 100644 index bc4b780b..00000000 --- a/java/tests/detailed/handler/MessageRouterHandlerEx.java +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.handler; - -import org.cef.CefClient; -import org.cef.browser.CefBrowser; -import org.cef.browser.CefFrame; -import org.cef.browser.CefMessageRouter; -import org.cef.browser.CefMessageRouter.CefMessageRouterConfig; -import org.cef.callback.CefQueryCallback; -import org.cef.handler.CefMessageRouterHandlerAdapter; - -public class MessageRouterHandlerEx extends CefMessageRouterHandlerAdapter { - private final CefClient client_; - private final CefMessageRouterConfig config_ = - new CefMessageRouterConfig("myQuery", "myQueryAbort"); - private CefMessageRouter router_ = null; - - public MessageRouterHandlerEx(final CefClient client) { - client_ = client; - } - - @Override - public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String request, - boolean persistent, CefQueryCallback callback) { - if (request.startsWith("hasExtension")) { - if (router_ != null) - callback.success(""); - else - callback.failure(0, ""); - } else if (request.startsWith("enableExt")) { - if (router_ != null) { - callback.failure(-1, "Already enabled"); - } else { - router_ = CefMessageRouter.create(config_, new JavaVersionMessageRouter()); - client_.addMessageRouter(router_); - callback.success(""); - } - } else if (request.startsWith("disableExt")) { - if (router_ == null) { - callback.failure(-2, "Already disabled"); - } else { - client_.removeMessageRouter(router_); - router_.dispose(); - router_ = null; - callback.success(""); - } - } else { - // not handled - return false; - } - return true; - } - - private class JavaVersionMessageRouter extends CefMessageRouterHandlerAdapter { - @Override - public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String request, - boolean persistent, CefQueryCallback callback) { - if (request.startsWith("jcefJava")) { - callback.success(System.getProperty("java.version")); - return true; - } - return false; - }; - } -} diff --git a/java/tests/detailed/handler/RequestHandler.java b/java/tests/detailed/handler/RequestHandler.java deleted file mode 100644 index d80e1251..00000000 --- a/java/tests/detailed/handler/RequestHandler.java +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.handler; - -import org.cef.browser.CefBrowser; -import org.cef.browser.CefFrame; -import org.cef.callback.CefAuthCallback; -import org.cef.callback.CefCallback; -import org.cef.handler.CefLoadHandler.ErrorCode; -import org.cef.handler.CefRequestHandler; -import org.cef.handler.CefResourceHandler; -import org.cef.handler.CefResourceRequestHandler; -import org.cef.handler.CefResourceRequestHandlerAdapter; -import org.cef.misc.BoolRef; -import org.cef.network.CefPostData; -import org.cef.network.CefPostDataElement; -import org.cef.network.CefRequest; - -import java.awt.Frame; -import java.util.HashMap; -import java.util.Vector; - -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; - -import tests.detailed.dialog.CertErrorDialog; -import tests.detailed.dialog.PasswordDialog; - -public class RequestHandler extends CefResourceRequestHandlerAdapter implements CefRequestHandler { - private final Frame owner_; - - public RequestHandler(Frame owner) { - owner_ = owner; - } - - @Override - public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, - boolean user_gesture, boolean is_redirect) { - CefPostData postData = request.getPostData(); - if (postData != null) { - Vector elements = new Vector(); - postData.getElements(elements); - for (CefPostDataElement el : elements) { - int numBytes = el.getBytesCount(); - if (numBytes <= 0) continue; - - byte[] readBytes = new byte[numBytes]; - if (el.getBytes(numBytes, readBytes) <= 0) continue; - - String readString = new String(readBytes); - if (readString.indexOf("ignore") > -1) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JOptionPane.showMessageDialog(owner_, - "The request was rejected because you've entered \"ignore\" into the form."); - } - }); - return true; - } - } - } - return false; - } - - @Override - public boolean onOpenURLFromTab( - CefBrowser browser, CefFrame frame, String target_url, boolean user_gesture) { - return false; - } - - @Override - public CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame, - CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator, - BoolRef disableDefaultHandling) { - return this; - } - - @Override - public boolean onBeforeResourceLoad(CefBrowser browser, CefFrame frame, CefRequest request) { - // If you send a HTTP-POST request to http://www.google.com/ - // google rejects your request because they don't allow HTTP-POST. - // - // This test extracts the value of the test form. - // (see "Show Form" entry within BrowserMenuBar) - // and sends its value as HTTP-GET request to Google. - if (request.getMethod().equalsIgnoreCase("POST") - && request.getURL().equals("http://www.google.com/")) { - String forwardTo = "http://www.google.com/#q="; - CefPostData postData = request.getPostData(); - boolean sendAsGet = false; - if (postData != null) { - Vector elements = new Vector(); - postData.getElements(elements); - for (CefPostDataElement el : elements) { - int numBytes = el.getBytesCount(); - if (numBytes <= 0) continue; - - byte[] readBytes = new byte[numBytes]; - if (el.getBytes(numBytes, readBytes) <= 0) continue; - - String readString = new String(readBytes).trim(); - String[] stringPairs = readString.split("&"); - for (String s : stringPairs) { - int startPos = s.indexOf('='); - if (s.startsWith("searchFor")) - forwardTo += s.substring(startPos + 1); - else if (s.startsWith("sendAsGet")) { - sendAsGet = true; - } - } - } - if (sendAsGet) postData.removeElements(); - } - if (sendAsGet) { - request.setFlags(0); - request.setMethod("GET"); - request.setURL(forwardTo); - request.setFirstPartyForCookies(forwardTo); - HashMap headerMap = new HashMap<>(); - request.getHeaderMap(headerMap); - headerMap.remove("Content-Type"); - headerMap.remove("Origin"); - request.setHeaderMap(headerMap); - } - } - return false; - } - - @Override - public CefResourceHandler getResourceHandler( - CefBrowser browser, CefFrame frame, CefRequest request) { - // the non existing domain "foo.bar" is handled by the ResourceHandler implementation - // E.g. if you try to load the URL http://www.foo.bar, you'll be forwarded - // to the ResourceHandler class. - if (request.getURL().endsWith("foo.bar/")) { - return new ResourceHandler(); - } - - if (request.getURL().endsWith("seterror.test/")) { - return new ResourceSetErrorHandler(); - } - - return null; - } - - @Override - public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy, - String host, int port, String realm, String scheme, CefAuthCallback callback) { - SwingUtilities.invokeLater(new PasswordDialog(owner_, callback)); - return true; - } - - @Override - public boolean onCertificateError( - CefBrowser browser, ErrorCode cert_error, String request_url, CefCallback callback) { - SwingUtilities.invokeLater(new CertErrorDialog(owner_, cert_error, request_url, callback)); - return true; - } - - @Override - public void onRenderProcessTerminated(CefBrowser browser, TerminationStatus status) { - System.out.println("render process terminated: " + status); - } -} diff --git a/java/tests/detailed/handler/ResourceHandler.java b/java/tests/detailed/handler/ResourceHandler.java deleted file mode 100644 index 4a36e0ee..00000000 --- a/java/tests/detailed/handler/ResourceHandler.java +++ /dev/null @@ -1,72 +0,0 @@ -package tests.detailed.handler; - -import org.cef.callback.CefCallback; -import org.cef.handler.CefLoadHandler; -import org.cef.handler.CefResourceHandlerAdapter; -import org.cef.misc.IntRef; -import org.cef.misc.StringRef; -import org.cef.network.CefRequest; -import org.cef.network.CefResponse; - -import java.nio.ByteBuffer; - -public class ResourceHandler extends CefResourceHandlerAdapter { - private int startPos = 0; - private static final String html = new String("\n" - + " \n" - + " ResourceHandler Test\n" - + " \n" - + " \n" - + "

ResourceHandler Test

\n" - + "

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

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

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

JavaScript Binding Test - Part 2

-

While this page was loaded, the JavaScript function -

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

-

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

-Second message router: - - -
- -
- - - diff --git a/java/tests/detailed/handler/localstorage.html b/java/tests/detailed/handler/localstorage.html deleted file mode 100644 index 87c6e68c..00000000 --- a/java/tests/detailed/handler/localstorage.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Click the "Add Line" button to add a line or the "Clear" button to clear.
-This data will persist across sessions if a cache path was specified.
- - -
- - - diff --git a/java/tests/detailed/handler/logo.png b/java/tests/detailed/handler/logo.png deleted file mode 100644 index a2a15f44e979524eeadfbaaec1da49ba3bb9b478..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24025 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 diff --git a/java/tests/detailed/handler/spellcheck.html b/java/tests/detailed/handler/spellcheck.html deleted file mode 100644 index 6334135a..00000000 --- a/java/tests/detailed/handler/spellcheck.html +++ /dev/null @@ -1,14 +0,0 @@ - - -Spellcheck Test - - - -The next paragraph contains some text to be validated against the spell-checker. -
Click into the following box. To replace a misspelled word use the -right-mouse-click.
-

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

- - diff --git a/java/tests/detailed/handler/transparency.html b/java/tests/detailed/handler/transparency.html deleted file mode 100644 index a8dd3b46..00000000 --- a/java/tests/detailed/handler/transparency.html +++ /dev/null @@ -1,63 +0,0 @@ - - - -Transparency Examples - - - - -

Image Transparency

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

Block Transparency

-White 0% White 25% White 50% White 75% White 100% -
-Black 0% Black 25% Black 50% Black 75% Black 100% - - - diff --git a/java/tests/detailed/ui/ControlPanel.java b/java/tests/detailed/ui/ControlPanel.java deleted file mode 100644 index c3923dcc..00000000 --- a/java/tests/detailed/ui/ControlPanel.java +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.ui; - -import org.cef.OS; -import org.cef.browser.CefBrowser; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.net.URI; -import java.net.URISyntaxException; - -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; - -@SuppressWarnings("serial") -public class ControlPanel extends JPanel { - private final JButton backButton_; - private final JButton forwardButton_; - private final JButton reloadButton_; - private final JTextField address_field_; - private final JLabel zoom_label_; - private double zoomLevel_ = 0; - private final CefBrowser browser_; - - public ControlPanel(CefBrowser browser) { - assert browser != null; - browser_ = browser; - - setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); - - add(Box.createHorizontalStrut(5)); - add(Box.createHorizontalStrut(5)); - - backButton_ = new JButton("Back"); - backButton_.setFocusable(false); - backButton_.setAlignmentX(LEFT_ALIGNMENT); - backButton_.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.goBack(); - } - }); - add(backButton_); - add(Box.createHorizontalStrut(5)); - - forwardButton_ = new JButton("Forward"); - forwardButton_.setFocusable(false); - forwardButton_.setAlignmentX(LEFT_ALIGNMENT); - forwardButton_.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.goForward(); - } - }); - add(forwardButton_); - add(Box.createHorizontalStrut(5)); - - reloadButton_ = new JButton("Reload"); - reloadButton_.setFocusable(false); - reloadButton_.setAlignmentX(LEFT_ALIGNMENT); - reloadButton_.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (reloadButton_.getText().equalsIgnoreCase("reload")) { - int mask = OS.isMacintosh() ? ActionEvent.META_MASK : ActionEvent.CTRL_MASK; - if ((e.getModifiers() & mask) != 0) { - System.out.println("Reloading - ignoring cached values"); - browser_.reloadIgnoreCache(); - } else { - System.out.println("Reloading - using cached values"); - browser_.reload(); - } - } else { - browser_.stopLoad(); - } - } - }); - add(reloadButton_); - add(Box.createHorizontalStrut(5)); - - JLabel addressLabel = new JLabel("Address:"); - addressLabel.setAlignmentX(LEFT_ALIGNMENT); - add(addressLabel); - add(Box.createHorizontalStrut(5)); - - address_field_ = new JTextField(100); - address_field_.setAlignmentX(LEFT_ALIGNMENT); - address_field_.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.loadURL(getAddress()); - } - }); - add(address_field_); - add(Box.createHorizontalStrut(5)); - - JButton goButton = new JButton("Go"); - goButton.setFocusable(false); - goButton.setAlignmentX(LEFT_ALIGNMENT); - goButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.loadURL(getAddress()); - } - }); - add(goButton); - add(Box.createHorizontalStrut(5)); - - JButton minusButton = new JButton("-"); - minusButton.setFocusable(false); - minusButton.setAlignmentX(CENTER_ALIGNMENT); - minusButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.setZoomLevel(--zoomLevel_); - zoom_label_.setText(new Double(zoomLevel_).toString()); - } - }); - add(minusButton); - - zoom_label_ = new JLabel("0.0"); - add(zoom_label_); - - JButton plusButton = new JButton("+"); - plusButton.setFocusable(false); - plusButton.setAlignmentX(CENTER_ALIGNMENT); - plusButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.setZoomLevel(++zoomLevel_); - zoom_label_.setText(new Double(zoomLevel_).toString()); - } - }); - add(plusButton); - } - - public void update( - CefBrowser browser, boolean isLoading, boolean canGoBack, boolean canGoForward) { - if (browser == browser_) { - backButton_.setEnabled(canGoBack); - forwardButton_.setEnabled(canGoForward); - reloadButton_.setText(isLoading ? "Abort" : "Reload"); - } - } - - public String getAddress() { - String address = address_field_.getText(); - // If the URI format is unknown "new URI" will throw an - // exception. In this case we interpret the value of the - // address field as search request. Therefore we simply add - // the "search" scheme. - try { - address = address.replaceAll(" ", "%20"); - URI test = new URI(address); - if (test.getScheme() != null) return address; - if (test.getHost() != null && test.getPath() != null) return address; - String specific = test.getSchemeSpecificPart(); - if (specific.indexOf('.') == -1) - throw new URISyntaxException(specific, "No dot inside domain"); - } catch (URISyntaxException e1) { - address = "search://" + address; - } - return address; - } - - public void setAddress(CefBrowser browser, String address) { - if (browser == browser_) address_field_.setText(address); - } - - public JTextField getAddressField() { - return address_field_; - } -} diff --git a/java/tests/detailed/ui/MenuBar.java b/java/tests/detailed/ui/MenuBar.java deleted file mode 100644 index 2734d525..00000000 --- a/java/tests/detailed/ui/MenuBar.java +++ /dev/null @@ -1,602 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.ui; - -import org.cef.OS; -import org.cef.browser.CefBrowser; -import org.cef.browser.CefDevToolsClient; -import org.cef.callback.CefPdfPrintCallback; -import org.cef.callback.CefRunFileDialogCallback; -import org.cef.callback.CefStringVisitor; -import org.cef.handler.CefDialogHandler.FileDialogMode; -import org.cef.misc.CefPdfPrintSettings; -import org.cef.network.CefCookieManager; -import org.cef.network.CefRequest; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.WindowEvent; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.util.Vector; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JRootPane; -import javax.swing.SwingUtilities; - -import tests.detailed.BrowserFrame; -import tests.detailed.MainFrame; -import tests.detailed.dialog.CookieManagerDialog; -import tests.detailed.dialog.DevToolsDialog; -import tests.detailed.dialog.DownloadDialog; -import tests.detailed.dialog.SearchDialog; -import tests.detailed.dialog.ShowTextDialog; -import tests.detailed.dialog.UrlRequestDialog; -import tests.detailed.util.DataUri; - -@SuppressWarnings("serial") -public class MenuBar extends JMenuBar { - class SaveAs implements CefStringVisitor { - private PrintWriter fileWriter_; - - public SaveAs(String fName) throws FileNotFoundException, UnsupportedEncodingException { - fileWriter_ = new PrintWriter(fName, "UTF-8"); - } - - @Override - public void visit(String string) { - fileWriter_.write(string); - fileWriter_.close(); - } - } - - private final MainFrame owner_; - private final CefBrowser browser_; - private String last_selected_file_ = ""; - private final JMenu bookmarkMenu_; - private final ControlPanel control_pane_; - private final DownloadDialog downloadDialog_; - private final CefCookieManager cookieManager_; - private boolean reparentPending_ = false; - private CefDevToolsClient devToolsClient_; - - public MenuBar(MainFrame owner, CefBrowser browser, ControlPanel control_pane, - DownloadDialog downloadDialog, CefCookieManager cookieManager) { - owner_ = owner; - browser_ = browser; - control_pane_ = control_pane; - downloadDialog_ = downloadDialog; - cookieManager_ = cookieManager; - - setEnabled(browser_ != null); - - JMenu fileMenu = new JMenu("File"); - - JMenuItem openFileItem = new JMenuItem("Open file..."); - openFileItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent arg0) { - JFileChooser fc = new JFileChooser(new File(last_selected_file_)); - // Show open dialog; this method does not return until the dialog is closed. - fc.showOpenDialog(owner_); - File selectedFile = fc.getSelectedFile(); - if (selectedFile != null) { - last_selected_file_ = selectedFile.getAbsolutePath(); - browser_.loadURL("file:///" + selectedFile.getAbsolutePath()); - } - } - }); - fileMenu.add(openFileItem); - - JMenuItem openFileDialog = new JMenuItem("Save as..."); - openFileDialog.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - CefRunFileDialogCallback callback = new CefRunFileDialogCallback() { - @Override - public void onFileDialogDismissed(Vector filePaths) { - if (!filePaths.isEmpty()) { - try { - SaveAs saveContent = new SaveAs(filePaths.get(0)); - browser_.getSource(saveContent); - } catch (FileNotFoundException | UnsupportedEncodingException e) { - browser_.executeJavaScript("alert(\"Can't save file\");", - control_pane_.getAddress(), 0); - } - } - } - }; - browser_.runFileDialog(FileDialogMode.FILE_DIALOG_SAVE, owner_.getTitle(), - "index.html", null, 0, callback); - } - }); - fileMenu.add(openFileDialog); - - JMenuItem printItem = new JMenuItem("Print..."); - printItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.print(); - } - }); - fileMenu.add(printItem); - - JMenuItem printToPdfItem = new JMenuItem("Print to PDF"); - printToPdfItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JFileChooser fc = new JFileChooser(); - fc.showSaveDialog(owner_); - File selectedFile = fc.getSelectedFile(); - if (selectedFile != null) { - CefPdfPrintSettings pdfSettings = new CefPdfPrintSettings(); - pdfSettings.display_header_footer = true; - // letter page size - pdfSettings.paper_width = 8.5; - pdfSettings.paper_height = 11; - browser.printToPDF( - selectedFile.getAbsolutePath(), pdfSettings, new CefPdfPrintCallback() { - @Override - public void onPdfPrintFinished(String path, boolean ok) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (ok) { - JOptionPane.showMessageDialog(owner_, - "PDF saved to " + path, "Success", - JOptionPane.INFORMATION_MESSAGE); - } else { - JOptionPane.showMessageDialog(owner_, "PDF failed", - "Failed", JOptionPane.ERROR_MESSAGE); - } - } - }); - } - }); - } - } - }); - fileMenu.add(printToPdfItem); - - JMenuItem searchItem = new JMenuItem("Search..."); - searchItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - new SearchDialog(owner_, browser_).setVisible(true); - } - }); - fileMenu.add(searchItem); - - fileMenu.addSeparator(); - - JMenuItem viewSource = new JMenuItem("View source"); - viewSource.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.viewSource(); - } - }); - fileMenu.add(viewSource); - - JMenuItem getSource = new JMenuItem("Get source..."); - getSource.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - ShowTextDialog visitor = new ShowTextDialog( - owner_, "Source of \"" + control_pane_.getAddress() + "\""); - browser_.getSource(visitor); - } - }); - fileMenu.add(getSource); - - JMenuItem getText = new JMenuItem("Get text..."); - getText.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - ShowTextDialog visitor = new ShowTextDialog( - owner_, "Content of \"" + control_pane_.getAddress() + "\""); - browser_.getText(visitor); - } - }); - fileMenu.add(getText); - - fileMenu.addSeparator(); - - JMenuItem showDownloads = new JMenuItem("Show Downloads"); - showDownloads.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - downloadDialog_.setVisible(true); - } - }); - fileMenu.add(showDownloads); - - JMenuItem showCookies = new JMenuItem("Show Cookies"); - showCookies.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - CookieManagerDialog cookieManager = - new CookieManagerDialog(owner_, "Cookie Manager", cookieManager_); - cookieManager.setVisible(true); - } - }); - fileMenu.add(showCookies); - - fileMenu.addSeparator(); - - JMenuItem exitItem = new JMenuItem("Exit"); - exitItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - owner_.dispatchEvent(new WindowEvent(owner_, WindowEvent.WINDOW_CLOSING)); - } - }); - fileMenu.add(exitItem); - - bookmarkMenu_ = new JMenu("Bookmarks"); - - JMenuItem addBookmarkItem = new JMenuItem("Add bookmark"); - addBookmarkItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - addBookmark(owner_.getTitle(), control_pane_.getAddress()); - } - }); - bookmarkMenu_.add(addBookmarkItem); - bookmarkMenu_.addSeparator(); - - JMenu testMenu = new JMenu("Tests"); - - JMenuItem testJSItem = new JMenuItem("JavaScript alert"); - testJSItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.executeJavaScript("alert('Hello World');", control_pane_.getAddress(), 1); - } - }); - testMenu.add(testJSItem); - - JMenuItem jsAlertItem = new JMenuItem("JavaScript alert (will be suppressed)"); - jsAlertItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.executeJavaScript("alert('Never displayed');", "http://dontshow.me", 1); - } - }); - testMenu.add(jsAlertItem); - - JMenuItem testShowText = new JMenuItem("Show Text"); - testShowText.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.loadURL(DataUri.create( - "text/html", "

Hello World

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

RequestHandler test

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

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

"; - form += "

Testcase 1

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

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

"; - form += "

Testcase 2

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

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

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

Browser status

"; - info += ""; - info += ""; - info += ""; - info += ""; - info += ""; - info += ""; - info += ""; - info += "
CanGoBack" + browser_.canGoBack() + "
CanGoForward" + browser_.canGoForward() + "
IsLoading" + browser_.isLoading() + "
isPopup" + browser_.isPopup() + "
hasDocument" + browser_.hasDocument() + "
Url" + browser_.getURL() + "
Zoom-Level" + browser_.getZoomLevel() + "
"; - String js = "var x=window.open(); x.document.open(); x.document.write('" + info - + "'); x.document.close();"; - browser_.executeJavaScript(js, "", 0); - } - }); - testMenu.add(showInfo); - - final JMenuItem showDevTools = new JMenuItem("Show DevTools"); - showDevTools.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - DevToolsDialog devToolsDlg = new DevToolsDialog(owner_, "DEV Tools", browser_); - devToolsDlg.addComponentListener(new ComponentAdapter() { - @Override - public void componentHidden(ComponentEvent e) { - showDevTools.setEnabled(true); - } - }); - devToolsDlg.setVisible(true); - showDevTools.setEnabled(false); - } - }); - testMenu.add(showDevTools); - - JMenu devToolsProtocolMenu = new JMenu("DevTools Protocol"); - JMenuItem autoDarkMode = devToolsProtocolMenu.add(new JCheckBoxMenuItem("Auto Dark Mode")); - autoDarkMode.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - // Toggle the auto dark mode override - String params = String.format("{ \"enabled\": %s }", autoDarkMode.isSelected()); - executeDevToolsMethod("Emulation.setAutoDarkModeOverride", params); - } - }); - JMenuItem checkContrast = devToolsProtocolMenu.add(new JMenuItem("Check Contrast")); - checkContrast.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - // Check contrast, which usually triggers a series of Audits.issueAdded events - executeDevToolsMethod("Audits.checkContrast"); - } - }); - JMenuItem enableCSS = devToolsProtocolMenu.add(new JMenuItem("Enable CSS Agent")); - enableCSS.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - // Enable the CSS agent, which usually triggers a series of CSS.styleSheetAdded - // events. We can only enable the CSS agent if the DOM agent is enabled first, so we - // need to chain the two commands. - executeDevToolsMethod("DOM.enable") - .thenCompose(unused -> executeDevToolsMethod("CSS.enable")); - } - }); - testMenu.add(devToolsProtocolMenu); - - JMenuItem testURLRequest = new JMenuItem("URL Request"); - testURLRequest.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - UrlRequestDialog dlg = new UrlRequestDialog(owner_, "URL Request Test"); - dlg.setVisible(true); - } - }); - testMenu.add(testURLRequest); - - JMenuItem reparent = new JMenuItem("Reparent"); - reparent.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - final BrowserFrame newFrame = new BrowserFrame("New Window"); - newFrame.setLayout(new BorderLayout()); - final JButton reparentButton = new JButton("Reparent <"); - reparentButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (reparentPending_) return; - reparentPending_ = true; - - if (reparentButton.getText().equals("Reparent <")) { - owner_.removeBrowser(new Runnable() { - public void run() { - newFrame.setBrowser(browser_); - reparentButton.setText("Reparent >"); - reparentPending_ = false; - } - }); - } else { - newFrame.removeBrowser(new Runnable() { - public void run() { - JRootPane rootPane = (JRootPane) owner_.getComponent(0); - Container container = rootPane.getContentPane(); - JPanel panel = (JPanel) container.getComponent(0); - owner_.setBrowser(browser_); - owner_.revalidate(); - reparentButton.setText("Reparent <"); - reparentPending_ = false; - } - }); - } - } - }); - newFrame.add(reparentButton, BorderLayout.NORTH); - newFrame.setSize(400, 400); - newFrame.setVisible(true); - } - }); - testMenu.add(reparent); - - JMenuItem newwindow = new JMenuItem("New window"); - newwindow.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - final MainFrame frame = new MainFrame(OS.isLinux(), false, false, 0, null); - frame.setSize(800, 600); - frame.setVisible(true); - } - }); - testMenu.add(newwindow); - - JMenuItem screenshotSync = new JMenuItem("Screenshot (on AWT thread, native res)"); - screenshotSync.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - long start = System.nanoTime(); - CompletableFuture shot = browser.createScreenshot(true); - System.out.println("Took screenshot from the AWT event thread in " - + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " msecs"); - try { - displayScreenshot(shot.get()); - } catch (InterruptedException | ExecutionException exc) { - // cannot happen, future is already resolved in this case - } - } - }); - screenshotSync.setEnabled(owner.isOsrEnabled()); - testMenu.add(screenshotSync); - - JMenuItem screenshotSyncScaled = new JMenuItem("Screenshot (on AWT thread, scaled)"); - screenshotSyncScaled.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - long start = System.nanoTime(); - CompletableFuture shot = browser.createScreenshot(false); - System.out.println("Took screenshot from the AWT event thread in " - + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " msecs"); - try { - displayScreenshot(shot.get()); - } catch (InterruptedException | ExecutionException exc) { - // cannot happen, future is already resolved in this case - } - } - }); - screenshotSyncScaled.setEnabled(owner.isOsrEnabled()); - testMenu.add(screenshotSyncScaled); - - JMenuItem screenshotAsync = new JMenuItem("Screenshot (from other thread, scaled)"); - screenshotAsync.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - long start = System.nanoTime(); - CompletableFuture shot = browser.createScreenshot(false); - shot.thenAccept((image) -> { - System.out.println("Took screenshot asynchronously in " - + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " msecs"); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - displayScreenshot(image); - } - }); - }); - } - }); - screenshotAsync.setEnabled(owner.isOsrEnabled()); - testMenu.add(screenshotAsync); - - add(fileMenu); - add(bookmarkMenu_); - add(testMenu); - } - - public void addBookmark(String name, String URL) { - if (bookmarkMenu_ == null) return; - - // Test if the bookmark already exists. If yes, update URL - Component[] entries = bookmarkMenu_.getMenuComponents(); - for (Component itemEntry : entries) { - if (!(itemEntry instanceof JMenuItem)) continue; - - JMenuItem item = (JMenuItem) itemEntry; - if (item.getText().equals(name)) { - item.setActionCommand(URL); - return; - } - } - - JMenuItem menuItem = new JMenuItem(name); - menuItem.setActionCommand(URL); - menuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.loadURL(e.getActionCommand()); - } - }); - bookmarkMenu_.add(menuItem); - validate(); - } - - private void displayScreenshot(BufferedImage aScreenshot) { - JFrame frame = new JFrame("Screenshot"); - ImageIcon image = new ImageIcon(); - image.setImage(aScreenshot); - frame.setLayout(new FlowLayout()); - JLabel label = new JLabel(image); - label.setPreferredSize(new Dimension(aScreenshot.getWidth(), aScreenshot.getHeight())); - frame.add(label); - frame.setVisible(true); - frame.pack(); - } - - private CompletableFuture executeDevToolsMethod(String methodName) { - return executeDevToolsMethod(methodName, null); - } - - private CompletableFuture executeDevToolsMethod( - String methodName, String paramsAsJson) { - if (devToolsClient_ == null) { - devToolsClient_ = browser_.getDevToolsClient(); - devToolsClient_.addEventListener( - (method, json) -> System.out.println("CDP event " + method + ": " + json)); - } - - return devToolsClient_.executeDevToolsMethod(methodName, paramsAsJson) - .handle((error, json) -> { - System.out.println( - "CDP result of " + methodName + ": " + (error != null ? error : json)); - return null; - }); - } - - public void addBookmarkSeparator() { - bookmarkMenu_.addSeparator(); - } -} diff --git a/java/tests/detailed/ui/StatusPanel.java b/java/tests/detailed/ui/StatusPanel.java deleted file mode 100644 index 6f9026ed..00000000 --- a/java/tests/detailed/ui/StatusPanel.java +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.ui; - -import java.awt.Dimension; - -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JProgressBar; - -@SuppressWarnings("serial") -public class StatusPanel extends JPanel { - private final JProgressBar progressBar_; - private final JLabel status_field_; - - public StatusPanel() { - setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); - - add(Box.createHorizontalStrut(5)); - add(Box.createHorizontalStrut(5)); - - progressBar_ = new JProgressBar(); - Dimension progressBarSize = progressBar_.getMaximumSize(); - progressBarSize.width = 100; - progressBar_.setMinimumSize(progressBarSize); - progressBar_.setMaximumSize(progressBarSize); - add(progressBar_); - add(Box.createHorizontalStrut(5)); - - status_field_ = new JLabel("Info"); - status_field_.setAlignmentX(LEFT_ALIGNMENT); - add(status_field_); - add(Box.createHorizontalStrut(5)); - add(Box.createVerticalStrut(21)); - } - - public void setIsInProgress(boolean inProgress) { - progressBar_.setIndeterminate(inProgress); - } - - public void setStatusText(String text) { - status_field_.setText(text); - } -} diff --git a/java/tests/detailed/util/DataUri.java b/java/tests/detailed/util/DataUri.java deleted file mode 100644 index 895ad858..00000000 --- a/java/tests/detailed/util/DataUri.java +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.util; - -/** - * Utility class for creating data: URIs that can be passed to CefBrowser.loadURL. - */ -public class DataUri { - public static String create(String mimeType, String contents) { - return "data:" + mimeType + ";base64," - + java.util.Base64.getEncoder().encodeToString(contents.getBytes()); - } -}; diff --git a/java/tests/junittests/DisplayHandlerTest.java b/java/tests/junittests/DisplayHandlerTest.java deleted file mode 100644 index 81b873af..00000000 --- a/java/tests/junittests/DisplayHandlerTest.java +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.junittests; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.cef.browser.CefBrowser; -import org.cef.browser.CefFrame; -import org.cef.handler.CefDisplayHandlerAdapter; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -// Test the DisplayHandler implementation. -@ExtendWith(TestSetupExtension.class) -class DisplayHandlerTest { - private final String testUrl_ = "http://test.com/test.html"; - private final String testContent_ = - "Test TitleTest!"; - - private boolean gotCallback_ = false; - - @Test - void onTitleChange() { - TestFrame frame = new TestFrame() { - @Override - protected void setupTest() { - client_.addDisplayHandler(new CefDisplayHandlerAdapter() { - @Override - public void onTitleChange(CefBrowser browser, String title) { - assertFalse(gotCallback_); - gotCallback_ = true; - assertEquals("Test Title", title); - terminateTest(); - } - }); - - addResource(testUrl_, testContent_, "text/html"); - - createBrowser(testUrl_); - - super.setupTest(); - } - }; - - frame.awaitCompletion(); - - assertTrue(gotCallback_); - } - - @Test - void onAddressChange() { - TestFrame frame = new TestFrame() { - @Override - protected void setupTest() { - client_.addDisplayHandler(new CefDisplayHandlerAdapter() { - @Override - public void onAddressChange(CefBrowser browser, CefFrame frame, String url) { - assertFalse(gotCallback_); - gotCallback_ = true; - assertEquals(url, testUrl_); - terminateTest(); - } - }); - - addResource(testUrl_, testContent_, "text/html"); - - createBrowser(testUrl_); - - super.setupTest(); - } - }; - - frame.awaitCompletion(); - - assertTrue(gotCallback_); - } -} diff --git a/java/tests/junittests/DragDataTest.java b/java/tests/junittests/DragDataTest.java deleted file mode 100644 index bd904309..00000000 --- a/java/tests/junittests/DragDataTest.java +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.junittests; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.cef.callback.CefDragData; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import java.util.Vector; - -// Test the TestFrame implementation. -@ExtendWith(TestSetupExtension.class) -class DragDataTest { - @Test - void createEmpty() { - CefDragData dragData = CefDragData.create(); - assertNotNull(dragData); - assertFalse(dragData.isReadOnly()); - - assertFalse(dragData.isLink()); - assertFalse(dragData.isFile()); - assertTrue(dragData.isFragment()); // Default state. - - assertEquals("", dragData.getLinkURL()); - assertEquals("", dragData.getLinkTitle()); - assertEquals("", dragData.getLinkMetadata()); - assertEquals("", dragData.getFragmentText()); - assertEquals("", dragData.getFragmentHtml()); - assertEquals("", dragData.getFragmentBaseURL()); - assertEquals(0, dragData.getFileContents(null)); - assertEquals("", dragData.getFileName()); - assertFalse(dragData.getFileNames(null)); - - // Explicit cleanup to avoid memory leaks. - dragData.dispose(); - } - - @Test - void createLink() { - CefDragData dragData = CefDragData.create(); - assertNotNull(dragData); - assertFalse(dragData.isReadOnly()); - - final String linkURL = "http://test.com/test.html"; - dragData.setLinkURL(linkURL); - assertEquals(linkURL, dragData.getLinkURL()); - - final String linkTitle = "Test Title"; - dragData.setLinkTitle(linkTitle); - assertEquals(linkTitle, dragData.getLinkTitle()); - - final String linkMetadata = "something"; - dragData.setLinkMetadata(linkMetadata); - assertEquals(linkMetadata, dragData.getLinkMetadata()); - - assertTrue(dragData.isLink()); - assertFalse(dragData.isFile()); - assertFalse(dragData.isFragment()); - - // Explicit cleanup to avoid memory leaks. - dragData.dispose(); - } - - @Test - void createFile() { - CefDragData dragData = CefDragData.create(); - assertNotNull(dragData); - assertFalse(dragData.isReadOnly()); - - final String path1 = "/path/to/file1.txt"; - final String path2 = "/path/to/file2.txt"; - - dragData.addFile(path1, "File 1"); - dragData.addFile(path2, "File 2"); - - Vector fileNames = new Vector<>(); - assertTrue(dragData.getFileNames(fileNames)); - - assertEquals(2, fileNames.size()); - assertEquals(path1, fileNames.get(0)); - assertEquals(path2, fileNames.get(1)); - - assertFalse(dragData.isLink()); - assertTrue(dragData.isFile()); - assertFalse(dragData.isFragment()); - - // Explicit cleanup to avoid memory leaks. - dragData.dispose(); - } - - @Test - void createFragment() { - CefDragData dragData = CefDragData.create(); - assertNotNull(dragData); - assertFalse(dragData.isReadOnly()); - - final String fragmentText = "something"; - dragData.setFragmentText(fragmentText); - assertEquals(fragmentText, dragData.getFragmentText()); - - final String fragmentHtml = "something"; - dragData.setFragmentHtml(fragmentHtml); - assertEquals(fragmentHtml, dragData.getFragmentHtml()); - - final String fragmentBaseURL = "http://test.com/test.html"; - dragData.setFragmentBaseURL(fragmentBaseURL); - assertEquals(fragmentBaseURL, dragData.getFragmentBaseURL()); - - assertFalse(dragData.isLink()); - assertFalse(dragData.isFile()); - assertTrue(dragData.isFragment()); - - // Explicit cleanup to avoid memory leaks. - dragData.dispose(); - } - - @Test - void cloneObject() { - CefDragData dragData = CefDragData.create(); - assertNotNull(dragData); - assertFalse(dragData.isReadOnly()); - - final String fragmentText = "something"; - final String fragmentBaseURL = "http://test.com/test.html"; - dragData.setFragmentText(fragmentText); - dragData.setFragmentBaseURL(fragmentBaseURL); - - CefDragData dragData2 = dragData.clone(); - assertFalse(dragData2.isReadOnly()); - assertEquals(fragmentText, dragData2.getFragmentText()); - assertEquals(fragmentBaseURL, dragData2.getFragmentBaseURL()); - - assertFalse(dragData2.isLink()); - assertFalse(dragData2.isFile()); - assertTrue(dragData2.isFragment()); - - // Explicit cleanup to avoid memory leaks. - dragData.dispose(); - dragData2.dispose(); - } - - @Test - void disposeObject() { - CefDragData dragData = CefDragData.create(); - assertNotNull(dragData); - assertFalse(dragData.isReadOnly()); - - final String fragmentText = "something"; - dragData.setFragmentText(fragmentText); - assertEquals(fragmentText, dragData.getFragmentText()); - - // Explicit cleanup to avoid memory leaks. - // After dispose() the Java object is no longer backed by a CEF object. - dragData.dispose(); - - assertEquals(null, dragData.getFragmentText()); - } -} diff --git a/java/tests/junittests/TestFrame.java b/java/tests/junittests/TestFrame.java deleted file mode 100644 index bdbc26a9..00000000 --- a/java/tests/junittests/TestFrame.java +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.junittests; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; - -import static tests.junittests.TestSetupContext.debugPrint; - -import org.cef.CefApp; -import org.cef.CefClient; -import org.cef.browser.CefBrowser; -import org.cef.browser.CefFrame; -import org.cef.callback.CefAuthCallback; -import org.cef.callback.CefCallback; -import org.cef.handler.CefCookieAccessFilter; -import org.cef.handler.CefLifeSpanHandler; -import org.cef.handler.CefLoadHandler; -import org.cef.handler.CefRequestHandler; -import org.cef.handler.CefResourceHandler; -import org.cef.handler.CefResourceRequestHandler; -import org.cef.misc.BoolRef; -import org.cef.misc.StringRef; -import org.cef.network.CefRequest; -import org.cef.network.CefRequest.TransitionType; -import org.cef.network.CefResponse; -import org.cef.network.CefURLRequest; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.util.HashMap; -import java.util.concurrent.CountDownLatch; - -import javax.swing.JFrame; - -// Base class for browsers that run tests. -class TestFrame extends JFrame implements CefLifeSpanHandler, CefLoadHandler, CefRequestHandler, - CefResourceRequestHandler { - private static final long serialVersionUID = -5570653778104813836L; - private boolean isClosed_ = false; - private CountDownLatch countdown_ = new CountDownLatch(1); - - // Resources that have been populated for the test. - private class ResourceContent { - String content; - String mimeType; - HashMap headerMap; - } - private HashMap resourceMap_ = null; - - protected final CefClient client_; - protected CefBrowser browser_ = null; - - TestFrame() { - client_ = CefApp.getInstance().createClient(); - assertNotNull(client_); - - // Browser window closing works as follows: - // 1. Sending WindowEvent.WINDOW_CLOSING calls WindowAdapter.windowClosing. - // 2. WindowAdapter.windowClosing calls CefBrowser.close(false). - // 3. CEF calls CefLifeSpanHandler.doClose() which calls CefBrowser.doClose() - // which returns true (canceling the close). - // 4. CefBrowser.doClose() triggers another call to WindowAdapter.windowClosing. - // 5. WindowAdapter.windowClosing calls CefBrowser.close(true). - // 6. For windowed browsers CEF destroys the native window handle. For OSR - // browsers CEF calls CefLifeSpanHandler.doClose() which calls - // CefBrowser.doClose() again which returns false (allowing the close). - // 7. CEF calls CefLifeSpanHandler.onBeforeClose and the browser is destroyed. - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - boolean isClosed = isClosed_; - - if (isClosed) { - // Cause browser.doClose() to return false so that OSR browsers - // can close. - browser_.setCloseAllowed(); - } - - // Results in another call to this method. - if (debugPrint()) - System.out.println("windowClosing CefBrowser.close(" + isClosed + ")"); - browser_.close(isClosed); - if (!isClosed_) { - isClosed_ = true; - } - if (isClosed) { - // Dispose after the 2nd call to this method. - if (debugPrint()) System.out.println("windowClosing Frame.dispose"); - dispose(); - } - } - }); - - client_.addLifeSpanHandler(this); - client_.addLoadHandler(this); - client_.addRequestHandler(this); - - setupTest(); - } - - protected void createBrowser(String startURL) { - assertNull(browser_); - browser_ = client_.createBrowser(startURL, false /* isTransparent */); - assertNotNull(browser_); - - pack(); - setSize(800, 600); - setVisible(true); - } - - // Override this method to perform test setup. - protected void setupTest() {} - - // Override this method to perform test cleanup. - protected void cleanupTest() { - if (debugPrint()) System.out.println("cleanupTest"); - client_.dispose(); - // Allow the test to complete. - countdown_.countDown(); - } - - // Call this method to terminate the test by dispatching a window close event. - protected final void terminateTest() { - if (debugPrint()) System.out.println("terminateTest"); - if (!isClosed_) { - dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING)); - } - } - - // Block until the test completes. - public final void awaitCompletion() { - try { - countdown_.await(); - } catch (InterruptedException e) { - } - if (debugPrint()) System.out.println("awaitCompletion returned"); - } - - protected void addResource(String url, String content, String mimeType) { - addResource(url, content, mimeType, null); - } - - // Add a resource that will be returned via getResourceHandler(). - protected void addResource( - String url, String content, String mimeType, HashMap headerMap) { - if (resourceMap_ == null) resourceMap_ = new HashMap<>(); - - assertNull(resourceMap_.get(url)); - - ResourceContent rc = new ResourceContent(); - rc.content = content; - rc.mimeType = mimeType; - rc.headerMap = headerMap; - - resourceMap_.put(url, rc); - } - - // CefLifeSpanHandler methods: - - @Override - public void onAfterCreated(CefBrowser browser) { - if (debugPrint()) System.out.println("onAfterCreated id=" + browser.getIdentifier()); - } - - @Override - public boolean onBeforePopup( - CefBrowser browser, CefFrame frame, String target_url, String target_frame_name) { - return false; - } - - @Override - public void onAfterParentChanged(CefBrowser browser) {} - - @Override - public boolean doClose(CefBrowser browser) { - boolean result = browser.doClose(); - if (debugPrint()) { - System.out.println( - "doClose id=" + browser.getIdentifier() + " CefBrowser.doClose=" + result); - } - return result; - } - - @Override - public void onBeforeClose(CefBrowser browser) { - if (debugPrint()) System.out.println("onBeforeClose id=" + browser.getIdentifier()); - cleanupTest(); - } - - // CefLoadHandler methods: - - @Override - public void onLoadingStateChange( - CefBrowser browser, boolean isLoading, boolean canGoBack, boolean canGoForward) {} - - @Override - public void onLoadStart(CefBrowser browser, CefFrame frame, TransitionType transitionType) {} - - @Override - public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) {} - - @Override - public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, - String errorText, String failedUrl) {} - - // CefRequestHandler methods: - - @Override - public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, - boolean user_gesture, boolean is_redirect) { - return false; - } - - @Override - public boolean onOpenURLFromTab( - CefBrowser browser, CefFrame frame, String target_url, boolean user_gesture) { - return false; - } - - @Override - public CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame, - CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator, - BoolRef disableDefaultHandling) { - return this; - } - - @Override - public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy, - String host, int port, String realm, String scheme, CefAuthCallback callback) { - return false; - } - - @Override - public boolean onCertificateError(CefBrowser browser, CefLoadHandler.ErrorCode cert_error, - String request_url, CefCallback callback) { - return false; - } - - @Override - public void onRenderProcessTerminated(CefBrowser browser, TerminationStatus status) {} - - // CefResourceRequestHandler methods: - - @Override - public CefCookieAccessFilter getCookieAccessFilter( - CefBrowser browser, CefFrame frame, CefRequest request) { - return null; - } - - @Override - public boolean onBeforeResourceLoad(CefBrowser browser, CefFrame frame, CefRequest request) { - return false; - } - - @Override - public CefResourceHandler getResourceHandler( - CefBrowser browser, CefFrame frame, CefRequest request) { - if (resourceMap_ != null) { - String url = request.getURL(); - - // Ignore the query component, if any. - int idx = url.indexOf('?'); - if (idx > 0) url = url.substring(0, idx); - - ResourceContent rc = resourceMap_.get(url); - if (rc != null) { - if (debugPrint()) System.out.println("Found resource for: " + url); - return new TestResourceHandler(rc.content, rc.mimeType, rc.headerMap); - } - } - - return null; - } - - @Override - public void onResourceRedirect(CefBrowser browser, CefFrame frame, CefRequest request, - CefResponse response, StringRef new_url) {} - - @Override - public boolean onResourceResponse( - CefBrowser browser, CefFrame frame, CefRequest request, CefResponse response) { - return false; - } - - @Override - public void onResourceLoadComplete(CefBrowser browser, CefFrame frame, CefRequest request, - CefResponse response, CefURLRequest.Status status, long receivedContentLength) {} - - @Override - public void onProtocolExecution( - CefBrowser browser, CefFrame frame, CefRequest request, BoolRef allowOsExecution) {} -} diff --git a/java/tests/junittests/TestFrameTest.java b/java/tests/junittests/TestFrameTest.java deleted file mode 100644 index e8f36c16..00000000 --- a/java/tests/junittests/TestFrameTest.java +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.junittests; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.cef.browser.CefBrowser; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -// Test the TestFrame implementation. -@ExtendWith(TestSetupExtension.class) -class TestFrameTest { - private boolean gotSetupTest_ = false; - private boolean gotCleanupTest_ = false; - private boolean gotLoadingStateChange_ = false; - - @Test - void minimal() { - final String testUrl = "http://test.com/test.html"; - TestFrame frame = new TestFrame() { - @Override - protected void setupTest() { - assertFalse(gotSetupTest_); - gotSetupTest_ = true; - - addResource(testUrl, "Test!", "text/html"); - - createBrowser(testUrl); - - super.setupTest(); - } - - @Override - protected void cleanupTest() { - assertFalse(gotCleanupTest_); - gotCleanupTest_ = true; - - super.cleanupTest(); - } - - @Override - public void onLoadingStateChange(CefBrowser browser, boolean isLoading, - boolean canGoBack, boolean canGoForward) { - if (!isLoading) { - assertFalse(gotLoadingStateChange_); - gotLoadingStateChange_ = true; - terminateTest(); - } - } - }; - - frame.awaitCompletion(); - - assertTrue(gotSetupTest_); - assertTrue(gotLoadingStateChange_); - assertTrue(gotCleanupTest_); - } -} diff --git a/java/tests/junittests/TestResourceHandler.java b/java/tests/junittests/TestResourceHandler.java deleted file mode 100644 index 23594f4f..00000000 --- a/java/tests/junittests/TestResourceHandler.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.junittests; - -import org.cef.callback.CefCallback; -import org.cef.handler.CefResourceHandlerAdapter; -import org.cef.misc.IntRef; -import org.cef.misc.StringRef; -import org.cef.network.CefRequest; -import org.cef.network.CefResponse; - -import java.nio.ByteBuffer; -import java.util.HashMap; - -class TestResourceHandler extends CefResourceHandlerAdapter { - private int offset_ = 0; - private final String content_; - private final String mimeType_; - private final HashMap headerMap_; - - TestResourceHandler(String content, String mimeType, HashMap headerMap) { - content_ = content; - mimeType_ = mimeType; - headerMap_ = headerMap; - } - - @Override - public boolean processRequest(CefRequest request, CefCallback callback) { - callback.Continue(); - return true; - } - - @Override - public void getResponseHeaders( - CefResponse response, IntRef response_length, StringRef redirectUrl) { - response_length.set(content_.length()); - response.setMimeType(mimeType_); - response.setStatus(200); - - if (headerMap_ != null) { - HashMap headerMap = new HashMap<>(); - response.getHeaderMap(headerMap); - headerMap.putAll(headerMap_); - response.setHeaderMap(headerMap); - } - } - - @Override - public boolean readResponse( - byte[] data_out, int bytes_to_read, IntRef bytes_read, CefCallback callback) { - int length = content_.length(); - if (offset_ >= length) return false; - - // Extract up to |bytes_to_read| bytes from |content_|. - int endPos = offset_ + bytes_to_read; - String dataToSend = (endPos > length) ? content_.substring(offset_) - : content_.substring(offset_, endPos); - - // Copy extracted bytes into |data_out| and set the read length to |bytes_read|. - ByteBuffer result = ByteBuffer.wrap(data_out); - result.put(dataToSend.getBytes()); - bytes_read.set(dataToSend.length()); - - offset_ = endPos; - return true; - } -} diff --git a/java/tests/junittests/TestSetupContext.java b/java/tests/junittests/TestSetupContext.java deleted file mode 100644 index 758fbffc..00000000 --- a/java/tests/junittests/TestSetupContext.java +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.junittests; - -import org.junit.jupiter.api.extension.ExtensionContext; - -import java.util.Optional; - -// Stores global test setup state for access from package classes. -class TestSetupContext { - private static boolean debugPrint_ = false; - - // Debug print statements may be enabled via `--config debugPrint=true`. - static boolean debugPrint() { - return debugPrint_; - } - - // Initialize from global configuration parameters. - static void initialize(ExtensionContext context) { - Optional debugPrint = context.getConfigurationParameter("debugPrint"); - if (debugPrint.isPresent() && debugPrint.get().equalsIgnoreCase("true")) { - debugPrint_ = true; - } - } -} diff --git a/java/tests/junittests/TestSetupExtension.java b/java/tests/junittests/TestSetupExtension.java deleted file mode 100644 index 66887719..00000000 --- a/java/tests/junittests/TestSetupExtension.java +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.junittests; - -import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL; - -import org.cef.CefApp; -import org.cef.CefApp.CefAppState; -import org.cef.CefSettings; -import org.cef.handler.CefAppHandlerAdapter; -import org.junit.jupiter.api.extension.BeforeAllCallback; -import org.junit.jupiter.api.extension.ExtensionContext; - -import java.util.concurrent.CountDownLatch; - -// All test cases must install this extension for CEF to be properly initialized -// and shut down. -// -// For example: -// -// @ExtendWith(TestSetupExtension.class) -// class FooTest { -// @Test -// void testCaseThatRequiresCEF() {} -// } -// -// This code is based on https://stackoverflow.com/a/51556718. -public class TestSetupExtension - implements BeforeAllCallback, ExtensionContext.Store.CloseableResource { - private static boolean initialized_ = false; - private static CountDownLatch countdown_ = new CountDownLatch(1); - - @Override - public void beforeAll(ExtensionContext context) { - if (!initialized_) { - initialized_ = true; - initialize(context); - } - } - - // Executed before any tests are run. - private void initialize(ExtensionContext context) { - TestSetupContext.initialize(context); - - if (TestSetupContext.debugPrint()) { - System.out.println("TestSetupExtension.initialize"); - } - - // Register a callback hook for when the root test context is shut down. - context.getRoot().getStore(GLOBAL).put("jcef_test_setup", this); - - // Perform startup initialization on platforms that require it. - if (!CefApp.startup(null)) { - System.out.println("Startup initialization failed!"); - return; - } - - CefApp.addAppHandler(new CefAppHandlerAdapter(null) { - @Override - public void stateHasChanged(org.cef.CefApp.CefAppState state) { - if (state == CefAppState.TERMINATED) { - // Signal completion of CEF shutdown. - countdown_.countDown(); - } - } - }); - - // Initialize the singleton CefApp instance. - CefSettings settings = new CefSettings(); - CefApp.getInstance(settings); - } - - // Executed after all tests have completed. - @Override - public void close() { - if (TestSetupContext.debugPrint()) { - System.out.println("TestSetupExtension.close"); - } - - CefApp.getInstance().dispose(); - - // Wait for CEF shutdown to complete. - try { - countdown_.await(); - } catch (InterruptedException e) { - } - } -} diff --git a/java/tests/simple/MainFrame.java b/java/tests/simple/MainFrame.java deleted file mode 100644 index 822c4c8f..00000000 --- a/java/tests/simple/MainFrame.java +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.simple; - -import org.cef.CefApp; -import org.cef.CefApp.CefAppState; -import org.cef.CefClient; -import org.cef.CefSettings; -import org.cef.OS; -import org.cef.browser.CefBrowser; -import org.cef.browser.CefFrame; -import org.cef.handler.CefAppHandlerAdapter; -import org.cef.handler.CefDisplayHandlerAdapter; -import org.cef.handler.CefFocusHandlerAdapter; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.KeyboardFocusManager; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -import javax.swing.JFrame; -import javax.swing.JTextField; - -/** - * This is a simple example application using JCEF. - * It displays a JFrame with a JTextField at its top and a CefBrowser in its - * center. The JTextField is used to enter and assign an URL to the browser UI. - * No additional handlers or callbacks are used in this example. - * - * The number of used JCEF classes is reduced (nearly) to its minimum and should - * assist you to get familiar with JCEF. - * - * For a more feature complete example have also a look onto the example code - * within the package "tests.detailed". - */ -public class MainFrame extends JFrame { - private static final long serialVersionUID = -5570653778104813836L; - private final JTextField address_; - private final CefApp cefApp_; - private final CefClient client_; - private final CefBrowser browser_; - private boolean browserFocus_ = true; - - /** - * To display a simple browser window, it suffices completely to create an - * instance of the class CefBrowser and to assign its UI component to your - * application (e.g. to your content pane). - * But to be more verbose, this CTOR keeps an instance of each object on the - * way to the browser UI. - */ - private MainFrame(String startURL, boolean useOSR, boolean isTransparent) { - // (1) The entry point to JCEF is always the class CefApp. There is only one - // instance per application and therefore you have to call the method - // "getInstance()" instead of a CTOR. - // - // CefApp is responsible for the global CEF context. It loads all - // required native libraries, initializes CEF accordingly, starts a - // background task to handle CEF's message loop and takes care of - // shutting down CEF after disposing it. - CefApp.addAppHandler(new CefAppHandlerAdapter(null) { - @Override - public void stateHasChanged(org.cef.CefApp.CefAppState state) { - // Shutdown the app if the native CEF part is terminated - if (state == CefAppState.TERMINATED) System.exit(0); - } - }); - CefSettings settings = new CefSettings(); - settings.windowless_rendering_enabled = useOSR; - cefApp_ = CefApp.getInstance(settings); - - // (2) JCEF can handle one to many browser instances simultaneous. These - // browser instances are logically grouped together by an instance of - // the class CefClient. In your application you can create one to many - // instances of CefClient with one to many CefBrowser instances per - // client. To get an instance of CefClient you have to use the method - // "createClient()" of your CefApp instance. Calling an CTOR of - // CefClient is not supported. - // - // CefClient is a connector to all possible events which come from the - // CefBrowser instances. Those events could be simple things like the - // change of the browser title or more complex ones like context menu - // events. By assigning handlers to CefClient you can control the - // behavior of the browser. See tests.detailed.MainFrame for an example - // of how to use these handlers. - client_ = cefApp_.createClient(); - - // (3) One CefBrowser instance is responsible to control what you'll see on - // the UI component of the instance. It can be displayed off-screen - // rendered or windowed rendered. To get an instance of CefBrowser you - // have to call the method "createBrowser()" of your CefClient - // instances. - // - // CefBrowser has methods like "goBack()", "goForward()", "loadURL()", - // and many more which are used to control the behavior of the displayed - // content. The UI is held within a UI-Compontent which can be accessed - // by calling the method "getUIComponent()" on the instance of CefBrowser. - // The UI component is inherited from a java.awt.Component and therefore - // it can be embedded into any AWT UI. - browser_ = client_.createBrowser(startURL, isTransparent); - - // (4) For this minimal browser, we need only a text field to enter an URL - // we want to navigate to and a CefBrowser window to display the content - // of the URL. To respond to the input of the user, we're registering an - // anonymous ActionListener. This listener is performed each time the - // user presses the "ENTER" key within the address field. - // If this happens, the entered value is passed to the CefBrowser - // instance to be loaded as URL. - address_ = new JTextField(startURL, 100); - address_.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - browser_.loadURL(address_.getText()); - } - }); - - // Update the address field when the browser URL changes. - client_.addDisplayHandler(new CefDisplayHandlerAdapter() { - @Override - public void onAddressChange(CefBrowser browser, CefFrame frame, String url) { - address_.setText(url); - } - }); - - // Clear focus from the browser when the address field gains focus. - address_.addFocusListener(new FocusAdapter() { - @Override - public void focusGained(FocusEvent e) { - if (!browserFocus_) return; - browserFocus_ = false; - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); - address_.requestFocus(); - } - }); - - // Clear focus from the address field when the browser gains focus. - client_.addFocusHandler(new CefFocusHandlerAdapter() { - @Override - public void onGotFocus(CefBrowser browser) { - if (browserFocus_) return; - browserFocus_ = true; - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); - browser.setFocus(true); - } - - @Override - public void onTakeFocus(CefBrowser browser, boolean next) { - browserFocus_ = false; - } - }); - - // (5) All UI components are assigned to the default content pane of this - // JFrame and afterwards the frame is made visible to the user. - getContentPane().add(address_, BorderLayout.NORTH); - pack(); - setSize(800, 600); - setVisible(true); - - // (6) To take care of shutting down CEF accordingly, it's important to call - // the method "dispose()" of the CefApp instance if the Java - // application will be closed. Otherwise you'll get asserts from CEF. - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - CefApp.getInstance().dispose(); - dispose(); - } - }); - } - - public static void main(String[] args) { - // Perform startup initialization on platforms that require it. - if (!CefApp.startup(args)) { - System.out.println("Startup initialization failed!"); - return; - } - - // The simple example application is created as anonymous class and points - // to Google as the very first loaded page. Windowed rendering mode is used by - // default. If you want to test OSR mode set |useOsr| to true and recompile. - boolean useOsr = false; - new MainFrame("http://www.google.com", useOsr, false); - } -} diff --git a/native/CefBrowser_N.cpp b/native/CefBrowser_N.cpp index d8d920dc..fbc2d6c4 100644 --- a/native/CefBrowser_N.cpp +++ b/native/CefBrowser_N.cpp @@ -1050,21 +1050,6 @@ void executeDevToolsMethod(CefRefPtr host, // } //} -jobject NewJNILongVector(JNIEnv* env, const std::vector& vals) { - ScopedJNIObjectLocal jvector(env, "java/util/Vector"); - if (!jvector) - return nullptr; - - std::vector::const_iterator iter; - for (iter = vals.begin(); iter != vals.end(); ++iter) { - ScopedJNIObjectLocal argument( - env, NewJNIObject(env, "java/lang/Long", "(J)V", (jlong)*iter)); - JNI_CALL_VOID_METHOD(env, jvector, "addElement", "(Ljava/lang/Object;)V", - argument.get()); - } - return jvector.Release(); -} - CefPdfPrintSettings GetJNIPdfPrintSettings(JNIEnv* env, jobject obj) { CefString tmp; CefPdfPrintSettings settings; @@ -1332,36 +1317,6 @@ Java_org_cef_browser_CefBrowser_1N_N_1GetFocusedFrame(JNIEnv* env, return jframe.Release(); } -JNIEXPORT jobject JNICALL -Java_org_cef_browser_CefBrowser_1N_N_1GetFrame(JNIEnv* env, - jobject obj, - jlong identifier) { - CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr); - CefRefPtr frame = browser->GetFrame(identifier); - if (!frame) - return nullptr; - ScopedJNIFrame jframe(env, frame); - return jframe.Release(); -} - -JNIEXPORT jobject JNICALL -Java_org_cef_browser_CefBrowser_1N_N_1GetFrame2(JNIEnv* env, - jobject obj, - jstring name) { - CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr); - CefRefPtr frame = browser->GetFrame(GetJNIString(env, name)); - if (!frame) - return nullptr; - ScopedJNIFrame jframe(env, frame); - return jframe.Release(); -} - -JNIEXPORT jint JNICALL -Java_org_cef_browser_CefBrowser_1N_N_1GetFrameCount(JNIEnv* env, jobject obj) { - CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, -1); - return (jint)browser->GetFrameCount(); -} - JNIEXPORT jobject JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetFrameByIdentifier(JNIEnv* env, jobject obj,