Skip to content

Commit c6af804

Browse files
committed
Edge callback listeners execute asyncly #1466
This commit cotributes to executing the registered listeners of Edge browser on Browser callbacks in a asynchronous fashion making sure no WebView related task is executed while a WebView callback is already executing making sure there's no deadlock. contributes to #1771 and #1919
1 parent 5eb3ba2 commit c6af804

File tree

2 files changed

+60
-49
lines changed

2 files changed

+60
-49
lines changed

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

+60-45
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ void browserDispose(Event event) {
814814
if (inCallback) {
815815
ICoreWebView2Controller controller1 = controller;
816816
controller.put_IsVisible(false);
817-
browser.getDisplay().asyncExec(() -> {
817+
executeAsynchronously(() -> {
818818
controller1.Close();
819819
controller1.Release();
820820
});
@@ -960,7 +960,7 @@ private String getExposedUrl(String url) {
960960
}
961961

962962
int handleCloseRequested(long pView, long pArgs) {
963-
browser.getDisplay().asyncExec(() -> {
963+
executeAsynchronously(() -> {
964964
if (browser.isDisposed()) return;
965965
WindowEvent event = new WindowEvent(browser);
966966
event.display = browser.getDisplay();
@@ -978,7 +978,7 @@ int handleDocumentTitleChanged(long pView, long pArgs) {
978978
long[] ppsz = new long[1];
979979
webViewProvider.getWebView(false).get_DocumentTitle(ppsz);
980980
String title = wstrToString(ppsz[0], true);
981-
browser.getDisplay().asyncExec(() -> {
981+
executeAsynchronously(() -> {
982982
if (browser.isDisposed()) return;
983983
TitleEvent event = new TitleEvent(browser);
984984
event.display = browser.getDisplay();
@@ -1031,10 +1031,12 @@ int handleNavigationStarting(long pView, long pArgs, boolean top) {
10311031
event.location = url;
10321032
event.top = top;
10331033
event.doit = true;
1034-
for (LocationListener listener : locationListeners) {
1035-
listener.changing(event);
1036-
if (browser.isDisposed()) return COM.S_OK;
1037-
}
1034+
executeAsynchronously(() -> {
1035+
for (LocationListener listener : locationListeners) {
1036+
listener.changing(event);
1037+
if (browser.isDisposed()) return;
1038+
}
1039+
});
10381040
// Save location and top for all events that use navigationId.
10391041
// will be eventually cleared again in handleNavigationCompleted().
10401042
navigations.put(pNavId[0], event);
@@ -1043,11 +1045,13 @@ int handleNavigationStarting(long pView, long pArgs, boolean top) {
10431045
settings.put_IsScriptEnabled(jsEnabled);
10441046
// Register browser functions in the new document.
10451047
if (!functions.isEmpty()) {
1046-
StringBuilder sb = new StringBuilder();
1047-
for (BrowserFunction function : functions.values()) {
1048-
sb.append(function.functionString);
1049-
}
1050-
execute(sb.toString());
1048+
executeAsynchronously(() -> {
1049+
StringBuilder sb = new StringBuilder();
1050+
for (BrowserFunction function : functions.values()) {
1051+
sb.append(function.functionString);
1052+
}
1053+
execute(sb.toString());
1054+
});
10511055
}
10521056
} else {
10531057
args.put_Cancel(true);
@@ -1093,7 +1097,7 @@ int handleSourceChanged(long pView, long pArgs) {
10931097
} else {
10941098
location = url;
10951099
}
1096-
browser.getDisplay().asyncExec(() -> {
1100+
executeAsynchronously(() -> {
10971101
if (browser.isDisposed()) return;
10981102
LocationEvent event = new LocationEvent(browser);
10991103
event.display = browser.getDisplay();
@@ -1110,7 +1114,7 @@ int handleSourceChanged(long pView, long pArgs) {
11101114
}
11111115

11121116
void sendProgressCompleted() {
1113-
browser.getDisplay().asyncExec(() -> {
1117+
executeAsynchronously(() -> {
11141118
if (browser.isDisposed()) return;
11151119
ProgressEvent event = new ProgressEvent(browser);
11161120
event.display = browser.getDisplay();
@@ -1160,22 +1164,24 @@ int handleBasicAuthenticationRequested(long pView, long pArgs) {
11601164
args.get_Uri(ppv);
11611165
String uri = wstrToString(ppv[0], true);
11621166

1163-
for (AuthenticationListener authenticationListener : this.authenticationListeners) {
1164-
AuthenticationEvent event = new AuthenticationEvent (browser);
1165-
event.location = uri;
1166-
authenticationListener.authenticate (event);
1167-
if (!event.doit) {
1168-
args.put_Cancel(true);
1169-
return COM.S_OK;
1170-
}
1171-
if (event.user != null && event.password != null) {
1172-
args.get_Response(ppv);
1173-
ICoreWebView2BasicAuthenticationResponse response = new ICoreWebView2BasicAuthenticationResponse(ppv[0]);
1174-
response.put_UserName(stringToWstr(event.user));
1175-
response.put_Password(stringToWstr(event.password));
1176-
return COM.S_OK;
1167+
executeAsynchronously(() -> {
1168+
for (AuthenticationListener authenticationListener : this.authenticationListeners) {
1169+
AuthenticationEvent event = new AuthenticationEvent (browser);
1170+
event.location = uri;
1171+
authenticationListener.authenticate (event);
1172+
if (!event.doit) {
1173+
args.put_Cancel(true);
1174+
return;
1175+
}
1176+
if (event.user != null && event.password != null) {
1177+
args.get_Response(ppv);
1178+
ICoreWebView2BasicAuthenticationResponse response = new ICoreWebView2BasicAuthenticationResponse(ppv[0]);
1179+
response.put_UserName(stringToWstr(event.user));
1180+
response.put_Password(stringToWstr(event.password));
1181+
return;
1182+
}
11771183
}
1178-
}
1184+
});
11791185

11801186
return COM.S_OK;
11811187
}
@@ -1236,9 +1242,11 @@ int handleStatusBarTextChanged(long pView, long pArgs) {
12361242
statusTextEvent.display = browser.getDisplay();
12371243
statusTextEvent.widget = browser;
12381244
statusTextEvent.text = text;
1239-
for (StatusTextListener statusTextListener : statusTextListeners) {
1240-
statusTextListener.changed(statusTextEvent);
1241-
}
1245+
executeAsynchronously(() -> {
1246+
for (StatusTextListener statusTextListener : statusTextListeners) {
1247+
statusTextListener.changed(statusTextEvent);
1248+
}
1249+
});
12421250
return COM.S_OK;
12431251
}
12441252

@@ -1267,7 +1275,7 @@ int handleNavigationCompleted(long pView, long pArgs, boolean top) {
12671275
int[] pIsSuccess = new int[1];
12681276
args.get_IsSuccess(pIsSuccess);
12691277
if (pIsSuccess[0] != 0) {
1270-
browser.getDisplay().asyncExec(() -> {
1278+
executeAsynchronously(() -> {
12711279
if (browser.isDisposed()) return;
12721280
LocationEvent event = new LocationEvent(browser);
12731281
event.display = browser.getDisplay();
@@ -1319,17 +1327,18 @@ int handleNewWindowRequested(long pView, long pArgs) {
13191327
args.GetDeferral(ppv);
13201328
ICoreWebView2Deferral deferral = new ICoreWebView2Deferral(ppv[0]);
13211329
inNewWindow = true;
1322-
browser.getDisplay().asyncExec(() -> {
13231330
try {
1324-
if (browser.isDisposed()) return;
1331+
if (browser.isDisposed()) return COM.S_OK;
13251332
WindowEvent openEvent = new WindowEvent(browser);
13261333
openEvent.display = browser.getDisplay();
13271334
openEvent.widget = browser;
13281335
openEvent.required = false;
1329-
for (OpenWindowListener openListener : openWindowListeners) {
1330-
openListener.open(openEvent);
1331-
if (browser.isDisposed()) return;
1332-
}
1336+
executeAsynchronously(() -> {
1337+
for (OpenWindowListener openListener : openWindowListeners) {
1338+
openListener.open(openEvent);
1339+
if (browser.isDisposed()) return;
1340+
}
1341+
});
13331342
if (openEvent.browser != null && !openEvent.browser.isDisposed()) {
13341343
WebBrowser other = openEvent.browser.webBrowser;
13351344
args.put_Handled(true);
@@ -1341,10 +1350,12 @@ int handleNewWindowRequested(long pView, long pArgs) {
13411350
showEvent.display = browser.getDisplay();
13421351
showEvent.widget = other.browser;
13431352
updateWindowFeatures(args, showEvent);
1344-
for (VisibilityWindowListener showListener : other.visibilityWindowListeners) {
1345-
showListener.show(showEvent);
1346-
if (other.browser.isDisposed()) return;
1347-
}
1353+
executeAsynchronously(() -> {
1354+
for (VisibilityWindowListener showListener : other.visibilityWindowListeners) {
1355+
showListener.show(showEvent);
1356+
if (other.browser.isDisposed()) return;
1357+
}
1358+
});
13481359
}
13491360
} else if (openEvent.required) {
13501361
args.put_Handled(true);
@@ -1355,7 +1366,6 @@ int handleNewWindowRequested(long pView, long pArgs) {
13551366
args.Release();
13561367
inNewWindow = false;
13571368
}
1358-
});
13591369
return COM.S_OK;
13601370
}
13611371

@@ -1426,7 +1436,8 @@ int handleAcceleratorKeyPressed(long pView, long pArgs) {
14261436
}
14271437
} else {
14281438
keyEvent.type = SWT.KeyUp;
1429-
browser.notifyListeners (keyEvent.type, keyEvent);
1439+
executeAsynchronously(() -> browser.notifyListeners (keyEvent.type, keyEvent));
1440+
14301441
if (!keyEvent.doit) {
14311442
args.put_Handled(true);
14321443
}
@@ -1500,6 +1511,10 @@ public boolean setText(String html, boolean trusted) {
15001511
return setWebpageData(URI_FOR_CUSTOM_TEXT_PAGE.toString(), null, null, html);
15011512
}
15021513

1514+
private void executeAsynchronously(Runnable runnable) {
1515+
browser.getDisplay().asyncExec(runnable);
1516+
}
1517+
15031518
private boolean setWebpageData(String url, String postData, String[] headers, String html) {
15041519
// Feature in WebView2. Partial URLs like "www.example.com" are not accepted.
15051520
// Prepend the protocol if it's missing.

tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java

-4
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,6 @@ public void changed(LocationEvent event) {
739739

740740
@Test
741741
public void test_LocationListener_LocationListener_ordered_changing () {
742-
assumeFalse("Currently broken for Edge", isEdge);
743742
List<String> locations = Collections.synchronizedList(new ArrayList<>());
744743
browser.addLocationListener(changingAdapter(event -> {
745744
locations.add(event.location);
@@ -1572,7 +1571,6 @@ public void completed(ProgressEvent event) {
15721571
*/
15731572
@Test
15741573
public void test_LocationListener_evaluateInCallback() {
1575-
assumeFalse("behavior is not (yet) supported by Edge browser", isEdge);
15761574

15771575
AtomicBoolean changingFinished = new AtomicBoolean(false);
15781576
AtomicBoolean changedFinished = new AtomicBoolean(false);
@@ -1622,7 +1620,6 @@ public void changed(LocationEvent event) {
16221620
/** Verify that evaluation works inside an OpenWindowListener */
16231621
@Test
16241622
public void test_OpenWindowListener_evaluateInCallback() {
1625-
assumeFalse("behavior is not (yet) supported by Edge browser", isEdge);
16261623

16271624
AtomicBoolean eventFired = new AtomicBoolean(false);
16281625
browser.addOpenWindowListener(event -> {
@@ -2183,7 +2180,6 @@ public void test_evaluate_array_mixedTypes () {
21832180
*/
21842181
@Test
21852182
public void test_BrowserFunction_callback () {
2186-
assumeFalse("Currently broken for Edge", isEdge);
21872183
AtomicBoolean javaCallbackExecuted = new AtomicBoolean(false);
21882184

21892185
class JavascriptCallback extends BrowserFunction { // Note: Local class defined inside method.

0 commit comments

Comments
 (0)