From 49bc3c18545c22821551575e038b6b9710b826bd Mon Sep 17 00:00:00 2001 From: Grisha Kruglov Date: Thu, 22 Aug 2019 16:56:13 -0700 Subject: [PATCH 1/3] WIP Use WebChannels for FxA integration --- .../org/mozilla/fenix/AppRequestInterceptor.kt | 4 ++-- .../org/mozilla/fenix/IntentReceiverActivity.kt | 1 + .../org/mozilla/fenix/browser/BrowserFragment.kt | 14 ++++++++++++++ .../mozilla/fenix/components/BackgroundServices.kt | 12 ++++++++---- .../fenix/customtabs/AuthCustomTabActivity.kt | 1 - 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt b/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt index 0824938409c6..87d1b192688e 100644 --- a/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt +++ b/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt @@ -25,8 +25,8 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor { } adjustTrackingProtection(host, context, session) - // Accounts uses interception to check for a "success URL" in the sign-in flow to finalize authentication. - return context.components.services.accountsAuthFeature.interceptor.onLoadRequest(session, uri) + + return null } private fun adjustTrackingProtection(host: String, context: Context, session: EngineSession) { diff --git a/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt b/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt index 90b1db780808..c34566b1ba20 100644 --- a/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt @@ -62,6 +62,7 @@ class IntentReceiverActivity : Activity() { private fun setIntentActivity(intent: Intent) { val openToBrowser = when { components.utils.customTabIntentProcessor.matches(intent) -> { + // TODO This is potentially unsafe. Any app on the system can set the auth extra. val activityClass = if (intent.hasExtra(getString(R.string.intent_extra_auth))) { AuthCustomTabActivity::class } else { diff --git a/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt index 79eb039ec10c..d5fd3b34b43a 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt @@ -27,6 +27,7 @@ import kotlinx.coroutines.withContext import mozilla.appservices.places.BookmarkRoot import mozilla.components.browser.session.Session import mozilla.components.feature.readerview.ReaderViewFeature +import mozilla.components.feature.accounts.WebChannelFeature import mozilla.components.feature.session.ThumbnailsFeature import mozilla.components.feature.sitepermissions.SitePermissions import mozilla.components.lib.state.ext.consumeFrom @@ -63,6 +64,7 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler { private val readerViewFeature = ViewBoundFeatureWrapper() private val thumbnailsFeature = ViewBoundFeatureWrapper() + private val webchannelIntegration = ViewBoundFeatureWrapper() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -102,6 +104,18 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler { view = view ) + webchannelIntegration.set( + feature = WebChannelFeature( + requireContext(), + customTabSessionId, + requireComponents.core.engine, + requireComponents.core.sessionManager, + requireComponents.backgroundServices.accountManager + ), + owner = this, + view = view + ) + readerViewFeature.set( feature = ReaderViewFeature( requireContext(), diff --git a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt index f6e95b3e22de..5c6c9b3d3f67 100644 --- a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt +++ b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt @@ -30,6 +30,7 @@ import mozilla.components.feature.push.PushType import mozilla.components.service.fxa.DeviceConfig import mozilla.components.service.fxa.ServerConfig import mozilla.components.service.fxa.SyncConfig +import mozilla.components.service.fxa.SyncEngine import mozilla.components.service.fxa.manager.FxaAccountManager import mozilla.components.service.fxa.sync.GlobalSyncableStoreProvider import mozilla.components.support.base.log.logger.Logger @@ -54,7 +55,7 @@ class BackgroundServices( ) { companion object { const val CLIENT_ID = "a2270f727f45f648" - const val REDIRECT_URL = "https://accounts.firefox.com/oauth/success/$CLIENT_ID" + const val REDIRECT_URL = "urn:ietf:wg:oauth:2.0:oob:oauth-redirect-webchannel" } fun defaultDeviceName(context: Context): String = context.getString( @@ -64,7 +65,9 @@ class BackgroundServices( Build.MODEL ) - private val serverConfig = ServerConfig.release(CLIENT_ID, REDIRECT_URL) +// private val serverConfig = ServerConfig.release(CLIENT_ID, REDIRECT_URL) +// TODO replace with release channel ^^ + private val serverConfig = ServerConfig("https://oauthchannel.dev.lcip.org", CLIENT_ID, REDIRECT_URL) private val deviceConfig = DeviceConfig( name = defaultDeviceName(context), type = DeviceType.MOBILE, @@ -82,7 +85,7 @@ class BackgroundServices( private val syncConfig = if (context.isInExperiment(Experiments.asFeatureSyncDisabled)) { null } else { - SyncConfig(setOf("history", "bookmarks"), syncPeriodInMinutes = 240L) // four hours + SyncConfig(setOf(SyncEngine.History, SyncEngine.Bookmarks), syncPeriodInMinutes = 240L) // four hours } val pushConfig by lazy { @@ -174,7 +177,8 @@ class BackgroundServices( // See https://github.com/mozilla-mobile/android-components/issues/3732 setOf("https://identity.mozilla.com/apps/oldsync") ).also { - Settings.getInstance(context).fxaHasSyncedItems = syncConfig?.syncableStores?.isNotEmpty() ?: false + // TODO this needs to change once we have a SyncManager + Settings.getInstance(context).fxaHasSyncedItems = syncConfig?.supportedEngines?.isNotEmpty() ?: false if (FeatureFlags.sendTabEnabled) { it.registerForDeviceEvents(deviceEventObserver, ProcessLifecycleOwner.get(), false) diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt b/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt index af762dcc7815..1a0432d05fe6 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt @@ -11,7 +11,6 @@ import org.mozilla.fenix.ext.components class AuthCustomTabActivity : CustomTabActivity() { private lateinit var accountManager: FxaAccountManager - // Navigate away from this activity when we have successful authentication private val accountStateObserver = object : AccountObserver { override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) { From bab6b3214b90776e9a88a63ed16ce3d45df9a030 Mon Sep 17 00:00:00 2001 From: Grisha Kruglov Date: Tue, 27 Aug 2019 19:13:22 -0700 Subject: [PATCH 2/3] install in custom tab --- .../customtabs/ExternalAppBrowserFragment.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt index b20c42139d5c..43b120f2b2a9 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt @@ -11,6 +11,7 @@ import kotlinx.android.synthetic.main.fragment_browser.view.* import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi import mozilla.components.browser.session.Session +import mozilla.components.feature.accounts.WebChannelFeature import mozilla.components.feature.sitepermissions.SitePermissions import mozilla.components.lib.state.ext.consumeFrom import mozilla.components.support.base.feature.BackHandler @@ -30,6 +31,7 @@ import org.mozilla.fenix.ext.requireComponents class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler { private val customTabsIntegration = ViewBoundFeatureWrapper() + private val webchannelIntegration = ViewBoundFeatureWrapper() override fun initializeUI(view: View): Session? { return super.initializeUI(view)?.also { @@ -50,6 +52,20 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler { view = view) } + // TODO this is weird. We have `webchannelIntegration` in the base class already, and above + // we're calling `super.initializeUI`... why is this necessray? + webchannelIntegration.set( + feature = WebChannelFeature( + requireContext(), + customTabSessionId, + requireComponents.core.engine, + requireComponents.core.sessionManager, + requireComponents.backgroundServices.accountManager + ), + owner = this, + view = view + ) + consumeFrom(browserStore) { browserToolbarView.update(it) } From 48bde91a0c1c0f652ea66a9506e71aa8b904a2d2 Mon Sep 17 00:00:00 2001 From: Grisha Kruglov Date: Wed, 28 Aug 2019 20:00:43 -0700 Subject: [PATCH 3/3] pass --- .../mozilla/fenix/components/BackgroundServices.kt | 14 +++++++++----- .../fenix/customtabs/AuthCustomTabActivity.kt | 3 ++- .../java/org/mozilla/fenix/home/HomeFragment.kt | 5 +++-- .../fenix/library/bookmarks/BookmarkFragment.kt | 3 ++- .../selectfolder/SelectBookmarkFolderFragment.kt | 3 ++- .../fenix/settings/AccountProblemFragment.kt | 3 ++- .../org/mozilla/fenix/settings/SettingsFragment.kt | 3 ++- .../mozilla/fenix/settings/TurnOnSyncFragment.kt | 3 ++- 8 files changed, 24 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt index 5c6c9b3d3f67..c545b9965e50 100644 --- a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt +++ b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt @@ -16,6 +16,7 @@ import mozilla.components.browser.storage.sync.PlacesBookmarksStorage import mozilla.components.browser.storage.sync.PlacesHistoryStorage import mozilla.components.concept.push.Bus import mozilla.components.concept.sync.AccountObserver +import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.DeviceCapability import mozilla.components.concept.sync.DeviceEvent import mozilla.components.concept.sync.DeviceEventsObserver @@ -67,7 +68,7 @@ class BackgroundServices( // private val serverConfig = ServerConfig.release(CLIENT_ID, REDIRECT_URL) // TODO replace with release channel ^^ - private val serverConfig = ServerConfig("https://oauthchannel.dev.lcip.org", CLIENT_ID, REDIRECT_URL) + private val serverConfig = ServerConfig("https://oauthchannel2.dev.lcip.org", CLIENT_ID, REDIRECT_URL) private val deviceConfig = DeviceConfig( name = defaultDeviceName(context), type = DeviceType.MOBILE, @@ -147,13 +148,16 @@ class BackgroundServices( Settings.getInstance(context).fxaSignedIn = false } - override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) { - if (newAccount) { - context.components.analytics.metrics.track(Event.FXANewSignup) + override fun onAuthenticated(account: OAuthAccount, authType: AuthType) { + if (authType != AuthType.Existing) { push.subscribeForType(PushType.Services) } - context.components.analytics.metrics.track(Event.SyncAuthSignIn) + if (authType == AuthType.Signup) { + context.components.analytics.metrics.track(Event.FXANewSignup) + } else if (authType == AuthType.Signin) { + context.components.analytics.metrics.track(Event.SyncAuthSignIn) + } Settings.getInstance(context).fxaSignedIn = true } diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt b/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt index 1a0432d05fe6..903dbf765834 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.customtabs import mozilla.components.concept.sync.AccountObserver +import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.OAuthAccount import mozilla.components.service.fxa.manager.FxaAccountManager import org.mozilla.fenix.ext.components @@ -13,7 +14,7 @@ class AuthCustomTabActivity : CustomTabActivity() { private lateinit var accountManager: FxaAccountManager // Navigate away from this activity when we have successful authentication private val accountStateObserver = object : AccountObserver { - override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) { + override fun onAuthenticated(account: OAuthAccount, authType: AuthType) { this@AuthCustomTabActivity.finish() } } diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 174d589e2f4d..3e7e9f1971f1 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -41,6 +41,7 @@ import mozilla.components.browser.menu.BrowserMenu import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import mozilla.components.concept.sync.AccountObserver +import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.OAuthAccount import mozilla.components.concept.sync.Profile import mozilla.components.feature.tab.collections.TabCollection @@ -741,8 +742,8 @@ class HomeFragment : Fragment(), AccountObserver { } } - override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) { - if (newAccount) { + override fun onAuthenticated(account: OAuthAccount, authType: AuthType) { + if (authType != AuthType.Existing) { view?.let { FenixSnackbar.make(it, Snackbar.LENGTH_SHORT).setText( it.context.getString(R.string.onboarding_firefox_account_sync_is_on) diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt index 894855f67931..f2c764ec912d 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt @@ -33,6 +33,7 @@ import mozilla.appservices.places.BookmarkRoot import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.storage.BookmarkNodeType import mozilla.components.concept.sync.AccountObserver +import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.OAuthAccount import mozilla.components.lib.state.ext.consumeFrom import mozilla.components.support.base.feature.BackHandler @@ -239,7 +240,7 @@ class BookmarkFragment : LibraryPageFragment(), BackHandler, Accou return bookmarkView.onBackPressed() } - override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) { + override fun onAuthenticated(account: OAuthAccount, authType: AuthType) { bookmarkInteractor.onSignedIn() lifecycleScope.launch { refreshBookmarks() diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderFragment.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderFragment.kt index a662358c8b04..84bb8b90baab 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderFragment.kt @@ -28,6 +28,7 @@ import kotlinx.coroutines.withContext import mozilla.appservices.places.BookmarkRoot import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.sync.AccountObserver +import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.OAuthAccount import org.mozilla.fenix.R import org.mozilla.fenix.ext.getColorFromAttr @@ -124,7 +125,7 @@ class SelectBookmarkFolderFragment : Fragment(), AccountObserver { else -> super.onOptionsItemSelected(item) } } - override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) { + override fun onAuthenticated(account: OAuthAccount, authType: AuthType) { bookmarkInteractor.onSignedIn() } diff --git a/app/src/main/java/org/mozilla/fenix/settings/AccountProblemFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/AccountProblemFragment.kt index 673b1f2b3773..59ad22be0a8d 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/AccountProblemFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/AccountProblemFragment.kt @@ -12,6 +12,7 @@ import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import kotlinx.coroutines.launch import mozilla.components.concept.sync.AccountObserver +import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.OAuthAccount import org.mozilla.fenix.R import org.mozilla.fenix.ext.getPreferenceKey @@ -66,7 +67,7 @@ class AccountProblemFragment : PreferenceFragmentCompat(), AccountObserver { } // We're told our auth problems have been fixed; close this fragment. - override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) = closeFragment() + override fun onAuthenticated(account: OAuthAccount, authType: AuthType) = closeFragment() // We're told there are no more auth problems since there is no more account; close this fragment. override fun onLoggedOut() = closeFragment() diff --git a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index d0e33a59571e..cf29fd42432e 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -24,6 +24,7 @@ import androidx.preference.PreferenceCategory import androidx.preference.PreferenceFragmentCompat import kotlinx.coroutines.launch import mozilla.components.concept.sync.AccountObserver +import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.OAuthAccount import mozilla.components.concept.sync.Profile import org.mozilla.fenix.BrowserDirection @@ -326,7 +327,7 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver { Navigation.findNavController(view!!).navigate(directions) } - override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) { + override fun onAuthenticated(account: OAuthAccount, authType: AuthType) { lifecycleScope.launch { context?.let { updateAccountUIState(it, it.components.backgroundServices.accountManager.accountProfile()) diff --git a/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt index 2963f42f9851..a22e552bc042 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt @@ -15,6 +15,7 @@ import androidx.navigation.findNavController import androidx.navigation.fragment.findNavController import kotlinx.android.synthetic.main.fragment_turn_on_sync.view.* import mozilla.components.concept.sync.AccountObserver +import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.OAuthAccount import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar @@ -72,7 +73,7 @@ class TurnOnSyncFragment : Fragment(), AccountObserver { return view } - override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) { + override fun onAuthenticated(account: OAuthAccount, authType: AuthType) { FenixSnackbar.make(view!!, FenixSnackbar.LENGTH_SHORT) .setText(requireContext().getString(R.string.sync_syncing_in_progress)) .show()