Skip to content

Commit f5c10bc

Browse files
committed
Handling 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.ui/#2734
1 parent b3e784d commit f5c10bc

File tree

1 file changed

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

1 file changed

+33
-18
lines changed

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

+33-18
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ 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, Function::identity, Display.getCurrent());
268268
completion.Release();
269269
return phr[0];
270270
}
@@ -282,7 +282,7 @@ int callAndWait(String[] pstr, ToIntFunction<IUnknown> callable) {
282282
phr[0] = callable.applyAsInt(completion);
283283
// "completion" callback may be called asynchronously,
284284
// so keep processing next OS message that may call it
285-
processOSMessagesUntil(() -> phr[0] != COM.S_OK || pstr[0] != null, browser.getDisplay());
285+
processOSMessagesUntil(() -> phr[0] != COM.S_OK || pstr[0] != null, Function::identity, browser.getDisplay());
286286
completion.Release();
287287
return phr[0];
288288
}
@@ -318,9 +318,8 @@ void releaseWebViews() {
318318
}
319319

320320
class WebViewProvider {
321-
322321
private CompletableFuture<WebViewWrapper> webViewWrapperFuture = wakeDisplayAfterFuture(new CompletableFuture<>());
323-
private CompletableFuture<Void> lastWebViewTask = webViewWrapperFuture.thenRun(() -> {});;
322+
private CompletableFuture<Void> lastWebViewTask = webViewWrapperFuture.thenRun(() -> {});
324323

325324
ICoreWebView2 initializeWebView(ICoreWebView2Controller controller) {
326325
long[] ppv = new long[1];
@@ -333,7 +332,12 @@ ICoreWebView2 initializeWebView(ICoreWebView2Controller controller) {
333332
webViewWrapper.webView_11 = initializeWebView_11(webView);
334333
webViewWrapper.webView_12 = initializeWebView_12(webView);
335334
webViewWrapper.webView_13 = initializeWebView_13(webView);
336-
webViewWrapperFuture.complete(webViewWrapper);
335+
boolean success = webViewWrapperFuture.complete(webViewWrapper);
336+
// Release the webViews if the webViewWrapperFuture has already timed out and completed exceptionally
337+
if(!success && webViewWrapperFuture.isCompletedExceptionally()) {
338+
webViewWrapper.releaseWebViews();
339+
return null;
340+
}
337341
return webView;
338342
}
339343

@@ -392,13 +396,13 @@ private ICoreWebView2_13 initializeWebView_13(ICoreWebView2 webView) {
392396

393397
private WebViewWrapper getWebViewWrapper(boolean waitForPendingWebviewTasksToFinish) {
394398
if(waitForPendingWebviewTasksToFinish) {
395-
processOSMessagesUntil(lastWebViewTask::isDone, browser.getDisplay());
399+
processOSMessagesUntil(lastWebViewTask::isDone, Function::identity, browser.getDisplay());
396400
}
397401
return webViewWrapperFuture.join();
398402
}
399403

400404
private WebViewWrapper getWebViewWrapper() {
401-
processOSMessagesUntil(webViewWrapperFuture::isDone, browser.getDisplay());
405+
processOSMessagesUntil(webViewWrapperFuture::isDone, () -> webViewWrapperFuture.completeExceptionally(createTimeOutException()), browser.getDisplay());
402406
return webViewWrapperFuture.join();
403407
}
404408

@@ -483,7 +487,7 @@ private <T> CompletableFuture<T> wakeDisplayAfterFuture(CompletableFuture<T> fut
483487
* events for initialization. Thus, this method does not implement an ordinary
484488
* readAndDispatch loop, but waits for an OS event to be processed.
485489
*/
486-
private static void processOSMessagesUntil(Supplier<Boolean> condition, Display display) {
490+
private static void processOSMessagesUntil(Supplier<Boolean> condition, Runnable timeoutHandler, Display display) {
487491
MSG msg = new MSG();
488492
AtomicBoolean timeoutOccurred = new AtomicBoolean();
489493
// The timer call also wakes up the display to avoid being stuck in display.sleep()
@@ -496,10 +500,15 @@ private static void processOSMessagesUntil(Supplier<Boolean> condition, Display
496500
}
497501
}
498502
if (!condition.get()) {
499-
SWT.error(SWT.ERROR_UNSPECIFIED, null, " Waiting for Edge operation to terminate timed out");
503+
timeoutHandler.run();
504+
throw createTimeOutException();
500505
}
501506
}
502507

508+
private static SWTException createTimeOutException() {
509+
return new SWTException(SWT.ERROR_UNSPECIFIED, " Waiting for Edge operation to terminate timed out");
510+
}
511+
503512
static ICoreWebView2CookieManager getCookieManager() {
504513
WebViewEnvironment environmentWrapper = webViewEnvironments.get(Display.getCurrent());
505514
if (environmentWrapper == null) {
@@ -616,16 +625,9 @@ private void createInstance(int previousAttempts) {
616625
}
617626

618627
private IUnknown createControllerInitializationCallback(int previousAttempts) {
619-
Runnable initializationRollback = () -> {
620-
if (environment2 != null) {
621-
environment2.Release();
622-
environment2 = null;
623-
}
624-
containingEnvironment.instances().remove(this);
625-
};
626628
Runnable initializationAbortion = () -> {
627629
webViewProvider.abortInitialization();
628-
initializationRollback.run();
630+
releaseEnvironment();
629631
};
630632
return newCallback((resultAsLong, pv) -> {
631633
int result = (int) resultAsLong;
@@ -651,7 +653,7 @@ private IUnknown createControllerInitializationCallback(int previousAttempts) {
651653
initializationAbortion.run();
652654
break;
653655
default:
654-
initializationRollback.run();
656+
releaseEnvironment();
655657
if (previousAttempts < MAXIMUM_CREATION_RETRIES) {
656658
System.err.println(String.format("Edge initialization failed, retrying (attempt %d / %d)", previousAttempts + 1, MAXIMUM_CREATION_RETRIES));
657659
createInstance(previousAttempts + 1);
@@ -665,10 +667,23 @@ private IUnknown createControllerInitializationCallback(int previousAttempts) {
665667
});
666668
}
667669

670+
private void releaseEnvironment() {
671+
if (environment2 != null) {
672+
environment2.Release();
673+
environment2 = null;
674+
}
675+
containingEnvironment.instances().remove(this);
676+
}
677+
668678
void setupBrowser(int hr, long pv) {
669679
long[] ppv = new long[] {pv};
670680
controller = new ICoreWebView2Controller(ppv[0]);
671681
final ICoreWebView2 webView = webViewProvider.initializeWebView(controller);
682+
if(webView == null) {
683+
controller.Release();
684+
releaseEnvironment();
685+
return;
686+
}
672687
webView.get_Settings(ppv);
673688
settings = new ICoreWebView2Settings(ppv[0]);
674689

0 commit comments

Comments
 (0)