tapjacking-browser-poc / app / src / main / java / com / beerphilipp / tapjacking / browser / CustomTabHelper.kt
CustomTabHelper.kt
Raw
package com.beerphilipp.tapjacking.browser

import android.content.ComponentName
import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.browser.customtabs.CustomTabsCallback
import androidx.browser.customtabs.CustomTabsClient
import androidx.browser.customtabs.CustomTabsServiceConnection
import androidx.browser.customtabs.CustomTabsSession


/**
 * CustomTabHandler is a class that manages the connection to the Custom Tabs service.
 *
 * see https://developer.chrome.com/docs/android/custom-tabs/guide-warmup-prefetch
 */
class CustomTabHelper {

    private var clientMap = mutableMapOf<String, CustomTabsClient>()
    private var sessionMap = mutableMapOf<String, CustomTabsSession>()

    companion object {
        private var instance: CustomTabHelper? = null
        fun getInstance(): CustomTabHelper {
            if (instance == null) {
                instance = CustomTabHelper()
            }
            return instance!!
        }
    }

    private val mConnection: CustomTabsServiceConnection = object : CustomTabsServiceConnection() {
        override fun onCustomTabsServiceConnected(
            name: ComponentName,
            client: CustomTabsClient
        ) {
            name.packageName.let {
                Log.e("CustomTabHandler", "Connected to $it")
                clientMap[it] = client
                // Warm up the browser process
                client.warmup(0 /* placeholder for future use */)
                // Create a new browser session
                sessionMap[it] = client.newSession(CustomTabsCallback())!!
                // Pre-render pages the user is likely to visit
                // you can do this any time while the service is connected
                sessionMap[it]!!.mayLaunchUrl(Uri.parse("https://webrtc.github.io/test-pages/src/iframe-video/"), null, null)
            }

        }

        override fun onServiceDisconnected(name: ComponentName) {
            name.packageName.let {
                clientMap.remove(it)
                sessionMap.remove(it)
            }
        }
    }

    fun bindCustomTabService(context: Context, packageName: String) {
        // Check for an existing connection
        clientMap[packageName]?.let {
            // Do nothing if there is an existing service connection
            return
        }

        val packages = ArrayList<String>()
        packages.add(packageName)

        // Get the default browser package name, this will be null if
        // the default browser does not provide a CustomTabsService
        val foundPackageName = CustomTabsClient.getPackageName(context, packages, true)
            ?: // Do nothing as service connection is not supported
            return
        CustomTabsClient.bindCustomTabsService(context, packageName, mConnection)
    }
}