From f633d04f5e167b1d64c7ad1c3bb4cc9b9dd6719a Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Fri, 25 Apr 2025 18:53:44 +0200 Subject: [PATCH] [Edge] Add fallback when WebView2 runtime is not present #2000 When using WebView2 as browser engine in SWT without a WebView2 runtime being available on the system, browser initialization fails. In order to more gracefully handle the case that a system has no such runtime installed (like on some Windows 10 systems), this change introduces an automatic fallback option to Internet Explorer in case no WebView2 runtime is found. It shows a dialog informing about the missing runtime, the option to fallback to IE and also allows to open further information provided via the FAQ. Fixes https://github.com/eclipse-platform/eclipse.platform.swt/issues/2000 --- .../org/eclipse/swt/browser/Browser.java | 74 ++++++++++++++++++- 1 file changed, 70 insertions(+), 4 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java b/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java index 6d0403b9082..3f4eb80708e 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java @@ -13,7 +13,10 @@ *******************************************************************************/ package org.eclipse.swt.browser; +import java.util.*; + import org.eclipse.swt.*; +import org.eclipse.swt.program.*; import org.eclipse.swt.widgets.*; /** @@ -93,10 +96,7 @@ public Browser (Composite parent, int style) { } style = getStyle (); - webBrowser = new BrowserFactory ().createWebBrowser (style); - if (webBrowser != null) { - webBrowser.setBrowser (this); - webBrowser.create (parent, style); + if (createWebBrowser(parent, style)) { return; } dispose (); @@ -119,6 +119,72 @@ public Browser (Composite parent, int style) { SWT.error (SWT.ERROR_NO_HANDLES, null, errMsg); } +private boolean createWebBrowser(Composite parent, int style) { + webBrowser = new BrowserFactory ().createWebBrowser (style); + if (webBrowser == null) { + return false; + } + webBrowser.setBrowser (this); + try { + webBrowser.create (parent, style); + return true; + } catch (SWTError error) { + boolean isEdge = "win32".equals(SWT.getPlatform()) && (style & SWT.IE) == 0; + if (isEdge && error.code == SWT.ERROR_NOT_IMPLEMENTED) { + WebViewUnavailableDialog.showAsync(getShell()); + } + throw error; + } +} + +private class WebViewUnavailableDialog { + private record DialogOption(int index, String message) {}; + private static final DialogOption USE_IE_OPTION = new DialogOption(SWT.YES, "Use IE"); + private static final DialogOption MORE_INFORMATION_OPTION = new DialogOption(SWT.NO, "Information"); + private static final DialogOption CANCEL_OPTION = new DialogOption(SWT.CANCEL, "Cancel"); + + private static final String DIALOG_TITLE = "Default browser engine not available"; + private static final String DIALOG_MESSAGE = "Microsoft Edge (WebView2) is not available. Do you want to use the legacy Internet Explorer?\n\nNote: It is necessary to reopen browsers for the change to take effect."; + private static final String FAQ_URL = "https://github.com/eclipse-platform/eclipse.platform/tree/master/docs/FAQ/FAQ_How_do_I_use_Edge-IE_as_the_Browser's_underlying_renderer.md"; + + private static final int DIALOG_OPTION_FLAGS = USE_IE_OPTION.index | MORE_INFORMATION_OPTION.index | CANCEL_OPTION.index; + private static final Map DIALOG_OPTION_LABELS = Map.of( // + USE_IE_OPTION.index, USE_IE_OPTION.message, // + MORE_INFORMATION_OPTION.index, MORE_INFORMATION_OPTION.message, // + CANCEL_OPTION.index, CANCEL_OPTION.message); + + private static boolean shownOnce; + + static void showAsync(Shell parentShell) { + if (shownOnce) { + return; + } + shownOnce = true; + parentShell.getDisplay().asyncExec(() -> { + processDialog(parentShell); + }); + } + + static private void processDialog(Shell parentShell) { + MessageBox fallbackInfoBox = new MessageBox(parentShell, SWT.ICON_ERROR | DIALOG_OPTION_FLAGS); + fallbackInfoBox.setText(DIALOG_TITLE); + fallbackInfoBox.setMessage(DIALOG_MESSAGE); + fallbackInfoBox.setButtonLabels(DIALOG_OPTION_LABELS); + boolean completed; + do { + int result = fallbackInfoBox.open(); + completed = true; + if (result == MORE_INFORMATION_OPTION.index) { + Program.launch(FAQ_URL); + completed = false; + } else if (result == USE_IE_OPTION.index) { + System.setProperty(PROPERTY_DEFAULTTYPE, "ie"); + DefaultType = SWT.IE; + } + } while (!completed); + } +} + static Composite checkParent (Composite parent) { String platform = SWT.getPlatform (); if (!"gtk".equals (platform)) return parent; //$NON-NLS-1$