Skip to content
This repository was archived by the owner on Nov 1, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
package mozilla.components.feature.accounts.push.ext

import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.components.support.ktx.kotlin.toNormalizedUrl
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
Expand All @@ -22,4 +24,23 @@ class StringKtTest {

assertTrue(endpoint.redactPartialUri().contains("redacted..."))
}

@Test
fun `default schema if http is missing`() {
assertEquals("https://www.example.com", "https://www.example.com".toNormalizedUrl())
assertEquals("htTPs://www.example.com", "htTPs://www.example.com".toNormalizedUrl())
assertEquals("HTTP://www.example.com", "HTTP://www.example.com".toNormalizedUrl())
assertEquals("http://www.example.com", "http://www.example.com".toNormalizedUrl())
assertEquals("http://www.example.com", "www.example.com".toNormalizedUrl())
assertEquals("http://example.com", "example.com".toNormalizedUrl())
assertEquals("http://example", "example".toNormalizedUrl())
assertEquals("http://example", " example ".toNormalizedUrl())

assertEquals("ftp://example.com", "ftp://example.com".toNormalizedUrl())
assertEquals("FTP://example.com", "FTP://example.com".toNormalizedUrl())

assertEquals("http://httpexample.com", "httpexample.com".toNormalizedUrl())
assertEquals("http://httpsexample.com", "httpsexample.com".toNormalizedUrl())
assertEquals("http://httpsexample.com", " httpsexample.com ".toNormalizedUrl())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import mozilla.components.feature.search.SearchUseCases
import mozilla.components.feature.session.SessionUseCases
import mozilla.components.feature.tabs.TabsUseCases
import mozilla.components.support.ktx.kotlin.isUrl
import mozilla.components.support.ktx.kotlin.toNormalizedUrl
import mozilla.components.support.utils.SafeIntent
import mozilla.components.support.utils.WebURLFinder

Expand Down Expand Up @@ -50,7 +51,7 @@ class TabIntentProcessor(
} else {
val caller = intent.externalPackage()
tabsUseCases.selectOrAddTab(
url,
url.toNormalizedUrl(),
private = isPrivate,
source = SessionState.Source.External.ActionView(caller),
flags = LoadUrlFlags.external()
Expand All @@ -61,7 +62,7 @@ class TabIntentProcessor(

/**
* Processes a send intent and tries to load [EXTRA_TEXT] as a URL.
* If its not a URL, a search is run instead.
* If it's not a URL, a search is run instead.
*/
private fun processSendIntent(intent: SafeIntent): Boolean {
val extraText = intent.getStringExtra(EXTRA_TEXT)
Expand Down Expand Up @@ -97,7 +98,10 @@ class TabIntentProcessor(
}

private fun addNewTab(url: String, source: SessionState.Source) {
tabsUseCases.addTab(url, source = source, flags = LoadUrlFlags.external(), private = isPrivate)
tabsUseCases.addTab(
url.toNormalizedUrl(),
source = source, flags = LoadUrlFlags.external(), private = isPrivate
)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,15 @@ class TabIntentProcessorTest {
val handler = TabIntentProcessor(TabsUseCases(store), useCases.loadUrl, searchUseCases.newTabSearch)
val intent: Intent = mock()
whenever(intent.action).thenReturn(Intent.ACTION_VIEW)
whenever(intent.dataString).thenReturn("https://mozilla.org")
whenever(intent.dataString).thenReturn("http://mozilla.org")

assertEquals(0, store.state.tabs.size)
handler.process(intent)
store.waitUntilIdle()
assertEquals(1, store.state.tabs.size)
assertTrue(store.state.tabs[0].source is SessionState.Source.External.ActionView)

val tab = store.state.findNormalOrPrivateTabByUrl("https://mozilla.org", private = false)
val tab = store.state.findNormalOrPrivateTabByUrl("http://mozilla.org", private = false)
assertNotNull(tab)

val otherTab = createTab("https://firefox.com")
Expand All @@ -118,12 +118,24 @@ class TabIntentProcessorTest {

// processing the same intent again doesn't add an additional tab
handler.process(intent)
// processing a similar intent which produces the same url doesn't add an additional tab
whenever(intent.dataString).thenReturn("mozilla.org")
handler.process(intent)

store.waitUntilIdle()
assertEquals(2, store.state.tabs.size)
assertEquals(tab, store.state.selectedTab)
// sources of existing tabs weren't affected
assertTrue(store.state.tabs[0].source is SessionState.Source.External.ActionView)
assertTrue(store.state.tabs[1].source is SessionState.Source.Internal.None)

// Intent with a url that's missing a scheme
whenever(intent.dataString).thenReturn("example.com")
handler.process(intent)
store.waitUntilIdle()
assertEquals(3, store.state.tabs.size)
assertTrue(store.state.tabs[0].source is SessionState.Source.External.ActionView)
assertNotNull(store.state.findNormalOrPrivateTabByUrl("http://example.com", private = false))
}

@Test
Expand Down Expand Up @@ -152,6 +164,14 @@ class TabIntentProcessorTest {
store.waitUntilIdle()
assertEquals(2, store.state.tabs.size)
assertEquals(tab, store.state.selectedTab)

// Intent with a url that's missing a scheme
whenever(intent.dataString).thenReturn("example.com")
handler.process(intent)
store.waitUntilIdle()
assertEquals(3, store.state.tabs.size)
assertTrue(store.state.tabs[0].source is SessionState.Source.External.ActionView)
assertNotNull(store.state.findNormalOrPrivateTabByUrl("http://example.com", private = false))
}

@Test
Expand Down Expand Up @@ -179,6 +199,14 @@ class TabIntentProcessorTest {
store.waitUntilIdle()
assertEquals(2, store.state.tabs.size)
assertEquals(tab, store.state.selectedTab)

// Intent with a url that's missing a scheme
whenever(intent.dataString).thenReturn("example.com")
handler.process(intent)
store.waitUntilIdle()
assertEquals(3, store.state.tabs.size)
assertTrue(store.state.tabs[0].source is SessionState.Source.External.ActionView)
assertNotNull(store.state.findNormalOrPrivateTabByUrl("http://example.com", private = false))
}

@Test
Expand Down Expand Up @@ -223,6 +251,14 @@ class TabIntentProcessorTest {
assertEquals(5, store.state.tabs.size)
assertEquals("HTTPS://tweets.mozilla.org", store.state.tabs[4].content.url)
assertTrue(store.state.tabs[4].source is SessionState.Source.External.ActionSend)

// Intent with a url that's missing a scheme
whenever(intent.getStringExtra(Intent.EXTRA_TEXT)).thenReturn("example.com")
handler.process(intent)
store.waitUntilIdle()
assertEquals(6, store.state.tabs.size)
assertTrue(store.state.tabs[5].source is SessionState.Source.External.ActionSend)
assertNotNull(store.state.findNormalOrPrivateTabByUrl("http://example.com", private = false))
}

@Test
Expand Down Expand Up @@ -286,6 +322,14 @@ class TabIntentProcessorTest {
assertEquals("http://mozilla.org", store.state.tabs[0].content.url)
assertEquals("", store.state.tabs[0].content.searchTerms)
assertTrue(store.state.tabs[0].source is SessionState.Source.External.ActionSearch)

// Intent with a url that's missing a scheme
whenever(intent.getStringExtra(SearchManager.QUERY)).thenReturn("example.com")
handler.process(intent)
store.waitUntilIdle()
assertEquals(2, store.state.tabs.size)
assertTrue(store.state.tabs[1].source is SessionState.Source.External.ActionSearch)
assertNotNull(store.state.findNormalOrPrivateTabByUrl("http://example.com", private = false))
}

@Test
Expand Down Expand Up @@ -336,6 +380,14 @@ class TabIntentProcessorTest {
assertEquals("http://mozilla.org", store.state.tabs[0].content.url)
assertEquals("", store.state.tabs[0].content.searchTerms)
assertTrue(store.state.tabs[0].source is SessionState.Source.External.ActionSearch)

// Intent with a url that's missing a scheme
whenever(intent.getStringExtra(SearchManager.QUERY)).thenReturn("example.com")
handler.process(intent)
store.waitUntilIdle()
assertEquals(2, store.state.tabs.size)
assertTrue(store.state.tabs[1].source is SessionState.Source.External.ActionSearch)
assertNotNull(store.state.findNormalOrPrivateTabByUrl("http://example.com", private = false))
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,21 @@ fun String.isExtensionUrl() = this.startsWith("moz-extension://")
*/
fun String.isResourceUrl() = this.startsWith("resource://")

fun String.toNormalizedUrl() = URLStringUtils.toNormalizedURL(this)
/**
* Appends `http` scheme if no scheme is present in this String.
*/
fun String.toNormalizedUrl(): String {
val s = this.trim()
// Most commonly we'll encounter http or https schemes.
// For these, avoid running through toNormalizedURL as an optimization.
return if (!s.startsWith("http://", ignoreCase = true) &&
!s.startsWith("https://", ignoreCase = true)
) {
URLStringUtils.toNormalizedURL(s)
} else {
s
}
}

fun String.isPhone() = re.phoneish.matches(this)

Expand Down