Path: blob/trunk/java/src/org/openqa/selenium/Platform.java
1865 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.NullMarked;24import org.jspecify.annotations.Nullable;2526/**27* Represents the known and supported Platforms that WebDriver runs on. This is pretty close to the28* Operating System, but differs slightly, because this class is used to extract information such as29* program locations and line endings.30*/31// Useful URLs:32// http://hg.openjdk.java.net/jdk7/modules/jdk/file/a37326fa7f95/src/windows/native/java/lang/java_props_md.c33@NullMarked34public enum Platform {3536/** Never returned, but can be used to request a browser running on any version of Windows. */37WINDOWS("windows") {38@Override39public @Nullable Platform family() {40return null;41}4243@Override44public String toString() {45return "windows";46}47},4849/**50* For versions of Windows that "feel like" Windows XP. These are ones that store files in51* "\Program Files\" and documents under "\\documents and settings\\username"52*/53XP("Windows Server 2003", "xp", "windows", "winnt", "windows_nt", "windows nt") {54@Override55public @Nullable Platform family() {56return WINDOWS;57}5859@Override60public String toString() {61return "Windows XP";62}63},6465/** For versions of Windows that "feel like" Windows Vista. */66VISTA("windows vista", "Windows Server 2008") {67@Override68public @Nullable Platform family() {69return WINDOWS;70}7172@Override73public String toString() {74return "Windows Vista";75}76},7778WIN7("windows 7", "win7") {79@Override80public @Nullable Platform family() {81return WINDOWS;82}8384@Override85public String toString() {86return "Windows 7";87}88},8990/** For versions of Windows that "feel like" Windows 8. */91WIN8("Windows Server 2012", "windows 8", "win8") {92@Override93public @Nullable Platform family() {94return WINDOWS;95}9697@Override98public String toString() {99return "Windows 8";100}101},102103WIN8_1("windows 8.1", "win8.1") {104@Override105public @Nullable Platform family() {106return WINDOWS;107}108109@Override110public String toString() {111return "Windows 8.1";112}113},114115WIN10("windows 10", "win10") {116@Override117public @Nullable Platform family() {118return WINDOWS;119}120121@Override122public String toString() {123return "Windows 10";124}125},126127WIN11("windows 11", "win11") {128@Override129public @Nullable Platform family() {130return WINDOWS;131}132133@Override134public String toString() {135return "Windows 11";136}137},138139MAC("mac", "darwin", "macOS", "mac os x", "os x") {140@Override141public @Nullable Platform family() {142return null;143}144145@Override146public String toString() {147return "mac";148}149},150151SNOW_LEOPARD("snow leopard", "os x 10.6", "macos 10.6") {152@Override153public @Nullable Platform family() {154return MAC;155}156157@Override158public String toString() {159return "OS X 10.6";160}161},162163MOUNTAIN_LION("mountain lion", "os x 10.8", "macos 10.8") {164@Override165public @Nullable Platform family() {166return MAC;167}168169@Override170public String toString() {171return "OS X 10.8";172}173},174175MAVERICKS("mavericks", "os x 10.9", "macos 10.9") {176@Override177public @Nullable Platform family() {178return MAC;179}180181@Override182public String toString() {183return "OS X 10.9";184}185},186187YOSEMITE("yosemite", "os x 10.10", "macos 10.10") {188@Override189public @Nullable Platform family() {190return MAC;191}192193@Override194public String toString() {195return "OS X 10.10";196}197},198199EL_CAPITAN("el capitan", "os x 10.11", "macos 10.11") {200@Override201public @Nullable Platform family() {202return MAC;203}204205@Override206public String toString() {207return "OS X 10.11";208}209},210211SIERRA("sierra", "os x 10.12", "macos 10.12") {212@Override213public @Nullable Platform family() {214return MAC;215}216217@Override218public String toString() {219return "macOS 10.12";220}221},222223HIGH_SIERRA("high sierra", "os x 10.13", "macos 10.13") {224@Override225public @Nullable Platform family() {226return MAC;227}228229@Override230public String toString() {231return "macOS 10.13";232}233},234235MOJAVE("mojave", "os x 10.14", "macos 10.14") {236@Override237public @Nullable Platform family() {238return MAC;239}240241@Override242public String toString() {243return "macOS 10.14";244}245},246247CATALINA("catalina", "os x 10.15", "macos 10.15") {248@Override249public @Nullable Platform family() {250return MAC;251}252253@Override254public String toString() {255return "macOS 10.15";256}257},258259BIG_SUR("big sur", "os x 11.0", "macos 11.0") {260@Override261public @Nullable Platform family() {262return MAC;263}264265@Override266public String toString() {267return "macOS 11.0";268}269},270271MONTEREY("monterey", "os x 12.0", "macos 12.0") {272@Override273public @Nullable Platform family() {274return MAC;275}276277@Override278public String toString() {279return "macOS 12.0";280}281},282283VENTURA("ventura", "os x 13.0", "macos 13.0") {284@Override285public @Nullable Platform family() {286return MAC;287}288289@Override290public String toString() {291return "macOS 13.0";292}293},294295SONOMA("sonoma", "os x 14.0", "macos 14.0") {296@Override297public @Nullable Platform family() {298return MAC;299}300301@Override302public String toString() {303return "macOS 14.0";304}305},306307SEQUOIA("sequoia", "os x 15.0", "macos 15.0") {308@Override309public @Nullable Platform family() {310return MAC;311}312313@Override314public String toString() {315return "macOS 15.0";316}317},318319/** Many platforms have UNIX traits, amongst them LINUX, Solaris and BSD. */320UNIX("solaris", "bsd") {321@Override322public @Nullable Platform family() {323return null;324}325},326327LINUX("linux") {328@Override329public @Nullable Platform family() {330return UNIX;331}332333@Override334public String toString() {335return "linux";336}337},338339ANDROID("android", "dalvik") {340@Override341public @Nullable Platform family() {342return null;343}344},345346IOS("iOS") {347@Override348public @Nullable Platform family() {349return null;350}351},352353/** Never returned, but can be used to request a browser running on any operating system. */354ANY("") {355@Override356public @Nullable Platform family() {357return ANY;358}359360@Override361public boolean is(Platform compareWith) {362return this == compareWith;363}364365@Override366public String toString() {367return "any";368}369};370371private static final Pattern VERSION_PATTERN = Pattern.compile("^(\\d+)\\.(\\d+).*");372private static @Nullable Platform current;373private final String[] partOfOsName;374private int minorVersion = 0;375private int majorVersion = 0;376377Platform(String... partOfOsName) {378this.partOfOsName = partOfOsName;379}380381/**382* Get current platform (not necessarily the same as operating system).383*384* @return current platform385*/386public static Platform getCurrent() {387if (current == null) {388current = extractFromSysProperty(System.getProperty("os.name"));389390String version = System.getProperty("os.version", "0.0.0");391int major = 0;392int minor = 0;393394final Matcher matcher = VERSION_PATTERN.matcher(version);395if (matcher.matches()) {396try {397major = Integer.parseInt(matcher.group(1));398minor = Integer.parseInt(matcher.group(2));399} catch (NumberFormatException e) {400// These things happen401}402}403404current.majorVersion = major;405current.minorVersion = minor;406}407return current;408}409410/**411* Extracts platforms based on system properties in Java and uses a heuristic to determine the412* most likely operating system. If unable to determine the operating system, it will default to413* UNIX.414*415* @param osName the operating system name to determine the platform of416* @return the most likely platform based on given operating system name417*/418public static Platform extractFromSysProperty(String osName) {419return extractFromSysProperty(osName, System.getProperty("os.version"));420}421422/**423* Extracts platforms based on system properties in Java and uses a heuristic to determine the424* most likely operating system. If unable to determine the operating system, it will default to425* UNIX.426*427* @param osName the operating system name to determine the platform of428* @param osVersion the operating system version to determine the platform of429* @return the most likely platform based on given operating system name and version430*/431public static Platform extractFromSysProperty(String osName, String osVersion) {432osName = osName.toLowerCase(Locale.ENGLISH);433// os.name for android is linux434if ("dalvik".equalsIgnoreCase(System.getProperty("java.vm.name"))) {435return Platform.ANDROID;436}437// Windows 8 can't be detected by osName alone438if (osVersion.equals("6.2") && osName.startsWith("windows nt")) {439return WIN8;440}441// Windows 8 can't be detected by osName alone442if (osVersion.equals("6.3") && osName.startsWith("windows nt")) {443return WIN8_1;444}445Platform mostLikely = UNIX;446String previousMatch = null;447for (Platform os : Platform.values()) {448for (String matcher : os.partOfOsName) {449if ("".equals(matcher)) {450continue;451}452matcher = matcher.toLowerCase(Locale.ENGLISH);453if (os.isExactMatch(osName, matcher)) {454return os;455}456if (os.isCurrentPlatform(osName, matcher) && isBetterMatch(previousMatch, matcher)) {457previousMatch = matcher;458mostLikely = os;459}460}461}462463// Default to assuming we're on a UNIX variant (including LINUX)464return mostLikely;465}466467/**468* Gets a platform with the name matching the parameter.469*470* @param name the platform name471* @return the Platform enum value matching the parameter472*/473public static Platform fromString(String name) {474for (Platform platform : values()) {475if (platform.toString().equalsIgnoreCase(name)) {476return platform;477}478}479480for (Platform os : Platform.values()) {481for (String matcher : os.partOfOsName) {482if (name.equalsIgnoreCase(matcher)) {483return os;484}485}486}487throw new WebDriverException("Unrecognized platform: " + name);488}489490/**491* Decides whether the previous match is better or not than the current match. If previous match492* is null, the newer match is always better.493*494* @param previous the previous match495* @param matcher the newer match496* @return true if newer match is better, false otherwise497*/498private static boolean isBetterMatch(@Nullable String previous, String matcher) {499return previous == null || matcher.length() >= previous.length();500}501502public String[] getPartOfOsName() {503return Arrays.copyOf(partOfOsName, partOfOsName.length);504}505506/**507* Heuristic for comparing two platforms. If platforms (which is not the same thing as operating508* systems) are found to be approximately similar in nature, this will return true. For instance509* the LINUX platform is similar to UNIX, and will give a positive result if compared.510*511* @param compareWith the platform to compare with512* @return true if platforms are approximately similar, false otherwise513*/514public boolean is(Platform compareWith) {515return516// Any platform is itself517this == compareWith518||519// Any platform is also ANY platform520compareWith == ANY521||522// And any Platform which is not a platform type belongs to the same family523(this.family() != null && this.family().is(compareWith));524}525526/**527* Returns a platform that represents a family for the current platform. For instance the LINUX if528* a part of the UNIX family, the XP is a part of the WINDOWS family.529*530* @return the family platform for the current one, or {@code null} if this {@code Platform}531* represents a platform family (such as Windows, or MacOS)532*/533public abstract @Nullable Platform family();534535private boolean isCurrentPlatform(String osName, String matchAgainst) {536return osName.contains(matchAgainst);537}538539private boolean isExactMatch(String osName, String matchAgainst) {540return matchAgainst.equals(osName);541}542543/**544* Returns the major version of this platform.545*546* @return the major version of specified platform547*/548public int getMajorVersion() {549return majorVersion;550}551552/**553* Returns the minor version of this platform.554*555* @return the minor version of specified platform556*/557public int getMinorVersion() {558return minorVersion;559}560}561562563