* For #4977 - Support opening Fennec pinned website shortcuts in Fenix Fennec's pinned website shortcuts are set to open the BrowserApp activity. So we need a new activity alias to actually catch such Intents. Otherwise they would open "org.mozilla.firefox/.App" without any way to inform that this is the result of the user clicking on a pinned shortcut. For actually checking if the newly received Intent is of a Fennec pinned shortcut we introduce a new FennecBookmarkShortcutsIntentProcessor which will prepare the Intent to open the shortcut's URL in a new tab. * For #4977 - Don't keep IntentReceiverActivity on the back stack For successive Fennec pinned shortcuts to create a new IntentReceiverActivity and be processed as normal we need to not keep this as our task root. * For #4977 - Test the FennecBookmarkShortcutsIntentProcessormaster
parent
fdb1f505cc
commit
8454f208af
|
@ -48,6 +48,14 @@
|
|||
android:resource="@xml/shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<!--
|
||||
Fennec declared entry for homescreen pinned shortcuts.
|
||||
-->
|
||||
<activity-alias
|
||||
android:name="org.mozilla.gecko.BrowserApp"
|
||||
android:targetActivity=".IntentReceiverActivity">
|
||||
</activity-alias>
|
||||
|
||||
<activity
|
||||
android:name=".HomeActivity"
|
||||
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize|layoutDirection|smallestScreenSize|screenLayout"
|
||||
|
|
|
@ -64,8 +64,9 @@ class IntentReceiverActivity : Activity() {
|
|||
|
||||
intent.setClassName(applicationContext, intentProcessorType.activityClassName)
|
||||
intent.putExtra(HomeActivity.OPEN_TO_BROWSER, intentProcessorType.shouldOpenToBrowser(intent))
|
||||
startActivity(intent)
|
||||
|
||||
// finish() before starting another activity. Don't keep this on the activities back stack.
|
||||
finish()
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import mozilla.components.feature.pwa.intent.TrustedWebActivityIntentProcessor
|
|||
import mozilla.components.feature.search.SearchUseCases
|
||||
import mozilla.components.feature.session.SessionUseCases
|
||||
import org.mozilla.fenix.BuildConfig
|
||||
import org.mozilla.fenix.home.intent.FennecBookmarkShortcutsIntentProcessor
|
||||
import org.mozilla.fenix.test.Mockable
|
||||
|
||||
/**
|
||||
|
@ -62,7 +63,8 @@ class IntentProcessors(
|
|||
apiKey = BuildConfig.DIGITAL_ASSET_LINKS_TOKEN,
|
||||
store = customTabsStore
|
||||
),
|
||||
WebAppIntentProcessor(sessionManager, sessionUseCases.loadUrl, ManifestStorage(context))
|
||||
WebAppIntentProcessor(sessionManager, sessionUseCases.loadUrl, ManifestStorage(context)),
|
||||
FennecBookmarkShortcutsIntentProcessor(sessionManager, sessionUseCases.loadUrl)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.home.intent
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.Intent.ACTION_VIEW
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.concept.engine.EngineSession
|
||||
import mozilla.components.feature.intent.ext.putSessionId
|
||||
import mozilla.components.feature.intent.processing.IntentProcessor
|
||||
import mozilla.components.feature.session.SessionUseCases
|
||||
import mozilla.components.support.utils.toSafeIntent
|
||||
|
||||
/**
|
||||
* Legacy processor for pinned websites shortcuts created by Fennec.
|
||||
* https://developer.android.com/guide/topics/ui/shortcuts/creating-shortcuts#pinned
|
||||
*/
|
||||
class FennecBookmarkShortcutsIntentProcessor(
|
||||
private val sessionManager: SessionManager,
|
||||
private val loadUrlUseCase: SessionUseCases.DefaultLoadUrlUseCase
|
||||
) : IntentProcessor {
|
||||
|
||||
/**
|
||||
* Returns true if this Intent is of a Fennec pinned shortcut.
|
||||
*/
|
||||
override fun matches(intent: Intent): Boolean {
|
||||
return intent.toSafeIntent().action == ACTION_FENNEC_HOMESCREEN_SHORTCUT
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is an Intent for a Fennec pinned website shortcut
|
||||
* prepare it for opening website's URL in a new tab.
|
||||
*/
|
||||
override suspend fun process(intent: Intent): Boolean {
|
||||
val safeIntent = intent.toSafeIntent()
|
||||
val url = safeIntent.dataString
|
||||
|
||||
return if (!url.isNullOrEmpty() && matches(intent)) {
|
||||
val session = Session(url, private = false, source = Session.Source.HOME_SCREEN)
|
||||
|
||||
sessionManager.add(session)
|
||||
loadUrlUseCase(url, session, EngineSession.LoadUrlFlags.external())
|
||||
intent.action = ACTION_VIEW
|
||||
intent.putSessionId(session.id)
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
companion object {
|
||||
/**
|
||||
* Fennec set action for the pinned website shortcut Intent.
|
||||
*/
|
||||
const val ACTION_FENNEC_HOMESCREEN_SHORTCUT = "org.mozilla.gecko.BOOKMARK"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.home.intent
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import assertk.assertAll
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isFalse
|
||||
import assertk.assertions.isTrue
|
||||
import io.mockk.Called
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.verify
|
||||
import io.mockk.verifyAll
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.concept.engine.EngineSession
|
||||
import mozilla.components.feature.intent.ext.getSessionId
|
||||
import mozilla.components.feature.session.SessionUseCases
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.TestApplication
|
||||
import org.mozilla.fenix.home.intent.FennecBookmarkShortcutsIntentProcessor.Companion.ACTION_FENNEC_HOMESCREEN_SHORTCUT
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import java.util.UUID
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(application = TestApplication::class)
|
||||
class FennecBookmarkShortcutsIntentProcessorTest {
|
||||
private val sessionManager = mockk<SessionManager>(relaxed = true)
|
||||
private val loadUrlUseCase = mockk<SessionUseCases.DefaultLoadUrlUseCase>(relaxed = true)
|
||||
|
||||
@Test
|
||||
fun `only match Fennec pinned shortcut Intents`() {
|
||||
val processor = FennecBookmarkShortcutsIntentProcessor(sessionManager, loadUrlUseCase)
|
||||
|
||||
assertAll {
|
||||
assertThat(processor.matches(Intent(ACTION_FENNEC_HOMESCREEN_SHORTCUT))).isTrue()
|
||||
assertThat(processor.matches(Intent("ShouldNotMatch"))).isFalse()
|
||||
assertThat(processor.matches(Intent())).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `do not process blank Intents`() = runBlocking {
|
||||
val processor = FennecBookmarkShortcutsIntentProcessor(sessionManager, loadUrlUseCase)
|
||||
val fennecShortcutsIntent = Intent(ACTION_FENNEC_HOMESCREEN_SHORTCUT)
|
||||
fennecShortcutsIntent.data = Uri.parse("http://mozilla.org")
|
||||
|
||||
val wasEmptyIntentProcessed = processor.matches(Intent())
|
||||
|
||||
assertThat(wasEmptyIntentProcessed).isFalse()
|
||||
verify {
|
||||
sessionManager wasNot Called
|
||||
loadUrlUseCase wasNot Called
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `processing a Fennec shortcut Intent results in loading it's URL in a new Session`() = runBlocking {
|
||||
mockkStatic(UUID::class)
|
||||
// The Session constructor uses UUID.randomUUID().toString() as the default value for it's id field
|
||||
every { UUID.randomUUID().toString() } returns "test"
|
||||
val processor = FennecBookmarkShortcutsIntentProcessor(sessionManager, loadUrlUseCase)
|
||||
val fennecShortcutsIntent = Intent(ACTION_FENNEC_HOMESCREEN_SHORTCUT)
|
||||
val testUrl = "http://mozilla.org"
|
||||
fennecShortcutsIntent.data = Uri.parse(testUrl)
|
||||
val expectedSession = Session(testUrl, private = false, source = Session.Source.HOME_SCREEN)
|
||||
|
||||
val wasIntentProcessed = processor.process(fennecShortcutsIntent)
|
||||
|
||||
assertAll {
|
||||
assertThat(wasIntentProcessed).isTrue()
|
||||
assertThat(fennecShortcutsIntent.action).isEqualTo(Intent.ACTION_VIEW)
|
||||
assertThat(fennecShortcutsIntent.getSessionId()).isEqualTo(expectedSession.id)
|
||||
}
|
||||
verifyAll {
|
||||
sessionManager.add(expectedSession)
|
||||
loadUrlUseCase(testUrl, expectedSession, EngineSession.LoadUrlFlags.external())
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue