@@ -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
575598public void create (Composite parent , int style ) {
576599 createInstance (0 );
@@ -587,21 +610,13 @@ private void createInstance(int previousAttempts) {
587610}
588611
589612private 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+
635663void setupBrowser (int hr , long pv ) {
636664 long [] ppv = new long [] {pv };
637665 controller = new ICoreWebView2Controller (ppv [0 ]);
0 commit comments