Skip to content

Commit 893b4dd

Browse files
committed
WIP: Edge Browser Scheduled Job timeout
1 parent 60ef7e9 commit 893b4dd

File tree

2 files changed

+93
-65
lines changed

2 files changed

+93
-65
lines changed

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

Lines changed: 92 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -287,149 +287,163 @@ static int callAndWait(String[] pstr, ToIntFunction<IUnknown> callable) {
287287
return phr[0];
288288
}
289289

290-
class WebViewProvider {
290+
class WebViewWrapper {
291+
private ICoreWebView2 webView;
292+
private ICoreWebView2_2 webView_2;
293+
private ICoreWebView2_10 webView_10;
294+
private ICoreWebView2_11 webView_11;
295+
private ICoreWebView2_12 webView_12;
296+
private ICoreWebView2_13 webView_13;
297+
}
291298

292-
private CompletableFuture<ICoreWebView2> webViewFuture = new CompletableFuture<>();
293-
private CompletableFuture<ICoreWebView2_2> webView_2Future = new CompletableFuture<>();
294-
private CompletableFuture<ICoreWebView2_10> webView_10Future = new CompletableFuture<>();
295-
private CompletableFuture<ICoreWebView2_11> webView_11Future = new CompletableFuture<>();
296-
private CompletableFuture<ICoreWebView2_12> webView_12Future = new CompletableFuture<>();
297-
private CompletableFuture<ICoreWebView2_13> webView_13Future = new CompletableFuture<>();
299+
class WebViewProvider {
298300

299-
private CompletableFuture<Void> lastWebViewTask = webViewFuture.thenRun(() -> {});
301+
private CompletableFuture<WebViewWrapper> webViewWrapperFuture = initializeWebViewFutureWithTimeOut();
302+
private CompletableFuture<Void> lastWebViewTask = webViewWrapperFuture.thenRun(() -> {});;
300303

301304
ICoreWebView2 initializeWebView(ICoreWebView2Controller controller) {
302305
long[] ppv = new long[1];
303306
controller.get_CoreWebView2(ppv);
304307
final ICoreWebView2 webView = new ICoreWebView2(ppv[0]);
305-
initializeWebView_2(webView);
306-
initializeWebView_10(webView);
307-
initializeWebView_11(webView);
308-
initializeWebView_12(webView);
309-
initializeWebView_13(webView);
310-
webViewFuture.complete(webView);
308+
final WebViewWrapper webViewWrapper = new WebViewWrapper();
309+
webViewWrapper.webView = webView;
310+
webViewWrapper.webView_2 = initializeWebView_2(webView);
311+
webViewWrapper.webView_10 = initializeWebView_10(webView);
312+
webViewWrapper.webView_11 = initializeWebView_11(webView);
313+
webViewWrapper.webView_12 = initializeWebView_12(webView);
314+
webViewWrapper.webView_13= initializeWebView_13(webView);
315+
webViewWrapperFuture.complete(webViewWrapper);
311316
return webView;
312317
}
313318

319+
private CompletableFuture<WebViewWrapper> initializeWebViewFutureWithTimeOut() {
320+
CompletableFuture<WebViewWrapper> webViewWrapperFuture = new CompletableFuture<>();
321+
webViewWrapperFuture.orTimeout(3, TimeUnit.MILLISECONDS).exceptionally(exception -> {
322+
releaseEnvironment();
323+
// Needs to be executed on the display thread since the exceptionally spawns a different thread
324+
browser.getDisplay().execute(() -> replaceWithErrorLabel());
325+
// Throw exception on the Display thread directly to prevent CompletableFuture
326+
// to wrap the exception and throw it silently
327+
// browser.getDisplay().execute(() -> SWT.error(SWT.ERROR_UNSPECIFIED, exception, "Edge Browser initialization timed out"));
328+
return null;
329+
});
330+
return webViewWrapperFuture;
331+
}
332+
314333
private void abortInitialization() {
315-
webViewFuture.cancel(true);
334+
webViewWrapperFuture.cancel(true);
316335
}
317336

318-
private void initializeWebView_2(ICoreWebView2 webView) {
337+
private ICoreWebView2_2 initializeWebView_2(ICoreWebView2 webView) {
319338
long[] ppv = new long[1];
320339
int hr = webView.QueryInterface(COM.IID_ICoreWebView2_2, ppv);
321340
if (hr == COM.S_OK) {
322-
webView_2Future.complete(new ICoreWebView2_2(ppv[0]));
323-
} else {
324-
webView_2Future.cancel(true);
341+
return new ICoreWebView2_2(ppv[0]);
325342
}
343+
return null;
326344
}
327345

328-
private void initializeWebView_10(ICoreWebView2 webView) {
346+
private ICoreWebView2_10 initializeWebView_10(ICoreWebView2 webView) {
329347
long[] ppv = new long[1];
330348
int hr = webView.QueryInterface(COM.IID_ICoreWebView2_10, ppv);
331349
if (hr == COM.S_OK) {
332-
webView_10Future.complete(new ICoreWebView2_10(ppv[0]));
333-
} else {
334-
webView_10Future.cancel(true);
350+
return new ICoreWebView2_10(ppv[0]);
335351
}
352+
return null;
336353
}
337354

338-
private void initializeWebView_11(ICoreWebView2 webView) {
355+
private ICoreWebView2_11 initializeWebView_11(ICoreWebView2 webView) {
339356
long[] ppv = new long[1];
340357
int hr = webView.QueryInterface(COM.IID_ICoreWebView2_11, ppv);
341358
if (hr == COM.S_OK) {
342-
webView_11Future.complete(new ICoreWebView2_11(ppv[0]));
343-
} else {
344-
webView_11Future.cancel(true);
359+
return new ICoreWebView2_11(ppv[0]);
345360
}
361+
return null;
346362
}
347363

348-
private void initializeWebView_12(ICoreWebView2 webView) {
364+
private ICoreWebView2_12 initializeWebView_12(ICoreWebView2 webView) {
349365
long[] ppv = new long[1];
350366
int hr = webView.QueryInterface(COM.IID_ICoreWebView2_12, ppv);
351367
if (hr == COM.S_OK) {
352-
webView_12Future.complete(new ICoreWebView2_12(ppv[0]));
353-
} else {
354-
webView_12Future.cancel(true);
368+
return new ICoreWebView2_12(ppv[0]);
355369
}
370+
return null;
356371
}
357372

358-
private void initializeWebView_13(ICoreWebView2 webView) {
373+
private ICoreWebView2_13 initializeWebView_13(ICoreWebView2 webView) {
359374
long[] ppv = new long[1];
360375
int hr = webView.QueryInterface(COM.IID_ICoreWebView2_13, ppv);
361376
if (hr == COM.S_OK) {
362-
webView_13Future.complete(new ICoreWebView2_13(ppv[0]));
363-
} else {
364-
webView_13Future.cancel(true);
377+
return new ICoreWebView2_13(ppv[0]);
365378
}
379+
return null;
366380
}
367381

368382
ICoreWebView2 getWebView(boolean waitForPendingWebviewTasksToFinish) {
369383
if(waitForPendingWebviewTasksToFinish) {
370384
waitForFutureToFinish(lastWebViewTask);
371385
}
372-
return webViewFuture.join();
386+
return webViewWrapperFuture.join().webView;
373387
}
374388

375389
ICoreWebView2_2 getWebView_2(boolean waitForPendingWebviewTasksToFinish) {
376390
if(waitForPendingWebviewTasksToFinish) {
377391
waitForFutureToFinish(lastWebViewTask);
378392
}
379-
return webView_2Future.join();
393+
return webViewWrapperFuture.join().webView_2;
380394
}
381395

382396
boolean isWebView_2Available() {
383-
waitForFutureToFinish(webView_2Future);
384-
return !webView_2Future.isCancelled();
397+
waitForFutureToFinish(webViewWrapperFuture);
398+
return webViewWrapperFuture.join().webView_2 != null;
385399
}
386400

387401
ICoreWebView2_10 getWebView_10(boolean waitForPendingWebviewTasksToFinish) {
388402
if(waitForPendingWebviewTasksToFinish) {
389403
waitForFutureToFinish(lastWebViewTask);
390404
}
391-
return webView_10Future.join();
405+
return webViewWrapperFuture.join().webView_10;
392406
}
393407

394408
boolean isWebView_10Available() {
395-
waitForFutureToFinish(webView_10Future);
396-
return !webView_10Future.isCancelled();
409+
waitForFutureToFinish(webViewWrapperFuture);
410+
return webViewWrapperFuture.join().webView_10 != null;
397411
}
398412

399413
ICoreWebView2_11 getWebView_11(boolean waitForPendingWebviewTasksToFinish) {
400414
if(waitForPendingWebviewTasksToFinish) {
401415
waitForFutureToFinish(lastWebViewTask);
402416
}
403-
return webView_11Future.join();
417+
return webViewWrapperFuture.join().webView_11;
404418
}
405419

406420
boolean isWebView_11Available() {
407-
waitForFutureToFinish(webView_11Future);
408-
return !webView_11Future.isCancelled();
421+
waitForFutureToFinish(webViewWrapperFuture);
422+
return webViewWrapperFuture.join().webView_11 != null;
409423
}
410424

411425
ICoreWebView2_12 getWebView_12(boolean waitForPendingWebviewTasksToFinish) {
412426
if(waitForPendingWebviewTasksToFinish) {
413427
waitForFutureToFinish(lastWebViewTask);
414428
}
415-
return webView_12Future.join();
429+
return webViewWrapperFuture.join().webView_12;
416430
}
417431

418432
boolean isWebView_12Available() {
419-
waitForFutureToFinish(webView_12Future);
420-
return !webView_12Future.isCancelled();
433+
waitForFutureToFinish(webViewWrapperFuture);
434+
return webViewWrapperFuture.join().webView_12 != null;
421435
}
422436

423437
ICoreWebView2_13 getWebView_13(boolean waitForPendingWebviewTasksToFinish) {
424438
if(waitForPendingWebviewTasksToFinish) {
425439
waitForFutureToFinish(lastWebViewTask);
426440
}
427-
return webView_13Future.join();
441+
return webViewWrapperFuture.join().webView_13;
428442
}
429443

430444
boolean isWebView_13Available() {
431-
waitForFutureToFinish(webView_13Future);
432-
return !webView_13Future.isCancelled();
445+
waitForFutureToFinish(webViewWrapperFuture);
446+
return webViewWrapperFuture.join().webView_13 != null;
433447
}
434448

435449
/*
@@ -571,6 +585,15 @@ private String getDataDir(Display display) {
571585
return dataDir;
572586
}
573587

588+
private void replaceWithErrorLabel() {
589+
Label errorLabel = new Label(browser.getParent(), SWT.WRAP);
590+
errorLabel.setForeground(browser.getDisplay().getSystemColor(SWT.COLOR_RED));
591+
errorLabel.setText("Edge browser initialization failed");
592+
errorLabel.setLocation(0, 0);
593+
errorLabel.setSize(browser.getSize());
594+
browser.setVisible(false);
595+
}
596+
574597
@Override
575598
public void create(Composite parent, int style) {
576599
createInstance(0);
@@ -587,21 +610,13 @@ private void createInstance(int previousAttempts) {
587610
}
588611

589612
private IUnknown createControllerInitializationCallback(int previousAttempts) {
590-
Runnable initializationRollback = () -> {
591-
webViewProvider.abortInitialization();
592-
if (environment2 != null) {
593-
environment2.Release();
594-
environment2 = null;
595-
}
596-
containingEnvironment.instances().remove(this);
597-
};
598613
return newCallback((result, pv) -> {
599614
if (browser.isDisposed()) {
600-
initializationRollback.run();
615+
rollbackInitialization();
601616
return COM.S_OK;
602617
}
603618
if (result == OS.HRESULT_FROM_WIN32(OS.ERROR_INVALID_STATE)) {
604-
initializationRollback.run();
619+
rollbackInitialization();
605620
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null,
606621
" Edge instance with same data folder but different environment options already exists");
607622
}
@@ -611,14 +626,14 @@ private IUnknown createControllerInitializationCallback(int previousAttempts) {
611626
setupBrowser((int) result, pv);
612627
break;
613628
case COM.E_WRONG_THREAD:
614-
initializationRollback.run();
629+
rollbackInitialization();
615630
error(SWT.ERROR_THREAD_INVALID_ACCESS, (int) result);
616631
break;
617632
case COM.E_ABORT:
618-
initializationRollback.run();
633+
rollbackInitialization();
619634
break;
620635
default:
621-
initializationRollback.run();
636+
rollbackInitialization();
622637
if (previousAttempts < MAXIMUM_CREATION_RETRIES) {
623638
System.err.println(String.format("Edge initialization failed, retrying (attempt %d / %d)", previousAttempts + 1, MAXIMUM_CREATION_RETRIES));
624639
createInstance(previousAttempts + 1);
@@ -632,6 +647,19 @@ private IUnknown createControllerInitializationCallback(int previousAttempts) {
632647
});
633648
}
634649

650+
private void rollbackInitialization() {
651+
webViewProvider.abortInitialization();
652+
releaseEnvironment();
653+
}
654+
655+
private void releaseEnvironment() {
656+
if (environment2 != null) {
657+
environment2.Release();
658+
environment2 = null;
659+
}
660+
containingEnvironment.instances().remove(this);
661+
}
662+
635663
void setupBrowser(int hr, long pv) {
636664
long[] ppv = new long[] {pv};
637665
controller = new ICoreWebView2Controller(ppv[0]);

tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ private int reportOpenedDescriptors() {
302302
}
303303

304304
private Browser createBrowser(Shell s, int flags) {
305-
long maximumBrowserCreationMilliseconds = 90_000;
305+
long maximumBrowserCreationMilliseconds = 10_000;
306306
long createStartTime = System.currentTimeMillis();
307307
Browser b = new Browser(s, flags);
308308
// Wait for asynchronous initialization via getting URL

0 commit comments

Comments
 (0)