tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 8a883112b1d656c1335e2f5599f77b59bd40cb60
parent c75b32977802a4899ce4fd3bef58d677c39a4656
Author: Mugurell <Mugurell@users.noreply.github.com>
Date:   Thu,  4 Dec 2025 11:37:32 +0000

Bug 2000617 - part 1 - Introduce the Unknown security state for a website connection r=android-reviewers,nalexander

Previously we only had secure and unsecure statuses but until the webpage details
are loaded there is a short time in which we don't know if the connection is
actually secured or not.

Differential Revision: https://phabricator.services.mozilla.com/D274290

Diffstat:
Mmobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/action/BrowserAction.kt | 6+++---
Mmobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/EngineObserver.kt | 4++--
Mmobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/ContentState.kt | 5+++--
Amobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/SecurityInfo.kt | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dmobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/SecurityInfoState.kt | 23-----------------------
Mmobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/ContentActionTest.kt | 11++++++-----
Mmobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/EngineObserverTest.kt | 6+++---
Mmobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/reducer/ContentStateReducerTest.kt | 8++++++++
Mmobile/android/android-components/components/feature/pwa/src/main/java/mozilla/components/feature/pwa/ext/SessionState.kt | 2+-
Mmobile/android/android-components/components/feature/pwa/src/test/java/mozilla/components/feature/pwa/WebAppShortcutManagerTest.kt | 4++--
Mmobile/android/android-components/components/feature/pwa/src/test/java/mozilla/components/feature/pwa/WebAppUseCasesTest.kt | 4++--
Mmobile/android/android-components/components/feature/pwa/src/test/java/mozilla/components/feature/pwa/ext/SessionStateKtTest.kt | 4++--
Mmobile/android/android-components/components/feature/toolbar/src/main/java/mozilla/components/feature/toolbar/ToolbarPresenter.kt | 2+-
Mmobile/android/android-components/components/feature/toolbar/src/test/java/mozilla/components/feature/toolbar/ToolbarPresenterTest.kt | 18++++++++----------
Mmobile/android/android-components/docs/changelog.md | 2++
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt | 4++--
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/TabPreview.kt | 2+-
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddleware.kt | 6+++---
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/CustomTabBrowserToolbarMiddleware.kt | 6+++---
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt | 4++--
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/ConnectionDetailsController.kt | 2+-
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerDetailsController.kt | 2+-
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelInteractor.kt | 2+-
Mmobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddlewareTest.kt | 12++++++------
Mmobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/toolbar/CustomTabBrowserToolbarMiddlewareTest.kt | 20+++++++-------------
Mmobile/android/focus-android/app/src/main/java/org/mozilla/focus/browser/integration/BrowserToolbarIntegration.kt | 2+-
Mmobile/android/focus-android/app/src/main/java/org/mozilla/focus/cfr/CfrMiddleware.kt | 2+-
Mmobile/android/focus-android/app/src/main/java/org/mozilla/focus/fragment/BrowserFragment.kt | 4++--
Mmobile/android/focus-android/app/src/test/java/org/mozilla/focus/browser/integration/BrowserToolbarIntegrationTest.kt | 8++++----
Mmobile/android/focus-android/app/src/test/java/org/mozilla/focus/cfr/CfrMiddlewareTest.kt | 10++++------
30 files changed, 161 insertions(+), 103 deletions(-)

diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/action/BrowserAction.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/action/BrowserAction.kt @@ -19,7 +19,7 @@ import mozilla.components.browser.state.state.LoadRequestState import mozilla.components.browser.state.state.MediaSessionState import mozilla.components.browser.state.state.ReaderState import mozilla.components.browser.state.state.SearchState -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.SessionState import mozilla.components.browser.state.state.TabGroup import mozilla.components.browser.state.state.TabSessionState @@ -606,11 +606,11 @@ sealed class ContentAction : BrowserAction() { ) : ContentAction() /** - * Updates the [SecurityInfoState] of the [ContentState] with the given [sessionId]. + * Updates the [SecurityInfo] of the [ContentState] with the given [sessionId]. */ data class UpdateSecurityInfoAction( val sessionId: String, - val securityInfo: SecurityInfoState, + val securityInfo: SecurityInfo, ) : ContentAction() /** diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/EngineObserver.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/EngineObserver.kt @@ -21,7 +21,7 @@ import mozilla.components.browser.state.selector.findTabOrCustomTab import mozilla.components.browser.state.state.AppIntentState import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.LoadRequestState -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.content.DownloadState import mozilla.components.browser.state.state.content.DownloadState.Status.INITIATED import mozilla.components.browser.state.state.content.FindResultState @@ -166,7 +166,7 @@ internal class EngineObserver( dispatchAsync( ContentAction.UpdateSecurityInfoAction( tabId, - SecurityInfoState(secure, host ?: "", issuer ?: "", certificate), + SecurityInfo.from(secure, host ?: "", issuer ?: "", certificate), ), ) } diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/ContentState.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/ContentState.kt @@ -5,6 +5,7 @@ package mozilla.components.browser.state.state import android.graphics.Bitmap +import mozilla.components.browser.state.state.SecurityInfo.Unknown import mozilla.components.browser.state.state.content.DownloadState import mozilla.components.browser.state.state.content.FindResultState import mozilla.components.browser.state.state.content.HistoryState @@ -28,7 +29,7 @@ import mozilla.components.concept.engine.window.WindowRequest * @property loading True if state is loading. * @property searchTerms The last used search terms, or an empty string if no * search was executed for this session. - * @property securityInfo The security information as [SecurityInfoState], + * @property securityInfo The security information as [SecurityInfo], * describing whether or not the this session is for a secure URL, as well * as the host and SSL certificate authority. * @property icon The icon of the page currently loaded by this session. @@ -74,7 +75,7 @@ data class ContentState( val progress: Int = 0, val loading: Boolean = false, val searchTerms: String = "", - val securityInfo: SecurityInfoState = SecurityInfoState(), + val securityInfo: SecurityInfo = Unknown, val icon: Bitmap? = null, val download: DownloadState? = null, val share: ShareResourceState? = null, diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/SecurityInfo.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/SecurityInfo.kt @@ -0,0 +1,79 @@ +/* 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 mozilla.components.browser.state.state + +import java.security.cert.X509Certificate + +/** + * Security status of the connection for a `Session`. + */ +sealed class SecurityInfo { + /** + * Domain for which the SSL certificate used for the connection was issued. + */ + open val host: String = "" + + /** + * Name of the certificate authority who issued the SSL certificate used for the connection. + */ + open val issuer: String = "" + + /** + * SSL certificate used for the connection. + */ + open val certificate: X509Certificate? = null + + /** + * Whether the connection is secure or not. + */ + val isSecure: Boolean = this is Secure + + /** + * Connection is secured with a valid SSL certificate. + */ + data class Secure( + override val host: String = "", + override val issuer: String = "", + override val certificate: X509Certificate? = null, + ) : SecurityInfo() + + /** + * Connection is is not secure. SSL certificate is missing or not valid. + */ + data class Insecure( + override val host: String = "", + override val issuer: String = "", + override val certificate: X509Certificate? = null, + ) : SecurityInfo() + + /** + * Security details of the current connection are not yet known. + * This is the default state, transient until the needed details are loaded. + */ + data object Unknown : SecurityInfo() + + companion object { + /** + * Helper factory of `SecurityInfo` instances. + * + * @param isSecure true if the tab is currently pointed to a URL with + * a valid SSL certificate, otherwise false. + * @param host domain for which the certificate was issued. + * @param issuer name of the certificate authority who issued the SSL certificate. + * @param certificate the certificate in question. + * + * @return an instance of `SecurityInfo` + */ + fun from( + isSecure: Boolean = false, + host: String = "", + issuer: String = "", + certificate: X509Certificate? = null, + ) = when (isSecure) { + true -> Secure(host, issuer, certificate) + false -> Insecure(host, issuer, certificate) + } + } +} diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/SecurityInfoState.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/SecurityInfoState.kt @@ -1,23 +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 mozilla.components.browser.state.state - -import java.security.cert.X509Certificate - -/** - * A value type holding security information for a Session. - * - * @property secure true if the tab is currently pointed to a URL with - * a valid SSL certificate, otherwise false. - * @property host domain for which the certificate was issued. - * @property issuer name of the certificate authority who issued the SSL certificate. - * @property certificate the certificate in question. - */ -data class SecurityInfoState( - val secure: Boolean = false, - val host: String = "", - val issuer: String = "", - val certificate: X509Certificate? = null, -) diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/ContentActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/ContentActionTest.kt @@ -24,7 +24,7 @@ import mozilla.components.browser.state.selector.findCustomTab import mozilla.components.browser.state.state.AppIntentState import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.LoadRequestState -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.content.DownloadState import mozilla.components.browser.state.state.content.FindResultState @@ -300,7 +300,7 @@ class ContentActionTest { @Test fun `UpdateSecurityInfo updates securityInfo`() { - val newSecurityInfo = SecurityInfoState(true, "mozilla.org", "The Mozilla Team") + val newSecurityInfo = SecurityInfo.from(true, "mozilla.org", "The Mozilla Team") assertNotEquals(newSecurityInfo, tab.content.securityInfo) assertNotEquals(newSecurityInfo, otherTab.content.securityInfo) @@ -313,9 +313,10 @@ class ContentActionTest { assertEquals(newSecurityInfo, tab.content.securityInfo) assertNotEquals(newSecurityInfo, otherTab.content.securityInfo) - assertEquals(true, tab.content.securityInfo.secure) - assertEquals("mozilla.org", tab.content.securityInfo.host) - assertEquals("The Mozilla Team", tab.content.securityInfo.issuer) + val tabSecurityInfo = (tab.content.securityInfo as SecurityInfo.Secure) + assertEquals("mozilla.org", tabSecurityInfo.host) + assertEquals("The Mozilla Team", tabSecurityInfo.issuer) + assertNull(tabSecurityInfo.certificate) } @Test diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/EngineObserverTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/EngineObserverTest.kt @@ -25,7 +25,7 @@ import mozilla.components.browser.state.state.AppIntentState import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.LoadRequestState import mozilla.components.browser.state.state.MediaSessionState -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.content.FindResultState import mozilla.components.browser.state.state.createTab import mozilla.components.browser.state.store.BrowserStore @@ -242,12 +242,12 @@ class EngineObserverTest { engineSession.loadUrl("http://mozilla.org") advanceUntilIdle() - assertEquals(SecurityInfoState(secure = false), store.state.tabs[0].content.securityInfo) + assertEquals(SecurityInfo.Insecure(), store.state.tabs[0].content.securityInfo) engineSession.loadUrl("https://mozilla.org") advanceUntilIdle() - assertEquals(SecurityInfoState(secure = true, "host", "issuer"), store.state.tabs[0].content.securityInfo) + assertEquals(SecurityInfo.Secure("host", "issuer"), store.state.tabs[0].content.securityInfo) } @Test diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/reducer/ContentStateReducerTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/reducer/ContentStateReducerTest.kt @@ -9,6 +9,7 @@ import mozilla.components.browser.state.action.ContentAction import mozilla.components.browser.state.selector.findTabOrCustomTabOrSelectedTab import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.ContentState +import mozilla.components.browser.state.state.SecurityInfo.Unknown import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.store.BrowserStore import mozilla.components.support.test.mock @@ -19,6 +20,13 @@ import org.junit.Test class ContentStateReducerTest { @Test + fun `GIVEN a new ContentState THEN it's security status is unknown`() { + val defaultContentState = ContentState("emptyStateUrl") + + assertTrue(defaultContentState.securityInfo is Unknown) + } + + @Test fun `updateContentState will return a new BrowserState with updated ContentState`() { val initialContentState = ContentState("emptyStateUrl") val browserState = diff --git a/mobile/android/android-components/components/feature/pwa/src/main/java/mozilla/components/feature/pwa/ext/SessionState.kt b/mobile/android/android-components/components/feature/pwa/src/main/java/mozilla/components/feature/pwa/ext/SessionState.kt @@ -20,7 +20,7 @@ import mozilla.components.concept.engine.manifest.WebAppManifest.DisplayMode.BRO */ fun SessionState.installableManifest(): WebAppManifest? { val manifest = content.webAppManifest ?: return null - return if (content.securityInfo.secure && manifest.display != BROWSER && manifest.hasLargeIcons()) { + return if (content.securityInfo.isSecure && manifest.display != BROWSER && manifest.hasLargeIcons()) { manifest } else { null diff --git a/mobile/android/android-components/components/feature/pwa/src/test/java/mozilla/components/feature/pwa/WebAppShortcutManagerTest.kt b/mobile/android/android-components/components/feature/pwa/src/test/java/mozilla/components/feature/pwa/WebAppShortcutManagerTest.kt @@ -15,7 +15,7 @@ import androidx.core.net.toUri import androidx.test.ext.junit.runners.AndroidJUnit4 import kotlinx.coroutines.test.runTest import mozilla.components.browser.icons.BrowserIcons -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.SessionState import mozilla.components.browser.state.state.createTab import mozilla.components.concept.engine.manifest.Size @@ -346,7 +346,7 @@ class WebAppShortcutManagerTest { return tab.copy( content = tab.content.copy( webAppManifest = manifest, - securityInfo = SecurityInfoState(secure = true), + securityInfo = SecurityInfo.Secure(), ), ) } diff --git a/mobile/android/android-components/components/feature/pwa/src/test/java/mozilla/components/feature/pwa/WebAppUseCasesTest.kt b/mobile/android/android-components/components/feature/pwa/src/test/java/mozilla/components/feature/pwa/WebAppUseCasesTest.kt @@ -7,7 +7,7 @@ package mozilla.components.feature.pwa import androidx.test.ext.junit.runners.AndroidJUnit4 import kotlinx.coroutines.test.runTest import mozilla.components.browser.state.state.BrowserState -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.createTab import mozilla.components.browser.state.store.BrowserStore @@ -140,7 +140,7 @@ private fun createTestSession( return tab.copy( content = tab.content.copy( - securityInfo = SecurityInfoState(secure = secure), + securityInfo = SecurityInfo.from(secure), webAppManifest = manifest, ), ) diff --git a/mobile/android/android-components/components/feature/pwa/src/test/java/mozilla/components/feature/pwa/ext/SessionStateKtTest.kt b/mobile/android/android-components/components/feature/pwa/src/test/java/mozilla/components/feature/pwa/ext/SessionStateKtTest.kt @@ -4,7 +4,7 @@ package mozilla.components.feature.pwa.ext -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.SessionState import mozilla.components.browser.state.state.createTab import mozilla.components.concept.engine.manifest.Size @@ -162,7 +162,7 @@ private fun createTestSession( return tab.copy( content = tab.content.copy( - securityInfo = SecurityInfoState(secure = secure), + securityInfo = SecurityInfo.from(secure), webAppManifest = manifest, ), ) diff --git a/mobile/android/android-components/components/feature/toolbar/src/main/java/mozilla/components/feature/toolbar/ToolbarPresenter.kt b/mobile/android/android-components/components/feature/toolbar/src/main/java/mozilla/components/feature/toolbar/ToolbarPresenter.kt @@ -71,7 +71,7 @@ class ToolbarPresenter( toolbar.siteInfo = if (tab.content.url.isContentUrl()) { Toolbar.SiteInfo.LOCAL_PDF - } else if (tab.content.securityInfo.secure) { + } else if (tab.content.securityInfo.isSecure) { Toolbar.SiteInfo.SECURE } else { Toolbar.SiteInfo.INSECURE diff --git a/mobile/android/android-components/components/feature/toolbar/src/test/java/mozilla/components/feature/toolbar/ToolbarPresenterTest.kt b/mobile/android/android-components/components/feature/toolbar/src/test/java/mozilla/components/feature/toolbar/ToolbarPresenterTest.kt @@ -11,7 +11,7 @@ import mozilla.components.browser.state.action.TabListAction import mozilla.components.browser.state.action.TrackingProtectionAction import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.ContentState -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.TrackingProtectionState import mozilla.components.browser.state.state.content.PermissionHighlightsState @@ -21,7 +21,6 @@ import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.toolbar.Toolbar import mozilla.components.feature.toolbar.internal.URLRenderer import mozilla.components.support.test.any -import mozilla.components.support.test.ext.joinBlocking import mozilla.components.support.test.mock import mozilla.components.support.test.rule.MainCoroutineRule import org.junit.Rule @@ -120,8 +119,7 @@ class ToolbarPresenterTest { store.dispatch( ContentAction.UpdateSecurityInfoAction( "tab1", - SecurityInfoState( - secure = true, + SecurityInfo.Secure( host = "mozilla.org", issuer = "Mozilla", ), @@ -144,7 +142,7 @@ class ToolbarPresenterTest { id = "tab1", content = ContentState( url = "https://www.mozilla.org", - securityInfo = SecurityInfoState(true, "mozilla.org", "Mozilla"), + securityInfo = SecurityInfo.Secure("mozilla.org", "Mozilla"), searchTerms = "Hello World", progress = 60, ), @@ -268,7 +266,7 @@ class ToolbarPresenterTest { id = "tab1", content = ContentState( url = "https://www.mozilla.org", - securityInfo = SecurityInfoState(true, "mozilla.org", "Mozilla"), + securityInfo = SecurityInfo.Secure("mozilla.org", "Mozilla"), searchTerms = "Hello World", progress = 60, ), @@ -311,7 +309,7 @@ class ToolbarPresenterTest { id = "tab1", content = ContentState( url = "https://www.mozilla.org", - securityInfo = SecurityInfoState(true, "mozilla.org", "Mozilla"), + securityInfo = SecurityInfo.Secure("mozilla.org", "Mozilla"), searchTerms = "Hello World", progress = 60, ), @@ -320,7 +318,7 @@ class ToolbarPresenterTest { id = "tab2", content = ContentState( url = "https://www.example.org", - securityInfo = SecurityInfoState(false, "example.org", "Example"), + securityInfo = SecurityInfo.Insecure("example.org", "Example"), searchTerms = "Example", permissionHighlights = PermissionHighlightsState(true), progress = 90, @@ -375,7 +373,7 @@ class ToolbarPresenterTest { id = "tab", content = ContentState( url = "https://www.mozilla.org", - securityInfo = SecurityInfoState(true, "mozilla.org", "Mozilla"), + securityInfo = SecurityInfo.Secure("mozilla.org", "Mozilla"), searchTerms = "Hello World", progress = 60, ), @@ -425,7 +423,7 @@ class ToolbarPresenterTest { id = "tab", content = ContentState( url = "https://www.mozilla.org", - securityInfo = SecurityInfoState(true, "mozilla.org", "Mozilla"), + securityInfo = SecurityInfo.Secure("mozilla.org", "Mozilla"), searchTerms = "Hello World", progress = 60, ), diff --git a/mobile/android/android-components/docs/changelog.md b/mobile/android/android-components/docs/changelog.md @@ -5,6 +5,8 @@ permalink: /changelog/ --- # 147.0 (In Development) +* **browser-state**: + * ⚠️ **Breaking change**: New `Unknown` third state for the `SecurityStatus` of the connection used in a tab. The `secure` property has been migrated to `isSecure`. [Bug 2000617](https://bugzilla.mozilla.org/show_bug.cgi?id=2000617). * **lib-state** * ⚠️ **Breaking change**: Removed thread marshalling from Stores [Bug 1980348](https://bugzilla.mozilla.org/show_bug.cgi?id=1980348). * `Store.dispatch` is now invoked on the calling thread. diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt @@ -636,7 +636,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler { url = tab.content.url, title = tab.content.title, isLocalPdf = tab.content.url.isContentUrl(), - isSecured = tab.content.securityInfo.secure, + isSecured = tab.content.securityInfo.isSecure, sitePermissions = sitePermissions, certificateName = tab.content.securityInfo.issuer, permissionHighlights = tab.content.permissionHighlights, @@ -649,7 +649,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler { url = tab.content.url, title = tab.content.title, isLocalPdf = tab.content.url.isContentUrl(), - isSecured = tab.content.securityInfo.secure, + isSecured = tab.content.securityInfo.isSecure, sitePermissions = sitePermissions, gravity = getAppropriateLayoutGravity(), certificateName = tab.content.securityInfo.issuer, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/TabPreview.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/TabPreview.kt @@ -199,7 +199,7 @@ class TabPreview @JvmOverloads constructor( onClick = object : BrowserToolbarEvent {}, ) } else if ( - tab?.content?.securityInfo?.secure == true && + tab?.content?.securityInfo?.isSecure == true && tab.trackingProtection.enabled && !tab.trackingProtection.ignoredOnTrackingProtection ) { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddleware.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddleware.kt @@ -626,7 +626,7 @@ class BrowserToolbarMiddleware( url = tab.content.url, title = tab.content.title, isLocalPdf = tab.content.url.isContentUrl(), - isSecured = tab.content.securityInfo.secure, + isSecured = tab.content.securityInfo.isSecure, sitePermissions = sitePermissions, certificateName = tab.content.securityInfo.issuer, permissionHighlights = tab.content.permissionHighlights, @@ -639,7 +639,7 @@ class BrowserToolbarMiddleware( url = tab.content.url, title = tab.content.title, isLocalPdf = tab.content.url.isContentUrl(), - isSecured = tab.content.securityInfo.secure, + isSecured = tab.content.securityInfo.isSecure, sitePermissions = sitePermissions, gravity = settings.toolbarPosition.androidGravity, certificateName = tab.content.securityInfo.issuer, @@ -1229,7 +1229,7 @@ class BrowserToolbarMiddleware( onClick = StartPageActions.SiteInfoClicked, ) } else if ( - selectedTab?.content?.securityInfo?.secure == true && + selectedTab?.content?.securityInfo?.isSecure == true && selectedTab.trackingProtection.enabled && !selectedTab.trackingProtection.ignoredOnTrackingProtection ) { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/CustomTabBrowserToolbarMiddleware.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/CustomTabBrowserToolbarMiddleware.kt @@ -190,7 +190,7 @@ class CustomTabBrowserToolbarMiddleware( url = customTab.content.url, title = customTab.content.title, isLocalPdf = customTab.content.url.isContentUrl(), - isSecured = customTab.content.securityInfo.secure, + isSecured = customTab.content.securityInfo.isSecure, sitePermissions = sitePermissions, certificateName = customTab.content.securityInfo.issuer, permissionHighlights = customTab.content.permissionHighlights, @@ -205,7 +205,7 @@ class CustomTabBrowserToolbarMiddleware( url = customTab.content.url, title = customTab.content.title, isLocalPdf = customTab.content.url.isContentUrl(), - isSecured = customTab.content.securityInfo.secure, + isSecured = customTab.content.securityInfo.isSecure, sitePermissions = sitePermissions, gravity = settings.toolbarPosition.androidGravity, certificateName = customTab.content.securityInfo.issuer, @@ -421,7 +421,7 @@ class CustomTabBrowserToolbarMiddleware( ), ) } else if ( - customTab?.content?.securityInfo?.secure == true && + customTab?.content?.securityInfo?.isSecure == true && customTab.trackingProtection.enabled && !customTab.trackingProtection.ignoredOnTrackingProtection ) { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt @@ -207,7 +207,7 @@ class ExternalAppBrowserFragment : BaseBrowserFragment() { url = tab.content.url, title = tab.content.title, isLocalPdf = tab.content.url.isContentUrl(), - isSecured = tab.content.securityInfo.secure, + isSecured = tab.content.securityInfo.isSecure, sitePermissions = sitePermissions, certificateName = tab.content.securityInfo.issuer, permissionHighlights = tab.content.permissionHighlights, @@ -221,7 +221,7 @@ class ExternalAppBrowserFragment : BaseBrowserFragment() { url = tab.content.url, title = tab.content.title, isLocalPdf = tab.content.url.isContentUrl(), - isSecured = tab.content.securityInfo.secure, + isSecured = tab.content.securityInfo.isSecure, sitePermissions = sitePermissions, gravity = getAppropriateLayoutGravity(), certificateName = tab.content.securityInfo.issuer, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/ConnectionDetailsController.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/ConnectionDetailsController.kt @@ -69,7 +69,7 @@ class DefaultConnectionDetailsController( url = tab.content.url, title = tab.content.title, isLocalPdf = tab.content.url.isContentUrl(), - isSecured = tab.content.securityInfo.secure, + isSecured = tab.content.securityInfo.isSecure, sitePermissions = sitePermissions, gravity = gravity, certificateName = tab.content.securityInfo.issuer, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerDetailsController.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/CookieBannerDetailsController.kt @@ -101,7 +101,7 @@ class DefaultCookieBannerDetailsController( url = tab.content.url, title = tab.content.title, isLocalPdf = tab.content.url.isContentUrl(), - isSecured = tab.content.securityInfo.secure, + isSecured = tab.content.securityInfo.isSecure, sitePermissions = sitePermissions, gravity = gravity, certificateName = tab.content.securityInfo.issuer, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelInteractor.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelInteractor.kt @@ -86,7 +86,7 @@ class TrackingProtectionPanelInteractor( url = tab.content.url, title = tab.content.title, isLocalPdf = tab.content.url.isContentUrl(), - isSecured = tab.content.securityInfo.secure, + isSecured = tab.content.securityInfo.isSecure, sitePermissions = sitePermissions, gravity = gravity, certificateName = tab.content.securityInfo.issuer, diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddlewareTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddlewareTest.kt @@ -38,7 +38,7 @@ import mozilla.components.browser.state.search.SearchEngine import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.ContentState import mozilla.components.browser.state.state.SearchState -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.TrackingProtectionState import mozilla.components.browser.state.state.content.DownloadState @@ -1801,7 +1801,7 @@ class BrowserToolbarMiddlewareTest { browserStore = browserStore, useCases = useCases, ) - every { tab.content.securityInfo.secure } returns true + every { tab.content.securityInfo } returns SecurityInfo.Secure() every { tab.trackingProtection.enabled } returns true every { tab.trackingProtection.ignoredOnTrackingProtection } returns false val expectedSecurityIndicator = ActionButtonRes( @@ -1824,7 +1824,7 @@ class BrowserToolbarMiddlewareTest { browserStore = browserStore, useCases = useCases, ) - every { tab.content.securityInfo.secure } returns false + every { tab.content.securityInfo } returns SecurityInfo.Insecure() val expectedSecurityIndicator = ActionButtonRes( drawableResId = iconsR.drawable.mozac_ic_shield_slash_24, contentDescription = toolbarR.string.mozac_browser_toolbar_content_description_site_info, @@ -1881,7 +1881,7 @@ class BrowserToolbarMiddlewareTest { var securityIndicator = toolbarPageActions[0] as ActionButtonRes assertEquals(expectedInsecureIndicator, securityIndicator) - browserStore.dispatch(UpdateSecurityInfoAction(tab.id, SecurityInfoState(true))) + browserStore.dispatch(UpdateSecurityInfoAction(tab.id, SecurityInfo.Secure())) mainLooperRule.idle() toolbarPageActions = toolbarStore.state.displayState.pageActionsStart assertEquals(1, toolbarPageActions.size) @@ -1959,7 +1959,7 @@ class BrowserToolbarMiddlewareTest { val toolbarStore = buildStore(middleware).also { it.dispatch(BrowserToolbarAction.Init()) } - browserStore.dispatch(UpdateSecurityInfoAction(tab.id, SecurityInfoState(true))) + browserStore.dispatch(UpdateSecurityInfoAction(tab.id, SecurityInfo.Secure())) mainLooperRule.idle() val toolbarPageActions = toolbarStore.state.displayState.pageActionsStart assertEquals(1, toolbarPageActions.size) @@ -2007,7 +2007,7 @@ class BrowserToolbarMiddlewareTest { val toolbarStore = buildStore(middleware).also { it.dispatch(BrowserToolbarAction.Init()) } - browserStore.dispatch(UpdateSecurityInfoAction(tab.id, SecurityInfoState(true))) + browserStore.dispatch(UpdateSecurityInfoAction(tab.id, SecurityInfo.Secure())) mainLooperRule.idle() val toolbarPageActions = toolbarStore.state.displayState.pageActionsStart diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/toolbar/CustomTabBrowserToolbarMiddlewareTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/toolbar/CustomTabBrowserToolbarMiddlewareTest.kt @@ -4,7 +4,6 @@ package org.mozilla.fenix.components.toolbar -import android.content.Context import android.graphics.Bitmap import android.net.InetAddresses import android.util.Patterns @@ -12,17 +11,13 @@ import androidx.appcompat.content.res.AppCompatResources import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toDrawable import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleOwner import androidx.navigation.NavController import io.mockk.every import io.mockk.mockk import io.mockk.verify import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.MainScope -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import mozilla.components.browser.state.action.ContentAction.UpdateProgressAction import mozilla.components.browser.state.action.ContentAction.UpdateSecurityInfoAction @@ -31,7 +26,7 @@ import mozilla.components.browser.state.action.ContentAction.UpdateUrlAction import mozilla.components.browser.state.action.TrackingProtectionAction import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.CustomTabSessionState -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.TrackingProtectionState import mozilla.components.browser.state.state.createCustomTab import mozilla.components.browser.state.state.createTab @@ -55,7 +50,6 @@ import mozilla.components.support.utils.ClipboardHandler import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotNull -import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Rule import org.junit.Test @@ -263,7 +257,7 @@ class CustomTabBrowserToolbarMiddlewareTest { @Test fun `GIVEN the website is secure WHEN initializing the toolbar THEN add an appropriate security indicator`() { - every { customTab.content.securityInfo.secure } returns true + every { customTab.content.securityInfo } returns SecurityInfo.Secure() every { customTab.trackingProtection.enabled } returns true every { customTab.trackingProtection.ignoredOnTrackingProtection } returns false val expectedSecurityIndicator = ActionButtonRes( @@ -282,7 +276,7 @@ class CustomTabBrowserToolbarMiddlewareTest { @Test fun `GIVEN the website is insecure WHEN initializing the toolbar THEN add an appropriate security indicator`() { - every { customTab.content.securityInfo.secure } returns false + every { customTab.content.securityInfo } returns SecurityInfo.Insecure() val expectedSecurityIndicator = ActionButtonRes( drawableResId = iconsR.drawable.mozac_ic_shield_slash_24, contentDescription = toolbarR.string.mozac_browser_toolbar_content_description_site_info, @@ -328,7 +322,7 @@ class CustomTabBrowserToolbarMiddlewareTest { var securityIndicator = toolbarPageActions[0] assertEquals(expectedInsecureIndicator, securityIndicator) - browserStore.dispatch(UpdateSecurityInfoAction(customTabId, SecurityInfoState(true))) + browserStore.dispatch(UpdateSecurityInfoAction(customTabId, SecurityInfo.Secure())) mainLooperRule.idle() toolbarPageActions = toolbarStore.state.displayState.pageActionsStart assertEquals(1, toolbarPageActions.size) @@ -356,7 +350,7 @@ class CustomTabBrowserToolbarMiddlewareTest { onClick = SiteInfoClicked, ) val toolbarStore = buildStore(middleware) - browserStore.dispatch(UpdateSecurityInfoAction(customTabId, SecurityInfoState(true))) + browserStore.dispatch(UpdateSecurityInfoAction(customTabId, SecurityInfo.Secure())) mainLooperRule.idle() val toolbarPageActions = toolbarStore.state.displayState.pageActionsStart assertEquals(1, toolbarPageActions.size) @@ -389,7 +383,7 @@ class CustomTabBrowserToolbarMiddlewareTest { onClick = SiteInfoClicked, ) val toolbarStore = buildStore(middleware) - browserStore.dispatch(UpdateSecurityInfoAction(customTabId, SecurityInfoState(true))) + browserStore.dispatch(UpdateSecurityInfoAction(customTabId, SecurityInfo.Secure())) mainLooperRule.idle() var toolbarPageActions = toolbarStore.state.displayState.pageActionsStart assertEquals(1, toolbarPageActions.size) @@ -429,7 +423,7 @@ class CustomTabBrowserToolbarMiddlewareTest { onClick = SiteInfoClicked, ) val toolbarStore = buildStore(middleware) - browserStore.dispatch(UpdateSecurityInfoAction(customTabId, SecurityInfoState(true))) + browserStore.dispatch(UpdateSecurityInfoAction(customTabId, SecurityInfo.Secure())) mainLooperRule.idle() var toolbarPageActions = toolbarStore.state.displayState.pageActionsStart assertEquals(1, toolbarPageActions.size) diff --git a/mobile/android/focus-android/app/src/main/java/org/mozilla/focus/browser/integration/BrowserToolbarIntegration.kt b/mobile/android/focus-android/app/src/main/java/org/mozilla/focus/browser/integration/BrowserToolbarIntegration.kt @@ -492,7 +492,7 @@ class BrowserToolbarIntegration( flow.mapNotNull { state -> state.findCustomTabOrSelectedTab(customTabId) } .distinctUntilChangedBy { tab -> tab.content.securityInfo } .collect { - val secure = it.content.securityInfo.secure + val secure = it.content.securityInfo.isSecure val url = it.content.url.trim() when { secure && Indicators.SECURITY in toolbar.display.indicators -> { diff --git a/mobile/android/focus-android/app/src/main/java/org/mozilla/focus/cfr/CfrMiddleware.kt b/mobile/android/focus-android/app/src/main/java/org/mozilla/focus/cfr/CfrMiddleware.kt @@ -99,7 +99,7 @@ class CfrMiddleware( private fun isSessionSecure(browserState: BrowserState) = browserState.findTabOrCustomTabOrSelectedTab( browserState.selectedTabId, - )?.content?.securityInfo?.secure == true + )?.content?.securityInfo?.isSecure == true private fun shouldShowCfrForTrackingProtection( action: BrowserAction, diff --git a/mobile/android/focus-android/app/src/main/java/org/mozilla/focus/fragment/BrowserFragment.kt b/mobile/android/focus-android/app/src/main/java/org/mozilla/focus/fragment/BrowserFragment.kt @@ -1078,7 +1078,7 @@ class BrowserFragment : cookieBannerReducerStore = cookieBannerReducerStore, tabUrl = tab.content.url, isTrackingProtectionOn = tab.trackingProtection.ignoredOnTrackingProtection.not(), - isConnectionSecure = tab.content.securityInfo.secure, + isConnectionSecure = tab.content.securityInfo.isSecure, blockedTrackersCount = requireContext().settings .getTotalBlockedTrackersCount(), toggleTrackingProtection = ::toggleTrackingProtection, @@ -1119,7 +1119,7 @@ class BrowserFragment : context = requireContext(), tabTitle = tab.content.title, tabUrl = tab.content.url, - isConnectionSecure = tab.content.securityInfo.secure, + isConnectionSecure = tab.content.securityInfo.isSecure, goBack = { trackingProtectionPanel?.show() }, ) trackingProtectionPanel?.hide() diff --git a/mobile/android/focus-android/app/src/test/java/org/mozilla/focus/browser/integration/BrowserToolbarIntegrationTest.kt b/mobile/android/focus-android/app/src/test/java/org/mozilla/focus/browser/integration/BrowserToolbarIntegrationTest.kt @@ -9,7 +9,7 @@ import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.runTest import mozilla.components.browser.state.action.ContentAction import mozilla.components.browser.state.state.BrowserState -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.createTab import mozilla.components.browser.state.store.BrowserStore @@ -200,8 +200,8 @@ class BrowserToolbarIntegrationTest { store.dispatch( ContentAction.UpdateSecurityInfoAction( selectedTab.id, - SecurityInfoState( - secure = secure, + SecurityInfo.from( + isSecure = secure, host = "mozilla.org", issuer = "Mozilla", ), @@ -218,7 +218,7 @@ class BrowserToolbarIntegrationTest { private fun createSecureTab(): TabSessionState { val tab = createTab("https://www.mozilla.org", id = "1") return tab.copy( - content = tab.content.copy(securityInfo = SecurityInfoState(secure = true)), + content = tab.content.copy(securityInfo = SecurityInfo.Secure()), ) } } diff --git a/mobile/android/focus-android/app/src/test/java/org/mozilla/focus/cfr/CfrMiddlewareTest.kt b/mobile/android/focus-android/app/src/test/java/org/mozilla/focus/cfr/CfrMiddlewareTest.kt @@ -8,7 +8,7 @@ import mozilla.components.browser.state.action.CookieBannerAction import mozilla.components.browser.state.action.TabListAction import mozilla.components.browser.state.action.TrackingProtectionAction import mozilla.components.browser.state.state.BrowserState -import mozilla.components.browser.state.state.SecurityInfoState +import mozilla.components.browser.state.state.SecurityInfo import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.createTab import mozilla.components.browser.state.store.BrowserStore @@ -111,8 +111,7 @@ class CfrMiddlewareTest { val updateSecurityInfoAction = ContentAction.UpdateSecurityInfoAction( "1", - SecurityInfoState( - secure = false, + SecurityInfo.Insecure( host = "test.org", issuer = "Test", ), @@ -145,8 +144,7 @@ class CfrMiddlewareTest { val updateSecurityInfoAction = ContentAction.UpdateSecurityInfoAction( "1", - SecurityInfoState( - secure = true, + SecurityInfo.Secure( host = "test.org", issuer = "Test", ), @@ -303,7 +301,7 @@ class CfrMiddlewareTest { return tab.copy( content = tab.content.copy( private = true, - securityInfo = SecurityInfoState(secure = isSecure), + securityInfo = SecurityInfo.from(isSecure), ), ) }