mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-11 13:11:01 +00:00
[fenix] Issue https://github.com/mozilla-mobile/fenix/issues/22489: Remove "Fennec to Fenix" migration code
This commit is contained in:
parent
a38538a52b
commit
51f88636e9
@ -177,14 +177,6 @@ android {
|
|||||||
androidTest {
|
androidTest {
|
||||||
resources.srcDirs += ['src/androidTest/resources']
|
resources.srcDirs += ['src/androidTest/resources']
|
||||||
}
|
}
|
||||||
beta {
|
|
||||||
java.srcDirs = ['src/migration/java']
|
|
||||||
manifest.srcFile "src/migration/AndroidManifest.xml"
|
|
||||||
}
|
|
||||||
release {
|
|
||||||
java.srcDirs = ['src/migration/java']
|
|
||||||
manifest.srcFile "src/migration/AndroidManifest.xml"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
splits {
|
splits {
|
||||||
@ -530,7 +522,6 @@ dependencies {
|
|||||||
implementation Deps.mozilla_support_rustlog
|
implementation Deps.mozilla_support_rustlog
|
||||||
implementation Deps.mozilla_support_utils
|
implementation Deps.mozilla_support_utils
|
||||||
implementation Deps.mozilla_support_locale
|
implementation Deps.mozilla_support_locale
|
||||||
implementation Deps.mozilla_support_migration
|
|
||||||
|
|
||||||
implementation Deps.mozilla_ui_colors
|
implementation Deps.mozilla_ui_colors
|
||||||
implementation Deps.mozilla_ui_icons
|
implementation Deps.mozilla_ui_icons
|
||||||
|
@ -1493,17 +1493,6 @@
|
|||||||
column="1"/>
|
column="1"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
<issue
|
|
||||||
id="UnusedResources"
|
|
||||||
message="The resource `R.anim.placeholder_animation` appears to be unused"
|
|
||||||
errorLine1="<translate"
|
|
||||||
errorLine2="^">
|
|
||||||
<location
|
|
||||||
file="src/main/res/anim/placeholder_animation.xml"
|
|
||||||
line="5"
|
|
||||||
column="1"/>
|
|
||||||
</issue>
|
|
||||||
|
|
||||||
<issue
|
<issue
|
||||||
id="IconXmlAndPng"
|
id="IconXmlAndPng"
|
||||||
message="The following images appear both as density independent `.xml` files and as bitmap files: /Users/oracle/Projects/fenix/app/src/main/res/drawable-hdpi/ic_logo_wordmark_normal.png, /Users/rotbolt/AndroidStudioProjects/fenix/app/src/main/res/drawable-night/ic_logo_wordmark_normal.xml">
|
message="The following images appear both as density independent `.xml` files and as bitmap files: /Users/oracle/Projects/fenix/app/src/main/res/drawable-hdpi/ic_logo_wordmark_normal.png, /Users/rotbolt/AndroidStudioProjects/fenix/app/src/main/res/drawable-night/ic_logo_wordmark_normal.xml">
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
History
|
|
||||||
Bookmarks
|
|
||||||
Logins
|
|
||||||
Open Tabs
|
|
||||||
Settings
|
|
11
app/src/beta/AndroidManifest.xml
Normal file
11
app/src/beta/AndroidManifest.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
sharedUserId: This release type is meant to replace Firefox (Beta channel) and therefore needs to inherit
|
||||||
|
its sharedUserId for all eternity. Shipping an app update without sharedUserId can have
|
||||||
|
fatal consequences. For example see:
|
||||||
|
- https://issuetracker.google.com/issues/36924841
|
||||||
|
- https://issuetracker.google.com/issues/36905922
|
||||||
|
-->
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:sharedUserId="${sharedUserId}">
|
||||||
|
</manifest>
|
@ -233,13 +233,6 @@
|
|||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".migration.MigrationProgressActivity"
|
|
||||||
android:noHistory="true"
|
|
||||||
android:launchMode="singleInstance"
|
|
||||||
android:exported="false">
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".crashes.CrashListActivity"
|
android:name=".crashes.CrashListActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
@ -100,8 +100,7 @@ class IntentReceiverActivity : Activity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return listOf(components.intentProcessors.migrationIntentProcessor) +
|
return components.intentProcessors.externalAppIntentProcessors +
|
||||||
components.intentProcessors.externalAppIntentProcessors +
|
|
||||||
components.intentProcessors.fennecPageShortcutIntentProcessor +
|
components.intentProcessors.fennecPageShortcutIntentProcessor +
|
||||||
components.intentProcessors.externalDeepLinkIntentProcessor +
|
components.intentProcessors.externalDeepLinkIntentProcessor +
|
||||||
modeDependentProcessors +
|
modeDependentProcessors +
|
||||||
|
@ -19,7 +19,6 @@ import mozilla.components.feature.addons.update.DefaultAddonUpdater
|
|||||||
import mozilla.components.feature.autofill.AutofillConfiguration
|
import mozilla.components.feature.autofill.AutofillConfiguration
|
||||||
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
||||||
import mozilla.components.support.base.worker.Frequency
|
import mozilla.components.support.base.worker.Frequency
|
||||||
import mozilla.components.support.migration.state.MigrationStore
|
|
||||||
import org.mozilla.fenix.BuildConfig
|
import org.mozilla.fenix.BuildConfig
|
||||||
import org.mozilla.fenix.Config
|
import org.mozilla.fenix.Config
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
@ -99,7 +98,6 @@ class Components(private val context: Context) {
|
|||||||
useCases.searchUseCases,
|
useCases.searchUseCases,
|
||||||
core.relationChecker,
|
core.relationChecker,
|
||||||
core.customTabsStore,
|
core.customTabsStore,
|
||||||
migrationStore,
|
|
||||||
core.webAppManifestStorage
|
core.webAppManifestStorage
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -157,7 +155,6 @@ class Components(private val context: Context) {
|
|||||||
val analytics by lazyMonitored { Analytics(context) }
|
val analytics by lazyMonitored { Analytics(context) }
|
||||||
val publicSuffixList by lazyMonitored { PublicSuffixList(context) }
|
val publicSuffixList by lazyMonitored { PublicSuffixList(context) }
|
||||||
val clipboardHandler by lazyMonitored { ClipboardHandler(context) }
|
val clipboardHandler by lazyMonitored { ClipboardHandler(context) }
|
||||||
val migrationStore by lazyMonitored { MigrationStore() }
|
|
||||||
val performance by lazyMonitored { PerformanceComponent() }
|
val performance by lazyMonitored { PerformanceComponent() }
|
||||||
val push by lazyMonitored { Push(context, analytics.crashReporter) }
|
val push by lazyMonitored { Push(context, analytics.crashReporter) }
|
||||||
val wifiConnectionMonitor by lazyMonitored { WifiConnectionMonitor(context as Application) }
|
val wifiConnectionMonitor by lazyMonitored { WifiConnectionMonitor(context as Application) }
|
||||||
|
@ -8,10 +8,9 @@ import android.content.Intent
|
|||||||
import mozilla.components.feature.intent.processing.IntentProcessor
|
import mozilla.components.feature.intent.processing.IntentProcessor
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
|
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
|
||||||
import org.mozilla.fenix.migration.MigrationProgressActivity
|
|
||||||
|
|
||||||
enum class IntentProcessorType {
|
enum class IntentProcessorType {
|
||||||
EXTERNAL_APP, NEW_TAB, MIGRATION, EXTERNAL_DEEPLINK, OTHER;
|
EXTERNAL_APP, NEW_TAB, EXTERNAL_DEEPLINK, OTHER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The destination activity based on this intent
|
* The destination activity based on this intent
|
||||||
@ -20,7 +19,6 @@ enum class IntentProcessorType {
|
|||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
EXTERNAL_APP -> ExternalAppBrowserActivity::class.java.name
|
EXTERNAL_APP -> ExternalAppBrowserActivity::class.java.name
|
||||||
NEW_TAB, EXTERNAL_DEEPLINK, OTHER -> HomeActivity::class.java.name
|
NEW_TAB, EXTERNAL_DEEPLINK, OTHER -> HomeActivity::class.java.name
|
||||||
MIGRATION -> MigrationProgressActivity::class.java.name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,7 +27,7 @@ enum class IntentProcessorType {
|
|||||||
fun shouldOpenToBrowser(intent: Intent): Boolean = when (this) {
|
fun shouldOpenToBrowser(intent: Intent): Boolean = when (this) {
|
||||||
EXTERNAL_APP -> true
|
EXTERNAL_APP -> true
|
||||||
NEW_TAB -> intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == 0
|
NEW_TAB -> intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == 0
|
||||||
MIGRATION, EXTERNAL_DEEPLINK, OTHER -> false
|
EXTERNAL_DEEPLINK, OTHER -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +35,6 @@ enum class IntentProcessorType {
|
|||||||
* Classifies the [IntentProcessorType] based on the [IntentProcessor] that handled the [Intent].
|
* Classifies the [IntentProcessorType] based on the [IntentProcessor] that handled the [Intent].
|
||||||
*/
|
*/
|
||||||
fun IntentProcessors.getType(processor: IntentProcessor?) = when {
|
fun IntentProcessors.getType(processor: IntentProcessor?) = when {
|
||||||
migrationIntentProcessor == processor -> IntentProcessorType.MIGRATION
|
|
||||||
externalAppIntentProcessors.contains(processor) ||
|
externalAppIntentProcessors.contains(processor) ||
|
||||||
customTabIntentProcessor == processor ||
|
customTabIntentProcessor == processor ||
|
||||||
privateCustomTabIntentProcessor == processor -> IntentProcessorType.EXTERNAL_APP
|
privateCustomTabIntentProcessor == processor -> IntentProcessorType.EXTERNAL_APP
|
||||||
|
@ -17,8 +17,6 @@ import mozilla.components.feature.session.SessionUseCases
|
|||||||
import mozilla.components.feature.tabs.CustomTabsUseCases
|
import mozilla.components.feature.tabs.CustomTabsUseCases
|
||||||
import mozilla.components.feature.tabs.TabsUseCases
|
import mozilla.components.feature.tabs.TabsUseCases
|
||||||
import mozilla.components.service.digitalassetlinks.RelationChecker
|
import mozilla.components.service.digitalassetlinks.RelationChecker
|
||||||
import mozilla.components.support.migration.MigrationIntentProcessor
|
|
||||||
import mozilla.components.support.migration.state.MigrationStore
|
|
||||||
import org.mozilla.fenix.customtabs.FennecWebAppIntentProcessor
|
import org.mozilla.fenix.customtabs.FennecWebAppIntentProcessor
|
||||||
import org.mozilla.fenix.home.intent.FennecBookmarkShortcutsIntentProcessor
|
import org.mozilla.fenix.home.intent.FennecBookmarkShortcutsIntentProcessor
|
||||||
import org.mozilla.fenix.intent.ExternalDeepLinkIntentProcessor
|
import org.mozilla.fenix.intent.ExternalDeepLinkIntentProcessor
|
||||||
@ -37,7 +35,6 @@ class IntentProcessors(
|
|||||||
private val searchUseCases: SearchUseCases,
|
private val searchUseCases: SearchUseCases,
|
||||||
private val relationChecker: RelationChecker,
|
private val relationChecker: RelationChecker,
|
||||||
private val customTabsStore: CustomTabsServiceStore,
|
private val customTabsStore: CustomTabsServiceStore,
|
||||||
private val migrationStore: MigrationStore,
|
|
||||||
private val manifestStorage: ManifestStorage
|
private val manifestStorage: ManifestStorage
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
@ -82,8 +79,4 @@ class IntentProcessors(
|
|||||||
val fennecPageShortcutIntentProcessor by lazyMonitored {
|
val fennecPageShortcutIntentProcessor by lazyMonitored {
|
||||||
FennecBookmarkShortcutsIntentProcessor(tabsUseCases.addTab)
|
FennecBookmarkShortcutsIntentProcessor(tabsUseCases.addTab)
|
||||||
}
|
}
|
||||||
|
|
||||||
val migrationIntentProcessor by lazyMonitored {
|
|
||||||
MigrationIntentProcessor(migrationStore)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,6 @@ sealed class Event {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
object FennecToFenixMigrated : Event()
|
|
||||||
object AddonsOpenInSettings : Event()
|
object AddonsOpenInSettings : Event()
|
||||||
object StudiesSettings : Event()
|
object StudiesSettings : Event()
|
||||||
object VoiceSearchTapped : Event()
|
object VoiceSearchTapped : Event()
|
||||||
|
@ -981,7 +981,6 @@ private val Event.wrapper: EventWrapper<*>?
|
|||||||
is Event.InteractWithSearchURLArea -> null
|
is Event.InteractWithSearchURLArea -> null
|
||||||
is Event.ClearedPrivateData -> null
|
is Event.ClearedPrivateData -> null
|
||||||
is Event.DismissedOnboarding -> null
|
is Event.DismissedOnboarding -> null
|
||||||
is Event.FennecToFenixMigrated -> null
|
|
||||||
is Event.AddonInstalled -> null
|
is Event.AddonInstalled -> null
|
||||||
is Event.SearchWidgetInstalled -> null
|
is Event.SearchWidgetInstalled -> null
|
||||||
is Event.SyncAuthFromSharedReuse, Event.SyncAuthFromSharedCopy -> null
|
is Event.SyncAuthFromSharedReuse, Event.SyncAuthFromSharedCopy -> null
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
/* 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.migration
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.View
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import mozilla.components.support.base.log.logger.Logger
|
|
||||||
import mozilla.components.support.ktx.android.content.getColorFromAttr
|
|
||||||
import mozilla.components.support.migration.AbstractMigrationProgressActivity
|
|
||||||
import mozilla.components.support.migration.AbstractMigrationService
|
|
||||||
import mozilla.components.support.migration.MigrationResults
|
|
||||||
import mozilla.components.support.migration.state.MigrationAction
|
|
||||||
import mozilla.components.support.migration.state.MigrationProgress
|
|
||||||
import mozilla.components.support.migration.state.MigrationStore
|
|
||||||
import org.mozilla.fenix.HomeActivity
|
|
||||||
import org.mozilla.fenix.IntentReceiverActivity
|
|
||||||
import org.mozilla.fenix.R
|
|
||||||
import org.mozilla.fenix.databinding.ActivityMigrationBinding
|
|
||||||
import org.mozilla.fenix.ext.components
|
|
||||||
|
|
||||||
class MigrationProgressActivity : AbstractMigrationProgressActivity() {
|
|
||||||
private val logger = Logger("MigrationProgressActivity")
|
|
||||||
private val statusAdapter = MigrationStatusAdapter()
|
|
||||||
override val store: MigrationStore by lazy { components.migrationStore }
|
|
||||||
|
|
||||||
private lateinit var binding: ActivityMigrationBinding
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
binding = ActivityMigrationBinding.inflate(layoutInflater)
|
|
||||||
setContentView(binding.root)
|
|
||||||
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun init() {
|
|
||||||
window.navigationBarColor = getColorFromAttr(R.attr.layer1)
|
|
||||||
|
|
||||||
val appName = binding.migrationDescription.context.getString(R.string.app_name)
|
|
||||||
|
|
||||||
binding.migrationDescription.apply {
|
|
||||||
text = context.getString(R.string.migration_description, appName)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.migrationStatusList.apply {
|
|
||||||
val margin = resources.getDimensionPixelSize(R.dimen.migration_margin)
|
|
||||||
addItemDecoration(MigrationStatusItemDecoration(margin))
|
|
||||||
layoutManager = LinearLayoutManager(this@MigrationProgressActivity)
|
|
||||||
adapter = statusAdapter
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.migrationWelcomeTitle.apply {
|
|
||||||
text = context.getString(R.string.migration_title, appName)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.migrationButtonTextView.text = getString(R.string.migration_updating_app_button_text, appName)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMigrationCompleted(results: MigrationResults) {
|
|
||||||
// Enable clicking the finish button
|
|
||||||
binding.migrationButton.apply {
|
|
||||||
setOnClickListener {
|
|
||||||
AbstractMigrationService.dismissNotification(context)
|
|
||||||
|
|
||||||
finish()
|
|
||||||
overridePendingTransition(0, 0)
|
|
||||||
|
|
||||||
store.dispatch(MigrationAction.Clear)
|
|
||||||
|
|
||||||
// If we received a user-initiated intent, throw this back to the intent receiver.
|
|
||||||
if (intent.hasExtra(HomeActivity.OPEN_TO_BROWSER)) {
|
|
||||||
intent.setClassName(applicationContext, IntentReceiverActivity::class.java.name)
|
|
||||||
startActivity(intent)
|
|
||||||
} else {
|
|
||||||
// Fallback: Just launch the browser
|
|
||||||
logger.warn("Intent does not contain OPEN_TO_BROWSER extra, launching HomeActivity")
|
|
||||||
startActivity(Intent(this@MigrationProgressActivity, HomeActivity::class.java))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.migrationButtonTextView.apply {
|
|
||||||
text = getString(R.string.migration_update_app_button, getString(R.string.app_name))
|
|
||||||
setTextColor(
|
|
||||||
ContextCompat.getColor(
|
|
||||||
context,
|
|
||||||
R.color.fx_mobile_text_color_oncolor_primary
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
binding.migrationButton.setBackgroundResource(R.drawable.migration_button_background)
|
|
||||||
binding.migrationButtonProgressBar.visibility = View.INVISIBLE
|
|
||||||
// Keep the results list up-to-date.
|
|
||||||
statusAdapter.updateData(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMigrationStateChanged(progress: MigrationProgress, results: MigrationResults) {
|
|
||||||
statusAdapter.updateData(results)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,109 +0,0 @@
|
|||||||
/* 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.migration
|
|
||||||
|
|
||||||
import android.graphics.Rect
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.annotation.Px
|
|
||||||
import androidx.core.view.isInvisible
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import mozilla.components.support.migration.Migration
|
|
||||||
import mozilla.components.support.migration.MigrationResults
|
|
||||||
import org.mozilla.fenix.R
|
|
||||||
import org.mozilla.fenix.databinding.MigrationListItemBinding
|
|
||||||
|
|
||||||
internal data class MigrationItem(
|
|
||||||
val migration: Migration,
|
|
||||||
val status: Boolean = false
|
|
||||||
)
|
|
||||||
|
|
||||||
// These are the only items we want to show migrating in the UI.
|
|
||||||
internal val whiteList = linkedMapOf(
|
|
||||||
Migration.Settings to R.string.settings_title,
|
|
||||||
Migration.History to R.string.preferences_sync_history,
|
|
||||||
Migration.Bookmarks to R.string.preferences_sync_bookmarks,
|
|
||||||
Migration.Logins to R.string.migration_text_passwords
|
|
||||||
)
|
|
||||||
|
|
||||||
internal class MigrationStatusAdapter :
|
|
||||||
ListAdapter<MigrationItem, MigrationStatusAdapter.ViewHolder>(DiffCallback) {
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
|
||||||
val view = LayoutInflater.from(parent.context)
|
|
||||||
.inflate(R.layout.migration_list_item, parent, false)
|
|
||||||
|
|
||||||
return ViewHolder(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
|
||||||
holder.bind(getItem(position))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter the [results] to only include items in [whiteList] and update the adapter.
|
|
||||||
*/
|
|
||||||
fun updateData(results: MigrationResults) {
|
|
||||||
val itemList = whiteList.keys.map {
|
|
||||||
if (results.containsKey(it)) {
|
|
||||||
MigrationItem(it, results.getValue(it).success)
|
|
||||||
} else {
|
|
||||||
MigrationItem(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
submitList(itemList)
|
|
||||||
}
|
|
||||||
|
|
||||||
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
|
||||||
|
|
||||||
private val context = view.context
|
|
||||||
private val binding = MigrationListItemBinding.bind(view)
|
|
||||||
private val title = binding.migrationItemName
|
|
||||||
private val status = binding.migrationStatusImage
|
|
||||||
|
|
||||||
fun bind(item: MigrationItem) {
|
|
||||||
// Get the resource ID for the item.
|
|
||||||
val migrationText = whiteList[item.migration]?.let {
|
|
||||||
context.getString(it)
|
|
||||||
}.orEmpty()
|
|
||||||
title.text = migrationText
|
|
||||||
status.isInvisible = !item.status
|
|
||||||
status.contentDescription = context.getString(R.string.migration_icon_description)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private object DiffCallback : DiffUtil.ItemCallback<MigrationItem>() {
|
|
||||||
|
|
||||||
override fun areItemsTheSame(oldItem: MigrationItem, newItem: MigrationItem) =
|
|
||||||
oldItem.migration.javaClass.simpleName == newItem.migration.javaClass.simpleName
|
|
||||||
|
|
||||||
override fun areContentsTheSame(oldItem: MigrationItem, newItem: MigrationItem) =
|
|
||||||
oldItem.migration.javaClass.simpleName == newItem.migration.javaClass.simpleName &&
|
|
||||||
oldItem.status == newItem.status
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class MigrationStatusItemDecoration(
|
|
||||||
@Px private val spacing: Int
|
|
||||||
) : RecyclerView.ItemDecoration() {
|
|
||||||
|
|
||||||
override fun getItemOffsets(
|
|
||||||
outRect: Rect,
|
|
||||||
view: View,
|
|
||||||
parent: RecyclerView,
|
|
||||||
state: RecyclerView.State
|
|
||||||
) {
|
|
||||||
val position = parent.getChildViewHolder(view).bindingAdapterPosition
|
|
||||||
val itemCount = state.itemCount
|
|
||||||
|
|
||||||
outRect.left = spacing
|
|
||||||
outRect.right = spacing
|
|
||||||
outRect.top = spacing
|
|
||||||
outRect.bottom = if (position == itemCount - 1) spacing else 0
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/* 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.migration
|
|
||||||
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import mozilla.components.lib.state.ext.flowScoped
|
|
||||||
import mozilla.components.support.base.log.logger.Logger
|
|
||||||
import mozilla.components.support.migration.state.MigrationProgress
|
|
||||||
import mozilla.components.support.migration.state.MigrationStore
|
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
|
||||||
import org.mozilla.fenix.components.metrics.MetricController
|
|
||||||
|
|
||||||
class MigrationTelemetryListener(
|
|
||||||
private val metrics: MetricController,
|
|
||||||
private val store: MigrationStore,
|
|
||||||
private val logger: Logger = Logger("MigrationTelemetryListener")
|
|
||||||
) {
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
fun start() {
|
|
||||||
// Observe for migration completed.
|
|
||||||
store.flowScoped { flow ->
|
|
||||||
flow.collect { state ->
|
|
||||||
logger.debug("Migration state: ${state.progress}")
|
|
||||||
if (state.progress == MigrationProgress.COMPLETED) {
|
|
||||||
metrics.track(Event.FennecToFenixMigrated)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 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/. -->
|
|
||||||
<translate
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:fromXDelta="0"
|
|
||||||
android:toXDelta="0"
|
|
||||||
android:duration="900" />
|
|
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 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/. -->
|
|
||||||
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<corners android:radius="4dp"/>
|
|
||||||
<solid android:color="@color/fx_mobile_action_color_secondary" />
|
|
||||||
</shape>
|
|
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 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/. -->
|
|
||||||
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<corners android:radius="4dp"/>
|
|
||||||
<solid android:color="#312A65" />
|
|
||||||
</shape>
|
|
@ -1,132 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><!-- 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/. -->
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/photonLightGrey05">
|
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_marginBottom="@dimen/migration_progress_margin"
|
|
||||||
android:fillViewport="true"
|
|
||||||
android:overScrollMode="never"
|
|
||||||
android:scrollbars="none"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/migration_button"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<!-- MozMultipleConstraintLayouts: we're not changing the migration code. -->
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:ignore="MozMultipleConstraintLayouts">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
|
||||||
android:id="@+id/migration_firefox_logo"
|
|
||||||
android:layout_width="@dimen/migration_firefox_logo_size"
|
|
||||||
android:layout_height="@dimen/migration_firefox_logo_size"
|
|
||||||
android:layout_marginStart="@dimen/migration_margin_horizontal_large"
|
|
||||||
android:fontFamily="@font/metropolis_bold"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/migration_welcome_title"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toLeftOf="@id/migration_welcome_title"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/migration_welcome_title"
|
|
||||||
app:srcCompat="@drawable/ic_firefox" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
android:id="@+id/migration_welcome_title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/migration_margin"
|
|
||||||
android:layout_marginTop="@dimen/migration_margin"
|
|
||||||
android:layout_marginEnd="@dimen/migration_margin_horizontal_large"
|
|
||||||
android:fontFamily="@font/metropolis_bold"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:lineHeight="24sp"
|
|
||||||
android:text="@string/migration_title"
|
|
||||||
android:textColor="@color/fx_mobile_text_color_action_secondary"
|
|
||||||
android:textSize="@dimen/migration_welcome_title_text_size"
|
|
||||||
android:textAppearance="@style/Header16TextStyle"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/migration_description"
|
|
||||||
app:layout_constraintLeft_toRightOf="@id/migration_firefox_logo"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="Welcome to the all-new Firefox Preview" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
android:id="@+id/migration_description"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="@dimen/migration_margin_horizontal_large"
|
|
||||||
android:layout_marginTop="@dimen/migration_margin"
|
|
||||||
android:layout_marginRight="@dimen/migration_margin_horizontal_large"
|
|
||||||
android:lineHeight="24sp"
|
|
||||||
android:text="@string/migration_description"
|
|
||||||
android:textColor="@color/primary_text_light_theme"
|
|
||||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/migration_status_list"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/migration_welcome_title" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/migration_status_list"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="@dimen/migration_margin_horizontal_large"
|
|
||||||
android:layout_marginTop="@dimen/migration_margin"
|
|
||||||
android:layout_marginRight="@dimen/migration_margin_horizontal_large"
|
|
||||||
android:nestedScrollingEnabled="false"
|
|
||||||
android:overScrollMode="never"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintHorizontal_bias="0.45"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/migration_description"
|
|
||||||
tools:itemCount="5"
|
|
||||||
tools:listitem="@layout/migration_list_item" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/migration_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="@dimen/migration_margin"
|
|
||||||
android:background="@drawable/button_background_grey"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent">
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/migration_button_progress_bar"
|
|
||||||
style="@style/Widget.AppCompat.ProgressBar"
|
|
||||||
android:layout_width="@dimen/migration_progress_size"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/migration_margin"
|
|
||||||
android:layout_marginEnd="@dimen/migration_progress_margin_start" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
android:id="@+id/migration_button_text_view"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="@dimen/migration_progress_margin_compound"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:text="@string/migration_updating_app_button_text"
|
|
||||||
android:textSize="@dimen/migration_button_text_size"
|
|
||||||
android:textAppearance="@style/NeutralButton"
|
|
||||||
tools:text="Updating Firefox…" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><!-- 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/. -->
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/migration_status_image"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:contentDescription="@string/migration_icon_description"
|
|
||||||
app:tint="@color/photonViolet60"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/mozac_ic_check"
|
|
||||||
tools:tint="@color/photonDarkGrey50" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/migration_item_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:textColor="@color/primary_text_light_theme"
|
|
||||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/migration_status_image"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="@sample/migration_items" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -121,17 +121,6 @@
|
|||||||
<dimen name="locale_item_subtitle_size">12sp</dimen>
|
<dimen name="locale_item_subtitle_size">12sp</dimen>
|
||||||
<dimen name="locale_item_height">48dp</dimen>
|
<dimen name="locale_item_height">48dp</dimen>
|
||||||
|
|
||||||
<!--Migration Activity-->
|
|
||||||
<dimen name="migration_margin_horizontal_large">20dp</dimen>
|
|
||||||
<dimen name="migration_margin">16dp</dimen>
|
|
||||||
<dimen name="migration_firefox_logo_size">48dp</dimen>
|
|
||||||
<dimen name="migration_welcome_title_text_size">20sp</dimen>
|
|
||||||
<dimen name="migration_button_text_size">14sp</dimen>
|
|
||||||
<dimen name="migration_progress_size">24dp</dimen>
|
|
||||||
<dimen name="migration_progress_margin">8dp</dimen>
|
|
||||||
<dimen name="migration_progress_margin_start">4dp</dimen>
|
|
||||||
<dimen name="migration_progress_margin_compound">44dp</dimen>
|
|
||||||
|
|
||||||
<!-- Share Fragment -->
|
<!-- Share Fragment -->
|
||||||
<dimen name="share_recent_apps_background_radius">10dp</dimen>
|
<dimen name="share_recent_apps_background_radius">10dp</dimen>
|
||||||
<dimen name="share_recent_apps_padding">8dp</dimen>
|
<dimen name="share_recent_apps_padding">8dp</dimen>
|
||||||
|
@ -1564,17 +1564,17 @@
|
|||||||
<string name="search_delete_search_engine_success_message">Deleted %s</string>
|
<string name="search_delete_search_engine_success_message">Deleted %s</string>
|
||||||
|
|
||||||
<!-- Title text shown for the migration screen to the new browser. Placeholder replaced with app name -->
|
<!-- Title text shown for the migration screen to the new browser. Placeholder replaced with app name -->
|
||||||
<string name="migration_title">Welcome to an all-new %s</string>
|
<string name="migration_title" moz:removedIn="100" tools:ignore="UnusedResources">Welcome to an all-new %s</string>
|
||||||
<!-- Description text followed by a list of things migrating (e.g. Bookmarks, History). Placeholder replaced with app name-->
|
<!-- Description text followed by a list of things migrating (e.g. Bookmarks, History). Placeholder replaced with app name-->
|
||||||
<string name="migration_description">A completely redesigned browser awaits, with improved performance and features to help you do more online.\n\nPlease wait while we update %s with your</string>
|
<string name="migration_description" moz:removedIn="100" tools:ignore="UnusedResources">A completely redesigned browser awaits, with improved performance and features to help you do more online.\n\nPlease wait while we update %s with your</string>
|
||||||
<!-- Text on the disabled button while in progress. Placeholder replaced with app name -->
|
<!-- Text on the disabled button while in progress. Placeholder replaced with app name -->
|
||||||
<string name="migration_updating_app_button_text">Updating %s…</string>
|
<string name="migration_updating_app_button_text" moz:removedIn="100" tools:ignore="UnusedResources">Updating %s…</string>
|
||||||
<!-- Text on the enabled button. Placeholder replaced with app name-->
|
<!-- Text on the enabled button. Placeholder replaced with app name-->
|
||||||
<string name="migration_update_app_button">Start %s</string>
|
<string name="migration_update_app_button" moz:removedIn="100" tools:ignore="UnusedResources">Start %s</string>
|
||||||
<!-- Accessibility description text for a completed migration item -->
|
<!-- Accessibility description text for a completed migration item -->
|
||||||
<string name="migration_icon_description">Migration completed</string>
|
<string name="migration_icon_description" moz:removedIn="100" tools:ignore="UnusedResources">Migration completed</string>
|
||||||
<!--Text on list of migrated items (e.g. Settings, History, etc.)-->
|
<!--Text on list of migrated items (e.g. Settings, History, etc.)-->
|
||||||
<string name="migration_text_passwords">Passwords</string>
|
<string name="migration_text_passwords" moz:removedIn="100" tools:ignore="UnusedResources">Passwords</string>
|
||||||
|
|
||||||
<!-- Heading for the instructions to allow a permission -->
|
<!-- Heading for the instructions to allow a permission -->
|
||||||
<string name="phone_feature_blocked_intro">To allow it:</string>
|
<string name="phone_feature_blocked_intro">To allow it:</string>
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
sharedUserId: This release type is meant to replace Firefox (Release channel) and therefore needs to inherit
|
|
||||||
its sharedUserId for all eternity. Shipping an app update without sharedUserId can have
|
|
||||||
fatal consequences. For example see:
|
|
||||||
- https://issuetracker.google.com/issues/36924841
|
|
||||||
- https://issuetracker.google.com/issues/36905922
|
|
||||||
-->
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:sharedUserId="${sharedUserId}">
|
|
||||||
<application
|
|
||||||
android:name="org.mozilla.fenix.MigratingFenixApplication"
|
|
||||||
tools:replace="android:name">
|
|
||||||
|
|
||||||
<!-- Overriding the alias of the main manifest to route app launches through our
|
|
||||||
MigrationDecisionActivity which will show the migration screen before launching
|
|
||||||
into the app if needed. -->
|
|
||||||
<activity-alias
|
|
||||||
android:name="${applicationId}.App"
|
|
||||||
android:targetActivity="org.mozilla.fenix.MigrationDecisionActivity"
|
|
||||||
tools:replace="android:targetActivity" />
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name="org.mozilla.fenix.MigrationDecisionActivity"
|
|
||||||
android:exported="false" />
|
|
||||||
|
|
||||||
<service android:name="org.mozilla.fenix.MigrationService" />
|
|
||||||
</application>
|
|
||||||
</manifest>
|
|
@ -1,93 +0,0 @@
|
|||||||
/* 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
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import mozilla.components.support.migration.FennecMigrator
|
|
||||||
import org.mozilla.fenix.session.PerformanceActivityLifecycleCallbacks
|
|
||||||
import org.mozilla.fenix.migration.MigrationTelemetryListener
|
|
||||||
import org.mozilla.fenix.perf.runBlockingIncrement
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An application class which knows how to migrate Fennec data.
|
|
||||||
*/
|
|
||||||
class MigratingFenixApplication : FenixApplication() {
|
|
||||||
init {
|
|
||||||
recordOnInit() // DO NOT MOVE ANYTHING ABOVE HERE: the timing of this measurement is critical.
|
|
||||||
|
|
||||||
PerformanceActivityLifecycleCallbacks.isTransientActivityInMigrationVariant = {
|
|
||||||
if (it is MigrationDecisionActivity) true else false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val fxaExpectChinaServers = Config.channel.isMozillaOnline
|
|
||||||
|
|
||||||
val migrator by lazy {
|
|
||||||
FennecMigrator.Builder(this, this.components.analytics.crashReporter)
|
|
||||||
.migrateOpenTabs(this.components.useCases.tabsUseCases)
|
|
||||||
.migrateHistory(this.components.core.lazyHistoryStorage)
|
|
||||||
.migrateBookmarks(
|
|
||||||
this.components.core.lazyBookmarksStorage,
|
|
||||||
this.components.core.pinnedSiteStorage
|
|
||||||
)
|
|
||||||
.migrateLogins(this.components.core.lazyPasswordsStorage)
|
|
||||||
.migrateFxa(lazy { this.components.backgroundServices.accountManager }, fxaExpectChinaServers)
|
|
||||||
.migrateAddons(
|
|
||||||
this.components.core.engine,
|
|
||||||
this.components.addonCollectionProvider,
|
|
||||||
this.components.addonUpdater
|
|
||||||
)
|
|
||||||
.migrateTelemetryIdentifiers()
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
val migrationPushSubscriber by lazy {
|
|
||||||
MigrationPushRenewer(
|
|
||||||
components.push.feature,
|
|
||||||
components.migrationStore
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val migrationTelemetryListener by lazy {
|
|
||||||
MigrationTelemetryListener(
|
|
||||||
components.analytics.metrics,
|
|
||||||
components.migrationStore
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setupInMainProcessOnly() {
|
|
||||||
// These migrations need to run before regular initialization happens.
|
|
||||||
migrateBlocking()
|
|
||||||
|
|
||||||
// Now that we have migrated from Fennec whether the user wants to enable telemetry we can
|
|
||||||
// initialize Glean
|
|
||||||
initializeGlean()
|
|
||||||
|
|
||||||
// Fenix application initialization can happen now.
|
|
||||||
super.setupInMainProcessOnly()
|
|
||||||
|
|
||||||
// The rest of the migrations can happen now.
|
|
||||||
migrationPushSubscriber.start()
|
|
||||||
migrationTelemetryListener.start()
|
|
||||||
migrator.startMigrationIfNeeded(components.migrationStore, MigrationService::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun migrateBlocking() {
|
|
||||||
val migrator = FennecMigrator.Builder(this, this.components.analytics.crashReporter)
|
|
||||||
.migrateGecko()
|
|
||||||
// Telemetry may have been disabled in Fennec, so we need to migrate Settings first
|
|
||||||
// to correctly initialize telemetry.
|
|
||||||
.migrateSettings()
|
|
||||||
.build()
|
|
||||||
|
|
||||||
runBlockingIncrement {
|
|
||||||
migrator.migrateAsync(components.migrationStore).await()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Context.getMigratorFromApplication(): FennecMigrator {
|
|
||||||
return (applicationContext as MigratingFenixApplication).migrator
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/* 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
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import mozilla.components.support.migration.state.MigrationProgress
|
|
||||||
import org.mozilla.fenix.ext.components
|
|
||||||
import org.mozilla.fenix.migration.MigrationProgressActivity
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The purpose of this activity, when launched, is to decide whether we want to show the migration
|
|
||||||
* screen ([MigrationProgressActivity]) or launch the browser normally ([HomeActivity]).
|
|
||||||
*/
|
|
||||||
class MigrationDecisionActivity : Activity() {
|
|
||||||
private val store by lazy { components.migrationStore }
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
val intent = if (intent != null) intent else Intent()
|
|
||||||
|
|
||||||
val activity = when (store.state.progress) {
|
|
||||||
MigrationProgress.NONE, MigrationProgress.COMPLETED -> HomeActivity::class.java
|
|
||||||
MigrationProgress.MIGRATING -> MigrationProgressActivity::class.java
|
|
||||||
}
|
|
||||||
|
|
||||||
intent.setClass(applicationContext, activity)
|
|
||||||
intent.putExtra(HomeActivity.OPEN_TO_BROWSER, false)
|
|
||||||
|
|
||||||
startActivity(intent)
|
|
||||||
finish()
|
|
||||||
|
|
||||||
// We are disabling animations here when switching activities because this results in a
|
|
||||||
// perceived faster launch. This activity will start immediately with a solid background
|
|
||||||
// and then we switch to the actual activity without an animation. This visually looks like
|
|
||||||
// a faster start than launching this activity invisibly and switching to the actual
|
|
||||||
// activity after that.
|
|
||||||
overridePendingTransition(0, R.anim.placeholder_animation)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/* 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
|
|
||||||
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import mozilla.components.concept.push.PushProcessor
|
|
||||||
import mozilla.components.lib.state.ext.flowScoped
|
|
||||||
import mozilla.components.support.base.log.logger.Logger
|
|
||||||
import mozilla.components.support.migration.state.MigrationProgress
|
|
||||||
import mozilla.components.support.migration.state.MigrationStore
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Force-renews push subscription after migration was complete.
|
|
||||||
*/
|
|
||||||
class MigrationPushRenewer(
|
|
||||||
private val service: PushProcessor?,
|
|
||||||
private val store: MigrationStore
|
|
||||||
) {
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
fun start() {
|
|
||||||
// Observe for migration completed.
|
|
||||||
store.flowScoped { flow ->
|
|
||||||
flow.collect { state ->
|
|
||||||
Logger("MigrationPushRenewer").debug("Migration state: ${state.progress}")
|
|
||||||
if (state.progress == MigrationProgress.COMPLETED) {
|
|
||||||
Logger("MigrationPushRenewer").debug("Renewing registration....")
|
|
||||||
|
|
||||||
// This should force a recreation of firebase device token, re-registration with
|
|
||||||
// the autopush service, and subsequent update of the FxA device record with
|
|
||||||
// new push subscription information.
|
|
||||||
service?.renewRegistration()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
/* 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
|
|
||||||
|
|
||||||
import mozilla.components.support.migration.AbstractMigrationService
|
|
||||||
import mozilla.components.support.migration.state.MigrationStore
|
|
||||||
import org.mozilla.fenix.ext.components
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Background service for running the migration from legacy Firefox for Android (Fennec).
|
|
||||||
*/
|
|
||||||
class MigrationService : AbstractMigrationService() {
|
|
||||||
override val migrator by lazy { getMigratorFromApplication() }
|
|
||||||
override val store: MigrationStore by lazy { components.migrationStore }
|
|
||||||
override val migrationDecisionActivity = MigrationDecisionActivity::class.java
|
|
||||||
}
|
|
11
app/src/release/AndroidManifest.xml
Normal file
11
app/src/release/AndroidManifest.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
sharedUserId: This release type is meant to replace Firefox (Release channel) and therefore needs to inherit
|
||||||
|
its sharedUserId for all eternity. Shipping an app update without sharedUserId can have
|
||||||
|
fatal consequences. For example see:
|
||||||
|
- https://issuetracker.google.com/issues/36924841
|
||||||
|
- https://issuetracker.google.com/issues/36905922
|
||||||
|
-->
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:sharedUserId="${sharedUserId}">
|
||||||
|
</manifest>
|
@ -53,7 +53,6 @@ class IntentReceiverActivityTest {
|
|||||||
every { intentProcessors.privateCustomTabIntentProcessor } returns mockIntentProcessor()
|
every { intentProcessors.privateCustomTabIntentProcessor } returns mockIntentProcessor()
|
||||||
every { intentProcessors.externalAppIntentProcessors } returns emptyList()
|
every { intentProcessors.externalAppIntentProcessors } returns emptyList()
|
||||||
every { intentProcessors.fennecPageShortcutIntentProcessor } returns mockIntentProcessor()
|
every { intentProcessors.fennecPageShortcutIntentProcessor } returns mockIntentProcessor()
|
||||||
every { intentProcessors.migrationIntentProcessor } returns mockIntentProcessor()
|
|
||||||
every { intentProcessors.externalDeepLinkIntentProcessor } returns mockIntentProcessor()
|
every { intentProcessors.externalDeepLinkIntentProcessor } returns mockIntentProcessor()
|
||||||
|
|
||||||
coEvery { intentProcessors.intentProcessor.process(any()) } returns true
|
coEvery { intentProcessors.intentProcessor.process(any()) } returns true
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
/* 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.migration
|
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import mozilla.components.support.migration.Migration
|
|
||||||
import mozilla.components.support.migration.MigrationRun
|
|
||||||
import mozilla.components.support.test.robolectric.testContext
|
|
||||||
import org.junit.Assert.assertEquals
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.mozilla.fenix.databinding.MigrationListItemBinding
|
|
||||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
|
||||||
|
|
||||||
@RunWith(FenixRobolectricTestRunner::class)
|
|
||||||
class MigrationStatusAdapterTest {
|
|
||||||
|
|
||||||
private lateinit var adapter: MigrationStatusAdapter
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun setup() {
|
|
||||||
adapter = MigrationStatusAdapter()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `getItemCount should return the number of items in whitelist`() {
|
|
||||||
assertEquals(0, adapter.itemCount)
|
|
||||||
|
|
||||||
adapter.updateData(
|
|
||||||
mapOf(
|
|
||||||
Migration.Addons to MigrationRun(0, success = true),
|
|
||||||
Migration.Settings to MigrationRun(0, success = true),
|
|
||||||
Migration.Bookmarks to MigrationRun(0, success = false)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
assertEquals(4, adapter.itemCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `creates and binds viewholder`() {
|
|
||||||
adapter.updateData(
|
|
||||||
mapOf(
|
|
||||||
Migration.History to MigrationRun(0, success = true)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
val holder1 = adapter.createViewHolder(FrameLayout(testContext), 0)
|
|
||||||
val holder2 = adapter.createViewHolder(FrameLayout(testContext), 0)
|
|
||||||
val binding1 = MigrationListItemBinding.bind(holder1.itemView)
|
|
||||||
val binding2 = MigrationListItemBinding.bind(holder2.itemView)
|
|
||||||
adapter.bindViewHolder(holder1, 0)
|
|
||||||
adapter.bindViewHolder(holder2, 1)
|
|
||||||
|
|
||||||
assertEquals("Settings", binding1.migrationItemName.text)
|
|
||||||
assertEquals(View.INVISIBLE, binding1.migrationStatusImage.visibility)
|
|
||||||
|
|
||||||
assertEquals("History", binding2.migrationItemName.text)
|
|
||||||
assertEquals(View.VISIBLE, binding2.migrationStatusImage.visibility)
|
|
||||||
assertEquals("Migration completed", binding2.migrationStatusImage.contentDescription)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
/* 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.migration
|
|
||||||
|
|
||||||
import io.mockk.MockKAnnotations
|
|
||||||
import io.mockk.impl.annotations.MockK
|
|
||||||
import io.mockk.verify
|
|
||||||
import io.mockk.verifyOrder
|
|
||||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.test.runBlockingTest
|
|
||||||
import mozilla.components.support.base.log.logger.Logger
|
|
||||||
import mozilla.components.support.migration.state.MigrationAction
|
|
||||||
import mozilla.components.support.migration.state.MigrationStore
|
|
||||||
import mozilla.components.support.test.ext.joinBlocking
|
|
||||||
import mozilla.components.support.test.rule.MainCoroutineRule
|
|
||||||
import org.junit.After
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Rule
|
|
||||||
import org.junit.Test
|
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
|
||||||
import org.mozilla.fenix.components.metrics.MetricController
|
|
||||||
|
|
||||||
class MigrationTelemetryListenerTest {
|
|
||||||
|
|
||||||
private val testDispatcher = TestCoroutineDispatcher()
|
|
||||||
|
|
||||||
@get:Rule
|
|
||||||
val coroutinesTestRule = MainCoroutineRule(testDispatcher)
|
|
||||||
|
|
||||||
@MockK(relaxed = true) private lateinit var metrics: MetricController
|
|
||||||
@MockK(relaxed = true) private lateinit var logger: Logger
|
|
||||||
private lateinit var store: MigrationStore
|
|
||||||
private lateinit var listener: MigrationTelemetryListener
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun setup() {
|
|
||||||
MockKAnnotations.init(this)
|
|
||||||
store = MigrationStore()
|
|
||||||
listener = MigrationTelemetryListener(
|
|
||||||
metrics = metrics,
|
|
||||||
store = store,
|
|
||||||
logger = logger
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
fun cleanUp() {
|
|
||||||
testDispatcher.cleanupTestCoroutines()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `progress state is logged`() = testDispatcher.runBlockingTest {
|
|
||||||
listener.start()
|
|
||||||
store.dispatch(MigrationAction.Started).joinBlocking()
|
|
||||||
store.dispatch(MigrationAction.Completed).joinBlocking()
|
|
||||||
store.dispatch(MigrationAction.Clear).joinBlocking()
|
|
||||||
|
|
||||||
verifyOrder {
|
|
||||||
logger.debug("Migration state: MIGRATING")
|
|
||||||
logger.debug("Migration state: COMPLETED")
|
|
||||||
logger.debug("Migration state: NONE")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `metrics are logged when migration is completed`() = testDispatcher.runBlockingTest {
|
|
||||||
listener.start()
|
|
||||||
store.dispatch(MigrationAction.Completed).joinBlocking()
|
|
||||||
|
|
||||||
verify { metrics.track(Event.FennecToFenixMigrated) }
|
|
||||||
}
|
|
||||||
}
|
|
@ -172,7 +172,6 @@ object Deps {
|
|||||||
const val mozilla_support_utils = "org.mozilla.components:support-utils:${Versions.mozilla_android_components}"
|
const val mozilla_support_utils = "org.mozilla.components:support-utils:${Versions.mozilla_android_components}"
|
||||||
const val mozilla_support_test = "org.mozilla.components:support-test:${Versions.mozilla_android_components}"
|
const val mozilla_support_test = "org.mozilla.components:support-test:${Versions.mozilla_android_components}"
|
||||||
const val mozilla_support_test_libstate = "org.mozilla.components:support-test-libstate:${Versions.mozilla_android_components}"
|
const val mozilla_support_test_libstate = "org.mozilla.components:support-test-libstate:${Versions.mozilla_android_components}"
|
||||||
const val mozilla_support_migration = "org.mozilla.components:support-migration:${Versions.mozilla_android_components}"
|
|
||||||
const val mozilla_support_locale = "org.mozilla.components:support-locale:${Versions.mozilla_android_components}"
|
const val mozilla_support_locale = "org.mozilla.components:support-locale:${Versions.mozilla_android_components}"
|
||||||
|
|
||||||
const val sentry = "io.sentry:sentry-android:${Versions.sentry}"
|
const val sentry = "io.sentry:sentry-android:${Versions.sentry}"
|
||||||
|
Loading…
Reference in New Issue
Block a user