From 410bfbc8a1e1e5ac4ffc4caa509f7955e2d697b2 Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Tue, 30 Jan 2024 14:27:20 +0100 Subject: [PATCH] Avoid callback release before its usage during Edge instantiation #1013 The handle to a newly instantiated Edge browser is provided via a callback. This callback may be either be invoked synchronously when creating a WebView2 controller (happens on first creation of an Edge browser instance in an application) or asynchronously via a processed OS event (from second creation of an Edge browser instance onwards). The callback is currently released before the OS events are processed, which may cause issues when instantiating more than one Edge browser in a single application. With this change, the callback is only released when it is not required and may not be called anymore. A test instantiating multiple (Edge) browsers in a single application is added to ensure that the asynchronous callback invocation is executed in a test. Contributes to https://github.com/eclipse-platform/eclipse.platform.swt/issues/1013 --- .../win32/org/eclipse/swt/browser/Edge.java | 8 ++++++-- .../Test_org_eclipse_swt_browser_Browser.java | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java b/bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java index 1d83f74be68..57f5c8a95cd 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java @@ -221,10 +221,12 @@ static int callAndWait(long[] ppv, ToIntFunction callable) { }); ppv[0] = 0; phr[0] = callable.applyAsInt(completion); - completion.Release(); + // "completion" callback may be called asynchronously, + // so keep processing next OS message that may call it while (phr[0] == COM.S_OK && ppv[0] == 0) { processNextOSMessage(); } + completion.Release(); return phr[0]; } @@ -239,10 +241,12 @@ static int callAndWait(String[] pstr, ToIntFunction callable) { }); pstr[0] = null; phr[0] = callable.applyAsInt(completion); - completion.Release(); + // "completion" callback may be called asynchronously, + // so keep processing next OS message that may call it while (phr[0] == COM.S_OK && pstr[0] == null) { processNextOSMessage(); } + completion.Release(); return phr[0]; } diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java index bef7f7e5cb7..6b501d2fdfc 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java @@ -280,6 +280,20 @@ public void test_Constructor_asyncParentDisposal() { assertFalse(browser.isDisposed()); } +@Test +public void test_Constructor_multipleInstantiationsInDifferentShells() { + final int numberOfBrowsers = 5; + for (int i = 0; i < numberOfBrowsers; i++) { + Shell browserShell = new Shell(Display.getCurrent()); + Browser browser = createBrowser(browserShell, SWT.EDGE); + assertFalse(browser.isDisposed()); + browser.dispose(); + assertTrue(browser.isDisposed()); + browserShell.dispose(); + assertTrue(browserShell.isDisposed()); + } +} + @Test public void test_evalute_Cookies () { final AtomicBoolean loaded = new AtomicBoolean(false);