diff --git a/platform/platform-api/src/com/intellij/ui/jcef/JBCefClient.java b/platform/platform-api/src/com/intellij/ui/jcef/JBCefClient.java
index 65c748fd2674..3fb1ed3c9759 100644
--- a/platform/platform-api/src/com/intellij/ui/jcef/JBCefClient.java
+++ b/platform/platform-api/src/com/intellij/ui/jcef/JBCefClient.java
@@ -27,13 +27,15 @@ import java.util.concurrent.atomic.AtomicInteger;
* A wrapper over {@link CefClient}.
*
* Provides facilities to add multiple handlers of the same type ({@code CefClient} doesn't).
- * All the handlers of the same type are called in the "last-added-last-called" order. When a return value is expected, the last handler's
- * return value is returned as the result. When a CEF callback is passed to the handler, it's the responsibility of the client to manage
- * the callback calls in case when multiple handlers are added.
+ * All the handlers of the same type are called in the "last-added-last-called" order.
+ *
+ * There are two ways to handle returning values.
+ * 1. Call all handlers and return true as the aggregate result if any handler returns true.
+ * 2. Call handler until the first handler returns true or not null value.
+ * Check the implementation of the corresponding handler in this class if using multiple handlers is needed.
*
* @see Embedded Browser (JCEF) (IntelliJ Platform Docs)
*/
-// [tav]: todo: think if we need some more sophisticated way to handle results of sequence of handles (like foldResults() callback)
@SuppressWarnings({"unused", "UnusedReturnValue"}) // [tav] todo: remove it ( or add*Handler methods not yet used)
public final class JBCefClient implements JBCefDisposable {
private static final Logger LOG = Logger.getInstance(JBCefClient.class);
@@ -46,7 +48,7 @@ public final class JBCefClient implements JBCefDisposable {
* Defines the size of the pool used by {@link JBCefJSQuery} after a native browser has been created.
*
* Accepts {@link Integer} values. JCEF does not allow registering new JavaScript queries after a native browser
- * has been created. To work around this limitation a pool of JS query slots can be reserved ahead. One slot
+ * has been created. To work around this limitation, a pool of JS query slots can be reserved ahead. One slot
* corresponds to a single {@link JBCefJSQuery} instance. The pool is not created by default unless it is explicitly
* requested via this property. The property should be added to a client before the first browser associated
* with the client is added to a UI hierarchy, otherwise it will have no effect.
@@ -212,7 +214,7 @@ public final class JBCefClient implements JBCefDisposable {
myCefClient.addContextMenuHandler(new CefContextMenuHandler() {
@Override
public void onBeforeContextMenu(CefBrowser browser, CefFrame frame, CefContextMenuParams params, CefMenuModel model) {
- myContextMenuHandler.handle(browser, handler -> {
+ myContextMenuHandler.handleAll(browser, handler -> {
handler.onBeforeContextMenu(browser, frame, params, model);
});
}
@@ -223,14 +225,14 @@ public final class JBCefClient implements JBCefDisposable {
CefContextMenuParams params,
int commandId,
int eventFlags) {
- return myContextMenuHandler.handleBoolean(browser, handler -> {
+ return myContextMenuHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.onContextMenuCommand(browser, frame, params, commandId, eventFlags);
});
}
@Override
public void onContextMenuDismissed(CefBrowser browser, CefFrame frame) {
- myContextMenuHandler.handle(browser, handler -> {
+ myContextMenuHandler.handleAll(browser, handler -> {
handler.onContextMenuDismissed(browser, frame);
});
}
@@ -252,7 +254,7 @@ public final class JBCefClient implements JBCefDisposable {
String defaultFilePath,
Vector acceptFilters,
CefFileDialogCallback callback) {
- return myDialogHandler.handleBoolean(browser, handler -> {
+ return myDialogHandler.handleBooleanFirst(browser, handler -> {
return handler.onFileDialog(browser, mode, title, defaultFilePath, acceptFilters, callback);
});
}
@@ -269,14 +271,14 @@ public final class JBCefClient implements JBCefDisposable {
myCefClient.addDisplayHandler(new CefDisplayHandler() {
@Override
public void onAddressChange(CefBrowser browser, CefFrame frame, String url) {
- myDisplayHandler.handle(browser, handler -> {
+ myDisplayHandler.handleAll(browser, handler -> {
handler.onAddressChange(browser, frame, url);
});
}
@Override
public void onTitleChange(CefBrowser browser, String title) {
- myDisplayHandler.handle(browser, handler -> {
+ myDisplayHandler.handleAll(browser, handler -> {
handler.onTitleChange(browser, title);
});
}
@@ -288,28 +290,28 @@ public final class JBCefClient implements JBCefDisposable {
@Override
public boolean onTooltip(CefBrowser browser, String text) {
- return myDisplayHandler.handleBoolean(browser, handler -> {
+ return myDisplayHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.onTooltip(browser, text);
});
}
@Override
public void onStatusMessage(CefBrowser browser, String value) {
- myDisplayHandler.handle(browser, handler -> {
+ myDisplayHandler.handleAll(browser, handler -> {
handler.onStatusMessage(browser, value);
});
}
@Override
public boolean onConsoleMessage(CefBrowser browser, CefSettings.LogSeverity level, String message, String source, int line) {
- return myDisplayHandler.handleBoolean(browser, handler -> {
+ return myDisplayHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.onConsoleMessage(browser, level, message, source, line);
});
}
@Override
public boolean onCursorChange(CefBrowser browser, int cursorType) {
- return myDisplayHandler.handleBoolean(browser, handler -> {
+ return myDisplayHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.onCursorChange(browser, cursorType);
});
}
@@ -329,14 +331,14 @@ public final class JBCefClient implements JBCefDisposable {
CefDownloadItem downloadItem,
String suggestedName,
CefBeforeDownloadCallback callback) {
- myDownloadHandler.handle(browser, handler -> {
+ myDownloadHandler.handleAll(browser, handler -> {
handler.onBeforeDownload(browser, downloadItem, suggestedName, callback);
});
}
@Override
public void onDownloadUpdated(CefBrowser browser, CefDownloadItem downloadItem, CefDownloadItemCallback callback) {
- myDownloadHandler.handle(browser, handler -> {
+ myDownloadHandler.handleAll(browser, handler -> {
handler.onDownloadUpdated(browser, downloadItem, callback);
});
}
@@ -353,7 +355,7 @@ public final class JBCefClient implements JBCefDisposable {
myCefClient.addDragHandler(new CefDragHandler() {
@Override
public boolean onDragEnter(CefBrowser browser, CefDragData dragData, int mask) {
- return myDragHandler.handleBoolean(browser, handler -> {
+ return myDragHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.onDragEnter(browser, dragData, mask);
});
}
@@ -375,7 +377,7 @@ public final class JBCefClient implements JBCefDisposable {
String requesting_url,
int requested_permissions,
CefMediaAccessCallback callback) {
- Boolean res = myPermissionHandler.handle(browser, handler -> {
+ Boolean res = myPermissionHandler.handleBooleanFirst(browser, handler -> {
return handler.onRequestMediaAccessPermission(browser, frame, requesting_url, requested_permissions, callback);
});
return ObjectUtils.notNull(res, false);
@@ -389,21 +391,21 @@ public final class JBCefClient implements JBCefDisposable {
myCefClient.addFocusHandler(new CefFocusHandler() {
@Override
public void onTakeFocus(CefBrowser browser, boolean next) {
- myFocusHandler.handle(browser, handler -> {
+ myFocusHandler.handleAll(browser, handler -> {
handler.onTakeFocus(browser, next);
});
}
@Override
public boolean onSetFocus(CefBrowser browser, FocusSource source) {
- return myFocusHandler.handleBoolean(browser, handler -> {
+ return myFocusHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.onSetFocus(browser, source);
});
}
@Override
public void onGotFocus(CefBrowser browser) {
- myFocusHandler.handle(browser, handler -> {
+ myFocusHandler.handleAll(browser, handler -> {
handler.onGotFocus(browser);
});
}
@@ -426,28 +428,28 @@ public final class JBCefClient implements JBCefDisposable {
String default_prompt_text,
CefJSDialogCallback callback,
BoolRef suppress_message) {
- return myJSDialogHandler.handleBoolean(browser, handler -> {
+ return myJSDialogHandler.handleBooleanFirst(browser, handler -> {
return handler.onJSDialog(browser, origin_url, dialog_type, message_text, default_prompt_text, callback, suppress_message);
});
}
@Override
public boolean onBeforeUnloadDialog(CefBrowser browser, String message_text, boolean is_reload, CefJSDialogCallback callback) {
- return myJSDialogHandler.handleBoolean(browser, handler -> {
+ return myJSDialogHandler.handleBooleanFirst(browser, handler -> {
return handler.onBeforeUnloadDialog(browser, message_text, is_reload, callback);
});
}
@Override
public void onResetDialogState(CefBrowser browser) {
- myJSDialogHandler.handle(browser, handler -> {
+ myJSDialogHandler.handleAll(browser, handler -> {
handler.onResetDialogState(browser);
});
}
@Override
public void onDialogClosed(CefBrowser browser) {
- myJSDialogHandler.handle(browser, handler -> {
+ myJSDialogHandler.handleAll(browser, handler -> {
handler.onDialogClosed(browser);
});
}
@@ -464,14 +466,14 @@ public final class JBCefClient implements JBCefDisposable {
myCefClient.addKeyboardHandler(new CefKeyboardHandler() {
@Override
public boolean onPreKeyEvent(CefBrowser browser, CefKeyEvent event, BoolRef is_keyboard_shortcut) {
- return myKeyboardHandler.handleBoolean(browser, handler -> {
+ return myKeyboardHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.onPreKeyEvent(browser, event, is_keyboard_shortcut);
});
}
@Override
public boolean onKeyEvent(CefBrowser browser, CefKeyEvent event) {
- return myKeyboardHandler.handleBoolean(browser, handler -> {
+ return myKeyboardHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.onKeyEvent(browser, event);
});
}
@@ -488,35 +490,35 @@ public final class JBCefClient implements JBCefDisposable {
myCefClient.addLifeSpanHandler(new CefLifeSpanHandler() {
@Override
public boolean onBeforePopup(CefBrowser browser, CefFrame frame, String target_url, String target_frame_name) {
- return myLifeSpanHandler.handleBoolean(browser, handler -> {
+ return myLifeSpanHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.onBeforePopup(browser, frame, target_url, target_frame_name);
});
}
@Override
public void onAfterCreated(CefBrowser browser) {
- myLifeSpanHandler.handle(browser, handler -> {
+ myLifeSpanHandler.handleAll(browser, handler -> {
handler.onAfterCreated(browser);
});
}
@Override
public void onAfterParentChanged(CefBrowser browser) {
- myLifeSpanHandler.handle(browser, handler -> {
+ myLifeSpanHandler.handleAll(browser, handler -> {
handler.onAfterParentChanged(browser);
});
}
@Override
public boolean doClose(CefBrowser browser) {
- return myLifeSpanHandler.handleBoolean(browser, handler -> {
+ return myLifeSpanHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.doClose(browser);
});
}
@Override
public void onBeforeClose(CefBrowser browser) {
- myLifeSpanHandler.handle(browser, handler -> {
+ myLifeSpanHandler.handleAll(browser, handler -> {
handler.onBeforeClose(browser);
});
}
@@ -533,28 +535,28 @@ public final class JBCefClient implements JBCefDisposable {
myCefClient.addLoadHandler(new CefLoadHandler() {
@Override
public void onLoadingStateChange(CefBrowser browser, boolean isLoading, boolean canGoBack, boolean canGoForward) {
- myLoadHandler.handle(browser, handler -> {
+ myLoadHandler.handleAll(browser, handler -> {
handler.onLoadingStateChange(browser, isLoading, canGoBack, canGoForward);
});
}
@Override
public void onLoadStart(CefBrowser browser, CefFrame frame, CefRequest.TransitionType transitionType) {
- myLoadHandler.handle(browser, handler -> {
+ myLoadHandler.handleAll(browser, handler -> {
handler.onLoadStart(browser, frame, transitionType);
});
}
@Override
public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) {
- myLoadHandler.handle(browser, handler -> {
+ myLoadHandler.handleAll(browser, handler -> {
handler.onLoadEnd(browser, frame, httpStatusCode);
});
}
@Override
public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, String errorText, String failedUrl) {
- myLoadHandler.handle(browser, handler -> {
+ myLoadHandler.handleAll(browser, handler -> {
handler.onLoadError(browser, frame, errorCode, errorText, failedUrl);
});
}
@@ -571,14 +573,14 @@ public final class JBCefClient implements JBCefDisposable {
myCefClient.addRequestHandler(new CefRequestHandler() {
@Override
public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, boolean user_gesture, boolean is_redirect) {
- return myRequestHandler.handleBoolean(browser, handler -> {
+ return myRequestHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.onBeforeBrowse(browser, frame, request, user_gesture, is_redirect);
});
}
@Override
public boolean onOpenURLFromTab(CefBrowser browser, CefFrame frame, String target_url, boolean user_gesture) {
- return myRequestHandler.handleBoolean(browser, handler -> {
+ return myRequestHandler.handleBooleanReturnAnyOf(browser, handler -> {
return handler.onOpenURLFromTab(browser, frame, target_url, user_gesture);
});
}
@@ -592,7 +594,7 @@ public final class JBCefClient implements JBCefDisposable {
String requestInitiator,
BoolRef disableDefaultHandling)
{
- return myRequestHandler.handle(browser, handler -> {
+ return myRequestHandler.handleFirst(browser, handler -> {
return handler.getResourceRequestHandler(browser, frame, request, isNavigation, isDownload, requestInitiator, disableDefaultHandling);
});
}
@@ -607,7 +609,7 @@ public final class JBCefClient implements JBCefDisposable {
String scheme,
CefAuthCallback callback)
{
- return myRequestHandler.handleBoolean(browser, handler -> {
+ return myRequestHandler.handleBooleanFirst(browser, handler -> {
return handler.getAuthCredentials(browser, origin_url, isProxy, host, port, realm, scheme, callback);
});
}
@@ -633,7 +635,7 @@ public final class JBCefClient implements JBCefDisposable {
@Override
public void onRenderProcessTerminated(CefBrowser browser, TerminationStatus status) {
- myRequestHandler.handle(browser, handler -> {
+ myRequestHandler.handleAll(browser, handler -> {
handler.onRenderProcessTerminated(browser, status);
});
}
@@ -729,25 +731,47 @@ public final class JBCefClient implements JBCefDisposable {
return myMap != null ? myMap.get(browser) : null;
}
- public @Nullable R handle(@NotNull CefBrowser browser, @NotNull HandlerCallable callable) {
- List list = get(browser);
- if (list == null) {
- return null;
- }
- final Ref lastResult = new Ref<>(null);
- list.forEach(handler -> lastResult.set(callable.handle(handler)));
- return lastResult.get();
- }
-
- public boolean handleBoolean(@NotNull CefBrowser browser, @NotNull HandlerCallable callable) {
- return ObjectUtils.notNull(handle(browser, callable), Boolean.FALSE);
- }
-
- public void handle(@NotNull CefBrowser browser, @NotNull HandlerRunnable runnable) {
+ public void handleAll(@NotNull CefBrowser browser, @NotNull HandlerRunnable runnable) {
List list = get(browser);
if (list == null) return;
list.forEach(handler -> runnable.handle(handler));
}
+
+ public boolean handleBooleanReturnAnyOf(@NotNull CefBrowser browser, @NotNull HandlerCallable callable) {
+ List list = get(browser);
+ if (list == null) return false;
+ boolean result = false;
+ for (T handler: list) {
+ result |= Boolean.TRUE.equals(callable.handle(handler));
+ }
+ return result;
+ }
+
+ public boolean handleBooleanFirst(@NotNull CefBrowser browser, @NotNull HandlerCallable callable) {
+ List list = get(browser);
+ if (list == null) return false;
+ boolean result = false;
+ for (T handler: list) {
+ if (Boolean.TRUE.equals(callable.handle(handler))) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public R handleFirst(@NotNull CefBrowser browser, @NotNull HandlerCallable callable) {
+ List list = get(browser);
+ if (list == null) return null;
+ for (T handler: list) {
+ R result = callable.handle(handler);
+ if (result != null) {
+ return result;
+ }
+ }
+
+ return null;
+ }
}
private interface HandlerCallable {