Skip to content

Commit

Permalink
Edge: properly handle initialization failures and abortion
Browse files Browse the repository at this point in the history
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

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.
  • Loading branch information
HeikoKlare committed Nov 7, 2024
1 parent c39b59c commit 86c452d
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,10 @@ ICoreWebView2 initializeWebView(ICoreWebView2Controller controller) {
return webView;
}

private void abortInitialization() {
webViewFuture.cancel(true);
}

private void initializeWebView_2(ICoreWebView2 webView) {
long[] ppv = new long[1];
int hr = webView.QueryInterface(COM.IID_ICoreWebView2_2, ppv);
Expand Down Expand Up @@ -567,35 +571,55 @@ private String getDataDir(Display display) {

@Override
public void create(Composite parent, int style) {
createInstance();
}

private void createInstance() {
containingEnvironment = createEnvironment();
long[] ppv = new long[1];
int hr = containingEnvironment.environment().QueryInterface(COM.IID_ICoreWebView2Environment2, ppv);
if (hr == COM.S_OK) environment2 = new ICoreWebView2Environment2(ppv[0]);
// The webview calls are queued to be executed when it is done executing the current task.
IUnknown setupBrowserCallback = newCallback((result, pv) -> {
if ((int)result == COM.S_OK) {
containingEnvironment.environment().CreateCoreWebView2Controller(browser.handle, controllerInitializedCallback());
}

private IUnknown controllerInitializedCallback() {
return newCallback((result, pv) -> {
Runnable rollbackInitialization = () -> {
webViewProvider.abortInitialization();
if (environment2 != null) {
environment2.Release();
}
};
if (browser.isDisposed()) {
rollbackInitialization.run();
}
if (result == OS.HRESULT_FROM_WIN32(OS.ERROR_INVALID_STATE)) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null,
" Edge instance with same data folder but different environment options already exists");
}
switch ((int) result) {
case COM.S_OK:
new IUnknown(pv).AddRef();
setupBrowser((int) result, pv);
break;
case COM.E_WRONG_THREAD:
error(SWT.ERROR_THREAD_INVALID_ACCESS, (int) result);
break;
case COM.E_ABORT:
rollbackInitialization.run();
break;
default:
System.err.println("Edge initialization failed, retrying");
rollbackInitialization.run();
createInstance();
break;
}
setupBrowser((int)result, pv);
return COM.S_OK;
});
containingEnvironment.environment().CreateCoreWebView2Controller(browser.handle, setupBrowserCallback);
}

void setupBrowser(int hr, long pv) {
if(browser.isDisposed()) {
browserDispose(new Event());
return;
}
switch (hr) {
case COM.S_OK:
break;
case COM.E_WRONG_THREAD:
error(SWT.ERROR_THREAD_INVALID_ACCESS, hr);
break;
default:
error(SWT.ERROR_NO_HANDLES, hr);
}
long[] ppv = new long[] {pv};
controller = new ICoreWebView2Controller(ppv[0]);
final ICoreWebView2 webView = webViewProvider.initializeWebView(controller);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ public class COM extends OS {
public static final int DV_E_STGMEDIUM = -2147221402;
public static final int DV_E_TYMED = -2147221399;
public static final int DVASPECT_CONTENT = 1;
public static final int E_ABORT = 0x80004004;
public static final int E_ACCESSDENIED = 0x80070005;
public static final int E_FAIL = -2147467259;
public static final int E_INVALIDARG = -2147024809;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ public class OS extends C {
public static final int EN_CHANGE = 0x300;
public static final int EP_EDITTEXT = 1;
public static final int ERROR_FILE_NOT_FOUND = 0x2;
public static final int ERROR_INVALID_STATE = 0x139F;
public static final int ERROR_NO_MORE_ITEMS = 0x103;
public static final int ERROR_CANCELED = 0x4C7;
public static final int ESB_DISABLE_BOTH = 0x3;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public static Collection<Object[]> browserFlagsToTest() {
if (SwtTestUtil.isWindows) {
// NOTE: This is currently disabled due to test issues in the CI
// Execute Edge tests first, because IE starts some OS timer that conflicts with Edge event handling
// browserFlags.add(0, new Object[] {SWT.EDGE});
browserFlags.add(0, new Object[] {SWT.EDGE});
}
browserFlags.add(new Object[] {SWT.NONE});
return browserFlags;
Expand Down

0 comments on commit 86c452d

Please sign in to comment.