Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Grid] Support auto downloads in Grid #11702

Merged
merged 7 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions common/src/web/downloads/download.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en" class="h-100">

<head>
<title>Downloads</title>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<link href="//cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>

<body class="d-flex flex-column h-100">
<main class="flex-shrink-2">
<div class="container">
<div class="row">
<div class="col-12">
<h1 class="display-6">Downloads</h1>
</div>
</div>
<div class="row">
<div class="col-md-12 py-2">
<div class="tp-align-right mt-3">
<a href="file_1.txt" id="file-1" download>
File 1
</a>
</div>
<div class="form-group tp-align-right mt-3">
<a href="file_2.jpg" id="file-2" download>
File 2
</a>
</div>
</div>

</div>
</div>
</main>
</body>

</html>
1 change: 1 addition & 0 deletions common/src/web/downloads/file_1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, World!
Binary file added common/src/web/downloads/file_2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions java/src/org/openqa/selenium/grid/data/DefaultSlotMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ public boolean matches(Capabilities stereotype, Capabilities capabilities) {
return false;
}

if (!managedDownloadsEnabled(stereotype, capabilities)) {
return false;
}

if (!platformVersionMatch(stereotype, capabilities)) {
return false;
}
Expand Down Expand Up @@ -106,6 +110,19 @@ private Boolean initialMatch(Capabilities stereotype, Capabilities capabilities)
.orElse(true);
}

private Boolean managedDownloadsEnabled(Capabilities stereotype, Capabilities capabilities) {
// First lets check if user wanted a Node with managed downloads enabled
Object raw = capabilities.getCapability("se:downloadsEnabled");
if (raw == null || !Boolean.parseBoolean(raw.toString())) {
// User didn't ask. So lets move on to the next matching criteria
return true;
}
// User wants managed downloads enabled to be done on this Node, let's check the stereotype
raw = stereotype.getCapability("se:downloadsEnabled");
// Try to match what the user requested
return raw != null && Boolean.parseBoolean(raw.toString());
}

private Boolean platformVersionMatch(Capabilities stereotype, Capabilities capabilities) {
/*
This platform version match is not W3C compliant but users can add Appium servers as
Expand Down
13 changes: 10 additions & 3 deletions java/src/org/openqa/selenium/grid/node/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
package org.openqa.selenium.grid.node;

import com.google.common.collect.ImmutableMap;

import org.openqa.selenium.BuildInfo;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.NoSuchSessionException;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.grid.data.CreateSessionRequest;
import org.openqa.selenium.grid.data.CreateSessionResponse;
import org.openqa.selenium.grid.data.NodeId;
Expand All @@ -41,13 +43,13 @@
import org.openqa.selenium.remote.tracing.SpanDecorator;
import org.openqa.selenium.remote.tracing.Tracer;
import org.openqa.selenium.status.HasReadyState;
import org.openqa.selenium.WebDriverException;

import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
Expand Down Expand Up @@ -210,16 +212,21 @@ public ImmutableMap<String, String> getOsInfo() {
return OS_INFO;
}

public abstract Either<WebDriverException, CreateSessionResponse> newSession(CreateSessionRequest sessionRequest);
public abstract Either<WebDriverException, CreateSessionResponse> newSession(
CreateSessionRequest sessionRequest);

public abstract HttpResponse executeWebDriverCommand(HttpRequest req);

public abstract Session getSession(SessionId id) throws NoSuchSessionException;

public TemporaryFilesystem getTemporaryFilesystem(SessionId id) throws IOException {
public TemporaryFilesystem getUploadsFilesystem(SessionId id) throws IOException {
throw new UnsupportedOperationException();
}

public TemporaryFilesystem getDownloadsFilesystem(UUID uuid) throws IOException {
throw new UnsupportedOperationException();
}

public abstract HttpResponse uploadFile(HttpRequest req, SessionId id);

public abstract HttpResponse downloadFile(HttpRequest req, SessionId id);
Expand Down
16 changes: 10 additions & 6 deletions java/src/org/openqa/selenium/grid/node/config/NodeFlags.java
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,16 @@ public class NodeFlags implements HasRoles {
private String nodeImplementation = DEFAULT_NODE_IMPLEMENTATION;

@Parameter(
names = {"--downloads-path"},
description = "The default location wherein all browser triggered file downloads would be "
+ "available to be retrieved from. This is usually the directory that you configure in "
+ "your browser as the default location for storing downloaded files.")
@ConfigValue(section = NODE_SECTION, name = "downloads-path", example = "")
private String downloadsPath = "";
names = {"--enable-managed-downloads"},
arity = 1,
description = "When enabled, the Grid node will automatically do the following: " +
"1. Creates a directory named '$HOME/.cache/selenium/downloads/' which "
+ "will now represent the directory into which files downloaded by "
+ "Chrome/Firefox/Edge browser will be under. " +
"2. For every new session, a sub-directory will be created/deleted so that "
+ "all files that were downloaded for a given session are stored in.")
@ConfigValue(section = NODE_SECTION, name = "enable-managed-downloads", example = "false")
public Boolean managedDownloadsEnabled;

@Override
public Set<Role> getRoles() {
Expand Down
14 changes: 12 additions & 2 deletions java/src/org/openqa/selenium/grid/node/config/NodeOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.openqa.selenium.json.JsonOutput;
import org.openqa.selenium.net.NetworkUtils;
import org.openqa.selenium.net.Urls;
import org.openqa.selenium.remote.Browser;
import org.openqa.selenium.remote.service.DriverService;

import java.io.File;
Expand Down Expand Up @@ -149,8 +150,9 @@ public Optional<URI> getPublicGridUri() {
}
}

public Optional<String> getDownloadsPath() {
return config.get(NODE_SECTION, "downloads-path");
public boolean isManagedDownloadsEnabled() {
return config.getBool(NODE_SECTION, "enable-managed-downloads")
.orElse(Boolean.FALSE);
}

public Node getNode() {
Expand Down Expand Up @@ -634,9 +636,17 @@ private Capabilities enhanceStereotype(Capabilities capabilities) {
.setCapability("se:vncEnabled", true)
.setCapability("se:noVncPort", noVncPort());
}
if (isManagedDownloadsEnabled() && canConfigureDownloadsDir(capabilities)) {
capabilities = new PersistentCapabilities(capabilities)
.setCapability("se:downloadsEnabled", true);
}
return capabilities;
}

private boolean canConfigureDownloadsDir(Capabilities caps) {
return Browser.FIREFOX.is(caps) || Browser.CHROME.is(caps) || Browser.EDGE.is(caps);
}

private void report(Map.Entry<WebDriverInfo, Collection<SessionFactory>> entry) {
StringBuilder caps = new StringBuilder();
try (JsonOutput out = JSON.newOutput(caps)) {
Expand Down
Loading