mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 02:15:35 +03:00
Merge pull request #7323 from vector-im/feature/mna/device-manager-parsing-os
[Device management] Improve the parsing for OS of Desktop/Web sessions (PSG-823)
This commit is contained in:
commit
f9eb6a64ea
3 changed files with 72 additions and 37 deletions
1
changelog.d/7321.wip
Normal file
1
changelog.d/7321.wip
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[Device management] Improve the parsing for OS of Desktop/Web sessions
|
|
@ -74,55 +74,77 @@ class ParseDeviceUserAgentUseCase @Inject constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseDesktopUserAgent(userAgent: String): DeviceExtendedInfo {
|
private fun parseDesktopUserAgent(userAgent: String): DeviceExtendedInfo {
|
||||||
|
val browserInfo = parseBrowserInfoFromDesktopUserAgent(userAgent)
|
||||||
|
val operatingSystem = parseOperatingSystemFromDesktopUserAgent(userAgent)
|
||||||
|
|
||||||
|
return DeviceExtendedInfo(
|
||||||
|
deviceType = DeviceType.DESKTOP,
|
||||||
|
deviceModel = null,
|
||||||
|
deviceOperatingSystem = operatingSystem,
|
||||||
|
clientName = browserInfo.name,
|
||||||
|
clientVersion = browserInfo.version,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class BrowserInfo(val name: String? = null, val version: String? = null)
|
||||||
|
|
||||||
|
private fun parseBrowserInfoFromDesktopUserAgent(userAgent: String): BrowserInfo {
|
||||||
val browserSegments = userAgent.split(" ")
|
val browserSegments = userAgent.split(" ")
|
||||||
val (browserName, browserVersion) = when {
|
return when {
|
||||||
isFirefox(browserSegments) -> {
|
isFirefox(browserSegments) -> {
|
||||||
Pair("Firefox", getBrowserVersion(browserSegments, "Firefox"))
|
BrowserInfo(BROWSER_FIREFOX, getBrowserVersion(browserSegments, BROWSER_FIREFOX))
|
||||||
}
|
}
|
||||||
isEdge(browserSegments) -> {
|
isEdge(browserSegments) -> {
|
||||||
Pair("Edge", getBrowserVersion(browserSegments, "Edge"))
|
BrowserInfo(BROWSER_EDGE, getBrowserVersion(browserSegments, BROWSER_EDGE))
|
||||||
}
|
}
|
||||||
isMobile(browserSegments) -> {
|
isMobile(browserSegments) -> {
|
||||||
when (val name = getMobileBrowserName(browserSegments)) {
|
when (val name = getMobileBrowserName(browserSegments)) {
|
||||||
null -> {
|
null -> {
|
||||||
Pair(null, null)
|
BrowserInfo()
|
||||||
}
|
}
|
||||||
"Safari" -> {
|
BROWSER_SAFARI -> {
|
||||||
Pair(name, getBrowserVersion(browserSegments, "Version"))
|
BrowserInfo(name, getBrowserVersion(browserSegments, "Version"))
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Pair(name, getBrowserVersion(browserSegments, name))
|
BrowserInfo(name, getBrowserVersion(browserSegments, name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isSafari(browserSegments) -> {
|
isSafari(browserSegments) -> {
|
||||||
Pair("Safari", getBrowserVersion(browserSegments, "Version"))
|
BrowserInfo(BROWSER_SAFARI, getBrowserVersion(browserSegments, "Version"))
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
when (val name = getRegularBrowserName(browserSegments)) {
|
when (val name = getRegularBrowserName(browserSegments)) {
|
||||||
null -> {
|
null -> {
|
||||||
Pair(null, null)
|
BrowserInfo()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Pair(name, getBrowserVersion(browserSegments, name))
|
BrowserInfo(name, getBrowserVersion(browserSegments, name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val deviceOperatingSystemSegments = userAgent.substringAfter("(").substringBefore(")").split("; ")
|
private fun parseOperatingSystemFromDesktopUserAgent(userAgent: String): String? {
|
||||||
val deviceOperatingSystem = if (deviceOperatingSystemSegments.getOrNull(1)?.startsWith("Android").orFalse()) {
|
val deviceOperatingSystemSegments = userAgent
|
||||||
deviceOperatingSystemSegments.getOrNull(1)
|
.substringAfter("(")
|
||||||
} else {
|
.substringBefore(")")
|
||||||
deviceOperatingSystemSegments.getOrNull(0)
|
.split("; ")
|
||||||
|
val firstSegment = deviceOperatingSystemSegments.getOrNull(0).orEmpty()
|
||||||
|
val secondSegment = deviceOperatingSystemSegments.getOrNull(1).orEmpty()
|
||||||
|
|
||||||
|
return when {
|
||||||
|
// e.g. (Macintosh; Intel Mac OS X 10_15_7) => macOS
|
||||||
|
firstSegment.startsWith(OPERATING_SYSTEM_MAC_KEYWORD) -> OPERATING_SYSTEM_MAC
|
||||||
|
// e.g. (Windows NT 10.0; Win64; x64) => Windows
|
||||||
|
firstSegment.startsWith(OPERATING_SYSTEM_WINDOWS_KEYWORD) -> OPERATING_SYSTEM_WINDOWS_KEYWORD
|
||||||
|
// e.g. (iPad; CPU OS 8_4_1 like Mac OS X) => iOS
|
||||||
|
firstSegment.startsWith(DEVICE_IPAD_KEYWORD) || firstSegment.startsWith(DEVICE_IPHONE_KEYWORD) -> OPERATING_SYSTEM_IOS
|
||||||
|
// e.g. (Linux; Android 9; SM-G973U Build/PPR1.180610.011) => Android
|
||||||
|
secondSegment.startsWith(OPERATING_SYSTEM_ANDROID_KEYWORD) -> OPERATING_SYSTEM_ANDROID_KEYWORD
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
return DeviceExtendedInfo(
|
|
||||||
deviceType = DeviceType.DESKTOP,
|
|
||||||
deviceModel = null,
|
|
||||||
deviceOperatingSystem = deviceOperatingSystem,
|
|
||||||
clientName = browserName,
|
|
||||||
clientVersion = browserVersion,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseWebUserAgent(userAgent: String): DeviceExtendedInfo {
|
private fun parseWebUserAgent(userAgent: String): DeviceExtendedInfo {
|
||||||
|
@ -136,7 +158,7 @@ class ParseDeviceUserAgentUseCase @Inject constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isFirefox(browserSegments: List<String>): Boolean {
|
private fun isFirefox(browserSegments: List<String>): Boolean {
|
||||||
return browserSegments.lastOrNull()?.startsWith("Firefox").orFalse()
|
return browserSegments.lastOrNull()?.startsWith(BROWSER_FIREFOX).orFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getBrowserVersion(browserSegments: List<String>, browserName: String): String? {
|
private fun getBrowserVersion(browserSegments: List<String>, browserName: String): String? {
|
||||||
|
@ -148,11 +170,11 @@ class ParseDeviceUserAgentUseCase @Inject constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isEdge(browserSegments: List<String>): Boolean {
|
private fun isEdge(browserSegments: List<String>): Boolean {
|
||||||
return browserSegments.lastOrNull()?.startsWith("Edge").orFalse()
|
return browserSegments.lastOrNull()?.startsWith(BROWSER_EDGE).orFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSafari(browserSegments: List<String>): Boolean {
|
private fun isSafari(browserSegments: List<String>): Boolean {
|
||||||
return browserSegments.lastOrNull()?.startsWith("Safari").orFalse() &&
|
return browserSegments.lastOrNull()?.startsWith(BROWSER_SAFARI).orFalse() &&
|
||||||
browserSegments.getOrNull(browserSegments.size - 2)?.startsWith("Version").orFalse()
|
browserSegments.getOrNull(browserSegments.size - 2)?.startsWith("Version").orFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +185,7 @@ class ParseDeviceUserAgentUseCase @Inject constructor() {
|
||||||
private fun getMobileBrowserName(browserSegments: List<String>): String? {
|
private fun getMobileBrowserName(browserSegments: List<String>): String? {
|
||||||
val possibleBrowserName = browserSegments.getOrNull(browserSegments.size - 3)?.split("/")?.firstOrNull()
|
val possibleBrowserName = browserSegments.getOrNull(browserSegments.size - 3)?.split("/")?.firstOrNull()
|
||||||
return if (possibleBrowserName == "Version") {
|
return if (possibleBrowserName == "Version") {
|
||||||
"Safari"
|
BROWSER_SAFARI
|
||||||
} else {
|
} else {
|
||||||
possibleBrowserName
|
possibleBrowserName
|
||||||
}
|
}
|
||||||
|
@ -187,5 +209,17 @@ class ParseDeviceUserAgentUseCase @Inject constructor() {
|
||||||
|
|
||||||
// Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
|
// Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
|
||||||
private const val WEB_KEYWORD = "Mozilla/"
|
private const val WEB_KEYWORD = "Mozilla/"
|
||||||
|
|
||||||
|
private const val OPERATING_SYSTEM_MAC_KEYWORD = "Macintosh"
|
||||||
|
private const val OPERATING_SYSTEM_MAC = "macOS"
|
||||||
|
private const val OPERATING_SYSTEM_IOS = "iOS"
|
||||||
|
private const val OPERATING_SYSTEM_WINDOWS_KEYWORD = "Windows"
|
||||||
|
private const val OPERATING_SYSTEM_ANDROID_KEYWORD = "Android"
|
||||||
|
private const val DEVICE_IPAD_KEYWORD = "iPad"
|
||||||
|
private const val DEVICE_IPHONE_KEYWORD = "iPhone"
|
||||||
|
|
||||||
|
private const val BROWSER_FIREFOX = "Firefox"
|
||||||
|
private const val BROWSER_SAFARI = "Safari"
|
||||||
|
private const val BROWSER_EDGE = "Edge"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,8 +62,8 @@ private val A_USER_AGENT_LIST_FOR_DESKTOP = listOf(
|
||||||
"Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) ElementNightly/2022091301 Chrome/104.0.5112.102 Electron/20.1.1 Safari/537.36",
|
"Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) ElementNightly/2022091301 Chrome/104.0.5112.102 Electron/20.1.1 Safari/537.36",
|
||||||
)
|
)
|
||||||
private val AN_EXPECTED_RESULT_LIST_FOR_DESKTOP = listOf(
|
private val AN_EXPECTED_RESULT_LIST_FOR_DESKTOP = listOf(
|
||||||
DeviceExtendedInfo(DeviceType.DESKTOP, null, "Macintosh", "Electron", "20.1.1"),
|
DeviceExtendedInfo(DeviceType.DESKTOP, null, "macOS", "Electron", "20.1.1"),
|
||||||
DeviceExtendedInfo(DeviceType.DESKTOP, null, "Windows NT 10.0", "Electron", "20.1.1"),
|
DeviceExtendedInfo(DeviceType.DESKTOP, null, "Windows", "Electron", "20.1.1"),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val A_USER_AGENT_LIST_FOR_WEB = listOf(
|
private val A_USER_AGENT_LIST_FOR_WEB = listOf(
|
||||||
|
@ -78,15 +78,15 @@ private val A_USER_AGENT_LIST_FOR_WEB = listOf(
|
||||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246",
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246",
|
||||||
)
|
)
|
||||||
private val AN_EXPECTED_RESULT_LIST_FOR_WEB = listOf(
|
private val AN_EXPECTED_RESULT_LIST_FOR_WEB = listOf(
|
||||||
DeviceExtendedInfo(DeviceType.WEB, null, "Macintosh", "Chrome", "104.0.5112.102"),
|
DeviceExtendedInfo(DeviceType.WEB, null, "macOS", "Chrome", "104.0.5112.102"),
|
||||||
DeviceExtendedInfo(DeviceType.WEB, null, "Windows NT 10.0", "Chrome", "104.0.5112.102"),
|
DeviceExtendedInfo(DeviceType.WEB, null, "Windows", "Chrome", "104.0.5112.102"),
|
||||||
DeviceExtendedInfo(DeviceType.WEB, null, "Macintosh", "Firefox", "39.0"),
|
DeviceExtendedInfo(DeviceType.WEB, null, "macOS", "Firefox", "39.0"),
|
||||||
DeviceExtendedInfo(DeviceType.WEB, null, "Macintosh", "Safari", "8.0.3"),
|
DeviceExtendedInfo(DeviceType.WEB, null, "macOS", "Safari", "8.0.3"),
|
||||||
DeviceExtendedInfo(DeviceType.WEB, null, "Android 9", "Chrome", "69.0.3497.100"),
|
DeviceExtendedInfo(DeviceType.WEB, null, "Android", "Chrome", "69.0.3497.100"),
|
||||||
DeviceExtendedInfo(DeviceType.WEB, null, "iPad", "Safari", "8.0"),
|
DeviceExtendedInfo(DeviceType.WEB, null, "iOS", "Safari", "8.0"),
|
||||||
DeviceExtendedInfo(DeviceType.WEB, null, "iPhone", "Safari", "8.0"),
|
DeviceExtendedInfo(DeviceType.WEB, null, "iOS", "Safari", "8.0"),
|
||||||
DeviceExtendedInfo(DeviceType.WEB, null, "Windows NT 6.0", "Firefox", "40.0"),
|
DeviceExtendedInfo(DeviceType.WEB, null, "Windows", "Firefox", "40.0"),
|
||||||
DeviceExtendedInfo(DeviceType.WEB, null, "Windows NT 10.0", "Edge", "12.246"),
|
DeviceExtendedInfo(DeviceType.WEB, null, "Windows", "Edge", "12.246"),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val AN_UNKNOWN_USER_AGENT_LIST = listOf(
|
private val AN_UNKNOWN_USER_AGENT_LIST = listOf(
|
||||||
|
|
Loading…
Reference in a new issue