Chrome custom tabs fail behind a proxy

554 views Asked by At

We have an Android application opening Chrome Custom Tabs to perform user authentication. (A stripped version of the fragment code is listed below.)

When the mobile network has a proxy address:port configured, the CCT browser displays a popup to gather credentials. This has 3 problems:

  1. The browser fails to authenticate and crashes
  2. The popup is crude and doesn't match our app's dialog style
  3. The app usually has the credentials already so no dialog is necessary--a method should allow them to be inserted without user input

Our old implementation used a WebViewClient which had the onReceivedHttpAuthRequest() callback. This gave control back to the app to present it's own dialog or supply the credentials directly.

Is there no way to do same with CCTs?

open class CustomTabsFragment {
    ...
    private var cctServiceConnection: CustomTabsServiceConnection? = null
    private var cctClient: CustomTabsClient? = null
    private var cctSession: CustomTabsSession? = null
    private var cctBuilder = CustomTabsIntent.Builder()
    private lateinit var chromePackageName: String
    lateinit var url: String

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        ...
        // get Bundle arguments
        url = requiredArguments().getString("url","")
        chromePackageName = requiredArguments().getString("package","")
        ...
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val uri = Uri.parse(url)
        cctServiceConnection = object : CustomTabsServiceConnection() {
            override fun onCustomTabsServiceConnected(name: ComponentName, mClient: CustomTabsClient) {
                cctClient = mClient
                cctClient?.let {
                    it.warmup(0L)
                    cctSession = it.newSession(chromeCustomTabsCallback)
                }
                cctSession?.let {
                    it.mayLaunchUrl(uri, null, null)
                    cctBuilder.setSession(it)

                    val customTabsIntent = cctBuilder
                        .setShowTitle(true)
                        .setDefaultShareMenuItemEnabled(false)
                        .setUrlBarHidingEnabled(true)
                        .setStartAnimations(requireActivity(), android.R.anim.fade_in, android.R.anim.fade_out)
                        .setExitAnimations(requireActivity(), android.R.anim.fade_in, android.R.anim.fade_out)
                        .build()

                    customTabsIntent.intent.data = uri
                    startActivityForResult(customTabsIntent.intent, 1000)
                }
            }

            override fun onServiceDisconnected(name: ComponentName?) {
                cctClient = null
                cctSession = null
            }
        }

        // Binds to the service.
        cctServiceConnection?.let {
            CustomTabsClient.bindCustomTabsService(requireContext(), chromePackageName, it)
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        val loginActivity = activity as? LoginActivity
        loginActivity?.let {
            if (requestCode == 1000 && !it.isAuthenticated) {
                // Handle close or back pressed when opening web page via chrome custom tabs
                findNavController().navigate(R.id.destinationFragment)
            }
        }
        super.onActivityResult(requestCode, resultCode, data)
    }

    private val chromeCustomTabsCallback = object : CustomTabsCallback() {
        override fun onNavigationEvent(navigationEvent: Int, extras: Bundle?) {
            super.onNavigationEvent(navigationEvent, extras)
            when (navigationEvent) {
                NAVIGATION_STARTED -> Logger("Chrome Custom Tabs Navigation started - the tab has started loading a page.")
                NAVIGATION_FINISHED -> Logger("Chrome Custom Tabs Navigation finished - the tab has finished loading a page.")
                NAVIGATION_FAILED -> Logger("Chrome Custom Tabs Navigation failed - the tab couldn't finish loading due to a failure.")
                NAVIGATION_ABORTED -> Logger("Chrome Custom Tabs Navigation aborted - loading was aborted by a user action before it finishes like clicking on a link or refreshing the page.")
                TAB_SHOWN -> Logger("Chrome Custom Tabs Navigation tab shown")
                TAB_HIDDEN -> Logger("Chrome Custom Tabs Navigation tab hidden")
                else -> Logger("Chrome Custom Tabs Navigation Unknown")
            }
        }
    }

    ...
}
0

There are 0 answers