Skip to content

Commit

Permalink
Use Chrome for Testing JSON endpoint for version discovering as of ch…
Browse files Browse the repository at this point in the history
…romedriver 115
  • Loading branch information
bonigarcia committed Jun 20, 2023
1 parent e9ac99c commit 0d49671
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 28 deletions.
28 changes: 10 additions & 18 deletions src/main/java/io/github/bonigarcia/wdm/WebDriverManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -1200,25 +1200,17 @@ protected String resolveDriverVersion(String driverVersion) {

if (optionalBrowserVersion.isPresent()) {
resolvedBrowserVersion = optionalBrowserVersion.get();
Optional<String> optionalDriverVersion;
// TODO restore this
if (resolvedBrowserVersion.contains(".")) {
optionalDriverVersion = Optional.of(resolvedBrowserVersion);
preferenceKey = getKeyForResolutionCache() + resolvedBrowserVersion;
Optional<String> optionalDriverVersion = getValueFromResolutionCache(
preferenceKey);

} else {
preferenceKey = getKeyForResolutionCache()
+ resolvedBrowserVersion;
optionalDriverVersion = getValueFromResolutionCache(
preferenceKey);

if (!optionalDriverVersion.isPresent()) {
optionalDriverVersion = getDriverVersionFromRepository(
optionalBrowserVersion);
}
if (!optionalDriverVersion.isPresent()) {
optionalDriverVersion = getVersionDetector()
.getDriverVersionFromProperties(preferenceKey);
}
if (!optionalDriverVersion.isPresent()) {
optionalDriverVersion = getDriverVersionFromRepository(
optionalBrowserVersion);
}
if (!optionalDriverVersion.isPresent()) {
optionalDriverVersion = getVersionDetector()
.getDriverVersionFromProperties(preferenceKey);
}
if (optionalDriverVersion.isPresent()) {
driverVersion = optionalDriverVersion.get();
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/io/github/bonigarcia/wdm/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ public class Config {
"wdm.chromeDriverMirrorUrl", URL.class);
ConfigKey<String> chromeDownloadUrlPattern = new ConfigKey<>(
"wdm.chromeDownloadUrlPattern", String.class);
ConfigKey<String> chromeGoodVersionsUrl = new ConfigKey<>(
"wdm.chromeGoodVersionsUrl", String.class);
ConfigKey<String> chromeLastGoodVersionsUrl = new ConfigKey<>(
"wdm.chromeLastGoodVersionsUrl", String.class);

ConfigKey<String> edgeDriverVersion = new ConfigKey<>(
"wdm.edgeDriverVersion", String.class);
Expand Down Expand Up @@ -790,6 +794,24 @@ public Config setChromeDownloadUrlPattern(String value) {
return this;
}

public String getChromeGoodVersionsUrl() {
return resolve(chromeGoodVersionsUrl);
}

public Config setChromeGoodVersionsUrl(String value) {
this.chromeGoodVersionsUrl.setValue(value);
return this;
}

public String getChromeLastGoodVersionsUrl() {
return resolve(chromeLastGoodVersionsUrl);
}

public Config setChromeLastGoodVersionsUrl(String value) {
this.chromeLastGoodVersionsUrl.setValue(value);
return this;
}

public String getEdgeDriverVersion() {
return resolve(edgeDriverVersion);
}
Expand Down
49 changes: 49 additions & 0 deletions src/main/java/io/github/bonigarcia/wdm/online/GoodVersions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* (C) Copyright 2023 Boni Garcia (https://bonigarcia.github.io/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.github.bonigarcia.wdm.online;

import java.util.List;

/**
* POJO to parse the Chrome for Testing (CfT) JSON endpoints
* (https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json).
*
* @author Boni Garcia
* @since 5.4.0
*/
public class GoodVersions {

public String timestamp;
public List<Versions> versions;

public class Versions {
public String version;
public String revision;
public Downloads downloads;
}

public class Downloads {
public List<PlatformUrl> chrome;
public List<PlatformUrl> chromedriver;
}

public class PlatformUrl {
public String platform;
public String url;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* (C) Copyright 2023 Boni Garcia (https://bonigarcia.github.io/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.github.bonigarcia.wdm.online;

import com.google.gson.annotations.SerializedName;

import io.github.bonigarcia.wdm.online.GoodVersions.Downloads;

/**
* POJO to parse the Chrome for Testing (CfT) JSON endpoints
* (https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json).
*
* @author Boni Garcia
* @since 5.4.0
*/
public class LastGoodVersions {

public String timestamp;
public Channels channels;

public class Channels {
@SerializedName("Stable")
public Channel stable;

@SerializedName("Beta")
public Channel beta;

@SerializedName("Dev")
public Channel dev;

@SerializedName("Canary")
public Channel canary;
}

public class Channel {
public String channel;
public String version;
public String revision;
public Downloads downloads;
}

}
52 changes: 52 additions & 0 deletions src/main/java/io/github/bonigarcia/wdm/online/Parser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* (C) Copyright 2023 Boni Garcia (https://bonigarcia.github.io/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.github.bonigarcia.wdm.online;

import static java.lang.invoke.MethodHandles.lookup;
import static org.slf4j.LoggerFactory.getLogger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.slf4j.Logger;

import com.google.gson.GsonBuilder;

/**
* JSON parser for online endpoints.
*
* @author Boni Garcia
* @since 5.4.0
*/
public class Parser {

static final Logger log = getLogger(lookup().lookupClass());

public static <T> T parseJson(HttpClient client, String url, Class<T> klass)
throws IOException {
HttpGet get = client.createHttpGet(new URL(url));
InputStream content = client.execute(get).getEntity().getContent();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(content))) {
return new GsonBuilder().create().fromJson(reader, klass);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Locale.ROOT;
import static java.util.Optional.empty;
import static java.util.stream.Collectors.toList;
import static org.slf4j.LoggerFactory.getLogger;

import java.io.File;
Expand All @@ -47,7 +48,11 @@

import io.github.bonigarcia.wdm.config.Config;
import io.github.bonigarcia.wdm.config.OperatingSystem;
import io.github.bonigarcia.wdm.online.GoodVersions;
import io.github.bonigarcia.wdm.online.GoodVersions.Versions;
import io.github.bonigarcia.wdm.online.HttpClient;
import io.github.bonigarcia.wdm.online.LastGoodVersions;
import io.github.bonigarcia.wdm.online.Parser;

/**
* Driver and browser version detector.
Expand Down Expand Up @@ -109,6 +114,41 @@ public Optional<String> getDriverVersionFromRepository(
Optional<String> driverVersion, URL driverUrl,
Charset versionCharset, String driverName, String versionLabel,
String latestLabel, Optional<String> optOsLabel) {

if (driverName.equalsIgnoreCase("chromedriver")) {
String cftUrl = null;
try {
if (driverVersion.isPresent()
&& Integer.parseInt(driverVersion.get()) >= 115) {
// Parse JSON using GoodVersions
cftUrl = config.getChromeGoodVersionsUrl();

System.out.println(driverVersion);
GoodVersions versions = Parser.parseJson(httpClient, cftUrl,
GoodVersions.class);
List<Versions> fileteredList = versions.versions.stream()
.filter(v -> v.version
.startsWith(driverVersion.get()))
.collect(toList());

return Optional.of(fileteredList
.get(fileteredList.size() - 1).version);
} else {
// Parse JSON using LastGoodVersions
cftUrl = config.getChromeLastGoodVersionsUrl();

System.out.println(driverVersion);
LastGoodVersions versions = Parser.parseJson(httpClient,
cftUrl, LastGoodVersions.class);
return Optional.of(versions.channels.stable.version);
}
} catch (Exception e) {
log.warn("Exception reading {} to get version of {} ({})",
cftUrl, driverName, e.getMessage());
}

}

String osLabel = optOsLabel.isPresent() ? optOsLabel.get() : "";
String url = driverVersion.isPresent()
? driverUrl + latestLabel + "_" + driverVersion.get() + osLabel
Expand All @@ -127,6 +167,7 @@ public Optional<String> getDriverVersionFromRepository(
log.debug("Latest version of {} according to {} is {}", driverName,
url, result.get());
}

return result;
}

Expand Down Expand Up @@ -282,17 +323,8 @@ protected Optional<String> getBrowserVersionUsingCommand(String command) {
String parsedBrowserVersion = browserVersionOutput
.replaceAll(config.getBrowserVersionDetectionRegex(), "");
log.trace("Detected browser version is {}", parsedBrowserVersion);
String majorVersion = getMajorVersion(parsedBrowserVersion);

// As of Chrome/chromedriver 115+, the online metadata for version
// discovery is different. See:
// https://googlechromelabs.github.io/chrome-for-testing/
if (command.toLowerCase(ROOT).contains("chrome")
&& Integer.parseInt(majorVersion) >= 115) {
return Optional.of(parsedBrowserVersion);
}

return Optional.of(majorVersion);
return Optional.of(getMajorVersion(parsedBrowserVersion));
} else {

return empty();
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/webdrivermanager.properties
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ wdm.chromeDriverUrl=https://chromedriver.storage.googleapis.com/
wdm.chromeDriverMirrorUrl=https://registry.npmmirror.com/-/binary/chromedriver/
wdm.chromeDriverExport=webdriver.chrome.driver
wdm.chromeDownloadUrlPattern=https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/%s/%s/chromedriver-%s.zip
wdm.chromeGoodVersionsUrl=https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json
wdm.chromeLastGoodVersionsUrl=https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json

wdm.geckoDriverUrl=https://raw.githubusercontent.com/bonigarcia/webdrivermanager/master/docs/mirror/geckodriver
wdm.geckoDriverMirrorUrl=https://registry.npmmirror.com/-/binary/geckodriver/
Expand Down

0 comments on commit 0d49671

Please sign in to comment.