17
17
18
18
package org .openqa .selenium .grid .node ;
19
19
20
+ import com .google .common .collect .ImmutableSet ;
21
+
20
22
import org .openqa .selenium .Capabilities ;
21
23
import org .openqa .selenium .devtools .CdpEndpointFinder ;
22
24
import org .openqa .selenium .grid .data .Session ;
32
34
import org .openqa .selenium .remote .http .WebSocket ;
33
35
34
36
import java .net .URI ;
37
+ import java .net .URISyntaxException ;
35
38
import java .util .Objects ;
36
39
import java .util .Optional ;
37
40
import java .util .function .BiFunction ;
42
45
import static org .openqa .selenium .internal .Debug .getDebugLogLevel ;
43
46
import static org .openqa .selenium .remote .http .HttpMethod .GET ;
44
47
45
- public class ProxyNodeCdp implements BiFunction <String , Consumer <Message >, Optional <Consumer <Message >>> {
48
+ public class ProxyNodeWebsockets implements BiFunction <String , Consumer <Message >,
49
+ Optional <Consumer <Message >>> {
46
50
47
51
private static final UrlTemplate CDP_TEMPLATE = new UrlTemplate ("/session/{sessionId}/se/cdp" );
48
- private static final Logger LOG = Logger .getLogger (ProxyNodeCdp .class .getName ());
52
+ private static final UrlTemplate VNC_TEMPLATE = new UrlTemplate ("/session/{sessionId}/se/vnc" );
53
+ private static final Logger LOG = Logger .getLogger (ProxyNodeWebsockets .class .getName ());
54
+ private static final ImmutableSet <String > CDP_ENDPOINT_CAPS =
55
+ ImmutableSet .of ("goog:chromeOptions" ,
56
+ "moz:debuggerAddress" ,
57
+ "ms:edgeOptions" );
49
58
private final HttpClient .Factory clientFactory ;
50
59
private final Node node ;
51
60
52
- public ProxyNodeCdp (HttpClient .Factory clientFactory , Node node ) {
61
+
62
+ public ProxyNodeWebsockets (HttpClient .Factory clientFactory , Node node ) {
53
63
this .clientFactory = Objects .requireNonNull (clientFactory );
54
64
this .node = Objects .requireNonNull (node );
55
65
}
56
66
57
67
@ Override
58
68
public Optional <Consumer <Message >> apply (String uri , Consumer <Message > downstream ) {
59
- UrlTemplate .Match match = CDP_TEMPLATE .match (uri );
60
- if (match == null ) {
69
+ UrlTemplate .Match cdpMatch = CDP_TEMPLATE .match (uri );
70
+ UrlTemplate .Match vncMatch = VNC_TEMPLATE .match (uri );
71
+
72
+ if (cdpMatch == null && vncMatch == null ) {
61
73
return Optional .empty ();
62
74
}
63
75
64
- LOG .fine ("Matching CDP session for " + match .getParameters ().get ("sessionId" ));
76
+ String sessionId = cdpMatch != null ?
77
+ cdpMatch .getParameters ().get ("sessionId" ) :
78
+ vncMatch .getParameters ().get ("sessionId" );
65
79
66
- SessionId id = new SessionId (match .getParameters ().get ("sessionId" ));
80
+ LOG .fine ("Matching websockets for session id: " + sessionId );
81
+ SessionId id = new SessionId (sessionId );
67
82
68
83
if (!node .isSessionOwner (id )) {
69
84
LOG .info ("Not owner of " + id );
@@ -72,40 +87,50 @@ public Optional<Consumer<Message>> apply(String uri, Consumer<Message> downstrea
72
87
73
88
Session session = node .getSession (id );
74
89
Capabilities caps = session .getCapabilities ();
90
+ LOG .fine ("Scanning for endpoint: " + caps );
75
91
76
- LOG .fine ("Scanning for CDP endpoint: " + caps );
77
-
78
- // Using strings here to avoid Node depending upon specific drivers.
79
- Optional <URI > cdpUri = CdpEndpointFinder .getReportedUri ("goog:chromeOptions" , caps )
80
- .flatMap (reported -> CdpEndpointFinder .getCdpEndPoint (clientFactory , reported ));
81
- if (cdpUri .isPresent ()) {
82
- LOG .log (getDebugLogLevel (), "Chrome endpoint found" );
83
- return cdpUri .map (cdp -> createCdpEndPoint (cdp , downstream ));
92
+ if (cdpMatch != null ) {
93
+ return findCdpEndpoint (downstream , caps );
84
94
}
95
+ return findVncEndpoint (downstream , caps );
96
+ }
85
97
86
- cdpUri = CdpEndpointFinder .getReportedUri ("moz:debuggerAddress" , caps )
87
- .flatMap (reported -> CdpEndpointFinder .getCdpEndPoint (clientFactory , reported ));
88
- if (cdpUri .isPresent ()) {
89
- LOG .log (getDebugLogLevel (), "Firefox endpoint found" );
90
- return cdpUri .map (cdp -> createCdpEndPoint (cdp , downstream ));
98
+ private Optional <Consumer <Message >> findCdpEndpoint (Consumer <Message > downstream ,
99
+ Capabilities caps ) {
100
+ // Using strings here to avoid Node depending upon specific drivers.
101
+ for (String cdpEndpointCap : CDP_ENDPOINT_CAPS ) {
102
+ Optional <URI > cdpUri = CdpEndpointFinder .getReportedUri (cdpEndpointCap , caps )
103
+ .flatMap (reported -> CdpEndpointFinder .getCdpEndPoint (clientFactory , reported ));
104
+ if (cdpUri .isPresent ()) {
105
+ LOG .log (getDebugLogLevel (), String .format ("Endpoint found in %s" , cdpEndpointCap ));
106
+ return cdpUri .map (cdp -> createWsEndPoint (cdp , downstream ));
107
+ }
91
108
}
109
+ return Optional .empty ();
110
+ }
92
111
93
- LOG .fine ("Searching for edge options" );
94
- cdpUri = CdpEndpointFinder .getReportedUri ("ms:edgeOptions" , caps )
95
- .flatMap (reported -> CdpEndpointFinder .getCdpEndPoint (clientFactory , reported ));
96
- if (cdpUri .isPresent ()) {
97
- LOG .log (getDebugLogLevel (), "Edge endpoint found" );
112
+ private Optional <Consumer <Message >> findVncEndpoint (Consumer <Message > downstream ,
113
+ Capabilities caps ) {
114
+ String vncLocalAddress = (String ) caps .getCapability ("se:vncLocalAddress" );
115
+ Optional <URI > vncUri ;
116
+ try {
117
+ vncUri = Optional .of (new URI (vncLocalAddress ));
118
+ } catch (URISyntaxException e ) {
119
+ LOG .warning ("Invalid URI for endpoint " + vncLocalAddress );
120
+ return Optional .empty ();
98
121
}
99
- return cdpUri .map (cdp -> createCdpEndPoint (cdp , downstream ));
122
+ LOG .log (getDebugLogLevel (), String .format ("Endpoint found in %s" , "se:vncLocalAddress" ));
123
+ return vncUri .map (vnc -> createWsEndPoint (vnc , downstream ));
100
124
}
101
125
102
- private Consumer <Message > createCdpEndPoint (URI uri , Consumer <Message > downstream ) {
126
+ private Consumer <Message > createWsEndPoint (URI uri , Consumer <Message > downstream ) {
103
127
Objects .requireNonNull (uri );
104
128
105
- LOG .info ("Establishing CDP connection to " + uri );
129
+ LOG .info ("Establishing connection to " + uri );
106
130
107
131
HttpClient client = clientFactory .createClient (ClientConfig .defaultConfig ().baseUri (uri ));
108
- WebSocket upstream = client .openSocket (new HttpRequest (GET , uri .toString ()), new ForwardingListener (downstream ));
132
+ WebSocket upstream = client .openSocket (
133
+ new HttpRequest (GET , uri .toString ()), new ForwardingListener (downstream ));
109
134
return upstream ::send ;
110
135
}
111
136
@@ -133,7 +158,7 @@ public void onText(CharSequence data) {
133
158
134
159
@ Override
135
160
public void onError (Throwable cause ) {
136
- LOG .log (Level .WARNING , "Error proxying CDP command" , cause );
161
+ LOG .log (Level .WARNING , "Error proxying websocket command" , cause );
137
162
}
138
163
}
139
164
}
0 commit comments