io.github.apkcloud.devicedetector.parser.client.Browser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of DeviceDetector Show documentation
Show all versions of DeviceDetector Show documentation
通用设备检测库将解析任何UserAgent并检测浏览器、操作系统、使用的设备(桌面、平板、移动、电视、车载、游戏机等等)、品牌和型号。
package io.github.apkcloud.devicedetector.parser.client;
import io.github.apkcloud.devicedetector.ClientHints;
import io.github.apkcloud.devicedetector.entity.Client;
import io.github.apkcloud.devicedetector.entity.ClientEngine;
import io.github.apkcloud.devicedetector.parser.client.browser.Engine;
import io.github.apkcloud.devicedetector.parser.client.browser.engine.Version;
import io.github.apkcloud.devicedetector.parser.client.hints.BrowserHints;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 用于检测浏览器的客户端解析器
*/
public class Browser extends AbstractClientParser {
private BrowserHints browserHints;
/**
* 包含正则表达式的 yml 文件的路径
*/
private String fixtureFile = "regexes/client/browsers.yml";
/**
* 解析器的内部名称
* 用于缓存
*/
private String parserName = "browser";
/**
* 已知的浏览器映射到其内部短代码
*/
protected static Map availableBrowsers = new HashMap<>() {
{
put("V1", "Via");
put("1P", "Pure Mini Browser");
put("4P", "Pure Lite Browser");
put("1R", "Raise Fast Browser");
put("R1", "Rabbit Private Browser");
put("FQ", "Fast Browser UC Lite");
put("FJ", "Fast Explorer");
put("1L", "Lightning Browser");
put("1C", "Cake Browser");
put("1I", "IE Browser Fast");
put("1V", "Vegas Browser");
put("1O", "OH Browser");
put("3O", "OH Private Browser");
put("1X", "XBrowser Mini");
put("1S", "Sharkee Browser");
put("2L", "Lark Browser");
put("3P", "Pluma");
put("1A", "Anka Browser");
put("AZ", "Azka Browser");
put("1D", "Dragon Browser");
put("1E", "Easy Browser");
put("DW", "Dark Web Browser");
put("18", "18+ Privacy Browser");
put("1B", "115 Browser");
put("DM", "1DM Browser");
put("1M", "1DM+ Browser");
put("2B", "2345 Browser");
put("3B", "360 Browser");
put("36", "360 Phone Browser");
put("7B", "7654 Browser");
put("AA", "Avant Browser");
put("AB", "ABrowse");
put("BW", "AdBlock Browser");
put("A7", "Adult Browser");
put("AF", "ANT Fresco");
put("AG", "ANTGalio");
put("AL", "Aloha Browser");
put("AH", "Aloha Browser Lite");
put("AM", "Amaya");
put("A3", "Amaze Browser");
put("A5", "Amerigo");
put("AO", "Amigo");
put("AN", "Android Browser");
put("AE", "AOL Desktop");
put("AD", "AOL Shield");
put("A4", "AOL Shield Pro");
put("A6", "AppBrowzer");
put("AP", "APUS Browser");
put("AR", "Arora");
put("AX", "Arctic Fox");
put("AV", "Amiga Voyager");
put("AW", "Amiga Aweb");
put("PN", "APN Browser");
put("AI", "Arvin");
put("AK", "Ask.com");
put("AU", "Asus Browser");
put("A0", "Atom");
put("AT", "Atomic Web Browser");
put("A2", "Atlas");
put("AS", "Avast Secure Browser");
put("VG", "AVG Secure Browser");
put("AC", "Avira Scout");
put("A1", "AwoX");
put("BA", "Beaker Browser");
put("BM", "Beamrise");
put("BB", "BlackBerry Browser");
put("H1", "BrowseHere");
put("B8", "Browser Hup Pro");
put("BD", "Baidu Browser");
put("BS", "Baidu Spark");
put("B9", "Bangla Browser");
put("BI", "Basilisk");
put("BV", "Belva Browser");
put("B5", "Beyond Private Browser");
put("BE", "Beonex");
put("B2", "Berry Browser");
put("BT", "Bitchute Browser");
put("BH", "BlackHawk");
put("B0", "Bloket");
put("BJ", "Bunjalloo");
put("BL", "B-Line");
put("B6", "Black Lion Browser");
put("BU", "Blue Browser");
put("BO", "Bonsai");
put("BN", "Borealis Navigator");
put("BR", "Brave");
put("BK", "BriskBard");
put("B3", "Browspeed Browser");
put("BX", "BrowseX");
put("BZ", "Browzar");
put("B7", "Browlser");
put("BY", "Biyubi");
put("BF", "Byffox");
put("B4", "BF Browser");
put("CA", "Camino");
put("CL", "CCleaner");
put("C8", "CG Browser");
put("CJ", "ChanjetCloud");
put("C6", "Chedot");
put("C9", "Cherry Browser");
put("C0", "Centaury");
put("CC", "Coc Coc");
put("C4", "CoolBrowser");
put("C2", "Colibri");
put("CD", "Comodo Dragon");
put("C1", "Coast");
put("CX", "Charon");
put("CE", "CM Browser");
put("C7", "CM Mini");
put("CF", "Chrome Frame");
put("HC", "Headless Chrome");
put("CH", "Chrome");
put("CI", "Chrome Mobile iOS");
put("CK", "Conkeror");
put("CM", "Chrome Mobile");
put("3C", "Chowbo");
put("CN", "CoolNovo");
put("CO", "CometBird");
put("2C", "Comfort Browser");
put("CB", "COS Browser");
put("CW", "Cornowser");
put("C3", "Chim Lac");
put("CP", "ChromePlus");
put("CR", "Chromium");
put("C5", "Chromium GOST");
put("CY", "Cyberfox");
put("CS", "Cheshire");
put("CT", "Crusta");
put("CG", "Craving Explorer");
put("CZ", "Crazy Browser");
put("CU", "Cunaguaro");
put("CV", "Chrome Webview");
put("YC", "CyBrowser");
put("DB", "dbrowser");
put("PD", "Peeps dBrowser");
put("D1", "Debuggable Browser");
put("DC", "Decentr");
put("DE", "Deepnet Explorer");
put("DG", "deg-degan");
put("DA", "Deledao");
put("DT", "Delta Browser");
put("D0", "Desi Browser");
put("DS", "DeskBrowse");
put("DF", "Dolphin");
put("DZ", "Dolphin Zero");
put("DO", "Dorado");
put("DR", "Dot Browser");
put("DL", "Dooble");
put("DI", "Dillo");
put("DU", "DUC Browser");
put("DD", "DuckDuckGo Privacy Browser");
put("EC", "Ecosia");
put("EW", "Edge WebView");
put("EI", "Epic");
put("EL", "Elinks");
put("EN", "EinkBro");
put("EB", "Element Browser");
put("EE", "Elements Browser");
put("EX", "Explore Browser");
put("EZ", "eZ Browser");
put("EU", "EUI Browser");
put("EP", "GNOME Web");
put("G1", "G Browser");
put("ES", "Espial TV Browser");
put("FA", "Falkon");
put("FX", "Faux Browser");
put("F4", "Fiery Browser");
put("F1", "Firefox Mobile iOS");
put("FB", "Firebird");
put("FD", "Fluid");
put("FE", "Fennec");
put("FF", "Firefox");
put("FK", "Firefox Focus");
put("FY", "Firefox Reality");
put("FR", "Firefox Rocket");
put("1F", "Firefox Klar");
put("F0", "Float Browser");
put("FL", "Flock");
put("FP", "Floorp");
put("FO", "Flow");
put("F2", "Flow Browser");
put("FM", "Firefox Mobile");
put("FW", "Fireweb");
put("FN", "Fireweb Navigator");
put("FH", "Flash Browser");
put("FS", "Flast");
put("F5", "Flyperlink");
put("FU", "FreeU");
put("F3", "Frost+");
put("FI", "Fulldive");
put("GA", "Galeon");
put("G8", "Gener8");
put("GH", "Ghostery Privacy Browser");
put("GI", "GinxDroid Browser");
put("GB", "Glass Browser");
put("GE", "Google Earth");
put("GP", "Google Earth Pro");
put("GO", "GOG Galaxy");
put("GR", "GoBrowser");
put("HB", "Harman Browser");
put("HS", "HasBrowser");
put("HA", "Hawk Turbo Browser");
put("HQ", "Hawk Quick Browser");
put("HE", "Helio");
put("HX", "Hexa Web Browser");
put("HI", "Hi Browser");
put("HO", "hola! Browser");
put("HJ", "HotJava");
put("HT", "HTC Browser");
put("HU", "Huawei Browser Mobile");
put("HP", "Huawei Browser");
put("H3", "HUB Browser");
put("IO", "iBrowser");
put("IS", "iBrowser Mini");
put("IB", "IBrowse");
put("I6", "iDesktop PC Browser");
put("IC", "iCab");
put("I2", "iCab Mobile");
put("I1", "Iridium");
put("I3", "Iron Mobile");
put("I4", "IceCat");
put("ID", "IceDragon");
put("IV", "Isivioo");
put("I8", "IVVI Browser");
put("IW", "Iceweasel");
put("IN", "Inspect Browser");
put("IE", "Internet Explorer");
put("I7", "Internet Browser Secure");
put("I5", "Indian UC Mini Browser");
put("IM", "IE Mobile");
put("IR", "Iron");
put("JB", "Japan Browser");
put("JS", "Jasmine");
put("JA", "JavaFX");
put("JL", "Jelly");
put("JI", "Jig Browser");
put("JP", "Jig Browser Plus");
put("JO", "Jio Browser");
put("J1", "JioPages");
put("KB", "K.Browser");
put("KF", "Keepsafe Browser");
put("KS", "Kids Safe Browser");
put("KI", "Kindle Browser");
put("KM", "K-meleon");
put("KO", "Konqueror");
put("KP", "Kapiko");
put("KN", "Kinza");
put("KW", "Kiwi");
put("KD", "Kode Browser");
put("KT", "KUTO Mini Browser");
put("KY", "Kylo");
put("KZ", "Kazehakase");
put("LB", "Cheetah Browser");
put("LA", "Lagatos Browser");
put("LR", "Lexi Browser");
put("LV", "Lenovo Browser");
put("LF", "LieBaoFast");
put("LG", "LG Browser");
put("LH", "Light");
put("L1", "Lilo");
put("LI", "Links");
put("IF", "Lolifox");
put("LO", "Lovense Browser");
put("LT", "LT Browser");
put("LU", "LuaKit");
put("LL", "Lulumi");
put("LS", "Lunascape");
put("LN", "Lunascape Lite");
put("LX", "Lynx");
put("L2", "Lynket Browser");
put("MD", "Mandarin");
put("M1", "mCent");
put("MB", "MicroB");
put("MC", "NCSA Mosaic");
put("MZ", "Meizu Browser");
put("ME", "Mercury");
put("M2", "Me Browser");
put("MF", "Mobile Safari");
put("MI", "Midori");
put("M3", "Midori Lite");
put("MO", "Mobicip");
put("MU", "MIUI Browser");
put("MS", "Mobile Silk");
put("MN", "Minimo");
put("MT", "Mint Browser");
put("MX", "Maxthon");
put("M4", "MaxTube Browser");
put("MA", "Maelstrom");
put("MM", "Mmx Browser");
put("NM", "MxNitro");
put("MY", "Mypal");
put("MR", "Monument Browser");
put("MW", "MAUI WAP Browser");
put("NW", "Navigateur Web");
put("NK", "Naked Browser");
put("NA", "Naked Browser Pro");
put("NR", "NFS Browser");
put("NB", "Nokia Browser");
put("NO", "Nokia OSS Browser");
put("NV", "Nokia Ovi Browser");
put("NX", "Nox Browser");
put("N1", "NOMone VR Browser");
put("NE", "NetSurf");
put("NF", "NetFront");
put("NL", "NetFront Life");
put("NP", "NetPositive");
put("NS", "Netscape");
put("WR", "NextWord Browser");
put("NT", "NTENT Browser");
put("OC", "Oculus Browser");
put("O1", "Opera Mini iOS");
put("OB", "Obigo");
put("O2", "Odin");
put("2O", "Odin Browser");
put("H2", "OceanHero");
put("OD", "Odyssey Web Browser");
put("OF", "Off By One");
put("O5", "Office Browser");
put("HH", "OhHai Browser");
put("OE", "ONE Browser");
put("Y1", "Opera Crypto");
put("OX", "Opera GX");
put("OG", "Opera Neon");
put("OH", "Opera Devices");
put("OI", "Opera Mini");
put("OM", "Opera Mobile");
put("OP", "Opera");
put("ON", "Opera Next");
put("OO", "Opera Touch");
put("OA", "Orca");
put("OS", "Ordissimo");
put("OR", "Oregano");
put("O0", "Origin In-Game Overlay");
put("OY", "Origyn Web Browser");
put("OV", "Openwave Mobile Browser");
put("O3", "OpenFin");
put("O4", "Open Browser");
put("4U", "Open Browser 4U");
put("5G", "Open Browser fast 5G");
put("OW", "OmniWeb");
put("OT", "Otter Browser");
put("PL", "Palm Blazer");
put("PM", "Pale Moon");
put("PY", "Polypane");
put("PP", "Oppo Browser");
put("P6", "Opus Browser");
put("PR", "Palm Pre");
put("PU", "Puffin");
put("2P", "Puffin Web Browser");
put("PW", "Palm WebPro");
put("PA", "Palmscape");
put("PE", "Perfect Browser");
put("P1", "Phantom.me");
put("PH", "Phantom Browser");
put("PX", "Phoenix");
put("PB", "Phoenix Browser");
put("PF", "PlayFree Browser");
put("PK", "PocketBook Browser");
put("PO", "Polaris");
put("PT", "Polarity");
put("LY", "PolyBrowser");
put("PI", "PrivacyWall");
put("P4", "Privacy Explorer Fast Safe");
put("P2", "Pi Browser");
put("P0", "PronHub Browser");
put("PC", "PSI Secure Browser");
put("RW", "Reqwireless WebViewer");
put("PS", "Microsoft Edge");
put("QA", "Qazweb");
put("Q2", "QQ Browser Lite");
put("Q1", "QQ Browser Mini");
put("QQ", "QQ Browser");
put("QS", "Quick Browser");
put("QT", "Qutebrowser");
put("QU", "Quark");
put("QZ", "QupZilla");
put("QM", "Qwant Mobile");
put("QW", "QtWebEngine");
put("RE", "Realme Browser");
put("RK", "Rekonq");
put("RM", "RockMelt");
put("SB", "Samsung Browser");
put("SA", "Sailfish Browser");
put("S8", "Seewo Browser");
put("SC", "SEMC-Browser");
put("SE", "Sogou Explorer");
put("SO", "Sogou Mobile Browser");
put("RF", "SOTI Surf");
put("2S", "Soul Browser");
put("T0", "Soundy Browser");
put("SF", "Safari");
put("PV", "Safari Technology Preview");
put("S5", "Safe Exam Browser");
put("SW", "SalamWeb");
put("VN", "Savannah Browser");
put("SD", "SavySoda");
put("S9", "Secure Browser");
put("SV", "SFive");
put("SH", "Shiira");
put("K1", "Sidekick");
put("S1", "SimpleBrowser");
put("3S", "SilverMob US");
put("SY", "Sizzy");
put("SK", "Skyfire");
put("SS", "Seraphic Sraf");
put("KK", "SiteKiosk");
put("SL", "Sleipnir");
put("S6", "Slimjet");
put("S7", "SP Browser");
put("9S", "Sony Small Browser");
put("8S", "Secure Private Browser");
put("T1", "Stampy Browser");
put("7S", "7Star");
put("SQ", "Smart Browser");
put("6S", "Smart Search & Web Browser");
put("LE", "Smart Lenovo Browser");
put("OZ", "Smooz");
put("SN", "Snowshoe");
put("B1", "Spectre Browser");
put("S2", "Splash");
put("SI", "Sputnik Browser");
put("SR", "Sunrise");
put("SP", "SuperBird");
put("SU", "Super Fast Browser");
put("5S", "SuperFast Browser");
put("HR", "Sushi Browser");
put("S3", "surf");
put("4S", "Surf Browser");
put("SG", "Stargon");
put("S0", "START Internet Browser");
put("S4", "Steam In-Game Overlay");
put("ST", "Streamy");
put("SX", "Swiftfox");
put("SZ", "Seznam Browser");
put("W1", "Sweet Browser");
put("2X", "SX Browser");
put("TP", "T+Browser");
put("TR", "T-Browser");
put("TO", "t-online.de Browser");
put("TA", "Tao Browser");
put("TF", "TenFourFox");
put("TB", "Tenta Browser");
put("TE", "Tesla Browser");
put("TZ", "Tizen Browser");
put("TI", "Tint Browser");
put("TC", "TUC Mini Browser");
put("TU", "Tungsten");
put("TG", "ToGate");
put("TS", "TweakStyle");
put("TV", "TV Bro");
put("U0", "U Browser");
put("UB", "UBrowser");
put("UC", "UC Browser");
put("UH", "UC Browser HD");
put("UM", "UC Browser Mini");
put("UT", "UC Browser Turbo");
put("UI", "Ui Browser Mini");
put("UR", "UR Browser");
put("UZ", "Uzbl");
put("UE", "Ume Browser");
put("V0", "vBrowser");
put("VA", "Vast Browser");
put("VE", "Venus Browser");
put("N0", "Nova Video Downloader Pro");
put("VS", "Viasat Browser");
put("VI", "Vivaldi");
put("VV", "vivo Browser");
put("V2", "Vivid Browser Mini");
put("VB", "Vision Mobile Browser");
put("VM", "VMware AirWatch");
put("WI", "Wear Internet Browser");
put("WP", "Web Explorer");
put("W3", "Web Browser & Explorer");
put("WE", "WebPositive");
put("WF", "Waterfox");
put("WB", "Wave Browser");
put("WA", "Wavebox");
put("WH", "Whale Browser");
put("WO", "wOSBrowser");
put("WT", "WeTab Browser");
put("WL", "Wolvic");
put("YG", "YAGI");
put("YJ", "Yahoo! Japan Browser");
put("YA", "Yandex Browser");
put("YL", "Yandex Browser Lite");
put("YN", "Yaani Browser");
put("Y2", "Yo Browser");
put("YB", "Yolo Browser");
put("YO", "YouCare");
put("YZ", "Yuzu Browser");
put("XR", "xBrowser");
put("XB", "X Browser Lite");
put("X0", "X-VPN");
put("X1", "xBrowser Pro Super Fast");
put("XN", "XNX Browser");
put("XT", "XtremeCast");
put("XS", "xStand");
put("XI", "Xiino");
put("XO", "Xooloo Internet");
put("XV", "Xvast");
put("ZE", "Zetakey");
put("ZV", "Zvu");
put("ZI", "Zirco Browser");
// 在旧版本中检测到浏览器
// put("IA", "Iceape"); => pim
// put("SM", "SeaMonkey"); => pim
}
};
/**
* 浏览器家族映射到其相关的浏览器短代码
*/
protected static Map> browserFamilies = new HashMap<>() {
{
put("Android Browser", Arrays.asList("AN", "MU"));
put("BlackBerry Browser", Arrays.asList("BB"));
put("Baidu", Arrays.asList("BD", "BS"));
put("Amiga", Arrays.asList("AV", "AW"));
put("Chrome", Arrays.asList(
"1B", "2B", "7S", "A0", "AC", "A4", "AE", "AH", "AI",
"AO", "AS", "BA", "BM", "BR", "C2", "C3", "C5", "C4",
"C6", "CC", "CD", "CE", "CF", "CG", "CH", "CI", "CL",
"CM", "CN", "CP", "CR", "CV", "CW", "DA", "DD", "DG",
"DR", "EC", "EE", "EU", "EW", "FA", "FS", "GB", "GI",
"H2", "HA", "HE", "HH", "HS", "I3", "IR", "JB", "KN",
"KW", "LF", "LL", "LO", "M1", "MA", "MD", "MR", "MS",
"MT", "MZ", "NM", "NR", "O0", "O2", "O3", "OC", "PB",
"PT", "QU", "QW", "RM", "S4", "S6", "S8", "S9", "SB",
"SG", "SS", "SU", "SV", "SW", "SY", "SZ", "T1", "TA",
"TB", "TG", "TR", "TS", "TU", "TV", "UB", "UR", "VE",
"VG", "VI", "VM", "WP", "WH", "XV", "YJ", "YN", "FH",
"B1", "BO", "HB", "PC", "LA", "LT", "PD", "HR", "HU",
"HP", "IO", "TP", "CJ", "HQ", "HI", "PN", "BW", "YO",
"DC", "G8", "DT", "AP", "AK", "UI", "SD", "VN", "4S",
"2S", "RF", "LR", "SQ", "BV", "L1", "F0", "KS", "V0",
"C8", "AZ", "MM", "BT", "N0", "P0", "F3", "VS", "DU",
"D0", "P1", "O4", "8S", "H3", "TE", "WB", "K1", "P2",
"XO", "U0", "B0", "VA", "X0", "NX", "O5", "R1", "I1",
"HO", "A5", "X1", "18", "B5", "B6", "TC", "A6", "2X",
"F4", "YG", "WR", "NA", "DM", "1M", "A7", "XN", "XT",
"XB", "W1", "HT", "B8", "F5", "B9", "WA", "T0", "HC"
));
put("Firefox", Arrays.asList(
"AX", "BI", "BF", "BH", "BN", "C0", "CU", "EI", "F1",
"FB", "FE", "FF", "FM", "FR", "FY", "GZ", "I4", "IF",
"IW", "LH", "LY", "MB", "MN", "MO", "MY", "OA", "OS",
"PI", "PX", "QA", "QM", "S5", "SX", "TF", "TO", "WF",
"ZV", "FP", "AD", "WL"
));
put("Internet Explorer", Arrays.asList("BZ", "CZ", "IE", "IM", "PS"));
put("Konqueror", Arrays.asList("KO"));
put("NetFront", Arrays.asList("NF"));
put("NetSurf", Arrays.asList("NE"));
put("Nokia Browser", Arrays.asList("DO", "NB", "NO", "NV"));
put("Opera", Arrays.asList("O1", "OG", "OH", "OI", "OM", "ON", "OO", "OP", "OX", "Y1"));
put("Safari", Arrays.asList("MF", "S7", "SF", "SO", "PV"));
put("Sailfish Browser", Arrays.asList("SA"));
}
};
/**
* 仅适用于移动设备的浏览器
*/
protected static List mobileOnlyBrowsers = Arrays.asList(
"36", "AH", "AI", "BL", "C1", "C4", "CB", "CW", "DB",
"DD", "DT", "EU", "EZ", "FK", "FM", "FR", "FX", "GH",
"GI", "GR", "HA", "HU", "IV", "JB", "KD", "M1", "MF",
"MN", "MZ", "NX", "OC", "OI", "OM", "OZ", "PU", "PI",
"PE", "QU", "RE", "S0", "S7", "SA", "SB", "SG", "SK",
"ST", "SU", "T1", "UH", "UM", "UT", "VE", "VV", "WI",
"WP", "YN", "IO", "IS", "HQ", "RW", "HI", "PN", "BW",
"YO", "PK", "MR", "AP", "AK", "UI", "SD", "VN", "4S",
"RF", "LR", "SQ", "BV", "L1", "F0", "KS", "V0", "C8",
"AZ", "MM", "BT", "N0", "P0", "F3", "DU", "D0", "P1",
"O4", "XO", "U0", "B0", "VA", "X0", "A5", "X1", "18",
"B5", "B6", "TC", "A6", "2X", "F4", "YG", "WR", "NA",
"DM", "1M", "A7", "XN", "XT", "XB", "W1", "HT", "B7",
"B9", "T0", "I8"
);
/**
* 包含从我们使用的操作系统名称到已知 ClientHints 值的映射列表
*/
protected static Map> clientHintMapping = new LinkedHashMap<>(){
{
put("Chrome", Arrays.asList("Google Chrome"));
}
};
public Browser() {
super();
this.browserHints = new BrowserHints();
}
public Browser(String ua) {
super(ua);
this.browserHints = new BrowserHints(ua);
}
public Browser(String ua, ClientHints clientHints) {
super(ua, clientHints);
this.browserHints = new BrowserHints(ua, clientHints);
}
/**
* 设置 ClientHints
*/
public void setClientHints(ClientHints clientHints) {
super.setClientHints(clientHints);
this.browserHints.setClientHints(clientHints);
}
/**
* 设置要解析的 UserAgent
*/
public void setUserAgent(String ua) {
super.setUserAgent(ua);
this.browserHints.setUserAgent(ua);
}
/**
* {@inheritDoc}
*/
@Override
public String getName() {
return parserName;
}
/**
* 返回所有可用的浏览器列表
*
* @return {@code Map}
*/
public static Map getAvailableBrowsers() {
return availableBrowsers;
}
/**
* 返回所有可用的浏览器家族列表
*
* @return {@code Map>}
*/
public static Map> getAvailableBrowserFamilies() {
return browserFamilies;
}
/**
* 根据浏览器名称返回浏览器的短代码
* @param name 浏览器名称
* @return String | null
*/
public static String getBrowserShortName(String name) {
for (Map.Entry entry : getAvailableBrowsers().entrySet()) {
if (name.equalsIgnoreCase(entry.getValue())) {
return entry.getKey();
}
}
return null;
}
/**
* 根据浏览器的名称或短代码返回浏览器家族
*
* @param browserLabel 名称或短代码
*
* @return String|null If null, "Unknown"
*/
public static String getBrowserFamily(String browserLabel) {
if (availableBrowsers.containsValue(browserLabel)) {
browserLabel = getKeyByValue(availableBrowsers, browserLabel);
}
for (Map.Entry> entry : browserFamilies.entrySet()) {
if (entry.getValue().contains(browserLabel)) {
return entry.getKey();
}
}
return null;
}
/**
* 判断给定的浏览器是不是仅限移动设备的浏览器
*
* @param browser 标签或浏览器名称
*
* @return boolean
*/
public static boolean isMobileOnlyBrowser(String browser) {
return mobileOnlyBrowsers.contains(browser)
|| (availableBrowsers.containsValue(browser) && mobileOnlyBrowsers.contains(getKeyByValue(availableBrowsers, browser)));
}
/**
* {@inheritDoc}
*/
public Map parse() throws Exception {
Map browserFromClientHints = parseBrowserFromClientHints();
Map browserFromUserAgent = parseBrowserFromUserAgent();
String name = "", version = "", shortName = "", engine = "", engineVersion = "";
// 在可能的情况下使用客户端提示而不是用户代理数据
if (!isNullOrEmpty(browserFromClientHints.get("name")) && !isNullOrEmpty(browserFromClientHints.get("version"))) {
name = browserFromClientHints.get("name");
version = browserFromClientHints.get("version");
shortName = browserFromClientHints.get("short_name");
engine = "";
engineVersion = "";
// 如果来自 ClientHints 的版本为 2022 或 2022.04,则为 Iridium 浏览器
// https://iridiumbrowser.de/news/2022/05/16/version-2022-04-released
if ("2021.12".equals(version) || "2022".equals(version) || "2022.04".equals(version)) {
name = "Iridium";
shortName = "I1";
engine = browserFromUserAgent.get("engine");
engineVersion = browserFromUserAgent.get("engine_version");
}
if ("Atom".equals(name) || "Huawei Browser".equals(name)) {
version = browserFromUserAgent.get("version");
}
// 如果 ClientHints 的报告为 Chromium,但 UserAgent 的检测到基于 Chromium 的浏览器,我们优先使用后者
if ("Chromium".equals(name)
&& !isNullOrEmpty(browserFromUserAgent.get("name"))
&& !"Chromium".equals(browserFromUserAgent.get("name"))) {
name = browserFromUserAgent.get("name");
shortName = browserFromUserAgent.get("short_name");
version = browserFromUserAgent.get("version");
}
// 修复移动浏览器名称,例如 Chrome => Chrome Mobile
if ((name + " Mobile").equals(browserFromUserAgent.get("name"))) {
name = browserFromUserAgent.get("name");
shortName = browserFromUserAgent.get("short_name");
}
// 如果在 UserAgent 中检测到另一个浏览器,但家族匹配,我们将使用 UserAgent 中检测到的引擎
if (!name.equals(browserFromUserAgent.get("name"))
&& Objects.equals(getBrowserFamily(name), getBrowserFamily(browserFromUserAgent.get("name")))) {
engine = browserFromUserAgent.getOrDefault("engine", "");
engineVersion = browserFromUserAgent.getOrDefault("engine_version", "");
}
if (name.equals(browserFromUserAgent.get("name"))) {
engine = browserFromUserAgent.getOrDefault("engine", "");
engineVersion = browserFromUserAgent.getOrDefault("engine_version", "");
// 如果 UserAgent 报告了更详细的版本,我们会尝试使用它来替代
if (!isNullOrEmpty(browserFromUserAgent.get("version"))
&& browserFromUserAgent.get("version").startsWith(version)
&& compareVersions(version, browserFromUserAgent.get("version")) == -1) {
version = browserFromUserAgent.get("version");
}
}
} else {
name = browserFromUserAgent.get("name");
version = browserFromUserAgent.get("version");
shortName = browserFromUserAgent.get("short_name");
engine = browserFromUserAgent.get("engine");
engineVersion = browserFromUserAgent.get("engine_version");
}
String family = getBrowserFamily(shortName);
Map appHash = this.browserHints.parse();
if (appHash != null && !Objects.equals(name, appHash.get("name"))) {
name = appHash.getOrDefault("name", "");
version = "";
shortName = getBrowserShortName(name);
Matcher matcher = Pattern.compile("Chrome/.+ Safari/537.36", Pattern.CASE_INSENSITIVE).matcher(userAgent);
if (matcher.find()) {
engine = "Blink";
family = getBrowserFamily(shortName) != null ? getBrowserFamily(shortName) : "Chrome";
engineVersion = buildEngineVersion(engine);
}
if (shortName == null) {
// 此异常不应该抛出。如果发生这种情况,则在 availableBrowsers 中缺少定义的浏览器名称
throw new Exception(String.format(
"在 availableBrowsers 中找不到检测到的浏览器名称“%s”。尝试解析UserAgent:%s",
name,
userAgent)
); // @codeCoverageIgnore
}
}
if (isNullOrEmpty(name)) {
return Collections.emptyMap();
}
// 对于浏览器,排除 Blink 引擎版本
if ("Blink".equals(engine) && "Flow Browser".equals(name)) {
engineVersion = "";
}
Map result = new HashMap<>();
result.put("type", "browser");
result.put("name", name);
result.put("short_name", shortName);
result.put("version", version);
result.put("engine", engine);
result.put("engine_version", engineVersion);
result.put("family", family);
return result;
}
/**
* 返回从 ClientHints 中可以有效检测到的浏览器
*
* @return {@code Map}
*/
protected Map parseBrowserFromClientHints() {
String name = "", version = "", shortName = "";
if (clientHints != null && !isNullOrEmpty(clientHints.getBrandList())) {
Map brands = clientHints.getBrandList();
for (Map.Entry entry : brands.entrySet()) {
String brand = applyClientHintMapping(entry.getKey(), clientHintMapping);
for (Map.Entry browserEntry : availableBrowsers.entrySet()) {
String browserShort = browserEntry.getKey();
String browserName = browserEntry.getValue();
if (fuzzyCompare(brand, browserName) || fuzzyCompare(brand + " Browser", browserName) || fuzzyCompare(brand, browserName + " Browser")) {
name = browserName;
shortName = browserShort;
version = entry.getValue();
break;
}
}
// 如果检测到的品牌不是 Chromium,我们将使用它,否则我们将继续寻找
if (!"".equals(name) && !"Chromium".equals(name)) {
break;
}
}
version = !isNullOrEmpty(clientHints.getBrandVersion()) ? clientHints.getBrandVersion() : version;
}
Map result = new HashMap<>();
result.put("name", name);
result.put("short_name", shortName);
result.put("version", buildVersion(version, Collections.emptyList()));
return result;
}
/**
* 返回从 UserAgent 中可以检测到的浏览器
*
* @return {@code Map}
*
* @throws Exception
*/
protected Map parseBrowserFromUserAgent() throws Exception {
Client regex = null;
List matches = null;
List regexes = getRegexes(fixtureFile, Client.class);
for (Client client : regexes) {
regex = client;
matches = matchUserAgent(client.getRegex());
if (!isNullOrEmpty(matches)) {
break;
}
}
if (isNullOrEmpty(matches) || regex == null) {
Map result = new HashMap<>();
result.put("name", "");
result.put("short_name", "");
result.put("version", "");
result.put("engine", "");
result.put("engine_version", "");
return result;
}
String name = buildByMatch(regex.getName(), matches);
String browserShort = getBrowserShortName(name);
if (browserShort != null) {
String version = buildVersion(regex.getVersion(), matches);
String engine = buildEngine(regex.getEngine(), version);
String engineVersion = buildEngineVersion(engine);
Map result = new HashMap<>();
result.put("name", name);
result.put("short_name", browserShort);
result.put("version", version);
result.put("engine", engine);
result.put("engine_version", engineVersion);
return result;
}
// 此异常不应该抛出。如果发生这种情况,则在 availableBrowsers 中缺少定义的浏览器名称
throw new Exception(String.format(
"在 availableBrowsers 中找不到检测到的浏览器名称“%s“。尝试解析UserAgent:%s",
name,
userAgent)); // @codeCoverageIgnore
}
/**
* @param engineData
* @param browserVersion
* @return String
*/
protected String buildEngine(ClientEngine engineData, String browserVersion) throws Exception {
String engine = "";
// 如果引擎设置为默认
if (engineData != null && engineData.getDefault() != null) {
engine = engineData.getDefault();
}
// 检查引擎是否设置了浏览器版本
if (engineData != null && engineData.getVersions() != null) {
for (Map.Entry entry : engineData.getVersions().entrySet()) {
String version = entry.getKey();
String versionEngine = entry.getValue();
if (compareVersions(browserVersion, version) < 0) {
continue;
}
engine = versionEngine;
}
}
// 尝试使用正则表达式检测引擎
if (isNullOrEmpty(engine)) {
Engine engineParser = new Engine();
engineParser.setUserAgent(userAgent);
Map result = engineParser.parse();
engine = result.getOrDefault("engine", "");
}
return engine;
}
/**
* @param engine
* @return String
*/
protected String buildEngineVersion(String engine) {
Version engineVersionParser = new Version(userAgent, engine);
Map result = engineVersionParser.parse();
return result.getOrDefault("version", "");
}
}