Skip to content

Commit

Permalink
Merge branch 'trunk' into add-js-filter-auth
Browse files Browse the repository at this point in the history
  • Loading branch information
pujagani authored Aug 20, 2024
2 parents 9cd48b7 + f4ef7be commit 12dd11f
Show file tree
Hide file tree
Showing 24 changed files with 383 additions and 73 deletions.
4 changes: 4 additions & 0 deletions common/src/web/javascriptPage.html
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,10 @@ <h1>Type Stuff</h1>
</div>
</div>

<form id="aParentFormId">
<input type="text" name="tagName">
</form>

</body>
</html>

Expand Down
88 changes: 88 additions & 0 deletions common/src/web/modal_dialogs/modern_modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<html>
<head>
<title>Modern Modal</title>
<style>
/* Modal background */
#modalBackground {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4);
}

/* Modal content */
#modalContent {
position: absolute;
background-color: #fff;
padding: 20px;
border: 1px solid #888;
width: 250px;
height: 200px;
z-index: 2;

/* Center the modal */
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

/* Close button */
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
}

.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
</style>
</head>

<body>
<p>Modal dialog sample</p>

<input id="trigger-modal-btn" type="button" value="trigger modal" onclick="openModal();">

<a id="trigger-modal-link" href="javascript:openModal()">trigger modal</a>

<!-- Modal structure -->
<div id="modalBackground">
<div id="modalContent">
<span id="modal-close" class="close" onclick="closeModal()">&times;</span>
<span id="modal-text">I am a modal</span>
<input type="text" id="modal-input"/>
</div>
</div>

<script>
function openModal() {
// Display the modal and dim the background
document.getElementById('modalBackground').style.display = 'block';
}

function closeModal() {
// Hide the modal and remove the dimming effect
document.getElementById('modalBackground').style.display = 'none';
}

// Optional: Close the modal when clicking outside of it
window.onclick = function(event) {
var modal = document.getElementById('modalBackground');
if (event.target == modal) {
closeModal();
}
}
</script>
</body>
</html>
9 changes: 6 additions & 3 deletions java/src/org/openqa/selenium/JavascriptExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.openqa.selenium.internal.Require;

/**
Expand All @@ -30,6 +32,7 @@
* request or when trying to access another frame. Most times when troubleshooting failure it's best
* to view the browser's console after executing the WebDriver request.
*/
@NullMarked
public interface JavascriptExecutor {
/**
* Executes JavaScript in the context of the currently selected frame or window. The script
Expand Down Expand Up @@ -63,7 +66,7 @@ public interface JavascriptExecutor {
* @param args The arguments to the script. May be empty
* @return One of Boolean, Long, Double, String, List, Map or WebElement. Or null.
*/
Object executeScript(String script, Object... args);
@Nullable Object executeScript(String script, @Nullable Object... args);

/**
* Execute an asynchronous piece of JavaScript in the context of the currently selected frame or
Expand Down Expand Up @@ -139,7 +142,7 @@ public interface JavascriptExecutor {
* @return One of Boolean, Long, String, List, Map, WebElement, or null.
* @see WebDriver.Timeouts#scriptTimeout(java.time.Duration)
*/
Object executeAsyncScript(String script, Object... args);
@Nullable Object executeAsyncScript(String script, @Nullable Object... args);

/**
* Commonly used scripts may be "pinned" to the WebDriver session, allowing them to be called
Expand Down Expand Up @@ -186,7 +189,7 @@ default Set<ScriptKey> getPinnedScripts() {
*
* @see #executeScript(String, Object...)
*/
default Object executeScript(ScriptKey key, Object... args) {
default @Nullable Object executeScript(ScriptKey key, @Nullable Object... args) {
Require.stateCondition(
key instanceof UnpinnedScriptKey, "Script key should have been generated by this driver");

Expand Down
2 changes: 2 additions & 0 deletions java/src/org/openqa/selenium/OutputType.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import org.jspecify.annotations.NullMarked;

/**
* Defines the output type for a screenshot.
*
* @see TakesScreenshot
* @param <T> Type for the screenshot output.
*/
@NullMarked
public interface OutputType<T> {
/** Obtain the screenshot as base64 data. */
OutputType<String> BASE64 =
Expand Down
3 changes: 3 additions & 0 deletions java/src/org/openqa/selenium/TakesScreenshot.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
// under the License.
package org.openqa.selenium;

import org.jspecify.annotations.NullMarked;

/**
* Indicates a driver or an HTML element that can capture a screenshot and store it in different
* ways.
Expand All @@ -29,6 +31,7 @@
*
* @see OutputType
*/
@NullMarked
public interface TakesScreenshot {
/**
* Capture the screenshot and store it in the specified location.
Expand Down
11 changes: 7 additions & 4 deletions java/src/org/openqa/selenium/WebDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.logging.Logs;

Expand All @@ -46,6 +48,7 @@
* <p>Most implementations of this interface follow <a href="https://w3c.github.io/webdriver/">W3C
* WebDriver specification</a>
*/
@NullMarked
public interface WebDriver extends SearchContext {
// Navigation

Expand Down Expand Up @@ -74,7 +77,7 @@ public interface WebDriver extends SearchContext {
*
* @return The URL of the page currently loaded in the browser
*/
String getCurrentUrl();
@Nullable String getCurrentUrl();

// General properties

Expand All @@ -87,7 +90,7 @@ public interface WebDriver extends SearchContext {
* @return The title of the current page, with leading and trailing whitespace stripped, or null
* if one is not already set
*/
String getTitle();
@Nullable String getTitle();

/**
* Find all elements within the current page using the given mechanism. This method is affected by
Expand Down Expand Up @@ -142,7 +145,7 @@ public interface WebDriver extends SearchContext {
*
* @return The source of the current page
*/
String getPageSource();
@Nullable String getPageSource();

/**
* Close the current window, quitting the browser if it's the last window currently open.
Expand Down Expand Up @@ -261,7 +264,7 @@ interface Options {
* @param name the name of the cookie
* @return the cookie, or null if no cookie with the given name is present
*/
Cookie getCookieNamed(String name);
@Nullable Cookie getCookieNamed(String name);

/**
* @return the interface for managing driver timeouts.
Expand Down
14 changes: 13 additions & 1 deletion java/src/org/openqa/selenium/grid/jmx/MBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ public Object getAttribute(String attribute) {
return ((Map<?, ?>) res)
.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toString()));
} else if (res instanceof Number) {
return res;
} else {
return res.toString();
}
Expand All @@ -241,7 +243,17 @@ public void setAttribute(Attribute attribute) {

@Override
public AttributeList getAttributes(String[] attributes) {
return null;
AttributeList resultList = new AttributeList();

// if attributeNames is empty, return an empty result list
if (attributes == null || attributes.length == 0) return resultList;

for (int i = 0; i < attributes.length; i++) {
Object value = getAttribute(attributes[i]);
resultList.add(new Attribute(attributes[i], value));
}

return resultList;
}

@Override
Expand Down
29 changes: 24 additions & 5 deletions java/src/org/openqa/selenium/grid/node/ProxyNodeWebsockets.java
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,30 @@ private Consumer<Message> createWsEndPoint(
LOG.info("Establishing connection to " + uri);

HttpClient client = clientFactory.createClient(ClientConfig.defaultConfig().baseUri(uri));
WebSocket upstream =
client.openSocket(
new HttpRequest(GET, uri.toString()),
new ForwardingListener(downstream, sessionConsumer, sessionId));
return upstream::send;
try {
WebSocket upstream =
client.openSocket(
new HttpRequest(GET, uri.toString()),
new ForwardingListener(downstream, sessionConsumer, sessionId));

return (msg) -> {
try {
upstream.send(msg);
} finally {
if (msg instanceof CloseMessage) {
try {
client.close();
} catch (Exception e) {
LOG.log(Level.WARNING, "Failed to shutdown the client of " + uri, e);
}
}
}
};
} catch (Exception e) {
LOG.log(Level.WARNING, "Connecting to upstream websocket failed", e);
client.close();
throw e;
}
}

private static class ForwardingListener implements WebSocket.Listener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,29 @@ public Optional<Consumer<Message>> apply(String uri, Consumer<Message> downstrea

HttpClient client =
clientFactory.createClient(ClientConfig.defaultConfig().baseUri(sessionUri));
WebSocket upstream =
client.openSocket(new HttpRequest(GET, uri), new ForwardingListener(downstream));

return Optional.of(upstream::send);

try {
WebSocket upstream =
client.openSocket(new HttpRequest(GET, uri), new ForwardingListener(downstream));

return Optional.of(
(msg) -> {
try {
upstream.send(msg);
} finally {
if (msg instanceof CloseMessage) {
try {
client.close();
} catch (Exception e) {
LOG.log(Level.WARNING, "Failed to shutdown the client of " + sessionUri, e);
}
}
}
});
} catch (Exception e) {
LOG.log(Level.WARNING, "Connecting to upstream websocket failed", e);
client.close();
return Optional.empty();
}
} catch (NoSuchSessionException e) {
LOG.warning("Attempt to connect to non-existent session: " + uri);
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,15 @@ private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) {

private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
if (frame instanceof CloseWebSocketFrame) {
CloseWebSocketFrame close = (CloseWebSocketFrame) frame.retain();
handshaker.close(ctx.channel(), close);
// Pass on to the rest of the channel
ctx.fireChannelRead(close);
try {
CloseWebSocketFrame close = (CloseWebSocketFrame) frame.retain();
handshaker.close(ctx.channel(), close);
// Pass on to the rest of the channel
ctx.fireChannelRead(close);
} finally {
// set null to ensure we do not send another close
ctx.channel().attr(key).set(null);
}
} else if (frame instanceof PingWebSocketFrame) {
ctx.write(new PongWebSocketFrame(frame.isFinalFragment(), frame.rsv(), frame.content()));
} else if (frame instanceof PongWebSocketFrame) {
Expand All @@ -187,7 +192,7 @@ private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame fram
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
try {
Consumer<Message> consumer = ctx.channel().attr(key).get();
Consumer<Message> consumer = ctx.channel().attr(key).getAndSet(null);

if (consumer != null) {
byte[] reason = Objects.toString(cause).getBytes(UTF_8);
Expand All @@ -201,12 +206,29 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
try {
consumer.accept(new CloseMessage(1011, new String(reason, UTF_8)));
} catch (Exception ex) {
LOG.log(Level.FINE, "failed to send the close message", ex);
LOG.log(Level.FINE, "failed to send the close message, code: 1011", ex);
}
}
} finally {
LOG.log(Level.FINE, "exception caught, close the context", cause);
ctx.close();
}
}

@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
try {
super.channelInactive(ctx);
} finally {
Consumer<Message> consumer = ctx.channel().attr(key).getAndSet(null);

if (consumer != null) {
try {
consumer.accept(new CloseMessage(1001, "channel got inactive"));
} catch (Exception ex) {
LOG.log(Level.FINE, "failed to send the close message, code: 1001", ex);
}
}
}
}
}
Loading

0 comments on commit 12dd11f

Please sign in to comment.