Skip to content

Commit 6cd6756

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 6cd6756

File tree

2 files changed

+108
-81
lines changed

2 files changed

+108
-81
lines changed

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

+108-77
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();
@@ -1284,42 +1292,66 @@ int handleNavigationCompleted(long pView, long pArgs, boolean top) {
12841292
return COM.S_OK;
12851293
}
12861294

1287-
void updateWindowFeatures(ICoreWebView2NewWindowRequestedEventArgs args, WindowEvent event) {
1288-
long[] ppv = new long[1];
1289-
int hr = args.get_WindowFeatures(ppv);
1290-
if (hr != COM.S_OK) return;
1291-
ICoreWebView2WindowFeatures features = new ICoreWebView2WindowFeatures(ppv[0]);
1292-
1293-
int[] px = new int[1], py = new int[1];
1294-
features.get_HasPosition(px);
1295-
if (px[0] != 0) {
1296-
features.get_Left(px);
1297-
features.get_Top(py);
1298-
event.location = new Point(px[0], py[0]);
1299-
}
1300-
features.get_HasSize(px);
1301-
if (px[0] != 0) {
1302-
features.get_Width(px);
1303-
features.get_Height(py);
1304-
event.size = new Point(px[0], py[0]);
1305-
}
1306-
// event.addressBar = ???
1307-
features.get_ShouldDisplayMenuBar(px);
1308-
event.menuBar = px[0] != 0;
1309-
features.get_ShouldDisplayStatus(px);
1310-
event.statusBar = px[0] != 0;
1311-
features.get_ShouldDisplayToolbar(px);
1312-
event.toolBar = px[0] != 0;
1295+
private class WindowFeatures {
1296+
boolean hasPosition;
1297+
boolean hasSize;
1298+
int x, y, width, height;
1299+
boolean shouldDisplayMenuBar;
1300+
boolean shouldDisplayStatus;
1301+
boolean shouldDisplayToolBar;
1302+
1303+
public WindowFeatures(ICoreWebView2NewWindowRequestedEventArgs args) {
1304+
long[] ppv = new long[1];
1305+
int hr = args.get_WindowFeatures(ppv);
1306+
if (hr != COM.S_OK) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
1307+
ICoreWebView2WindowFeatures features = new ICoreWebView2WindowFeatures(ppv[0]);
1308+
int[] px = new int[1];
1309+
features.get_HasPosition(px);
1310+
this.hasPosition = px[0] != 0;
1311+
if(this.hasPosition) {
1312+
features.get_Left(px);
1313+
this.x = px[0];
1314+
features.get_Top(px);
1315+
this.y = px[0];
1316+
}
1317+
features.get_HasSize(px);
1318+
this.hasSize = px[0] != 0;
1319+
if (this.hasSize) {
1320+
features.get_Width(px);
1321+
this.width = px[0];
1322+
features.get_Height(px);
1323+
this.height = px[0];
1324+
}
1325+
features.get_ShouldDisplayMenuBar(px);
1326+
this.shouldDisplayMenuBar = px[0] != 0;
1327+
features.get_ShouldDisplayStatus(px);
1328+
this.shouldDisplayStatus = px[0] != 0;
1329+
features.get_ShouldDisplayToolbar(px);
1330+
this.shouldDisplayToolBar = px[0] != 0;
1331+
}
1332+
}
1333+
1334+
void updateWindowFeatures(WindowFeatures windowFeatures, WindowEvent event) {
1335+
if (windowFeatures.hasPosition) {
1336+
event.location = new Point(windowFeatures.x, windowFeatures.y);
1337+
}
1338+
if (windowFeatures.hasSize) {
1339+
event.size = new Point(windowFeatures.width, windowFeatures.height);
1340+
}
1341+
event.menuBar = windowFeatures.shouldDisplayMenuBar;
1342+
event.statusBar = windowFeatures.shouldDisplayStatus;
1343+
event.toolBar = windowFeatures.shouldDisplayToolBar;
13131344
}
13141345

13151346
int handleNewWindowRequested(long pView, long pArgs) {
13161347
ICoreWebView2NewWindowRequestedEventArgs args = new ICoreWebView2NewWindowRequestedEventArgs(pArgs);
13171348
args.AddRef();
1318-
long[] ppv = new long[1];
1319-
args.GetDeferral(ppv);
1320-
ICoreWebView2Deferral deferral = new ICoreWebView2Deferral(ppv[0]);
1349+
WindowFeatures windowFeatures = new WindowFeatures(args);
1350+
long[] ppszUrl = new long[1];
1351+
args.get_Uri(ppszUrl);
1352+
String url = getExposedUrl(wstrToString(ppszUrl[0], true));
13211353
inNewWindow = true;
1322-
browser.getDisplay().asyncExec(() -> {
1354+
executeAsynchronously(() -> {
13231355
try {
13241356
if (browser.isDisposed()) return;
13251357
WindowEvent openEvent = new WindowEvent(browser);
@@ -1332,30 +1364,24 @@ int handleNewWindowRequested(long pView, long pArgs) {
13321364
}
13331365
if (openEvent.browser != null && !openEvent.browser.isDisposed()) {
13341366
WebBrowser other = openEvent.browser.webBrowser;
1335-
args.put_Handled(true);
13361367
if (other instanceof Edge otherEdge) {
1337-
args.put_NewWindow(otherEdge.webViewProvider.getWebView(true).getAddress());
1338-
1368+
otherEdge.setUrl(url, null, null);
13391369
// Send show event to the other browser.
13401370
WindowEvent showEvent = new WindowEvent (other.browser);
13411371
showEvent.display = browser.getDisplay();
13421372
showEvent.widget = other.browser;
1343-
updateWindowFeatures(args, showEvent);
1344-
for (VisibilityWindowListener showListener : other.visibilityWindowListeners) {
1345-
showListener.show(showEvent);
1346-
if (other.browser.isDisposed()) return;
1347-
}
1373+
updateWindowFeatures(windowFeatures, showEvent);
1374+
for (VisibilityWindowListener showListener : other.visibilityWindowListeners) {
1375+
showListener.show(showEvent);
1376+
if (other.browser.isDisposed()) return;
1377+
}
13481378
}
1349-
} else if (openEvent.required) {
1350-
args.put_Handled(true);
13511379
}
13521380
} finally {
1353-
deferral.Complete();
1354-
deferral.Release();
1355-
args.Release();
13561381
inNewWindow = false;
13571382
}
13581383
});
1384+
args.put_Handled(true);
13591385
return COM.S_OK;
13601386
}
13611387

@@ -1426,7 +1452,8 @@ int handleAcceleratorKeyPressed(long pView, long pArgs) {
14261452
}
14271453
} else {
14281454
keyEvent.type = SWT.KeyUp;
1429-
browser.notifyListeners (keyEvent.type, keyEvent);
1455+
executeAsynchronously(() -> browser.notifyListeners (keyEvent.type, keyEvent));
1456+
14301457
if (!keyEvent.doit) {
14311458
args.put_Handled(true);
14321459
}
@@ -1500,6 +1527,10 @@ public boolean setText(String html, boolean trusted) {
15001527
return setWebpageData(URI_FOR_CUSTOM_TEXT_PAGE.toString(), null, null, html);
15011528
}
15021529

1530+
private void executeAsynchronously(Runnable runnable) {
1531+
browser.getDisplay().asyncExec(runnable);
1532+
}
1533+
15031534
private boolean setWebpageData(String url, String postData, String[] headers, String html) {
15041535
// Feature in WebView2. Partial URLs like "www.example.com" are not accepted.
15051536
// 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)