mirror of
https://github.com/bitwarden/android.git
synced 2024-11-24 18:36:32 +03:00
Add logic to ensure url has a valid https protocol (#3933)
This commit is contained in:
parent
4f55d622cb
commit
1c2ccd5305
4 changed files with 82 additions and 3 deletions
|
@ -5,6 +5,8 @@ import android.view.accessibility.AccessibilityNodeInfo
|
|||
import androidx.core.net.toUri
|
||||
import com.x8bit.bitwarden.data.autofill.accessibility.model.FillableFields
|
||||
import com.x8bit.bitwarden.data.autofill.accessibility.util.getSupportedBrowserOrNull
|
||||
import com.x8bit.bitwarden.data.autofill.accessibility.util.toUriOrNull
|
||||
import com.x8bit.bitwarden.data.platform.util.hasHttpProtocol
|
||||
|
||||
/**
|
||||
* The default implementation for the [AccessibilityParser].
|
||||
|
@ -29,10 +31,19 @@ class AccessibilityParserImpl : AccessibilityParser {
|
|||
rootNode
|
||||
.findAccessibilityNodeInfosByViewId("$packageName:id/$viewId")
|
||||
.map { accessibilityNodeInfo ->
|
||||
browser.urlExtractor(accessibilityNodeInfo.text.toString())
|
||||
browser
|
||||
.urlExtractor(accessibilityNodeInfo.text.toString())
|
||||
?.trim()
|
||||
?.let { rawUrl ->
|
||||
if (rawUrl.contains(other = ".") && !rawUrl.hasHttpProtocol()) {
|
||||
"https://$rawUrl"
|
||||
} else {
|
||||
rawUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.firstOrNull()
|
||||
?.toUri()
|
||||
?.toUriOrNull()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,12 @@ fun String.toUriOrNull(): URI? =
|
|||
fun String.isAndroidApp(): Boolean =
|
||||
this.startsWith(ANDROID_APP_PROTOCOL)
|
||||
|
||||
/**
|
||||
* Whether this [String] starts with an http or https protocol.
|
||||
*/
|
||||
fun String.hasHttpProtocol(): Boolean =
|
||||
this.startsWith(prefix = "http://") || this.startsWith(prefix = "https://")
|
||||
|
||||
/**
|
||||
* Try and extract the web host from this [String] if it represents an Android app.
|
||||
*/
|
||||
|
|
|
@ -61,7 +61,7 @@ class AccessibilityParserTest {
|
|||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `parseForUriOrPackageName should return the site url as a URI when package is a supported browser and URL is found`() {
|
||||
fun `parseForUriOrPackageName should return the site url un-augmented with https protocol as a URI when package is a supported browser and URL is found`() {
|
||||
val testBrowser = Browser(packageName = "com.android.chrome", urlFieldId = "url_bar")
|
||||
val url = "https://www.google.com"
|
||||
val urlNode = mockk<AccessibilityNodeInfo> {
|
||||
|
@ -81,4 +81,50 @@ class AccessibilityParserTest {
|
|||
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `parseForUriOrPackageName should return the site url un-augmented with http protocol as a URI when package is a supported browser and URL is found`() {
|
||||
val testBrowser = Browser(packageName = "com.android.chrome", urlFieldId = "url_bar")
|
||||
val url = "http://www.google.com"
|
||||
val urlNode = mockk<AccessibilityNodeInfo> {
|
||||
every { text } returns url
|
||||
}
|
||||
val rootNode = mockk<AccessibilityNodeInfo> {
|
||||
every { packageName } returns testBrowser.packageName
|
||||
every {
|
||||
findAccessibilityNodeInfosByViewId(
|
||||
"$packageName:id/${testBrowser.possibleUrlFieldIds.first()}",
|
||||
)
|
||||
} returns listOf(urlNode)
|
||||
}
|
||||
val expectedResult = url.toUri()
|
||||
|
||||
val result = accessibilityParser.parseForUriOrPackageName(rootNode = rootNode)
|
||||
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `parseForUriOrPackageName should return the site url augmented with https protocol as a URI when package is a supported browser and URL is found`() {
|
||||
val testBrowser = Browser(packageName = "com.android.chrome", urlFieldId = "url_bar")
|
||||
val url = "www.google.com"
|
||||
val urlNode = mockk<AccessibilityNodeInfo> {
|
||||
every { text } returns url
|
||||
}
|
||||
val rootNode = mockk<AccessibilityNodeInfo> {
|
||||
every { packageName } returns testBrowser.packageName
|
||||
every {
|
||||
findAccessibilityNodeInfosByViewId(
|
||||
"$packageName:id/${testBrowser.possibleUrlFieldIds.first()}",
|
||||
)
|
||||
} returns listOf(urlNode)
|
||||
}
|
||||
val expectedResult = "https://$url".toUri()
|
||||
|
||||
val result = accessibilityParser.parseForUriOrPackageName(rootNode = rootNode)
|
||||
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.x8bit.bitwarden.data.platform.manager.ResourceCacheManager
|
|||
import com.x8bit.bitwarden.data.platform.util.findLastSubstringIndicesOrNull
|
||||
import com.x8bit.bitwarden.data.platform.util.getDomainOrNull
|
||||
import com.x8bit.bitwarden.data.platform.util.getWebHostFromAndroidUriOrNull
|
||||
import com.x8bit.bitwarden.data.platform.util.hasHttpProtocol
|
||||
import com.x8bit.bitwarden.data.platform.util.isAndroidApp
|
||||
import com.x8bit.bitwarden.data.platform.util.parseDomainOrNull
|
||||
import com.x8bit.bitwarden.data.platform.util.toUriOrNull
|
||||
|
@ -48,6 +49,21 @@ class StringExtensionsTest {
|
|||
assertFalse("com.x8bit.bitwarden".isAndroidApp())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hasHttpProtocol should return false when doesn't start with an appropriate protocol`() {
|
||||
assertFalse("androidapp://com.x8bit.bitwarden".hasHttpProtocol())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hasHttpProtocol should return true when it starts with the http protocol`() {
|
||||
assertTrue("http://www.google.com".hasHttpProtocol())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hasHttpProtocol should return true when it starts with the https protocol`() {
|
||||
assertTrue("https://www.google.com".hasHttpProtocol())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getWebHostFromAndroidUriOrNull should return null when not android app`() {
|
||||
assertNull("com.x8bit.bitwarden".getWebHostFromAndroidUriOrNull())
|
||||
|
|
Loading…
Reference in a new issue