Skip to content

Commit be96afd

Browse files
committed
Avoid using the NewSessionPayload directly
This simplifies creating ActiveSessions since we now know exactly which capabilities we're matching against. This also avoids the remote end attempting to read the payload more than once from the underlying HttpRequest. If we ever manage to not store the entire freaking payload in there, this will avoid some hard to debug issues.
1 parent 776b45d commit be96afd

File tree

7 files changed

+60
-65
lines changed

7 files changed

+60
-65
lines changed

java/server/src/com/thoughtworks/selenium/webdriven/WebDriverBackedSeleniumServlet.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,18 @@
2121

2222
import com.google.common.base.Joiner;
2323
import com.google.common.base.Splitter;
24+
import com.google.common.collect.ImmutableSet;
2425

2526
import com.thoughtworks.selenium.CommandProcessor;
2627
import com.thoughtworks.selenium.SeleniumException;
2728

2829
import org.openqa.selenium.remote.DesiredCapabilities;
30+
import org.openqa.selenium.remote.Dialect;
2931
import org.openqa.selenium.remote.SessionId;
3032
import org.openqa.selenium.remote.server.ActiveSession;
3133
import org.openqa.selenium.remote.server.ActiveSessionFactory;
3234
import org.openqa.selenium.remote.server.ActiveSessionListener;
3335
import org.openqa.selenium.remote.server.ActiveSessions;
34-
import org.openqa.selenium.remote.server.NewSessionPayload;
3536
import org.openqa.selenium.remote.server.WebDriverServlet;
3637

3738
import java.io.IOException;
@@ -211,11 +212,11 @@ private void startNewSession(
211212
}
212213

213214
try {
214-
try (NewSessionPayload payload = NewSessionPayload.create(caps)) {
215-
ActiveSession session = new ActiveSessionFactory().createSession(payload);
216-
sessions.put(session);
217-
sessionId = session.getId();
218-
}
215+
ActiveSession session = new ActiveSessionFactory().createSession(
216+
ImmutableSet.copyOf(Dialect.values()),
217+
caps);
218+
sessions.put(session);
219+
sessionId = session.getId();
219220
} catch (Exception e) {
220221
log("Unable to start session", e);
221222
sendError(

java/server/src/org/openqa/selenium/remote/server/ActiveSessionFactory.java

+10-10
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@
3333
import org.openqa.selenium.Capabilities;
3434
import org.openqa.selenium.SessionNotCreatedException;
3535
import org.openqa.selenium.WebDriver;
36+
import org.openqa.selenium.remote.Dialect;
3637

3738
import java.io.IOException;
3839
import java.util.LinkedHashMap;
3940
import java.util.Map;
4041
import java.util.Objects;
4142
import java.util.ServiceLoader;
43+
import java.util.Set;
4244
import java.util.function.Function;
4345
import java.util.function.Predicate;
4446
import java.util.logging.Logger;
@@ -176,17 +178,15 @@ private static Predicate<Capabilities> containsKey(Pattern pattern) {
176178
return toCompare -> toCompare.asMap().keySet().stream().anyMatch(pattern.asPredicate());
177179
}
178180

179-
public ActiveSession createSession(NewSessionPayload newSessionPayload) throws IOException {
180-
return newSessionPayload.stream()
181-
.peek(caps -> LOG.info("Capabilities are: " + caps))
182-
// Grab any factories that claim to be able to build each capability
183-
.flatMap(caps -> factories.entrySet().stream()
184-
.filter(e -> e.getKey().test(caps))
185-
.peek(e -> LOG.info(String.format("%s matched %s", caps, e.getValue())))
186-
.map(Map.Entry::getValue))
181+
public ActiveSession createSession(Set<Dialect> downstreamDialects, Capabilities caps) {
182+
LOG.info("Capabilities are: " + caps);
183+
return factories.entrySet().stream()
184+
.filter(e -> e.getKey().test(caps))
185+
.peek(e -> LOG.info(String.format("%s matched %s", caps, e.getValue())))
186+
.map(Map.Entry::getValue)
187187
.findFirst()
188-
.map(factory -> factory.apply(newSessionPayload))
188+
.map(factory -> factory.apply(downstreamDialects, caps))
189189
.orElseThrow(() -> new SessionNotCreatedException(
190-
"Unable to create a new session because of no configuration."));
190+
"Unable to create a new session because of no configuration. " + caps));
191191
}
192192
}

java/server/src/org/openqa/selenium/remote/server/InMemorySession.java

+4-25
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,13 @@
1818
package org.openqa.selenium.remote.server;
1919

2020

21-
import static java.nio.charset.StandardCharsets.UTF_8;
22-
2321
import com.google.common.base.Preconditions;
2422
import com.google.common.base.StandardSystemProperty;
2523
import com.google.common.collect.ImmutableMap;
2624
import com.google.common.collect.ImmutableSet;
27-
import com.google.common.io.CharStreams;
2825

2926
import org.openqa.selenium.Capabilities;
3027
import org.openqa.selenium.HasCapabilities;
31-
import org.openqa.selenium.ImmutableCapabilities;
3228
import org.openqa.selenium.SessionNotCreatedException;
3329
import org.openqa.selenium.WebDriver;
3430
import org.openqa.selenium.io.TemporaryFilesystem;
@@ -38,12 +34,8 @@
3834
import org.openqa.selenium.remote.http.HttpRequest;
3935
import org.openqa.selenium.remote.http.HttpResponse;
4036

41-
import java.io.BufferedReader;
4237
import java.io.File;
4338
import java.io.IOException;
44-
import java.io.InputStream;
45-
import java.io.InputStreamReader;
46-
import java.io.Reader;
4739
import java.util.Map;
4840
import java.util.Set;
4941
import java.util.UUID;
@@ -138,32 +130,19 @@ public Factory(DriverProvider provider) {
138130
}
139131

140132
@Override
141-
public ActiveSession apply(NewSessionPayload payload) {
133+
public ActiveSession apply(Set<Dialect> downstreamDialects, Capabilities caps) {
142134
// Assume the blob fits in the available memory.
143-
try (
144-
InputStream is = payload.getPayload().get();
145-
Reader ir = new InputStreamReader(is, UTF_8);
146-
Reader reader = new BufferedReader(ir)) {
147-
Map<?, ?> raw = toBean.convert(Map.class, CharStreams.toString(reader));
148-
Object desired = raw.get("desiredCapabilities");
149-
150-
if (!(desired instanceof Map)) {
151-
return null;
152-
}
153-
154-
@SuppressWarnings("unchecked") ImmutableCapabilities caps =
155-
new ImmutableCapabilities((Map<String, ?>) desired);
156-
135+
try {
157136
if (!provider.canCreateDriverInstanceFor(caps)) {
158137
return null;
159138
}
160139

161140
WebDriver driver = provider.newInstance(caps);
162141

163142
// Prefer the OSS dialect.
164-
Dialect downstream = payload.getDownstreamDialects().contains(Dialect.OSS) ?
143+
Dialect downstream = downstreamDialects.contains(Dialect.OSS) ?
165144
Dialect.OSS :
166-
payload.getDownstreamDialects().iterator().next();
145+
downstreamDialects.iterator().next();
167146
return new InMemorySession(driver, caps, downstream);
168147
} catch (IOException|IllegalStateException e) {
169148
throw new SessionNotCreatedException("Cannot establish new session", e);

java/server/src/org/openqa/selenium/remote/server/ServicedSession.java

+11-8
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,18 @@
2323
import com.google.common.base.Preconditions;
2424
import com.google.common.base.StandardSystemProperty;
2525

26+
import org.openqa.selenium.Capabilities;
2627
import org.openqa.selenium.ImmutableCapabilities;
2728
import org.openqa.selenium.SessionNotCreatedException;
2829
import org.openqa.selenium.WebDriver;
2930
import org.openqa.selenium.io.TemporaryFilesystem;
3031
import org.openqa.selenium.net.PortProber;
3132
import org.openqa.selenium.remote.Augmenter;
33+
import org.openqa.selenium.remote.Command;
3234
import org.openqa.selenium.remote.CommandCodec;
3335
import org.openqa.selenium.remote.CommandExecutor;
3436
import org.openqa.selenium.remote.Dialect;
37+
import org.openqa.selenium.remote.DriverCommand;
3538
import org.openqa.selenium.remote.ProtocolHandshake;
3639
import org.openqa.selenium.remote.RemoteWebDriver;
3740
import org.openqa.selenium.remote.Response;
@@ -50,10 +53,10 @@
5053

5154
import java.io.File;
5255
import java.io.IOException;
53-
import java.io.InputStream;
5456
import java.lang.reflect.Method;
5557
import java.net.URL;
5658
import java.util.Map;
59+
import java.util.Set;
5760
import java.util.function.Supplier;
5861

5962
class ServicedSession implements ActiveSession {
@@ -169,10 +172,10 @@ public static class Factory implements SessionFactory {
169172
}
170173

171174
@Override
172-
public ActiveSession apply(NewSessionPayload payload) {
175+
public ActiveSession apply(Set<Dialect> downstreamDialects, Capabilities capabilities) {
173176
DriverService service = createService.get();
174177

175-
try (InputStream in = payload.getPayload().get()) {
178+
try {
176179
service.start();
177180

178181
PortProber.waitForPortUp(service.getUrl().getPort(), 30, SECONDS);
@@ -181,18 +184,18 @@ public ActiveSession apply(NewSessionPayload payload) {
181184

182185
HttpClient client = new ApacheHttpClient.Factory().createClient(url);
183186

184-
ProtocolHandshake.Result result = new ProtocolHandshake()
185-
.createSession(client, in, payload.getPayloadSize())
186-
.orElseThrow(() -> new SessionNotCreatedException("Unable to create session"));
187+
Command command = new Command(null, DriverCommand.NEW_SESSION, capabilities.asMap());
188+
189+
ProtocolHandshake.Result result = new ProtocolHandshake().createSession(client, command);
187190

188191
SessionCodec codec;
189192
Dialect upstream = result.getDialect();
190193
Dialect downstream;
191-
if (payload.getDownstreamDialects().contains(result.getDialect())) {
194+
if (downstreamDialects.contains(result.getDialect())) {
192195
codec = new Passthrough(url);
193196
downstream = upstream;
194197
} else {
195-
downstream = payload.getDownstreamDialects().iterator().next();
198+
downstream = downstreamDialects.iterator().next();
196199

197200
codec = new ProtocolConverter(
198201
url,

java/server/src/org/openqa/selenium/remote/server/SessionFactory.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
package org.openqa.selenium.remote.server;
1919

2020

21+
import org.openqa.selenium.Capabilities;
22+
import org.openqa.selenium.remote.Dialect;
23+
24+
import java.util.Set;
25+
2126
interface SessionFactory {
22-
ActiveSession apply(NewSessionPayload payload);
27+
ActiveSession apply(Set<Dialect> downstreamDialects, Capabilities capabilities);
2328
}

java/server/src/org/openqa/selenium/remote/server/commandhandler/BeginSession.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.io.IOException;
4141
import java.io.InputStreamReader;
4242
import java.io.Reader;
43+
import java.util.Objects;
4344
import java.util.logging.Level;
4445

4546
public class BeginSession implements CommandHandler {
@@ -69,7 +70,19 @@ public void execute(HttpRequest req, HttpResponse resp) throws IOException {
6970
req.consumeContentStream(),
7071
req.getContentEncoding());
7172
NewSessionPayload payload = new NewSessionPayload(contentLength, reader)) {
72-
session = sessionFactory.createSession(payload);
73+
session = payload.stream()
74+
.map(caps -> {
75+
try {
76+
return sessionFactory.createSession(payload.getDownstreamDialects(), caps);
77+
} catch (SessionNotCreatedException e) {
78+
// Do nothing. We'll complain at the end.
79+
return null;
80+
}
81+
})
82+
.filter(Objects::nonNull)
83+
.findFirst()
84+
.orElseThrow(
85+
() -> new SessionNotCreatedException("Unable to create session: " + payload));
7386
allSessions.put(session);
7487
}
7588

java/server/test/org/openqa/selenium/remote/server/ActiveSessionFactoryTest.java

+8-14
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.openqa.selenium.Capabilities;
2929
import org.openqa.selenium.ImmutableCapabilities;
3030
import org.openqa.selenium.WebDriver;
31+
import org.openqa.selenium.remote.Dialect;
3132

3233
import java.io.IOException;
3334
import java.util.Map;
@@ -47,31 +48,24 @@ protected Iterable<DriverProvider> loadDriverProviders() {
4748
}
4849
};
4950

50-
try (NewSessionPayload payload = new NewSessionPayload(toPayload(caps.getBrowserName()))) {
51-
ActiveSession session = sessionFactory.createSession(payload);
52-
assertEquals(driver, session.getWrappedDriver());
53-
}
51+
ActiveSession session = sessionFactory.createSession(ImmutableSet.of(Dialect.W3C), caps);
52+
assertEquals(driver, session.getWrappedDriver());
5453
}
5554

5655
@Test
5756
public void canBindNewFactoriesAtRunTime() throws IOException {
5857
ActiveSession session = Mockito.mock(ActiveSession.class);
5958

6059
ActiveSessionFactory sessionFactory = new ActiveSessionFactory()
61-
.bind(caps -> "cheese".equals(caps.getBrowserName()), payload -> session);
60+
.bind(caps -> "cheese".equals(caps.getBrowserName()), (dialects, caps) -> session);
6261

63-
try (NewSessionPayload payload = new NewSessionPayload(toPayload("cheese"))) {
64-
ActiveSession created = sessionFactory.createSession(payload);
62+
ActiveSession created = sessionFactory.createSession(ImmutableSet.copyOf(Dialect.values()), toPayload("cheese"));
6563

66-
assertSame(session, created);
67-
}
64+
assertSame(session, created);
6865
}
6966

70-
private Map<String, Object> toPayload(String browserName) {
71-
return ImmutableMap.of(
72-
"capabilities", ImmutableMap.of(
73-
"alwaysMatch", ImmutableMap.of("browserName", browserName)),
74-
"desiredCapabilities", ImmutableMap.of("browserName", browserName));
67+
private Capabilities toPayload(String browserName) {
68+
return new ImmutableCapabilities("browserName", browserName);
7569
}
7670

7771
private static class StubbedProvider implements DriverProvider {

0 commit comments

Comments
 (0)