Skip to content

Commit 9558d07

Browse files
authored
Merge branch 'trunk' into jspecify
2 parents 44a35bd + f4ef7be commit 9558d07

File tree

13 files changed

+329
-51
lines changed

13 files changed

+329
-51
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<html>
2+
<head>
3+
<title>Modern Modal</title>
4+
<style>
5+
/* Modal background */
6+
#modalBackground {
7+
display: none;
8+
position: fixed;
9+
z-index: 1;
10+
left: 0;
11+
top: 0;
12+
width: 100%;
13+
height: 100%;
14+
overflow: auto;
15+
background-color: rgba(0,0,0,0.4);
16+
}
17+
18+
/* Modal content */
19+
#modalContent {
20+
position: absolute;
21+
background-color: #fff;
22+
padding: 20px;
23+
border: 1px solid #888;
24+
width: 250px;
25+
height: 200px;
26+
z-index: 2;
27+
28+
/* Center the modal */
29+
top: 50%;
30+
left: 50%;
31+
transform: translate(-50%, -50%);
32+
}
33+
34+
/* Close button */
35+
.close {
36+
color: #aaa;
37+
float: right;
38+
font-size: 28px;
39+
font-weight: bold;
40+
cursor: pointer;
41+
}
42+
43+
.close:hover,
44+
.close:focus {
45+
color: black;
46+
text-decoration: none;
47+
cursor: pointer;
48+
}
49+
</style>
50+
</head>
51+
52+
<body>
53+
<p>Modal dialog sample</p>
54+
55+
<input id="trigger-modal-btn" type="button" value="trigger modal" onclick="openModal();">
56+
57+
<a id="trigger-modal-link" href="javascript:openModal()">trigger modal</a>
58+
59+
<!-- Modal structure -->
60+
<div id="modalBackground">
61+
<div id="modalContent">
62+
<span id="modal-close" class="close" onclick="closeModal()">&times;</span>
63+
<span id="modal-text">I am a modal</span>
64+
<input type="text" id="modal-input"/>
65+
</div>
66+
</div>
67+
68+
<script>
69+
function openModal() {
70+
// Display the modal and dim the background
71+
document.getElementById('modalBackground').style.display = 'block';
72+
}
73+
74+
function closeModal() {
75+
// Hide the modal and remove the dimming effect
76+
document.getElementById('modalBackground').style.display = 'none';
77+
}
78+
79+
// Optional: Close the modal when clicking outside of it
80+
window.onclick = function(event) {
81+
var modal = document.getElementById('modalBackground');
82+
if (event.target == modal) {
83+
closeModal();
84+
}
85+
}
86+
</script>
87+
</body>
88+
</html>

java/src/org/openqa/selenium/grid/jmx/MBean.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ public Object getAttribute(String attribute) {
221221
return ((Map<?, ?>) res)
222222
.entrySet().stream()
223223
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toString()));
224+
} else if (res instanceof Number) {
225+
return res;
224226
} else {
225227
return res.toString();
226228
}
@@ -241,7 +243,17 @@ public void setAttribute(Attribute attribute) {
241243

242244
@Override
243245
public AttributeList getAttributes(String[] attributes) {
244-
return null;
246+
AttributeList resultList = new AttributeList();
247+
248+
// if attributeNames is empty, return an empty result list
249+
if (attributes == null || attributes.length == 0) return resultList;
250+
251+
for (int i = 0; i < attributes.length; i++) {
252+
Object value = getAttribute(attributes[i]);
253+
resultList.add(new Attribute(attributes[i], value));
254+
}
255+
256+
return resultList;
245257
}
246258

247259
@Override

java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,30 @@ private Consumer<Message> createWsEndPoint(
226226
LOG.info("Establishing connection to " + uri);
227227

228228
HttpClient client = clientFactory.createClient(ClientConfig.defaultConfig().baseUri(uri));
229-
WebSocket upstream =
230-
client.openSocket(
231-
new HttpRequest(GET, uri.toString()),
232-
new ForwardingListener(downstream, sessionConsumer, sessionId));
233-
return upstream::send;
229+
try {
230+
WebSocket upstream =
231+
client.openSocket(
232+
new HttpRequest(GET, uri.toString()),
233+
new ForwardingListener(downstream, sessionConsumer, sessionId));
234+
235+
return (msg) -> {
236+
try {
237+
upstream.send(msg);
238+
} finally {
239+
if (msg instanceof CloseMessage) {
240+
try {
241+
client.close();
242+
} catch (Exception e) {
243+
LOG.log(Level.WARNING, "Failed to shutdown the client of " + uri, e);
244+
}
245+
}
246+
}
247+
};
248+
} catch (Exception e) {
249+
LOG.log(Level.WARNING, "Connecting to upstream websocket failed", e);
250+
client.close();
251+
throw e;
252+
}
234253
}
235254

236255
private static class ForwardingListener implements WebSocket.Listener {

java/src/org/openqa/selenium/grid/router/ProxyWebsocketsIntoGrid.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,29 @@ public Optional<Consumer<Message>> apply(String uri, Consumer<Message> downstrea
6868

6969
HttpClient client =
7070
clientFactory.createClient(ClientConfig.defaultConfig().baseUri(sessionUri));
71-
WebSocket upstream =
72-
client.openSocket(new HttpRequest(GET, uri), new ForwardingListener(downstream));
73-
74-
return Optional.of(upstream::send);
75-
71+
try {
72+
WebSocket upstream =
73+
client.openSocket(new HttpRequest(GET, uri), new ForwardingListener(downstream));
74+
75+
return Optional.of(
76+
(msg) -> {
77+
try {
78+
upstream.send(msg);
79+
} finally {
80+
if (msg instanceof CloseMessage) {
81+
try {
82+
client.close();
83+
} catch (Exception e) {
84+
LOG.log(Level.WARNING, "Failed to shutdown the client of " + sessionUri, e);
85+
}
86+
}
87+
}
88+
});
89+
} catch (Exception e) {
90+
LOG.log(Level.WARNING, "Connecting to upstream websocket failed", e);
91+
client.close();
92+
return Optional.empty();
93+
}
7694
} catch (NoSuchSessionException e) {
7795
LOG.warning("Attempt to connect to non-existent session: " + uri);
7896
return Optional.empty();

java/src/org/openqa/selenium/netty/server/WebSocketUpgradeHandler.java

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,15 @@ private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) {
165165

166166
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
167167
if (frame instanceof CloseWebSocketFrame) {
168-
CloseWebSocketFrame close = (CloseWebSocketFrame) frame.retain();
169-
handshaker.close(ctx.channel(), close);
170-
// Pass on to the rest of the channel
171-
ctx.fireChannelRead(close);
168+
try {
169+
CloseWebSocketFrame close = (CloseWebSocketFrame) frame.retain();
170+
handshaker.close(ctx.channel(), close);
171+
// Pass on to the rest of the channel
172+
ctx.fireChannelRead(close);
173+
} finally {
174+
// set null to ensure we do not send another close
175+
ctx.channel().attr(key).set(null);
176+
}
172177
} else if (frame instanceof PingWebSocketFrame) {
173178
ctx.write(new PongWebSocketFrame(frame.isFinalFragment(), frame.rsv(), frame.content()));
174179
} else if (frame instanceof PongWebSocketFrame) {
@@ -187,7 +192,7 @@ private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame fram
187192
@Override
188193
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
189194
try {
190-
Consumer<Message> consumer = ctx.channel().attr(key).get();
195+
Consumer<Message> consumer = ctx.channel().attr(key).getAndSet(null);
191196

192197
if (consumer != null) {
193198
byte[] reason = Objects.toString(cause).getBytes(UTF_8);
@@ -201,12 +206,29 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
201206
try {
202207
consumer.accept(new CloseMessage(1011, new String(reason, UTF_8)));
203208
} catch (Exception ex) {
204-
LOG.log(Level.FINE, "failed to send the close message", ex);
209+
LOG.log(Level.FINE, "failed to send the close message, code: 1011", ex);
205210
}
206211
}
207212
} finally {
208213
LOG.log(Level.FINE, "exception caught, close the context", cause);
209214
ctx.close();
210215
}
211216
}
217+
218+
@Override
219+
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
220+
try {
221+
super.channelInactive(ctx);
222+
} finally {
223+
Consumer<Message> consumer = ctx.channel().attr(key).getAndSet(null);
224+
225+
if (consumer != null) {
226+
try {
227+
consumer.accept(new CloseMessage(1001, "channel got inactive"));
228+
} catch (Exception ex) {
229+
LOG.log(Level.FINE, "failed to send the close message, code: 1001", ex);
230+
}
231+
}
232+
}
233+
}
212234
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium;
19+
20+
import static org.assertj.core.api.Assertions.assertThat;
21+
import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOf;
22+
23+
import org.junit.jupiter.api.Test;
24+
import org.openqa.selenium.testing.JupiterTestBase;
25+
26+
class ModernModalTest extends JupiterTestBase {
27+
28+
@Test
29+
void testButtonOpensModal() {
30+
driver.get(pages.modernModalPage);
31+
driver.findElement(By.id("trigger-modal-btn")).click();
32+
33+
WebElement modal = driver.findElement(By.id("modalContent"));
34+
wait.until(visibilityOf(modal));
35+
assertThat(modal.isDisplayed()).isTrue();
36+
}
37+
38+
@Test
39+
void testLinkOpensModal() {
40+
driver.get(pages.modernModalPage);
41+
driver.findElement(By.id("trigger-modal-link")).click();
42+
43+
WebElement modal = driver.findElement(By.id("modalContent"));
44+
wait.until(visibilityOf(modal));
45+
assertThat(modal.isDisplayed()).isTrue();
46+
}
47+
48+
@Test
49+
void testCloseModal() {
50+
driver.get(pages.modernModalPage);
51+
driver.findElement(By.id("trigger-modal-btn")).click();
52+
53+
WebElement modal = driver.findElement(By.id("modalContent"));
54+
wait.until(visibilityOf(modal));
55+
56+
driver.findElement(By.id("modal-close")).click();
57+
assertThat(modal.isDisplayed()).isFalse();
58+
}
59+
}

java/test/org/openqa/selenium/chrome/ChromeDriverFunctionalTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@
5050

5151
class ChromeDriverFunctionalTest extends JupiterTestBase {
5252

53-
private final String CLIPBOARD_READ = "clipboard-read";
54-
private final String CLIPBOARD_WRITE = "clipboard-write";
55-
5653
@Test
5754
@NoDriverBeforeTest
5855
public void builderGeneratesDefaultChromeOptions() {
@@ -109,7 +106,9 @@ void canSetPermission() {
109106
HasPermissions permissions = (HasPermissions) driver;
110107

111108
driver.get(pages.clicksPage);
109+
String CLIPBOARD_READ = "clipboard-read";
112110
assumeThat(checkPermission(driver, CLIPBOARD_READ)).isEqualTo("prompt");
111+
String CLIPBOARD_WRITE = "clipboard-write";
113112
assumeThat(checkPermission(driver, CLIPBOARD_WRITE)).isEqualTo("granted");
114113

115114
permissions.setPermission(CLIPBOARD_READ, "denied");

0 commit comments

Comments
 (0)