diff --git a/java/org/cef/callback/CefQueryCallback.java b/java/org/cef/callback/CefQueryCallback.java index 0972bf2e..fe54ce71 100644 --- a/java/org/cef/callback/CefQueryCallback.java +++ b/java/org/cef/callback/CefQueryCallback.java @@ -4,6 +4,8 @@ package org.cef.callback; +import java.nio.ByteBuffer; + /** * Interface representing a query callback. */ @@ -11,10 +13,17 @@ public interface CefQueryCallback { /** * Notify the associated JavaScript onSuccess callback that the query has * completed successfully. - * @param response Response passed to JavaScript. + * @param response Response text passed to JavaScript. */ public void success(String response); + /** + * Notify the associated JavaScript onSuccess callback that the query has + * completed successfully. + * @param response Response buffer passed to JavaScript. May be null. + */ + public void success(ByteBuffer response); + /** * Notify the associated JavaScript onFailure callback that the query has * failed. @@ -22,4 +31,12 @@ public interface CefQueryCallback { * @param error_message Error message passed to JavaScript. */ public void failure(int error_code, String error_message); + + /** + * Returns whether this callback is persistent and therefore whether + * {@link CefQueryCallback#success(String)} may be called multiple times. + * Persistent queries must be explicitly canceled, either from the browser + * or via {@link CefQueryCallback#failure(int, String)}. + */ + public boolean isPersistent(); } diff --git a/java/org/cef/callback/CefQueryCallback_N.java b/java/org/cef/callback/CefQueryCallback_N.java index 14b32e3a..e62e0b15 100644 --- a/java/org/cef/callback/CefQueryCallback_N.java +++ b/java/org/cef/callback/CefQueryCallback_N.java @@ -4,6 +4,8 @@ package org.cef.callback; +import java.nio.ByteBuffer; + class CefQueryCallback_N extends CefNativeAdapter implements CefQueryCallback { CefQueryCallback_N() {} @@ -16,7 +18,16 @@ protected void finalize() throws Throwable { @Override public void success(String response) { try { - N_Success(getNativeRef(null), response); + N_Success(getNativeRef(null), response, isPersistent()); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + + @Override + public void success(ByteBuffer response) { + try { + N_SuccessBinary(getNativeRef(null), response, isPersistent()); } catch (UnsatisfiedLinkError ule) { ule.printStackTrace(); } @@ -31,6 +42,21 @@ public void failure(int error_code, String error_message) { } } - private final native void N_Success(long self, String response); + @Override + public boolean isPersistent() { + return false; + } + + private final native void N_Success(long self, String response, boolean persistent); + private final native void N_SuccessBinary(long self, ByteBuffer response, boolean persistent); private final native void N_Failure(long self, int error_code, String error_message); } + +class CefQueryCallback_N_Persistent extends CefQueryCallback_N { + CefQueryCallback_N_Persistent() {} + + @Override + public boolean isPersistent() { + return true; + } +} diff --git a/java/org/cef/handler/CefMessageRouterHandler.java b/java/org/cef/handler/CefMessageRouterHandler.java index 4827a476..53413a8f 100644 --- a/java/org/cef/handler/CefMessageRouterHandler.java +++ b/java/org/cef/handler/CefMessageRouterHandler.java @@ -9,18 +9,21 @@ import org.cef.callback.CefNative; import org.cef.callback.CefQueryCallback; +import java.nio.ByteBuffer; + /** * Implement this interface to handle queries. All methods will be executed on the browser process * UI thread. */ public interface CefMessageRouterHandler extends CefNative { /** - * Called when the browser receives a JavaScript query. + * Called when the browser receives a JavaScript text query. * * @param browser The corresponding browser. * @param frame The frame generating the event. Instance only valid within the scope of this * method. * @param queryId The unique ID for the query. + * @param request The query text. * @param persistent True if the query is persistent. * @param callback Object used to continue or cancel the query asynchronously. * @return True to handle the query or false to propagate the query to other registered @@ -31,6 +34,24 @@ public interface CefMessageRouterHandler extends CefNative { public boolean onQuery(CefBrowser browser, CefFrame frame, long queryId, String request, boolean persistent, CefQueryCallback callback); + /** + * Called when the browser receives a JavaScript binary query. + * + * @param browser The corresponding browser. + * @param frame The frame generating the event. Instance only valid within the scope of this + * method. + * @param queryId The unique ID for the query. + * @param request The query direct buffer. Valid only for the scope of this method. + * @param persistent True if the query is persistent. + * @param callback Object used to continue or cancel the query asynchronously. + * @return True to handle the query or false to propagate the query to other registered + * handlers, if any. If no handlers return true from this method then the query will be + * automatically canceled with an error code of -1 delivered to the JavaScript onFailure + * callback. + */ + public boolean onQuery(CefBrowser browser, CefFrame frame, long queryId, ByteBuffer request, + boolean persistent, CefQueryCallback callback); + /** * Called when a pending JavaScript query is canceled. * diff --git a/java/org/cef/handler/CefMessageRouterHandlerAdapter.java b/java/org/cef/handler/CefMessageRouterHandlerAdapter.java index c924dbfe..a91ba622 100644 --- a/java/org/cef/handler/CefMessageRouterHandlerAdapter.java +++ b/java/org/cef/handler/CefMessageRouterHandlerAdapter.java @@ -9,6 +9,8 @@ import org.cef.callback.CefNativeAdapter; import org.cef.callback.CefQueryCallback; +import java.nio.ByteBuffer; + /** * An abstract adapter class for receiving message router events. * The methods in this class are empty. @@ -22,6 +24,12 @@ public boolean onQuery(CefBrowser browser, CefFrame frame, long queryId, String return false; } + @Override + public boolean onQuery(CefBrowser browser, CefFrame frame, long queryId, ByteBuffer request, + boolean persistent, CefQueryCallback callback) { + return false; + } + @Override public void onQueryCanceled(CefBrowser browser, CefFrame frame, long queryId) { return; diff --git a/java/tests/detailed/handler/MessageRouterHandlerEx.java b/java/tests/detailed/handler/MessageRouterHandlerEx.java index bc4b780b..f534f31b 100644 --- a/java/tests/detailed/handler/MessageRouterHandlerEx.java +++ b/java/tests/detailed/handler/MessageRouterHandlerEx.java @@ -12,11 +12,14 @@ import org.cef.callback.CefQueryCallback; import org.cef.handler.CefMessageRouterHandlerAdapter; +import java.nio.ByteBuffer; + public class MessageRouterHandlerEx extends CefMessageRouterHandlerAdapter { private final CefClient client_; private final CefMessageRouterConfig config_ = new CefMessageRouterConfig("myQuery", "myQueryAbort"); private CefMessageRouter router_ = null; + private boolean binary_direct_ = false; public MessageRouterHandlerEx(final CefClient client) { client_ = client; @@ -47,6 +50,39 @@ public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String router_ = null; callback.success(""); } + } else if (request.startsWith("doPersistent")) { + if (persistent) { + callback.success("Hello,"); + callback.success("World!"); + callback.failure(0, "Finished"); + } else { + callback.failure(-1, "Request not marked as persistent"); + } + } else { + // not handled + return false; + } + return true; + } + + @Override + public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, ByteBuffer request, + boolean persistent, CefQueryCallback callback) { + if (request != null) { + int size = request.capacity(); + boolean direct = (binary_direct_ = !binary_direct_); + ByteBuffer response = direct ? ByteBuffer.allocateDirect(size) + : ByteBuffer.allocate(size); + // reverse bytes + for (int i = 0; i < size; i++) { + byte b = request.get(i); + response.put(size - i - 1, b); + } + callback.success(response); + if (persistent) { + callback.failure(0, direct ? "Finished (direct)" + : "Finished (array)"); + } } else { // not handled return false; diff --git a/java/tests/detailed/handler/binding_test2.html b/java/tests/detailed/handler/binding_test2.html index 8a61a96f..866c2cd9 100644 --- a/java/tests/detailed/handler/binding_test2.html +++ b/java/tests/detailed/handler/binding_test2.html @@ -17,6 +17,44 @@ }); } +function doPersistent() { + document.getElementById('persist').value = ''; + window.cefQuery({ + request: 'doPersistent', + persistent: true, + onSuccess: function(response) { + document.getElementById('persist').value += ' MESSAGE: [ ' + response + '];'; + }, + onFailure: function(error_code, error_message) { + document.getElementById('persist').value += ' FINISHED: ' + error_code + ' ' + error_message; + } + }); +} + +function doBinary() { + document.getElementById('binary').value = 'ORIGINAL: ['; + const binaryData = new Uint8Array([10, 20, 30, 40, 50]); + for (let i = 0; i < binaryData.length; i++) { + document.getElementById('binary').value += ' ' + binaryData.at(i); + } + document.getElementById('binary').value += ' ];'; + window.cefQuery({ + request: binaryData.buffer, + persistent: true, + onSuccess: function(response) { + document.getElementById('binary').value += ' RESPONSE: ['; + const echoedBinaryData = new Uint8Array(response); + for (let i = 0; i < echoedBinaryData.length; i++) { + document.getElementById('binary').value += ' ' + echoedBinaryData.at(i); + } + document.getElementById('binary').value += ' ];'; + }, + onFailure: function(error_code, error_message) { + document.getElementById('binary').value += ' FINISHED: ' + error_code + ' ' + error_message; + } + }); +} + function execute(cmd) { window.cefQuery({ request: cmd, @@ -75,6 +113,18 @@
This button tests persistent queries. When the button is pressed, it clears the output, +and when it receives a success message, it appends it to the output. When it finally receives +a failure message, it appends the error_code followed by the error_message.
+ + +This button tests binary queries. When the button is pressed, it clears the output and +replaces it with a representation of the binary data sent in the query. When it receives a +success message, it appends a similar representation of the binary data received (which has +been reversed by Java). When it finally receives a failure message, it appends the error_code +followed by the error_message.
+ +