Skip to content

Commit 0ef9e48

Browse files
amartya4256HeikoKlare
authored andcommitted
Handle WebViewWrapperFuture on operation timeout
This commit conributes to handle how webViewWrapperFuture should exceptionally complete if there happens an Edge operation timeout in processOSMessagesUntil method. Contributes to eclipse-platform#1466 and eclipse-platform/eclipse.platform.ui#2734
1 parent 91e1ce7 commit 0ef9e48

File tree

1 file changed

+43
-18
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser

1 file changed

+43
-18
lines changed

bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java

+43-18
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,9 @@ static int callAndWait(long[] ppv, ToIntFunction<IUnknown> callable) {
264264
phr[0] = callable.applyAsInt(completion);
265265
// "completion" callback may be called asynchronously,
266266
// so keep processing next OS message that may call it
267-
processOSMessagesUntil(() -> phr[0] != COM.S_OK || ppv[0] != 0, Display.getCurrent());
267+
processOSMessagesUntil(() -> phr[0] != COM.S_OK || ppv[0] != 0, exception -> {
268+
throw exception;
269+
}, Display.getCurrent());
268270
completion.Release();
269271
return phr[0];
270272
}
@@ -282,7 +284,9 @@ int callAndWait(String[] pstr, ToIntFunction<IUnknown> callable) {
282284
phr[0] = callable.applyAsInt(completion);
283285
// "completion" callback may be called asynchronously,
284286
// so keep processing next OS message that may call it
285-
processOSMessagesUntil(() -> phr[0] != COM.S_OK || pstr[0] != null, browser.getDisplay());
287+
processOSMessagesUntil(() -> phr[0] != COM.S_OK || pstr[0] != null, exception -> {
288+
throw exception;
289+
}, browser.getDisplay());
286290
completion.Release();
287291
return phr[0];
288292
}
@@ -324,9 +328,8 @@ void releaseWebViews() {
324328
}
325329

326330
class WebViewProvider {
327-
328331
private CompletableFuture<WebViewWrapper> webViewWrapperFuture = wakeDisplayAfterFuture(new CompletableFuture<>());
329-
private CompletableFuture<Void> lastWebViewTask = webViewWrapperFuture.thenRun(() -> {});;
332+
private CompletableFuture<Void> lastWebViewTask = webViewWrapperFuture.thenRun(() -> {});
330333

331334
ICoreWebView2 initializeWebView(ICoreWebView2Controller controller) {
332335
long[] ppv = new long[1];
@@ -339,7 +342,12 @@ ICoreWebView2 initializeWebView(ICoreWebView2Controller controller) {
339342
webViewWrapper.webView_11 = initializeWebView_11(webView);
340343
webViewWrapper.webView_12 = initializeWebView_12(webView);
341344
webViewWrapper.webView_13 = initializeWebView_13(webView);
342-
webViewWrapperFuture.complete(webViewWrapper);
345+
boolean success = webViewWrapperFuture.complete(webViewWrapper);
346+
// Release the webViews if the webViewWrapperFuture has already timed out and completed exceptionally
347+
if(!success && webViewWrapperFuture.isCompletedExceptionally()) {
348+
webViewWrapper.releaseWebViews();
349+
return null;
350+
}
343351
return webView;
344352
}
345353

@@ -398,13 +406,19 @@ private ICoreWebView2_13 initializeWebView_13(ICoreWebView2 webView) {
398406

399407
private WebViewWrapper getWebViewWrapper(boolean waitForPendingWebviewTasksToFinish) {
400408
if(waitForPendingWebviewTasksToFinish) {
401-
processOSMessagesUntil(lastWebViewTask::isDone, browser.getDisplay());
409+
processOSMessagesUntil(lastWebViewTask::isDone, exception -> {
410+
lastWebViewTask.completeExceptionally(exception);
411+
throw exception;
412+
}, browser.getDisplay());
402413
}
403414
return webViewWrapperFuture.join();
404415
}
405416

406417
private WebViewWrapper getWebViewWrapper() {
407-
processOSMessagesUntil(webViewWrapperFuture::isDone, browser.getDisplay());
418+
processOSMessagesUntil(webViewWrapperFuture::isDone, exception -> {
419+
webViewWrapperFuture.completeExceptionally(exception);
420+
throw exception;
421+
}, browser.getDisplay());
408422
return webViewWrapperFuture.join();
409423
}
410424

@@ -488,8 +502,9 @@ private <T> CompletableFuture<T> wakeDisplayAfterFuture(CompletableFuture<T> fut
488502
* leads to a failure in browser initialization if processed in between the OS
489503
* events for initialization. Thus, this method does not implement an ordinary
490504
* readAndDispatch loop, but waits for an OS event to be processed.
505+
* @throws Throwable
491506
*/
492-
private static void processOSMessagesUntil(Supplier<Boolean> condition, Display display) {
507+
private static void processOSMessagesUntil(Supplier<Boolean> condition, Consumer<SWTException> timeoutHandler, Display display) {
493508
MSG msg = new MSG();
494509
AtomicBoolean timeoutOccurred = new AtomicBoolean();
495510
// The timer call also wakes up the display to avoid being stuck in display.sleep()
@@ -502,10 +517,14 @@ private static void processOSMessagesUntil(Supplier<Boolean> condition, Display
502517
}
503518
}
504519
if (!condition.get()) {
505-
SWT.error(SWT.ERROR_UNSPECIFIED, null, " Waiting for Edge operation to terminate timed out");
520+
timeoutHandler.accept(createTimeOutException());
506521
}
507522
}
508523

524+
private static SWTException createTimeOutException() {
525+
return new SWTException(SWT.ERROR_UNSPECIFIED, "Waiting for Edge operation to terminate timed out");
526+
}
527+
509528
static ICoreWebView2CookieManager getCookieManager() {
510529
WebViewEnvironment environmentWrapper = webViewEnvironments.get(Display.getCurrent());
511530
if (environmentWrapper == null) {
@@ -622,16 +641,9 @@ private void createInstance(int previousAttempts) {
622641
}
623642

624643
private IUnknown createControllerInitializationCallback(int previousAttempts) {
625-
Runnable initializationRollback = () -> {
626-
if (environment2 != null) {
627-
environment2.Release();
628-
environment2 = null;
629-
}
630-
containingEnvironment.instances().remove(this);
631-
};
632644
Runnable initializationAbortion = () -> {
633645
webViewProvider.abortInitialization();
634-
initializationRollback.run();
646+
releaseEnvironment();
635647
};
636648
return newCallback((resultAsLong, pv) -> {
637649
int result = (int) resultAsLong;
@@ -657,7 +669,7 @@ private IUnknown createControllerInitializationCallback(int previousAttempts) {
657669
initializationAbortion.run();
658670
break;
659671
default:
660-
initializationRollback.run();
672+
releaseEnvironment();
661673
if (previousAttempts < MAXIMUM_CREATION_RETRIES) {
662674
System.err.println(String.format("Edge initialization failed, retrying (attempt %d / %d)", previousAttempts + 1, MAXIMUM_CREATION_RETRIES));
663675
createInstance(previousAttempts + 1);
@@ -671,10 +683,23 @@ private IUnknown createControllerInitializationCallback(int previousAttempts) {
671683
});
672684
}
673685

686+
private void releaseEnvironment() {
687+
if (environment2 != null) {
688+
environment2.Release();
689+
environment2 = null;
690+
}
691+
containingEnvironment.instances().remove(this);
692+
}
693+
674694
void setupBrowser(int hr, long pv) {
675695
long[] ppv = new long[] {pv};
676696
controller = new ICoreWebView2Controller(ppv[0]);
677697
final ICoreWebView2 webView = webViewProvider.initializeWebView(controller);
698+
if(webView == null) {
699+
controller.Release();
700+
releaseEnvironment();
701+
return;
702+
}
678703
webView.get_Settings(ppv);
679704
settings = new ICoreWebView2Settings(ppv[0]);
680705

0 commit comments

Comments
 (0)