Dan Ballard pushed to branch firefox-android-115.2.1-13.5-1 at The Tor Project / Applications / firefox-android
Commits: cf78d7f5 by clairehurst at 2024-05-13T14:35:02-07:00 fixup! Add Tor integration and UI
- - - - -
18 changed files:
- fenix/app/src/main/AndroidManifest.xml - fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt - fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt - − fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapFragment.kt - fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt - − fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerTAS.kt - − fenix/app/src/main/java/org/mozilla/fenix/tor/controller/TorBootstrapController.kt - − fenix/app/src/main/java/org/mozilla/fenix/tor/interactor/TorBootstrapInteractor.kt - − fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapAdapter.kt - − fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapConnectViewHolder.kt - − fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapLoggerViewHolder.kt - − fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapPagerAdapter.kt - − fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapPagerViewHolder.kt - − fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapView.kt - − fenix/app/src/main/res/drawable/ic_tor_connect_computer_graphic.xml - − fenix/app/src/main/res/layout/tor_bootstrap_connect.xml - − fenix/app/src/main/res/layout/tor_bootstrap_logger.xml - − fenix/app/src/main/res/layout/tor_bootstrap_pager.xml
Changes:
===================================== fenix/app/src/main/AndroidManifest.xml ===================================== @@ -367,12 +367,6 @@ tools:node="remove" /> </provider> <!-- Define Orbotservice's TorService --> - <service - android:name="org.torproject.android.service.TorService" - android:enabled="true" - android:exported="false" - android:stopWithTask="true"> - </service> </application>
</manifest>
===================================== fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt ===================================== @@ -103,7 +103,6 @@ import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_MAX_THRESHO import org.mozilla.fenix.wallpapers.Wallpaper import java.util.UUID import java.util.concurrent.TimeUnit -import org.torproject.android.service.util.Prefs
/** *The main application class for Fenix. Records data to measure initialization performance. @@ -234,8 +233,8 @@ open class FenixApplication : LocaleAwareApplication(), Provider { Log.addSink(FenixLogSink(logsDebug = Config.channel.isDebug, AndroidLogSink())) }
- @OptIn(DelicateCoroutinesApi::class) // GlobalScope usage - open fun setupInMainProcessOnly() { + @VisibleForTesting + protected open fun setupInMainProcessOnly() { ProfilerMarkerFactProcessor.create { components.core.engine.profiler }.register()
run { @@ -273,11 +272,6 @@ open class FenixApplication : LocaleAwareApplication(), Provider { if (!megazordSetup.isCompleted) { runBlockingIncrement { megazordSetup.await() } } - - GlobalScope.launch(Dispatchers.IO) { - // Give TAS the base Context - Prefs.setContext(applicationContext) - } }
setupLeakCanary()
===================================== fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt ===================================== @@ -44,7 +44,6 @@ import org.mozilla.fenix.perf.StartupStateProvider import org.mozilla.fenix.perf.StrictModeManager import org.mozilla.fenix.perf.lazyMonitored import org.mozilla.fenix.tor.TorControllerGV -import org.mozilla.fenix.tor.TorControllerTAS import org.mozilla.fenix.utils.ClipboardHandler import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.wifi.WifiConnectionMonitor
===================================== fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapFragment.kt deleted ===================================== @@ -1,197 +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.tor - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.view.children -import androidx.fragment.app.Fragment -import androidx.lifecycle.lifecycleScope -import org.mozilla.fenix.BuildConfig -import org.mozilla.fenix.databinding.FragmentHomeBinding -import org.mozilla.fenix.ext.requireComponents -import org.mozilla.fenix.tor.interactor.DefaultTorBootstrapInteractor -import org.mozilla.fenix.tor.interactor.TorBootstrapInteractor -import androidx.navigation.fragment.findNavController -import com.google.android.material.appbar.AppBarLayout -import org.mozilla.fenix.HomeActivity -import org.mozilla.fenix.R -import org.mozilla.fenix.ext.components -import org.mozilla.fenix.ext.hideToolbar -import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.tor.controller.DefaultTorBootstrapController -import org.mozilla.fenix.tor.view.TorBootstrapView - - -@Suppress("TooManyFunctions", "LargeClass") -class TorBootstrapFragment : Fragment() { - - internal var _binding: FragmentHomeBinding? = null - private val binding get() = _binding!! - - - private var torBootstrapView: TorBootstrapView? = null - - private var _torBootstrapInteractor: TorBootstrapInteractor? = null - private val torBootstrapInteractor: TorBootstrapInteractor - get() = _torBootstrapInteractor!! - - private lateinit var torBootstrapStatus: TorBootstrapStatus - - - @Suppress("LongMethod") - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { - _binding = FragmentHomeBinding.inflate(inflater, container, false) - val components = requireComponents - - torBootstrapStatus = TorBootstrapStatus( - !BuildConfig.DISABLE_TOR, - components.torController, - ::dispatchModeChanges - ) - - if (!torBootstrapStatus.isBootstrapping()) { - openHome() - } - - // Was _sessionControlInteractor - _torBootstrapInteractor = DefaultTorBootstrapInteractor( - controller = DefaultTorBootstrapController( - handleTorBootstrapConnect = ::handleTorBootstrapConnect, - cancelTorBootstrap = ::cancelTorBootstrap, - initiateTorBootstrap = ::initiateTorBootstrap, - openTorNetworkSettings = ::openTorNetworkSettings - ), - ) - - torBootstrapView = TorBootstrapView( - containerView = binding.sessionControlRecyclerView, - viewLifecycleOwner = viewLifecycleOwner, - interactor = torBootstrapInteractor, - ) - - adjustHomeFragmentView() - updateSessionControlView() - showSessionControlView() - - return binding.root - } - - private fun updateSessionControlView() { - torBootstrapView?.update(requireContext().components.appStore.state) - } - - // This function should be paired with showSessionControlView() - private fun adjustHomeFragmentView() { - binding.sessionControlRecyclerView.apply { - visibility = View.INVISIBLE - } - - binding.sessionControlRecyclerView.apply { - setPadding(0, 0, 0, 0) - (layoutParams as ViewGroup.MarginLayoutParams).setMargins(0, 0, 0, 0) - } - - binding.homeAppBar.apply { - visibility = View.GONE - - // Reset this as SCROLL in case it was previously set as NO_SCROLL after bootstrap - children.forEach { - (it.layoutParams as AppBarLayout.LayoutParams).scrollFlags = - AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL - } - } - binding.onionPatternImage.apply { - visibility = View.GONE - } - binding.toolbarLayout.apply { - visibility = View.GONE - } - } - - // This function should be paired with adjustHomeFragmentView() - private fun showSessionControlView() { - binding.sessionControlRecyclerView.apply { - visibility = View.VISIBLE - } - } - - private fun dispatchModeChanges(isBootstrapping: Boolean) { - //requireComponents.appStore.dispatch(AppAction.ModeChange(mode)) - if (!isBootstrapping) { - openHome() - } else { - adjustHomeFragmentView() - updateSessionControlView() - showSessionControlView() - } - } - - override fun onStop() { - super.onStop() - torBootstrapStatus.unregisterTorListener() - } - - override fun onResume() { - super.onResume() - - torBootstrapStatus.registerTorListener() - - // fenix#40176: Ensure the Home fragment is rendered correctly when we resume. - val isBootstraping = torBootstrapStatus.isBootstrapping() - - if (!isBootstraping) { - openHome() - } - - adjustHomeFragmentView() - updateSessionControlView() - showSessionControlView() - - hideToolbar() - - // Whenever a tab is selected its last access timestamp is automatically updated by A-C. - // However, in the case of resuming the app to the home fragment, we already have an - // existing selected tab, but its last access timestamp is outdated. No action is - // triggered to cause an automatic update on warm start (no tab selection occurs). So we - // update it manually here. - requireComponents.useCases.sessionUseCases.updateLastAccess() - (requireActivity() as HomeActivity).navigateToHome() - } - - private fun handleTorBootstrapConnect() { - requireComponents.torController.onTorConnecting() - } - - private fun cancelTorBootstrap() { - requireComponents.torController.stopTor() - } - - private fun initiateTorBootstrap(withDebugLogging: Boolean = false) { - requireComponents.torController.initiateTorBootstrap(lifecycleScope, withDebugLogging) - } - - private fun openTorNetworkSettings() { - val directions = - TorBootstrapFragmentDirections.actionTorbootstrapFragmentToSettingsFragment( - requireContext().getString(R.string.pref_key_connection) - ) - findNavController().navigate(directions) - } - - private fun openHome() { - val directions = - TorBootstrapFragmentDirections - .actionStartupHome() - findNavController().navigate(directions) - } - -}
===================================== fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt ===================================== @@ -29,25 +29,6 @@ internal enum class TorStatus(val status: String) { ON("ON"), STOPPING("STOPPING"), UNKNOWN("UNKNOWN"); - - companion object { - fun fromString(status: String): TorStatus { - return when (status) { - "ON" -> ON - "STARTING" -> STARTING - "STOPPING" -> STOPPING - "OFF" -> OFF - else -> UNKNOWN - } - } - } - - fun isOff() = this == OFF - fun isOn() = this == ON - fun isStarting() = this == STARTING - fun isStarted() = ((this == STARTING) || (this == ON)) - fun isStopping() = this == STOPPING - fun isUnknown() = this == UNKNOWN }
interface TorController: TorEvents {
===================================== fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerTAS.kt deleted ===================================== @@ -1,342 +0,0 @@ -package org.mozilla.fenix.tor - -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter -import androidx.lifecycle.LifecycleCoroutineScope -import androidx.localbroadcastmanager.content.LocalBroadcastManager -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.launch -import kotlinx.coroutines.withTimeoutOrNull -import org.mozilla.fenix.BuildConfig -import org.torproject.android.service.TorService -import org.torproject.android.service.TorServiceConstants -import org.torproject.android.service.util.Prefs - -@SuppressWarnings("TooManyFunctions") -class TorControllerTAS (private val context: Context): TorController { - private val lbm: LocalBroadcastManager = LocalBroadcastManager.getInstance(context) - private val entries = mutableListOf<Pair<String?, String?>>() - override val logEntries get() = entries - override var quickstart: Boolean = false // Stub, is never used - - private var torListeners = mutableListOf<TorEvents>() - - private var pendingRegisterChangeList = mutableListOf<Pair<TorEvents, Boolean>>() - private var lockTorListenersMutation = false - - private var lastKnownStatus = TorStatus.OFF - private var wasTorBootstrapped = false - private var isTorRestarting = false - - // This may be a lie - private var isTorBootstrapped = false - get() = ((lastKnownStatus == TorStatus.ON) && wasTorBootstrapped) - - val isDebugLoggingEnabled get() = - context - .getSharedPreferences("org.torproject.android_preferences", Context.MODE_PRIVATE) - .getBoolean("pref_enable_logging", false) - - override val isStarting get() = lastKnownStatus.isStarting() - override val isRestarting get() = isTorRestarting - override val isBootstrapped get() = isTorBootstrapped - override val isConnected get() = (lastKnownStatus.isStarted() && !isTorRestarting) - - override var bridgesEnabled: Boolean - get() = Prefs.bridgesEnabled() - set(value) { Prefs.putBridgesEnabled(value) } - - override var bridgeTransport: TorBridgeTransportConfig - get() { - return TorBridgeTransportConfigUtil.getStringToBridgeTransport( - Prefs.getBridgesList() - ) - } - set(value) { - if (value == TorBridgeTransportConfig.USER_PROVIDED) { - // Don't set the pref when the value is USER_PROVIDED because - // "user_provided" is not a valid bridge or transport type. - // This call should be followed by setting userProvidedBridges. - return - } - Prefs.setBridgesList(value.transportName) - } - - override var userProvidedBridges: String? - get() { - val bridges = Prefs.getBridgesList() - val bridgeType = - TorBridgeTransportConfigUtil.getStringToBridgeTransport(bridges) - return when (bridgeType) { - TorBridgeTransportConfig.USER_PROVIDED -> bridges - else -> null - } - } - set(value) { - Prefs.setBridgesList(value) - } - - override fun start() { - // Register receiver - lbm.registerReceiver( - persistentBroadcastReceiver, - IntentFilter(TorServiceConstants.ACTION_STATUS) - ) - lbm.registerReceiver( - persistentBroadcastReceiver, - IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG) - ) - } - - override fun stop() { - lbm.unregisterReceiver(persistentBroadcastReceiver) - } - - private val persistentBroadcastReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - if (intent.action == null || - (intent.action != TorServiceConstants.ACTION_STATUS && - intent.action != TorServiceConstants.LOCAL_ACTION_LOG) - ) { - return - } - val action = intent.action - - val logentry: String? - val status: String? - if (action == TorServiceConstants.LOCAL_ACTION_LOG) { - logentry = intent.getExtras() - ?.getCharSequence(TorServiceConstants.LOCAL_EXTRA_LOG) as? String? - } else { - logentry = null - } - - status = intent.getExtras() - ?.getCharSequence(TorServiceConstants.EXTRA_STATUS) as? String? - - if (logentry == null && status == null) { - return - } - - onTorStatusUpdate(logentry, status) - - if (status == null) { - return - } - - val newStatus = TorStatus.fromString(status) - - if (newStatus.isUnknown() && wasTorBootstrapped) { - stopTor() - } - - entries.add(Pair(logentry, status)) - - if (logentry != null && logentry.contains(TorServiceConstants.TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)) { - wasTorBootstrapped = true - onTorConnected() - } - - if (lastKnownStatus.isStopping() && newStatus.isOff()) { - if (isTorRestarting) { - initiateTorBootstrap() - } else { - onTorStopped() - } - } - - if (lastKnownStatus.isOff() && newStatus.isStarting()) { - isTorRestarting = false - } - - lastKnownStatus = newStatus - } - } - - override fun onTorConnecting() { - lockTorListenersMutation = true - torListeners.forEach { it.onTorConnecting() } - lockTorListenersMutation = false - - handlePendingRegistrationChanges() - } - - override fun onTorConnected() { - lockTorListenersMutation = true - torListeners.forEach { it.onTorConnected() } - lockTorListenersMutation = false - - handlePendingRegistrationChanges() - } - - override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) { - lockTorListenersMutation = true - torListeners.forEach { it.onTorStatusUpdate(entry, status) } - lockTorListenersMutation = false - - handlePendingRegistrationChanges() - } - - override fun onTorStopped() { - lockTorListenersMutation = true - torListeners.forEach { it.onTorStopped() } - lockTorListenersMutation = false - - handlePendingRegistrationChanges() - } - - override fun registerTorListener(l: TorEvents) { - if (torListeners.contains(l)) { - return - } - - if (lockTorListenersMutation) { - pendingRegisterChangeList.add(Pair(l, true)) - } else { - torListeners.add(l) - } - } - - override fun unregisterTorListener(l: TorEvents) { - if (!torListeners.contains(l)) { - return - } - - if (lockTorListenersMutation) { - pendingRegisterChangeList.add(Pair(l, false)) - } else { - torListeners.remove(l) - } - } - - override fun registerTorLogListener(l: TorLogs) {} - override fun unregisterTorLogListener(l: TorLogs) {} - - private fun handlePendingRegistrationChanges() { - pendingRegisterChangeList.forEach { - if (it.second) { - registerTorListener(it.first) - } else { - unregisterTorListener(it.first) - } - } - - pendingRegisterChangeList.clear() - } - - /** - * Receive the current Tor status. - * - * Send a request for the current status and receive the response. - * Returns true if Tor is running, false otherwise. - * - */ - private suspend fun checkTorIsStarted(): Boolean { - val channel = Channel<Boolean>() - - // Register receiver - val lbm: LocalBroadcastManager = LocalBroadcastManager.getInstance(context) - val localBroadcastReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - val action = intent.action ?: return - // We only want ACTION_STATUS messages - if (action != TorServiceConstants.ACTION_STATUS) { - return - } - // The current status has the EXTRA_STATUS key - val currentStatus = - intent.getStringExtra(TorServiceConstants.EXTRA_STATUS) - channel.trySend(currentStatus === TorServiceConstants.STATUS_ON) - } - } - lbm.registerReceiver( - localBroadcastReceiver, - IntentFilter(TorServiceConstants.ACTION_STATUS) - ) - - // Request service status - sendServiceAction(TorServiceConstants.ACTION_STATUS) - - // Wait for response and unregister receiver - var torIsStarted = false - withTimeoutOrNull(torServiceResponseTimeout) { - torIsStarted = channel.receive() - } - lbm.unregisterReceiver(localBroadcastReceiver) - return torIsStarted - } - - override fun initiateTorBootstrap(lifecycleScope: LifecycleCoroutineScope?, withDebugLogging: Boolean) { - if (BuildConfig.DISABLE_TOR) { - return - } - - context.getSharedPreferences("org.torproject.android_preferences", Context.MODE_PRIVATE) - .edit().putBoolean("pref_enable_logging", withDebugLogging).apply() - - if (lifecycleScope == null) { - sendServiceAction(TorServiceConstants.ACTION_START) - } else { - lifecycleScope.launch { - val torNeedsStart = !checkTorIsStarted() - if (torNeedsStart) { - sendServiceAction(TorServiceConstants.ACTION_START) - } - } - } - } - - override fun stopTor() { - if (BuildConfig.DISABLE_TOR) { - return - } - - val torService = Intent(context, TorService::class.java) - context.stopService(torService) - } - - override fun setTorStopped() { - lastKnownStatus = TorStatus.OFF - onTorStopped() - } - - override fun restartTor() { - // tor-android-service doesn't dynamically update the torrc file, - // and it doesn't use SETCONF, so we completely restart the service. - // However, don't restart if we aren't started and we weren't - // previously started. - if (!lastKnownStatus.isStarted() && !wasTorBootstrapped) { - return - } - - if (!lastKnownStatus.isStarted() && wasTorBootstrapped) { - // If we aren't started, but we were previously bootstrapped, - // then we handle a "restart" request as a "start" restart - initiateTorBootstrap() - } else { - // |isTorRestarting| tracks the state of restart. When we receive an |OFF| state - // from TorService in persistentBroadcastReceiver::onReceive we restart the Tor - // service. - isTorRestarting = true - stopTor() - } - } - - private fun sendServiceAction(action: String) { - val torServiceStatus = Intent(context, TorService::class.java) - torServiceStatus.action = action - context.startService(torServiceStatus) - } - - companion object { - const val torServiceResponseTimeout = 5000L - } - - // Compat with TorControlGV Stubs - - override fun getLastErrorState() : TorError? { - return null; - } -}
===================================== fenix/app/src/main/java/org/mozilla/fenix/tor/controller/TorBootstrapController.kt deleted ===================================== @@ -1,63 +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.tor.controller - -import org.mozilla.fenix.tor.interactor.TorBootstrapInteractor - -interface TorBootstrapController { - /** - * @see [TorBootstrapInteractor.onTorBootstrapConnectClicked] - */ - fun handleTorBootstrapConnectClicked() - - /** - * @see [TorBootstrapInteractor.onTorStopBootstrapping] - */ - fun handleTorStopBootstrapping() - - /** - * @see [TorBootstrapInteractor.onTorStartBootstrapping] - */ - fun handleTorStartBootstrapping() - - /** - * @see [TorBootstrapInteractor.onTorStartDebugBootstrapping] - */ - fun handleTorStartDebugBootstrapping() - - /** - * @see [TorBootstrapInteractor.onTorBootstrapNetworkSettingsClicked] - */ - fun handleTorNetworkSettingsClicked() - - -} - -class DefaultTorBootstrapController( - private val handleTorBootstrapConnect: () -> Unit, - private val initiateTorBootstrap: (Boolean) -> Unit, - private val cancelTorBootstrap: () -> Unit, - private val openTorNetworkSettings: () -> Unit -) : TorBootstrapController { - override fun handleTorBootstrapConnectClicked() { - handleTorBootstrapConnect() - } - - override fun handleTorStopBootstrapping() { - cancelTorBootstrap() - } - - override fun handleTorStartBootstrapping() { - initiateTorBootstrap(false) - } - - override fun handleTorStartDebugBootstrapping() { - initiateTorBootstrap(true) - } - - override fun handleTorNetworkSettingsClicked() { - openTorNetworkSettings() - } -}
===================================== fenix/app/src/main/java/org/mozilla/fenix/tor/interactor/TorBootstrapInteractor.kt deleted ===================================== @@ -1,60 +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.tor.interactor - -import org.mozilla.fenix.tor.controller.TorBootstrapController - -interface TorBootstrapInteractor { - /** - * Initiates Tor bootstrapping. Called when a user clicks on the "Connect" button. - */ - fun onTorBootstrapConnectClicked() - - /** - * Initiates Tor bootstrapping. Called when a user clicks on the "Connect" button. - */ - fun onTorStartBootstrapping() - - /** - * Stop Tor bootstrapping. Called when a user clicks on the "settings" cog/button. - */ - fun onTorStopBootstrapping() - - /** - * Initiates Tor bootstrapping with debug logging. Called when bootstrapping fails with - * the control.txt file not existing. - */ - fun onTorStartDebugBootstrapping() - - /** - * Open Tor Network Settings preference screen - */ - fun onTorBootstrapNetworkSettingsClicked() -} - -class DefaultTorBootstrapInteractor( - private val controller: TorBootstrapController, -) : TorBootstrapInteractor { - - override fun onTorBootstrapConnectClicked() { - controller.handleTorBootstrapConnectClicked() - } - - override fun onTorStopBootstrapping() { - controller.handleTorStopBootstrapping() - } - - override fun onTorStartBootstrapping() { - controller.handleTorStartBootstrapping() - } - - override fun onTorStartDebugBootstrapping() { - controller.handleTorStartDebugBootstrapping() - } - - override fun onTorBootstrapNetworkSettingsClicked() { - controller.handleTorNetworkSettingsClicked() - } -}
===================================== fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapAdapter.kt deleted ===================================== @@ -1,83 +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.tor.view - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.annotation.LayoutRes -import androidx.lifecycle.LifecycleOwner -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ListAdapter -import androidx.recyclerview.widget.RecyclerView -import org.mozilla.fenix.components.Components -import org.mozilla.fenix.home.topsites.TopSitePagerViewHolder -import org.mozilla.fenix.tor.interactor.TorBootstrapInteractor - -sealed class AdapterItem(@LayoutRes val viewType: Int) { - object TorBootstrap : AdapterItem(TorBootstrapPagerViewHolder.LAYOUT_ID) - - - open fun sameAs(other: AdapterItem) = this::class == other::class - open fun getChangePayload(newItem: AdapterItem): Any? = null - open fun contentsSameAs(other: AdapterItem) = this::class == other::class - -} - -class AdapterItemDiffCallback : DiffUtil.ItemCallback<AdapterItem>() { - override fun areItemsTheSame(oldItem: AdapterItem, newItem: AdapterItem) = - oldItem.sameAs(newItem) - - @Suppress("DiffUtilEquals") - override fun areContentsTheSame(oldItem: AdapterItem, newItem: AdapterItem) = - oldItem.contentsSameAs(newItem) - - override fun getChangePayload(oldItem: AdapterItem, newItem: AdapterItem): Any? { - return oldItem.getChangePayload(newItem) ?: return super.getChangePayload(oldItem, newItem) - } -} - - - -class TorBootstrapAdapter( - private val interactor: TorBootstrapInteractor, - private val viewLifecycleOwner: LifecycleOwner, - private val components: Components, -) : ListAdapter<AdapterItem, RecyclerView.ViewHolder>(AdapterItemDiffCallback()) { - - // This method triggers the ComplexMethod lint error when in fact it's quite simple. - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false) - return when (viewType) { - TorBootstrapPagerViewHolder.LAYOUT_ID -> TorBootstrapPagerViewHolder( - view, - components, - interactor - ) - else -> throw IllegalStateException() - } - } - - override fun getItemViewType(position: Int) = getItem(position).viewType - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: MutableList<Any>) { - if (payloads.isEmpty()) { - onBindViewHolder(holder, position) - } else { - when (holder) { - is TopSitePagerViewHolder -> { - if (payloads[0] is org.mozilla.fenix.home.sessioncontrol.AdapterItem.TopSitePagerPayload) { - val payload = payloads[0] as org.mozilla.fenix.home.sessioncontrol.AdapterItem.TopSitePagerPayload - holder.update(payload) - } - } - } - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - // no-op. This ViewHolder receives the HomeStore as argument and will observe that - // without the need for us to manually update from here the data to be displayed. - } -}
===================================== fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapConnectViewHolder.kt deleted ===================================== @@ -1,89 +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.tor.view - -import android.view.View -import androidx.recyclerview.widget.RecyclerView -import org.mozilla.fenix.R -import org.mozilla.fenix.components.Components -import org.mozilla.fenix.databinding.TorBootstrapConnectBinding -import org.mozilla.fenix.tor.TorEvents -import org.mozilla.fenix.tor.interactor.TorBootstrapInteractor - -class TorBootstrapConnectViewHolder( - private val view: View, - private val components: Components, - private val interactor: TorBootstrapInteractor -) : RecyclerView.ViewHolder(view), TorEvents { - - var binding: TorBootstrapConnectBinding - - init { - binding = TorBootstrapConnectBinding.bind(view) - - with(binding.torBootstrapNetworkSettingsButton) { - setOnClickListener { - interactor.onTorStopBootstrapping() - interactor.onTorBootstrapNetworkSettingsClicked() - - with(binding.torBootstrapProgress) { - visibility = View.INVISIBLE - } - - with(binding.torBootstrapConnectButton) { - visibility = View.VISIBLE - } - } - } - - with(binding.torBootstrapConnectButton) { - setOnClickListener { - interactor.onTorBootstrapConnectClicked() - interactor.onTorStartBootstrapping() - - visibility = View.INVISIBLE - - with(binding.torBootstrapProgress) { - visibility = View.VISIBLE - } - } - } - - components.torController.registerTorListener(this) - } - - @SuppressWarnings("EmptyFunctionBlock") - override fun onTorConnecting() { - } - - override fun onTorConnected() { - components.torController.unregisterTorListener(this) - } - - @SuppressWarnings("EmptyFunctionBlock") - override fun onTorStopped() { - } - - override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) { - if (entry == null) return - - binding.torBootstrapStatusMessage.text = entry - if (entry.startsWith(BOOTSTRAPPED_PREFIX)) { - val percentIdx = entry.indexOf("%") - val percent = entry.substring( - BOOTSTRAPPED_PREFIX.length, - percentIdx - ) - with(binding.torBootstrapProgress) { - this.progress = percent.toInt() - } - } - } - - companion object { - const val LAYOUT_ID = R.layout.tor_bootstrap_connect - const val BOOTSTRAPPED_PREFIX = "NOTICE: Bootstrapped " - } -}
===================================== fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapLoggerViewHolder.kt deleted ===================================== @@ -1,76 +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.tor.view - -import android.text.method.ScrollingMovementMethod -import android.view.View -import androidx.recyclerview.widget.RecyclerView -import org.mozilla.fenix.R -import org.mozilla.fenix.components.Components -import org.mozilla.fenix.databinding.TorBootstrapLoggerBinding -import org.mozilla.fenix.tor.TorEvents - -class TorBootstrapLoggerViewHolder( - private val view: View, - private val components: Components - ) : RecyclerView.ViewHolder(view), TorEvents { - - private var entries = mutableListOf<String>() - private var binding: TorBootstrapLoggerBinding - - init { - binding = TorBootstrapLoggerBinding.bind(view) - components.torController.registerTorListener(this) - - val currentEntries = components.torController.logEntries - .filter { it.first != null } - .filter { !(it.first!!.startsWith("Circuit") && it.second == "ON") } - // Keep synchronized with format in onTorStatusUpdate - .flatMap { listOf("(${it.second}) '${it.first}'") } - val entriesLen = currentEntries.size - val subListOffset = if (entriesLen > MAX_NEW_ENTRIES) MAX_NEW_ENTRIES else entriesLen - entries = currentEntries.subList((entriesLen - subListOffset), entriesLen) as MutableList<String> - val initLog = "---------------" + view.resources.getString(R.string.tor_initializing_log) + "---------------" - entries.add(0, initLog) - - with(binding.torBootstrapLogEntries) { - movementMethod = ScrollingMovementMethod() - text = formatLogEntries(entries) - } - } - - private fun formatLogEntries(entries: List<String>) = entries.joinToString("\n") - - @SuppressWarnings("EmptyFunctionBlock") - override fun onTorConnecting() { - } - - override fun onTorConnected() { - components.torController.unregisterTorListener(this) - } - - @SuppressWarnings("EmptyFunctionBlock") - override fun onTorStopped() { - } - - override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) { - if (status == null || entry == null) return - if (status == "ON" && entry.startsWith("Circuit")) return - - if (entries.size > MAX_LINES) { - entries = entries.drop(1) as MutableList<String> - } - entries.add("($status) '$entry'") - - binding.torBootstrapLogEntries.text = formatLogEntries(entries) - } - - companion object { - const val LAYOUT_ID = R.layout.tor_bootstrap_logger - const val MAX_NEW_ENTRIES = 24 - const val MAX_LINES = 25 - } - -}
===================================== fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapPagerAdapter.kt deleted ===================================== @@ -1,43 +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.tor.view - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import org.mozilla.fenix.components.Components -import org.mozilla.fenix.tor.interactor.TorBootstrapInteractor - -class TorBootstrapPagerAdapter( - private val components: Components, - private val interactor: TorBootstrapInteractor -) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - if (viewType == BOOTSTRAP_UI_PAGE_TYPE) { - val viewDVH = LayoutInflater.from(parent.context) - .inflate(TorBootstrapConnectViewHolder.LAYOUT_ID, parent, false) - return TorBootstrapConnectViewHolder(viewDVH, components, interactor) - } else { - val viewLVH = LayoutInflater.from(parent.context) - .inflate(TorBootstrapLoggerViewHolder.LAYOUT_ID, parent, false) - return TorBootstrapLoggerViewHolder(viewLVH, components) - } - } - - @SuppressWarnings("EmptyFunctionBlock") - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - } - - override fun getItemViewType(position: Int): Int = position - - override fun getItemCount(): Int = BOOTSTRAP_PAGE_COUNT - - companion object { - const val BOOTSTRAP_UI_PAGE_TYPE = 0 - const val BOOTSTRAP_LOG_PAGE_TYPE = 1 - const val BOOTSTRAP_PAGE_COUNT = 2 - } -}
===================================== fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapPagerViewHolder.kt deleted ===================================== @@ -1,32 +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.tor.view - -import android.view.View -import androidx.recyclerview.widget.RecyclerView -import org.mozilla.fenix.R -import org.mozilla.fenix.components.Components -import org.mozilla.fenix.databinding.TorBootstrapPagerBinding -import org.mozilla.fenix.tor.interactor.TorBootstrapInteractor - -class TorBootstrapPagerViewHolder( - view: View, - components: Components, - interactor: TorBootstrapInteractor - ) : RecyclerView.ViewHolder(view) { - - private val bootstrapPagerAdapter = TorBootstrapPagerAdapter(components, interactor) - - init { - val binding = TorBootstrapPagerBinding.bind(view) - binding.bootstrapPager.apply { - adapter = bootstrapPagerAdapter - } - } - - companion object { - const val LAYOUT_ID = R.layout.tor_bootstrap_pager - } -}
===================================== fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapView.kt deleted ===================================== @@ -1,49 +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.tor.view - -import androidx.lifecycle.LifecycleOwner -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import org.mozilla.fenix.components.appstate.AppState -import org.mozilla.fenix.ext.components -import org.mozilla.fenix.tor.interactor.TorBootstrapInteractor - - -class TorBootstrapView( - containerView: RecyclerView, - viewLifecycleOwner: LifecycleOwner, - interactor: TorBootstrapInteractor, -) { - - val view: RecyclerView = containerView //as RecyclerView - - private fun bootstrapAdapterItems() = listOf(AdapterItem.TorBootstrap) - - private val torBootstrapAdapter = TorBootstrapAdapter( - interactor, - viewLifecycleOwner, - containerView.context.components, - ) - - //private val torBootstrapAdapter = - // TorBootstrapAdapter(interactor, containerView.context.components) - //private val torBootstrapAdapter = TorBootstrapPagerAdapter(containerView.context.components, interactor) - - init { - containerView.apply { - adapter = torBootstrapAdapter - layoutManager = LinearLayoutManager(containerView.context) - } - } - - private fun AppState.toAdapterList(): List<AdapterItem> { - return bootstrapAdapterItems() - } - - fun update(state: AppState) { - torBootstrapAdapter.submitList(state.toAdapterList()) - } -}
===================================== fenix/app/src/main/res/drawable/ic_tor_connect_computer_graphic.xml deleted ===================================== @@ -1,506 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="302dp" - android:height="263dp" - android:viewportWidth="302" - android:viewportHeight="263"> - <path - android:pathData="M279.49,222.64l-94.22,-0l-0,-79.61l94.22,-0z" - android:strokeWidth="1" - android:fillType="nonZero" - android:strokeColor="#00000000"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="203.70642" - android:startX="231.9" - android:endY="160.04314" - android:endX="232.90999" - android:type="linear"> - <item android:offset="0.08" android:color="#FF7E4696"/> - <item android:offset="0.39" android:color="#9B7E4696"/> - <item android:offset="0.85" android:color="#007E4696"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M112.74,217.05l-102.32,-0l-0,-102.32l102.32,-0z" - android:strokeWidth="1" - android:fillType="nonZero" - android:strokeColor="#00000000"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="203.36" - android:startX="60.96" - android:endY="124.990005" - android:endX="62.249996" - android:type="linear"> - <item android:offset="0.08" android:color="#FF00D9B5"/> - <item android:offset="0.3" android:color="#BA00D9B5"/> - <item android:offset="0.8" android:color="#1100D9B5"/> - <item android:offset="0.85" android:color="#0000D9B5"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M58,1L183.49,1C186.526,1.016 188.984,3.474 189,6.51L189,100.25L52.47,100.25L52.47,6.51C52.486,3.466 54.956,1.005 58,1Z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#65318E" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M60.55,8.87h120.41v108.53h-120.41z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M60.55,8.87h120.41v108.53h-120.41z" - android:strokeWidth="1" - android:fillType="nonZero" - android:strokeColor="#00000000"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="-56.010002" - android:startX="120.75" - android:endY="120.520004" - android:endX="120.75" - android:type="linear"> - <item android:offset="0.08" android:color="#FF00D9B5"/> - <item android:offset="0.12" android:color="#F700D9B5"/> - <item android:offset="0.19" android:color="#E200D9B5"/> - <item android:offset="0.26" android:color="#BF00D9B5"/> - <item android:offset="0.35" android:color="#8E00D9B5"/> - <item android:offset="0.44" android:color="#5100D9B5"/> - <item android:offset="0.54" android:color="#0700D9B5"/> - <item android:offset="0.54" android:color="#0000D9B5"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M77.5,120.83h134.33v10.38h-134.33z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#65318E" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M52.47,100.25l0,10.29l25.03,20.67l0,-10.38z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#65318E" - android:strokeColor="#F0D4FD" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M60.33,33.17h43.89v37.87h-43.89z" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#65318E" - android:fillType="nonZero"/> - <path - android:pathData="M178.05,170.61L61.43,170.61L61.43,87C61.43,85.895 62.325,85 63.43,85L176,85C177.105,85 178,85.895 178,87L178.05,170.61Z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M66.88,89.57h105.71v76.37h-105.71z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M177.06,170.61l-115.63,0l21.37,17.75l115.64,0z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#65318E" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M82.8,188.36h115.11v8.96h-115.11z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M61.43,170.61l0,7.04l21.37,19.67l0,-8.96z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M190.59,183L74,183L74,99.29C74.027,98.177 74.937,97.29 76.05,97.29L188.54,97.29C189.653,97.29 190.563,98.177 190.59,99.29L190.59,183Z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M79.42,101.91h105.71v76.37h-105.71z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M189.73,182.95l-115.77,0l21.37,17.75l115.77,0z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#65318E" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M95.33,200.7h115.38v8.96h-115.38z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M73.96,182.95l0,6.78l21.37,19.93l0,-8.96z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M203.12,195.29L86.5,195.29L86.5,111.63C86.5,110.525 87.395,109.63 88.5,109.63L201.08,109.63C202.185,109.63 203.08,110.525 203.08,111.63L203.12,195.29Z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M91.95,114.25h105.71v76.37h-105.71z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M202.4,195.29l-115.9,0l21.37,17.75l115.9,0z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#65318E" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M107.87,213.04h115.64v8.96h-115.64z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M86.5,195.29l0,6.51l21.37,20.2l0,-8.96z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M215.66,207.63L99,207.63L99,124C99,122.895 99.895,122 101,122L213.61,122C214.715,122 215.61,122.895 215.61,124L215.66,207.63Z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M104.49,126.59h105.71v76.37h-105.71z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M215.06,207.63l-116.03,0l21.37,17.75l116.03,0z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#65318E" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M120.4,225.38h115.9v8.96h-115.9z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M99.03,207.63l0,6.25l21.37,20.46l0,-8.96z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M228.19,220L111.57,220L111.57,136.31C111.57,135.205 112.465,134.31 113.57,134.31L226.15,134.31C227.255,134.31 228.15,135.205 228.15,136.31L228.19,220Z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M117.02,138.93h105.71v76.37h-105.71z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M227.73,219.97l-116.16,0l21.37,17.75l116.16,0z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#65318E" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M132.94,237.72h116.16v8.96h-116.16z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M111.57,219.97l0,5.99l21.37,19.72l0,-7.96z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M245.52,234.67L128.9,234.67L128.9,151C128.9,149.895 129.795,149 130.9,149L243.48,149C244.585,149 245.48,149.895 245.48,151L245.52,234.67Z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M134.36,153.64h105.71v76.37h-105.71z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M245.06,234.67l-116.16,0l21.37,17.76l116.16,0z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#65318E" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M150.27,252.43h116.16v8.96h-116.16z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M60.33,33.89h41.01v38.59h-41.01z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#65318E" - android:strokeColor="#65318E" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M67.24,33.89h34.1v30.04h-34.1z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#65318E" - android:strokeColor="#65318E" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M150.62,58.81L150.62,151L279.49,151L279.49,58.81C279.49,55.01 276.41,51.93 272.61,51.93L157.5,51.93C153.7,51.93 150.62,55.01 150.62,58.81ZM273.46,142.2L156.65,142.2L156.65,61.41L273.46,61.41L273.46,142.2Z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M277.38,150.95l-126.76,0l23.62,19.62l126.76,0z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M174.24,170.57h126.76v9.9h-126.76z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M150.62,150.95l0,9.81l23.62,19.71l0,-9.9z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#490260" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M157.37,61.41h116.09v80.79h-116.09z" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#65318E" - android:fillType="nonZero"/> - <path - android:pathData="M157.37,61.41h116.09v80.79h-116.09z" - android:strokeWidth="1" - android:fillType="nonZero" - android:strokeColor="#00000000"> - <aapt:attr name="android:fillColor"> - <gradient - android:startY="18.45" - android:startX="215.42" - android:endY="112.96" - android:endX="215.42" - android:type="linear"> - <item android:offset="0.08" android:color="#FFF0D4FD"/> - <item android:offset="0.27" android:color="#C4F0D4FD"/> - <item android:offset="0.7" android:color="#33F0D4FD"/> - <item android:offset="0.85" android:color="#00F0D4FD"/> - </gradient> - </aapt:attr> - </path> - <path - android:pathData="M157.37,61.41h1.72v80.79h-1.72z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#490260" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M5.78,27.13L119,27.13C121.64,27.13 123.78,29.27 123.78,31.91L123.78,119.64L1,119.64L1,31.9C1.006,29.264 3.144,27.13 5.78,27.13Z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M9.05,34.34h106.66v76.63h-106.66z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M121.75,119.63l-120.75,0l22.5,18.69l120.74,0z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M23.5,138.32h120.75v9.43h-120.75z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#00D9B5" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M1,119.63l0,9.34l22.5,18.78l0,-9.43z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#490260" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M9.82,35.75h104.98v74.01h-104.98z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M9.82,35.75h104.98v74.01h-104.98z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M58.1,35.75L115.36,35.75L115.36,102.15L65.3,102.15C61.341,102.156 58.122,98.959 58.1,95L58.1,35.75Z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M69.28,35.43h46.09v53.39h-46.09z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#F0D4FD" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M9.05,110.21L9.05,34.34L12.25,34.34L12.25,107C12.253,107.85 11.917,108.667 11.316,109.269C10.716,109.871 9.9,110.21 9.05,110.21Z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#490260" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> - <path - android:pathData="M132.94,246.68l17.33,14.71l0,-8.96l-17.33,-14.71z" - android:strokeLineJoin="round" - android:strokeWidth="1.76" - android:fillColor="#FFFFFF" - android:strokeColor="#490260" - android:fillType="nonZero" - android:strokeLineCap="round"/> -</vector>
===================================== fenix/app/src/main/res/layout/tor_bootstrap_connect.xml deleted ===================================== @@ -1,100 +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/. --> -<RelativeLayout 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:layout_gravity="bottom" - android:layout_marginLeft="16dp" - android:layout_marginRight="16dp" > - - <ImageView - android:id="@+id/tor_bootstrap_network_settings_button" - app:srcCompat="@drawable/mozac_ic_settings" - android:scaleType="fitCenter" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_marginTop="20dp" - android:layout_alignParentTop="true" - android:layout_alignParentEnd="true" - tools:ignore="ContentDescription" /> - - <ImageView - android:id="@+id/tor_bootstrap_image" - app:srcCompat="@drawable/ic_tor_connect_computer_graphic" - android:scaleType="fitCenter" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_marginTop="80dp" - android:layout_marginBottom="10dp" - android:layout_centerHorizontal="true" - android:layout_below="@id/tor_bootstrap_network_settings_button" - android:layout_above="@id/tor_bootstrap_connect_button" - android:gravity="center" - tools:ignore="ContentDescription" /> - - <androidx.appcompat.widget.SwitchCompat - android:id="@+id/quick_start_toggle" - android:visibility="gone" - android:checked="false" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_above="@id/tor_bootstrap_connect_button" /> - - <Button - android:id="@+id/tor_bootstrap_connect_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:width="160dp" - android:height="36dp" - android:layout_marginBottom="10dp" - android:layout_centerHorizontal="true" - android:layout_above="@id/tor_bootstrap_status_message" - android:gravity="center|center_vertical" - android:text="@string/tor_bootstrap_connect" - android:fontFamily="Roboto-Medium" - android:textColor="#FF000000" - android:textSize="18sp" - android:lineSpacingMultiplier="0.89" - android:background="@drawable/rounded_corners" /> - - <TextView - android:id="@+id/tor_bootstrap_status_message" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="32dp" - android:layout_centerHorizontal="true" - android:paddingStart="8dp" - android:paddingEnd="8dp" - android:gravity="center" - android:lines="3" - android:layout_above="@id/tor_bootstrap_swipe_log" /> - - <TextView - android:id="@+id/tor_bootstrap_swipe_log" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:width="360dp" - android:height="24dp" - android:layout_marginBottom="15dp" - android:layout_centerHorizontal="true" - android:layout_alignParentBottom="true" - android:gravity="center" - android:textSize="14sp" - android:textColor="#FFFFFFFF" - android:fontFamily="Roboto-Regular" - android:lineSpacingMultiplier="1.71" - android:text="@string/tor_bootstrap_swipe_for_logs" - android:layout_above="@id/tor_bootstrap_progress" /> - - <ProgressBar - android:id="@+id/tor_bootstrap_progress" - style="?android:attr/progressBarStyleHorizontal" - android:layout_width="match_parent" - android:layout_height="3dp" - android:visibility="invisible" - android:layout_alignParentBottom="true" /> -</RelativeLayout>
===================================== fenix/app/src/main/res/layout/tor_bootstrap_logger.xml deleted ===================================== @@ -1,22 +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/. --> -<FrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="match_parent"> - <TextView - android:id="@+id/tor_bootstrap_log_entries" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:gravity="bottom" - android:textColor="@android:color/white" - android:fontFamily="RobotoMono-Regular" - android:textSize="12sp" - android:textIsSelectable="true" - android:layout_marginLeft="20dp" - android:layout_marginRight="20dp" - android:layout_marginBottom="20dp" /> -</FrameLayout>
===================================== fenix/app/src/main/res/layout/tor_bootstrap_pager.xml deleted ===================================== @@ -1,18 +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/. --> - -<com.google.android.material.appbar.AppBarLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical" - android:background="?torBootstrapBackground"> - - <androidx.viewpager2.widget.ViewPager2 - android:id="@+id/bootstrap_pager" - android:layout_width="match_parent" - android:layout_height="match_parent" /> -</com.google.android.material.appbar.AppBarLayout>
View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/commit/cf78...