Skip to content

Commit 38ddb37

Browse files
committed
[grid] Accepting TZ and screenResolution
A user can now get a container in the time zone and screen resolution they prefer.
1 parent 32ce0b4 commit 38ddb37

File tree

1 file changed

+87
-11
lines changed

1 file changed

+87
-11
lines changed

java/server/src/org/openqa/selenium/grid/docker/DockerSessionFactory.java

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717

1818
package org.openqa.selenium.grid.docker;
1919

20-
import com.google.common.collect.ImmutableMap;
2120
import org.openqa.selenium.Capabilities;
21+
import org.openqa.selenium.Dimension;
2222
import org.openqa.selenium.ImmutableCapabilities;
2323
import org.openqa.selenium.SessionNotCreatedException;
2424
import org.openqa.selenium.TimeoutException;
@@ -57,14 +57,17 @@
5757
import java.net.URL;
5858
import java.time.Duration;
5959
import java.time.Instant;
60+
import java.util.Arrays;
6061
import java.util.Collections;
6162
import java.util.HashMap;
6263
import java.util.Map;
6364
import java.util.Objects;
6465
import java.util.Optional;
66+
import java.util.TimeZone;
6567
import java.util.logging.Level;
6668
import java.util.logging.Logger;
6769

70+
import static java.util.Optional.ofNullable;
6871
import static org.openqa.selenium.docker.ContainerConfig.image;
6972
import static org.openqa.selenium.remote.Dialect.W3C;
7073
import static org.openqa.selenium.remote.http.Contents.string;
@@ -130,7 +133,11 @@ public Optional<ActiveSession> apply(CreateSessionRequest sessionRequest) {
130133
attributeMap.put(AttributeKey.LOGGER_CLASS.getKey(),
131134
EventAttribute.setValue(this.getClass().getName()));
132135
LOG.info("Creating container, mapping container port 4444 to " + port);
133-
Container container = docker.create(image(browserImage).map(Port.tcp(4444), Port.tcp(port)));
136+
Map<String, String> browserContainerEnvVars = getBrowserContainerEnvVars(sessionRequest.getCapabilities());
137+
Container container = docker.create(
138+
image(browserImage)
139+
.env(browserContainerEnvVars)
140+
.map(Port.tcp(4444), Port.tcp(port)));
134141
container.start();
135142
ContainerInfo containerInfo = container.inspect();
136143

@@ -188,9 +195,10 @@ public Optional<ActiveSession> apply(CreateSessionRequest sessionRequest) {
188195
Capabilities capabilities = new ImmutableCapabilities((Map<?, ?>) response.getValue());
189196
Container videoContainer = null;
190197
if (isVideoRecordingAvailable && recordVideoForSession(sessionRequest.getCapabilities())) {
191-
Map<String, String> envVars = ImmutableMap.of(
192-
"DISPLAY_CONTAINER_NAME", containerInfo.getIp(),
193-
"FILE_NAME", String.format("%s.mp4", id));
198+
Map<String, String> envVars = getVideoContainerEnvVars(
199+
sessionRequest.getCapabilities(),
200+
containerInfo.getIp(),
201+
id.toString());
194202
Map<String, String> volumeBinds = Collections.singletonMap(storagePath, "/videos");
195203
videoContainer = docker.create(image(videoImage).env(envVars).bind(volumeBinds));
196204
videoContainer.start();
@@ -223,13 +231,81 @@ public Optional<ActiveSession> apply(CreateSessionRequest sessionRequest) {
223231
}
224232
}
225233

226-
private boolean recordVideoForSession(Capabilities sessionRequestCapabilities) {
227-
Object rawSeleniumOptions = sessionRequestCapabilities.getCapability("se:options");
228-
if (rawSeleniumOptions instanceof Map) {
229-
@SuppressWarnings("unchecked") Map<String, Object> seleniumOptions = (Map<String, Object>) rawSeleniumOptions;
230-
return Boolean.parseBoolean(seleniumOptions.getOrDefault("recordVideo", false).toString());
234+
private Map<String, String> getBrowserContainerEnvVars(Capabilities sessionRequestCapabilities) {
235+
Optional<Dimension> screenResolution =
236+
ofNullable(getScreenResolution(sessionRequestCapabilities));
237+
Map<String, String> envVars = new HashMap<>();
238+
if (screenResolution.isPresent()) {
239+
envVars.put("SCREEN_WIDTH", String.valueOf(screenResolution.get().getWidth()));
240+
envVars.put("SCREEN_HEIGHT", String.valueOf(screenResolution.get().getHeight()));
241+
}
242+
Optional<TimeZone> timeZone = ofNullable(getTimeZone(sessionRequestCapabilities));
243+
timeZone.ifPresent(zone -> envVars.put("TZ", zone.getID()));
244+
return envVars;
245+
}
246+
247+
private Map<String, String> getVideoContainerEnvVars(Capabilities sessionRequestCapabilities,
248+
String containerIp, String fileName) {
249+
Map<String, String> envVars = new HashMap<>();
250+
envVars.put("DISPLAY_CONTAINER_NAME", containerIp);
251+
envVars.put("FILE_NAME", String.format("%s.mp4", fileName));
252+
Optional<Dimension> screenResolution =
253+
ofNullable(getScreenResolution(sessionRequestCapabilities));
254+
screenResolution.ifPresent(dimension -> envVars
255+
.put("VIDEO_SIZE", String.format("%sx%s", dimension.getWidth(), dimension.getHeight())));
256+
return envVars;
257+
}
258+
259+
private TimeZone getTimeZone(Capabilities sessionRequestCapabilities) {
260+
Optional<Object> timeZone =
261+
ofNullable(getCapability(sessionRequestCapabilities, "timeZone"));
262+
if (timeZone.isPresent()) {
263+
String tz = timeZone.get().toString();
264+
if (Arrays.asList(TimeZone.getAvailableIDs()).contains(tz)) {
265+
return TimeZone.getTimeZone(tz);
231266
}
232-
return false;
267+
}
268+
return null;
269+
}
270+
271+
private Dimension getScreenResolution(Capabilities sessionRequestCapabilities) {
272+
Optional<Object> screenResolution =
273+
ofNullable(getCapability(sessionRequestCapabilities, "screenResolution"));
274+
if (screenResolution.isEmpty()) {
275+
return null;
276+
}
277+
try {
278+
String[] resolution = screenResolution.get().toString().split("x");
279+
int screenWidth = Integer.parseInt(resolution[0]);
280+
int screenHeight = Integer.parseInt(resolution[1]);
281+
if (screenWidth > 0 && screenHeight > 0) {
282+
return new Dimension(screenWidth, screenHeight);
283+
} else {
284+
LOG.warning("One of the values provided for screenResolution is negative, " +
285+
"defaults will be used. Received value: " + screenResolution);
286+
}
287+
} catch (Exception e) {
288+
LOG.warning("Values provided for screenResolution are not valid integers or " +
289+
"either width or height are missing, defaults will be used." +
290+
"Received value: " + screenResolution);
291+
}
292+
return null;
293+
}
294+
295+
private boolean recordVideoForSession(Capabilities sessionRequestCapabilities) {
296+
Optional<Object> recordVideo =
297+
ofNullable(getCapability(sessionRequestCapabilities, "recordVideo"));
298+
return recordVideo.isPresent() && Boolean.parseBoolean(recordVideo.get().toString());
299+
}
300+
301+
private Object getCapability(Capabilities sessionRequestCapabilities, String capabilityName) {
302+
Object rawSeleniumOptions = sessionRequestCapabilities.getCapability("se:options");
303+
if (rawSeleniumOptions instanceof Map) {
304+
@SuppressWarnings("unchecked")
305+
Map<String, Object> seleniumOptions = (Map<String, Object>) rawSeleniumOptions;
306+
return seleniumOptions.get(capabilityName);
307+
}
308+
return null;
233309
}
234310

235311
private void waitForServerToStart(HttpClient client, Duration duration) {

0 commit comments

Comments
 (0)