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 eclipse-platform#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)