Skip to content

Commit d7febc4

Browse files
committed
Edge: properly handle initialization failures and abortion
There is currently only few handling for failures during initialization of an Edge browser / WebView instance. The Microsoft documentation provides further information on this, in particular: - ERROR_INVALID_STATE indicates that multiple Edge instances with the same data folder but different environment options exist - E_ABORT indicates an active abortion of the initialization process - On any other non-OK return value than the above ones, the app should retry initialization of the instance; to avoid endless waiting, the number of retries is currently limited to 5 This change adds appropriate handling for these scenarios, consisting of uniform rollback logic when the initialization fails or is aborted and retry logic to make repeated creation attempts. Contributes to #1664
1 parent 6104592 commit d7febc4

File tree

3 files changed

+55
-20
lines changed
  • bundles/org.eclipse.swt
    • Eclipse SWT Browser/win32/org/eclipse/swt/browser
    • Eclipse SWT PI/win32/org/eclipse/swt/internal

3 files changed

+55
-20
lines changed

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

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ class Edge extends WebBrowser {
5757
private static final URI URI_FOR_CUSTOM_TEXT_PAGE = setupAndGetLocationForCustomTextPage();
5858
private static final String ABOUT_BLANK = "about:blank";
5959

60+
private static final int MAXIMUM_CREATION_RETRIES = 5;
61+
6062
private record WebViewEnvironment(ICoreWebView2Environment environment, ArrayList<Edge> instances) {
6163
public WebViewEnvironment(ICoreWebView2Environment environment) {
6264
this (environment, new ArrayList<>());
@@ -309,6 +311,10 @@ ICoreWebView2 initializeWebView(ICoreWebView2Controller controller) {
309311
return webView;
310312
}
311313

314+
private void abortInitialization() {
315+
webViewFuture.cancel(true);
316+
}
317+
312318
private void initializeWebView_2(ICoreWebView2 webView) {
313319
long[] ppv = new long[1];
314320
int hr = webView.QueryInterface(COM.IID_ICoreWebView2_2, ppv);
@@ -567,39 +573,66 @@ private String getDataDir(Display display) {
567573

568574
@Override
569575
public void create(Composite parent, int style) {
576+
createInstance(0);
577+
}
578+
579+
private void createInstance(int previousAttempts) {
570580
containingEnvironment = createEnvironment();
571581
containingEnvironment.instances().add(this);
572582
long[] ppv = new long[1];
573583
int hr = containingEnvironment.environment().QueryInterface(COM.IID_ICoreWebView2Environment2, ppv);
574584
if (hr == COM.S_OK) environment2 = new ICoreWebView2Environment2(ppv[0]);
575585
// The webview calls are queued to be executed when it is done executing the current task.
576-
IUnknown setupBrowserCallback = newCallback((result, pv) -> {
577-
if ((int)result == COM.S_OK) {
586+
containingEnvironment.environment().CreateCoreWebView2Controller(browser.handle, createControllerInitializationCallback(previousAttempts));
587+
}
588+
589+
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+
};
598+
return newCallback((result, pv) -> {
599+
if (browser.isDisposed()) {
600+
initializationRollback.run();
601+
return COM.S_OK;
602+
}
603+
if (result == OS.HRESULT_FROM_WIN32(OS.ERROR_INVALID_STATE)) {
604+
initializationRollback.run();
605+
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null,
606+
" Edge instance with same data folder but different environment options already exists");
607+
}
608+
switch ((int) result) {
609+
case COM.S_OK:
578610
new IUnknown(pv).AddRef();
611+
setupBrowser((int) result, pv);
612+
break;
613+
case COM.E_WRONG_THREAD:
614+
initializationRollback.run();
615+
error(SWT.ERROR_THREAD_INVALID_ACCESS, (int) result);
616+
break;
617+
case COM.E_ABORT:
618+
initializationRollback.run();
619+
break;
620+
default:
621+
initializationRollback.run();
622+
if (previousAttempts < MAXIMUM_CREATION_RETRIES) {
623+
System.err.println(String.format("Edge initialization failed, retrying (attempt %d / %d)", previousAttempts + 1, MAXIMUM_CREATION_RETRIES));
624+
createInstance(previousAttempts + 1);
625+
} else {
626+
SWT.error(SWT.ERROR_UNSPECIFIED, null,
627+
String.format(" Aborting Edge initialiation after %d retries", MAXIMUM_CREATION_RETRIES));
628+
}
629+
break;
579630
}
580-
setupBrowser((int)result, pv);
581631
return COM.S_OK;
582632
});
583-
containingEnvironment.environment().CreateCoreWebView2Controller(browser.handle, setupBrowserCallback);
584633
}
585634

586635
void setupBrowser(int hr, long pv) {
587-
if(browser.isDisposed()) {
588-
browserDispose(new Event());
589-
return;
590-
}
591-
switch (hr) {
592-
case COM.S_OK:
593-
break;
594-
case COM.E_WRONG_THREAD:
595-
containingEnvironment.instances().remove(this);
596-
error(SWT.ERROR_THREAD_INVALID_ACCESS, hr);
597-
break;
598-
default:
599-
System.err.println("WebView instantiation failed with result: " + hr);
600-
containingEnvironment.instances().remove(this);
601-
error(SWT.ERROR_NO_HANDLES, hr);
602-
}
603636
long[] ppv = new long[] {pv};
604637
controller = new ICoreWebView2Controller(ppv[0]);
605638
final ICoreWebView2 webView = webViewProvider.initializeWebView(controller);

bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/ole/win32/COM.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ public class COM extends OS {
183183
public static final int DV_E_STGMEDIUM = -2147221402;
184184
public static final int DV_E_TYMED = -2147221399;
185185
public static final int DVASPECT_CONTENT = 1;
186+
public static final int E_ABORT = 0x80004004;
186187
public static final int E_ACCESSDENIED = 0x80070005;
187188
public static final int E_FAIL = -2147467259;
188189
public static final int E_INVALIDARG = -2147024809;

bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ public class OS extends C {
457457
public static final int EN_CHANGE = 0x300;
458458
public static final int EP_EDITTEXT = 1;
459459
public static final int ERROR_FILE_NOT_FOUND = 0x2;
460+
public static final int ERROR_INVALID_STATE = 0x139F;
460461
public static final int ERROR_NO_MORE_ITEMS = 0x103;
461462
public static final int ERROR_CANCELED = 0x4C7;
462463
public static final int ESB_DISABLE_BOTH = 0x3;

0 commit comments

Comments
 (0)