-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Preparing chrome driver to download in headless mode #5262
Preparing chrome driver to download in headless mode #5262
Conversation
The method send commands to the browser to avoid blocking of downloading in headless mode. (The issue is described here: SeleniumHQ#5159)
Instead of providing a single method which sets this command, we should actually provide a method that allows sending arbitrary commands to DevTools. After that, anyone can easily use it to allow downloading. In Ruby, such API can look like this: driver.send_chromium_command(cmd: 'Page.setDownloadBehavior', params: {behavior: 'allow', downloadPath: '/User/paulo/projects/app/tmp'}) |
Also don't forget adding tests that cover new code. |
By the way, why do you create a new http client instead of using CommandExecutor to send a command? |
I've thought about this feature a bit more. Yes, a function to send custom commands is a good thing, we should add it. But in this special case it looks like a workaround. Implementing a capability that enables/disables file download would be much more in line with Selenium strategy to handle such features. |
Why isn't this simply making a change to the |
of downloading in headless mode. (The issue is described here: SeleniumHQ#5159)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is super-close to being ready. Thanks for waiting for us.
I've added a couple of "stylistic comments": we can fix those ourselves, but it'd be nice if you could fix those too.
@@ -133,6 +134,8 @@ public JsonHttpCommandCodec() { | |||
defineCommand(TOUCH_MOVE, post("/session/:sessionId/touch/move")); | |||
defineCommand(TOUCH_SCROLL, post("/session/:sessionId/touch/scroll")); | |||
defineCommand(TOUCH_UP, post("/session/:sessionId/touch/up")); | |||
|
|||
defineCommand(SEND_COMMAND_TO_BROWSER, post("/session/:sessionId/chromium/send_command_and_get_result")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is Chrome specific, and so shouldn't be in the general JsonHttpCommandCodec. The best place is ChromeDriverCommandExecutor
@@ -179,6 +180,10 @@ public ChromeDriver(ChromeDriverService service, ChromeOptions options) { | |||
@Deprecated | |||
public ChromeDriver(ChromeDriverService service, Capabilities capabilities) { | |||
super(new ChromeDriverCommandExecutor(service), capabilities); | |||
if (capabilities.getCapability("enableDownloading")!=null){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stylistic comment: Prefer a little more space around things: ) != null) {
@@ -179,6 +180,10 @@ public ChromeDriver(ChromeDriverService service, ChromeOptions options) { | |||
@Deprecated | |||
public ChromeDriver(ChromeDriverService service, Capabilities capabilities) { | |||
super(new ChromeDriverCommandExecutor(service), capabilities); | |||
if (capabilities.getCapability("enableDownloading")!=null){ | |||
sendCommandForDownloadChromeHeadLess( | |||
(String) capabilities.getCapability("enableDownloading")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may get a ClassCastException
here. There are two ways to avoid this: either make the check above be capabilities.getCapability("enableDownloading") instanceof String
, or use String.valueOf
here.
@@ -179,6 +180,10 @@ public ChromeDriver(ChromeDriverService service, ChromeOptions options) { | |||
@Deprecated | |||
public ChromeDriver(ChromeDriverService service, Capabilities capabilities) { | |||
super(new ChromeDriverCommandExecutor(service), capabilities); | |||
if (capabilities.getCapability("enableDownloading")!=null){ | |||
sendCommandForDownloadChromeHeadLess( | |||
(String) capabilities.getCapability("enableDownloading")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enableDownloading
is not a legal capability name. chromium:enableDownloading
is. The reasoning is here: https://w3c.github.io/webdriver/webdriver-spec.html#dfn-extension-capability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: We're not the Chromium project and shouldn't introduce capabilities in their namespace.
How about using the selenium:chrome
prefix?
* @param downloadPath | ||
*/ | ||
public void sendCommandForDownloadChromeHeadLess(String downloadPath) { | ||
if (downloadPath.length()>0){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if the path is zero length? That seems like an unusual position to be in. Log or throw an error?
* @param downloadPath | ||
*/ | ||
public void sendCommandForDownloadChromeHeadLess(String downloadPath) { | ||
if (downloadPath.length()>0){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stylistic comment: if (!downloadPath.isEmpty()) {
is preferable.
@@ -24,4 +24,7 @@ | |||
private ChromeDriverCommand() {} | |||
|
|||
static final String LAUNCH_APP = "launchApp"; | |||
static final String SEND_COMMANDS_FOR_DOWNLOAD_CHROME_HEAD_LESS | |||
= "sendCommandForDownloadChromeHeadLess"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Headless
is one word, not two, and so doesn't need camelcasing in this way.
if (enableDownloading){ | ||
setCapability(ENABLE_DOWNLOADING, downloadPath); | ||
}else { | ||
setCapability(ENABLE_DOWNLOADING, ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting the capability to null
will remove it from the map, which is probably more desirable.
@@ -235,6 +236,15 @@ public ChromeOptions setAcceptInsecureCerts(boolean acceptInsecureCerts) { | |||
return this; | |||
} | |||
|
|||
public ChromeOptions setEnableDownloading(boolean enableDownloading, String downloadPath){ | |||
if (enableDownloading){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stylistic note: whitespace around braces: if (enableDownloading) {
.
@@ -47,6 +47,7 @@ | |||
String ELEMENT_SCROLL_BEHAVIOR = "elementScrollBehavior"; | |||
String HAS_TOUCHSCREEN = "hasTouchScreen"; | |||
String OVERLAPPING_CHECK_DISABLED = "overlappingCheckDisabled"; | |||
String ENABLE_DOWNLOADING = "chromium:enableDownloading"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name enableDownloading
implies this is a boolean capability. How about downloadDir
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for review. I believe that "downloadDir" is not so appropriate in this case because it sounds like specifying download directory rather than applying download behavior for specific path. It could cause some misunderstanding as to why we introduce this capability. What about AllowHeadlessDownloadTo?
From one hand, it is boolean, from the other hand, it specify the downloading directory. There are no ways to allow downloading without specifying directory for downloading. There are no way to specify directory for downloading without allowing downloading.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not specific to headless, so how about allowDownloadsTo
?
of downloading in headless mode. (The issue is described here: SeleniumHQ#5159)
After talking with the chromedriver team, the See the issue raised in the chromium bugtracker: https://bugs.chromium.org/p/chromedriver/issues/detail?id=2307 |
Do I need to continue looking at this PR? |
The chromium change is to the api interface but they still support the call used in this PR. The changes here are necessary in order to use the API that chromium is providing. Oh - perhaps this is taken care of by #5989 instead? |
|
@shs96c Are we still going to accept this patch? |
This went stale a while ago, and probably it should be possible through the new interface with CDP. If there is the need to have this in the Java tree, please talk to us in our Slack/IRC channel. |
The method send commands to the browser to avoid blocking
of downloading in headless mode.
(The issue is described here:
#5159)
X
in the preceding checkbox, I verify that I have signed the Contributor License AgreementThis change is