Path: blob/trunk/java/src/org/openqa/selenium/Platform.java
3992 views
// Licensed to the Software Freedom Conservancy (SFC) under one1// or more contributor license agreements. See the NOTICE file2// distributed with this work for additional information3// regarding copyright ownership. The SFC licenses this file4// to you under the Apache License, Version 2.0 (the5// "License"); you may not use this file except in compliance6// with the License. You may obtain a copy of the License at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing,11// software distributed under the License is distributed on an12// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13// KIND, either express or implied. See the License for the14// specific language governing permissions and limitations15// under the License.1617package org.openqa.selenium;1819import java.util.Arrays;20import java.util.Locale;21import java.util.regex.Matcher;22import java.util.regex.Pattern;23import org.jspecify.annotations.Nullable;2425/**26* Represents the known and supported Platforms that WebDriver runs on. This is pretty close to the27* Operating System, but differs slightly, because this class is used to extract information such as28* program locations and line endings.29*/30// Useful URLs:31// http://hg.openjdk.java.net/jdk7/modules/jdk/file/a37326fa7f95/src/windows/native/java/lang/java_props_md.c32public enum Platform {3334/** Never returned, but can be used to request a browser running on any version of Windows. */35WINDOWS("windows") {36@Override37public @Nullable Platform family() {38return null;39}4041@Override42public String toString() {43return "windows";44}45},4647/**48* For versions of Windows that "feel like" Windows XP. These are ones that store files in49* "\Program Files\" and documents under "\\documents and settings\\username"50*/51XP("Windows Server 2003", "xp", "windows", "winnt", "windows_nt", "windows nt") {52@Override53public @Nullable Platform family() {54return WINDOWS;55}5657@Override58public String toString() {59return "Windows XP";60}61},6263/** For versions of Windows that "feel like" Windows Vista. */64VISTA("windows vista", "Windows Server 2008") {65@Override66public @Nullable Platform family() {67return WINDOWS;68}6970@Override71public String toString() {72return "Windows Vista";73}74},7576WIN7("windows 7", "win7") {77@Override78public @Nullable Platform family() {79return WINDOWS;80}8182@Override83public String toString() {84return "Windows 7";85}86},8788/** For versions of Windows that "feel like" Windows 8. */89WIN8("Windows Server 2012", "windows 8", "win8") {90@Override91public @Nullable Platform family() {92return WINDOWS;93}9495@Override96public String toString() {97return "Windows 8";98}99},100101WIN8_1("windows 8.1", "win8.1") {102@Override103public @Nullable Platform family() {104return WINDOWS;105}106107@Override108public String toString() {109return "Windows 8.1";110}111},112113WIN10("windows 10", "win10") {114@Override115public @Nullable Platform family() {116return WINDOWS;117}118119@Override120public String toString() {121return "Windows 10";122}123},124125WIN11("windows 11", "win11") {126@Override127public @Nullable Platform family() {128return WINDOWS;129}130131@Override132public String toString() {133return "Windows 11";134}135},136137MAC("mac", "darwin", "macOS", "mac os x", "os x") {138@Override139public @Nullable Platform family() {140return null;141}142143@Override144public String toString() {145return "mac";146}147},148149SNOW_LEOPARD("snow leopard", "os x 10.6", "macos 10.6") {150@Override151public @Nullable Platform family() {152return MAC;153}154155@Override156public String toString() {157return "OS X 10.6";158}159},160161MOUNTAIN_LION("mountain lion", "os x 10.8", "macos 10.8") {162@Override163public @Nullable Platform family() {164return MAC;165}166167@Override168public String toString() {169return "OS X 10.8";170}171},172173MAVERICKS("mavericks", "os x 10.9", "macos 10.9") {174@Override175public @Nullable Platform family() {176return MAC;177}178179@Override180public String toString() {181return "OS X 10.9";182}183},184185YOSEMITE("yosemite", "os x 10.10", "macos 10.10") {186@Override187public @Nullable Platform family() {188return MAC;189}190191@Override192public String toString() {193return "OS X 10.10";194}195},196197EL_CAPITAN("el capitan", "os x 10.11", "macos 10.11") {198@Override199public @Nullable Platform family() {200return MAC;201}202203@Override204public String toString() {205return "OS X 10.11";206}207},208209SIERRA("sierra", "os x 10.12", "macos 10.12") {210@Override211public @Nullable Platform family() {212return MAC;213}214215@Override216public String toString() {217return "macOS 10.12";218}219},220221HIGH_SIERRA("high sierra", "os x 10.13", "macos 10.13") {222@Override223public @Nullable Platform family() {224return MAC;225}226227@Override228public String toString() {229return "macOS 10.13";230}231},232233MOJAVE("mojave", "os x 10.14", "macos 10.14") {234@Override235public @Nullable Platform family() {236return MAC;237}238239@Override240public String toString() {241return "macOS 10.14";242}243},244245CATALINA("catalina", "os x 10.15", "macos 10.15") {246@Override247public @Nullable Platform family() {248return MAC;249}250251@Override252public String toString() {253return "macOS 10.15";254}255},256257BIG_SUR("big sur", "os x 11.0", "macos 11.0") {258@Override259public @Nullable Platform family() {260return MAC;261}262263@Override264public String toString() {265return "macOS 11.0";266}267},268269MONTEREY("monterey", "os x 12.0", "macos 12.0") {270@Override271public @Nullable Platform family() {272return MAC;273}274275@Override276public String toString() {277return "macOS 12.0";278}279},280281VENTURA("ventura", "os x 13.0", "macos 13.0") {282@Override283public @Nullable Platform family() {284return MAC;285}286287@Override288public String toString() {289return "macOS 13.0";290}291},292293SONOMA("sonoma", "os x 14.0", "macos 14.0") {294@Override295public @Nullable Platform family() {296return MAC;297}298299@Override300public String toString() {301return "macOS 14.0";302}303},304305SEQUOIA("sequoia", "os x 15.0", "macos 15.0") {306@Override307public @Nullable Platform family() {308return MAC;309}310311@Override312public String toString() {313return "macOS 15.0";314}315},316317/** Many platforms have UNIX traits, amongst them LINUX, Solaris and BSD. */318UNIX("solaris", "bsd") {319@Override320public @Nullable Platform family() {321return null;322}323},324325LINUX("linux") {326@Override327public @Nullable Platform family() {328return UNIX;329}330331@Override332public String toString() {333return "linux";334}335},336337ANDROID("android", "dalvik") {338@Override339public @Nullable Platform family() {340return null;341}342},343344IOS("iOS") {345@Override346public @Nullable Platform family() {347return null;348}349},350351/** Never returned, but can be used to request a browser running on any operating system. */352ANY("") {353@Override354public @Nullable Platform family() {355return ANY;356}357358@Override359public boolean is(Platform compareWith) {360return this == compareWith;361}362363@Override364public String toString() {365return "any";366}367};368369private static final Pattern VERSION_PATTERN = Pattern.compile("^(\\d+)\\.(\\d+).*");370private static @Nullable Platform current;371private final String[] partOfOsName;372private int minorVersion = 0;373private int majorVersion = 0;374375Platform(String... partOfOsName) {376this.partOfOsName = partOfOsName;377}378379/**380* Get current platform (not necessarily the same as operating system).381*382* @return current platform383*/384public static Platform getCurrent() {385if (current == null) {386current = extractFromSysProperty(System.getProperty("os.name"));387388String version = System.getProperty("os.version", "0.0.0");389int major = 0;390int minor = 0;391392final Matcher matcher = VERSION_PATTERN.matcher(version);393if (matcher.matches()) {394try {395major = Integer.parseInt(matcher.group(1));396minor = Integer.parseInt(matcher.group(2));397} catch (NumberFormatException e) {398// These things happen399}400}401402current.majorVersion = major;403current.minorVersion = minor;404}405return current;406}407408/**409* Extracts platforms based on system properties in Java and uses a heuristic to determine the410* most likely operating system. If unable to determine the operating system, it will default to411* UNIX.412*413* @param osName the operating system name to determine the platform of414* @return the most likely platform based on given operating system name415*/416public static Platform extractFromSysProperty(String osName) {417return extractFromSysProperty(osName, System.getProperty("os.version"));418}419420/**421* Extracts platforms based on system properties in Java and uses a heuristic to determine the422* most likely operating system. If unable to determine the operating system, it will default to423* UNIX.424*425* @param osName the operating system name to determine the platform of426* @param osVersion the operating system version to determine the platform of427* @return the most likely platform based on given operating system name and version428*/429public static Platform extractFromSysProperty(String osName, String osVersion) {430osName = osName.toLowerCase(Locale.ENGLISH);431// os.name for android is linux432if ("dalvik".equalsIgnoreCase(System.getProperty("java.vm.name"))) {433return Platform.ANDROID;434}435// Windows 8 can't be detected by osName alone436if (osVersion.equals("6.2") && osName.startsWith("windows nt")) {437return WIN8;438}439// Windows 8 can't be detected by osName alone440if (osVersion.equals("6.3") && osName.startsWith("windows nt")) {441return WIN8_1;442}443Platform mostLikely = UNIX;444String previousMatch = null;445for (Platform os : Platform.values()) {446for (String matcher : os.partOfOsName) {447if (matcher.isEmpty()) {448continue;449}450matcher = matcher.toLowerCase(Locale.ENGLISH);451if (os.isExactMatch(osName, matcher)) {452return os;453}454if (os.isCurrentPlatform(osName, matcher) && isBetterMatch(previousMatch, matcher)) {455previousMatch = matcher;456mostLikely = os;457}458}459}460461// Default to assuming we're on a UNIX variant (including LINUX)462return mostLikely;463}464465/**466* Gets a platform with the name matching the parameter.467*468* @param name the platform name469* @return the Platform enum value matching the parameter470*/471public static Platform fromString(String name) {472for (Platform platform : values()) {473if (platform.toString().equalsIgnoreCase(name)) {474return platform;475}476}477478for (Platform os : Platform.values()) {479for (String matcher : os.partOfOsName) {480if (name.equalsIgnoreCase(matcher)) {481return os;482}483}484}485throw new WebDriverException("Unrecognized platform: " + name);486}487488/**489* Decides whether the previous match is better or not than the current match. If previous match490* is null, the newer match is always better.491*492* @param previous the previous match493* @param matcher the newer match494* @return true if newer match is better, false otherwise495*/496private static boolean isBetterMatch(@Nullable String previous, String matcher) {497return previous == null || matcher.length() >= previous.length();498}499500public String[] getPartOfOsName() {501return Arrays.copyOf(partOfOsName, partOfOsName.length);502}503504/**505* Heuristic for comparing two platforms. If platforms (which is not the same thing as operating506* systems) are found to be approximately similar in nature, this will return true. For instance507* the LINUX platform is similar to UNIX, and will give a positive result if compared.508*509* @param compareWith the platform to compare with510* @return true if platforms are approximately similar, false otherwise511*/512public boolean is(Platform compareWith) {513return514// Any platform is itself515this == compareWith516||517// Any platform is also ANY platform518compareWith == ANY519||520// And any Platform which is not a platform type belongs to the same family521(this.family() != null && this.family().is(compareWith));522}523524/**525* Returns a platform that represents a family for the current platform. For instance the LINUX if526* a part of the UNIX family, the XP is a part of the WINDOWS family.527*528* @return the family platform for the current one, or {@code null} if this {@code Platform}529* represents a platform family (such as Windows, or MacOS)530*/531public abstract @Nullable Platform family();532533private boolean isCurrentPlatform(String osName, String matchAgainst) {534return osName.contains(matchAgainst);535}536537private boolean isExactMatch(String osName, String matchAgainst) {538return matchAgainst.equals(osName);539}540541/**542* Returns the major version of this platform.543*544* @return the major version of specified platform545*/546public int getMajorVersion() {547return majorVersion;548}549550/**551* Returns the minor version of this platform.552*553* @return the minor version of specified platform554*/555public int getMinorVersion() {556return minorVersion;557}558}559560561