Commit 23598e41 authored by Tiger Oakes's avatar Tiger Oakes
Browse files

Add sameOriginAs Uri helper

parent 7cb28895
......@@ -31,6 +31,7 @@ import mozilla.components.concept.engine.permission.PermissionRequest
import mozilla.components.concept.engine.prompt.PromptRequest
import mozilla.components.concept.engine.window.WindowRequest
import mozilla.components.support.base.observer.Consumable
import mozilla.components.support.ktx.android.net.isInScope
/**
* [EngineSession.Observer] implementation responsible to update the state of a [Session] from the events coming out of
......@@ -83,13 +84,6 @@ internal class EngineObserver(
uri.query == originalUri.query
}
private fun isHostEquals(sessionUrl: String, newUrl: String): Boolean {
val sessionUri = sessionUrl.toUri()
val newUri = newUrl.toUri()
return sessionUri.scheme == newUri.scheme && sessionUri.host == newUri.host
}
/**
* Checks that the [newUrl] is in scope of the web app manifest.
*
......@@ -100,9 +94,7 @@ internal class EngineObserver(
val scopeUri = scope.toUri()
val newUri = newUrl.toUri()
return isHostEquals(scope, newUrl) &&
scopeUri.port == newUri.port &&
newUri.path.orEmpty().startsWith(scopeUri.path.orEmpty())
return newUri.isInScope(listOf(scopeUri))
}
override fun onLoadRequest(
......
......@@ -10,6 +10,7 @@ import mozilla.components.browser.state.state.BrowserState
import mozilla.components.browser.state.state.ContentState
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.state.content.HistoryState
import mozilla.components.support.ktx.android.net.sameSchemeAndHostAs
internal object ContentStateReducer {
/**
......@@ -142,5 +143,5 @@ private fun isHostEquals(sessionUrl: String, newUrl: String): Boolean {
val sessionUri = Uri.parse(sessionUrl)
val newUri = Uri.parse(newUrl)
return sessionUri.scheme == newUri.scheme && sessionUri.host == newUri.host
return sessionUri.sameSchemeAndHostAs(newUri)
}
......@@ -25,3 +25,27 @@ val Uri.hostWithoutCommonPrefixes: String?
*/
val Uri.isHttpOrHttps: Boolean
get() = scheme == "http" || scheme == "https"
/**
* Checks that the given URL is in scope of the web app specified by [trustedScopes].
*
* https://www.w3.org/TR/appmanifest/#dfn-within-scope
*/
fun Uri.isInScope(trustedScopes: Iterable<Uri>): Boolean {
val path = path.orEmpty()
return trustedScopes.any { scope ->
sameOriginAs(scope) && path.startsWith(scope.path.orEmpty())
}
}
/**
* Checks that Uri has the same scheme and host as [other].
*/
fun Uri.sameSchemeAndHostAs(other: Uri) = scheme == other.scheme && host == other.host
/**
* Checks that Uri has the same origin as [other].
*
* https://html.spec.whatwg.org/multipage/origin.html#same-origin
*/
fun Uri.sameOriginAs(other: Uri) = sameSchemeAndHostAs(other) && port == other.port
......@@ -5,13 +5,13 @@
package mozilla.components.support.ktx.android.net
import androidx.core.net.toUri
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import androidx.test.ext.junit.runners.AndroidJUnit4
@RunWith(AndroidJUnit4::class)
class UriTest {
......@@ -67,4 +67,46 @@ class UriTest {
assertFalse("google.com".toUri().isHttpOrHttps)
assertFalse("git@github.com:mozilla/gecko-dev.git".toUri().isHttpOrHttps)
}
@Test
fun testIsInScope() {
val url = "https://mozilla.github.io/my-app/".toUri()
val prefix = "https://mozilla.github.io/prefix-of/resource.html".toUri()
assertFalse(url.isInScope(emptyList()))
assertTrue(url.isInScope(listOf("https://mozilla.github.io/my-app/".toUri())))
assertFalse(url.isInScope(listOf("https://firefox.com/out-of-scope/".toUri())))
assertFalse(url.isInScope(listOf("https://mozilla.github.io/my-app-almost-in-scope".toUri())))
assertTrue(prefix.isInScope(listOf("https://mozilla.github.io/prefix".toUri())))
assertTrue(prefix.isInScope(listOf("https://mozilla.github.io/prefix-of/".toUri())))
}
@Test
fun testSameSchemeAndHostAs() {
// Host mismatch.
assertFalse("https://foo.bar".toUri().sameSchemeAndHostAs("https://foo.baz".toUri()))
// Scheme mismatch.
assertFalse("http://127.0.0.1".toUri().sameSchemeAndHostAs("https://127.0.0.1".toUri()))
// Port mismatch.
assertTrue("https://foo.bar:444".toUri().sameSchemeAndHostAs("https://foo.bar:555".toUri()))
// Port OK but scheme different.
assertFalse("https://foo.bar:443".toUri().sameSchemeAndHostAs("ftp://foo.bar:443".toUri()))
assertTrue("https://foo.bar/bobo".toUri().sameSchemeAndHostAs("https://foo.bar:443/obob".toUri()))
assertTrue("https://foo.bar:333".toUri().sameSchemeAndHostAs("https://foo.bar:443:333".toUri()))
}
@Test
fun testSameOriginAs() {
// Host mismatch.
assertFalse("https://foo.bar".toUri().sameOriginAs("https://foo.baz".toUri()))
// Scheme mismatch.
assertFalse("http://127.0.0.1".toUri().sameOriginAs("https://127.0.0.1".toUri()))
// Port mismatch.
assertFalse("https://foo.bar:444".toUri().sameOriginAs("https://foo.bar:555".toUri()))
// Port OK but scheme different.
assertFalse("https://foo.bar:443".toUri().sameOriginAs("ftp://foo.bar:443".toUri()))
assertTrue("https://foo.bar:443/bobo".toUri().sameOriginAs("https://foo.bar:443/obob".toUri()))
assertTrue("https://foo.bar:333".toUri().sameOriginAs("https://foo.bar:333".toUri()))
}
}
......@@ -44,6 +44,11 @@ permalink: /changelog/
* **feature-tabs**
* ⚠️ **This is a breaking change**: `TabsFeature` now supports providing custom use case implementations. Therefore, an instance of `SelectTabUseCase` and `RemoveTabUseCase` have to be provided.
* **support-ktx**
* Added `Uri.sameHostAs` to check if two Uris have the same host (both http/https, both same domain).
* Added `Uri.sameOriginAs` to check if two Uris have the same origin (same host, same port).
* Added `Uri.isInScope` to check if a Uri is within one of the given scopes.
# 44.0.0
* [Commits](https://github.com/mozilla-mobile/android-components/compare/v43.0.0...v44.0.0)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment