From f3eb4b982ea6a1586583516b94b2fe739fd21e9c Mon Sep 17 00:00:00 2001 From: davinci9196 Date: Tue, 26 Nov 2024 16:56:35 +0800 Subject: [PATCH 1/2] MainActivity: Add Javascript interactive content --- .../gms/accountsettings/ui/MainActivity.kt | 130 +++++++++++++++++- .../gms/accountsettings/ui/WebViewHelper.kt | 6 + 2 files changed, 131 insertions(+), 5 deletions(-) diff --git a/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/MainActivity.kt b/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/MainActivity.kt index 7040c9dbed..c48b6112dd 100644 --- a/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/MainActivity.kt +++ b/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/MainActivity.kt @@ -7,18 +7,20 @@ package org.microg.gms.accountsettings.ui import android.accounts.Account import android.accounts.AccountManager +import android.content.Intent import android.os.Bundle -import android.text.TextUtils import android.util.Log import android.view.View +import android.view.inputmethod.InputMethodManager +import android.webkit.JavascriptInterface import android.webkit.WebView -import android.widget.FrameLayout import android.widget.ProgressBar import android.widget.RelativeLayout import android.widget.RelativeLayout.LayoutParams.MATCH_PARENT import android.widget.RelativeLayout.LayoutParams.WRAP_CONTENT import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.updateLayoutParams +import org.json.JSONException +import org.json.JSONObject import org.microg.gms.auth.AuthConstants import org.microg.gms.common.Constants @@ -95,6 +97,7 @@ private val SCREEN_ID_TO_URL = hashMapOf( 10729 to "https://myaccount.google.com/data-and-privacy/data-visibility", 10759 to "https://myaccount.google.com/address/home", 10760 to "https://myaccount.google.com/address/work", + 14500 to "https://profilewidgets.google.com/alternate-profile/edit?interop=o&opts=sb", ) private val ALLOWED_WEB_PREFIXES = setOf( @@ -114,7 +117,8 @@ private val ALLOWED_WEB_PREFIXES = setOf( "https://fit.google.com/privacy/settings", "https://maps.google.com/maps/timeline", "https://myadcenter.google.com/controls", - "https://families.google.com/kidonboarding" + "https://families.google.com/kidonboarding", + "https://profilewidgets.google.com/alternate-profile/edit", ) private val ACTION_TO_SCREEN_ID = hashMapOf( @@ -126,6 +130,7 @@ private val ACTION_TO_SCREEN_ID = hashMapOf( class MainActivity : AppCompatActivity() { private lateinit var webView: WebView + private var accountName: String? = null private fun getSelectedAccountName(): String? = null @@ -146,7 +151,7 @@ class MainActivity : AppCompatActivity() { val callingPackage = intent?.getStringExtra(EXTRA_CALLING_PACKAGE_NAME) ?: callingActivity?.packageName ?: Constants.GMS_PACKAGE_NAME val ignoreAccount = intent?.getBooleanExtra(EXTRA_IGNORE_ACCOUNT, false) ?: false - val accountName = if (ignoreAccount) null else { + accountName = if (ignoreAccount) null else { val accounts = AccountManager.get(this).getAccountsByType(AuthConstants.DEFAULT_ACCOUNT_TYPE) val accountName = intent.getStringExtra(EXTRA_ACCOUNT_NAME) ?: intent.getParcelableExtra("account")?.name ?: getSelectedAccountName() accounts.find { it.name.equals(accountName) }?.name @@ -175,6 +180,7 @@ class MainActivity : AppCompatActivity() { webView = WebView(this).apply { layoutParams = RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT) visibility = View.INVISIBLE + addJavascriptInterface(UiBridge(), "ocUi") } layout.addView(webView) setContentView(layout) @@ -198,4 +204,118 @@ class MainActivity : AppCompatActivity() { super.onBackPressed() } } + + private inner class UiBridge { + private var resultBundle: Bundle? = null + + @JavascriptInterface + fun close() { + Log.d(TAG, "close: ") + val intent = Intent() + if (resultBundle != null) { + intent.putExtras(resultBundle!!) + } + setResult(RESULT_OK, intent) + finish() + } + + @JavascriptInterface + fun closeWithResult(resultJsonStr: String?) { + Log.d(TAG, "closeWithResult: resultJsonStr -> $resultJsonStr") + setResult(resultJsonStr) + close() + } + + @JavascriptInterface + fun goBackOrClose() { + Log.d(TAG, "goBackOrClose: ") + onBackPressed() + } + + @JavascriptInterface + fun hideKeyboard() { + Log.d(TAG, "hideKeyboard: ") + val currentFocus = window.currentFocus + if (currentFocus != null) { + val inputMethodManager = this@MainActivity.getSystemService("input_method") as InputMethodManager? + inputMethodManager?.hideSoftInputFromWindow(currentFocus.windowToken, 0) + } + } + + @JavascriptInterface + fun isCloseWithResultSupported(): Boolean { + return true + } + + @JavascriptInterface + fun isOpenHelpEnabled(): Boolean { + return true + } + + @JavascriptInterface + fun isOpenScreenEnabled(): Boolean { + return true + } + + @JavascriptInterface + fun isSetResultSupported(): Boolean { + return true + } + + @JavascriptInterface + fun open(str: String?) { + Log.d(TAG, "open: str -> $str") + } + + @JavascriptInterface + fun openHelp(str: String?) { + Log.d(TAG, "openHelp: str -> $str") + } + + @JavascriptInterface + fun openScreen(screenId: Int, str: String?) { + Log.d(TAG, "openScreen: screenId -> $screenId str -> $str accountName -> $accountName") + val intent = Intent(this@MainActivity, MainActivity::class.java).apply { + putExtra(EXTRA_SCREEN_ID, screenId) + putExtra(EXTRA_ACCOUNT_NAME, accountName) + } + startActivity(intent) + } + + @JavascriptInterface + fun setBackStop() { + Log.d(TAG, "setBackStop: ") + webView.clearHistory() + } + + @JavascriptInterface + fun setResult(resultJsonStr: String?) { + Log.d(TAG, "setResult: resultJsonStr -> $resultJsonStr") + val map = jsonToMap(resultJsonStr) ?: return + resultBundle = Bundle().apply { + for ((key, value) in map) { + putString("result.$key", value) + } + } + } + + private fun jsonToMap(jsonStr: String?): Map? { + val hashMap = HashMap() + if (!jsonStr.isNullOrEmpty()) { + try { + val jSONObject = JSONObject(jsonStr) + val keys = jSONObject.keys() + while (keys.hasNext()) { + val next = keys.next() + val obj = jSONObject[next] + hashMap[next] = obj as String + } + } catch (e: JSONException) { + Log.d(TAG, "Unable to parse result JSON string", e) + return null + } + } + return hashMap + } + } } \ No newline at end of file diff --git a/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/WebViewHelper.kt b/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/WebViewHelper.kt index 71bebf9f90..ffbbf45367 100644 --- a/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/WebViewHelper.kt +++ b/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/WebViewHelper.kt @@ -20,6 +20,7 @@ import androidx.webkit.WebViewClientCompat import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.json.JSONObject import org.microg.gms.auth.AuthManager import org.microg.gms.common.Constants.GMS_PACKAGE_NAME import org.microg.gms.common.PackageUtils @@ -126,5 +127,10 @@ class WebViewHelper(private val activity: AppCompatActivity, private val webView settings.useWideViewPort = false settings.setSupportZoom(false) settings.javaScriptCanOpenWindowsAutomatically = false + settings.userAgentString = "${settings.userAgentString} ${ + String.format(Locale.getDefault(), "OcIdWebView (%s)", JSONObject().apply { + put("os", "Android") + }.toString()) + }" } } \ No newline at end of file From 1f77f97d9d21c3d9938adcb72df4695d3f1196d6 Mon Sep 17 00:00:00 2001 From: davinci9196 Date: Tue, 26 Nov 2024 17:48:00 +0800 Subject: [PATCH 2/2] cleanup --- .../kotlin/org/microg/gms/accountsettings/ui/MainActivity.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/MainActivity.kt b/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/MainActivity.kt index c48b6112dd..0393c06fb5 100644 --- a/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/MainActivity.kt +++ b/play-services-core/src/main/kotlin/org/microg/gms/accountsettings/ui/MainActivity.kt @@ -235,11 +235,6 @@ class MainActivity : AppCompatActivity() { @JavascriptInterface fun hideKeyboard() { Log.d(TAG, "hideKeyboard: ") - val currentFocus = window.currentFocus - if (currentFocus != null) { - val inputMethodManager = this@MainActivity.getSystemService("input_method") as InputMethodManager? - inputMethodManager?.hideSoftInputFromWindow(currentFocus.windowToken, 0) - } } @JavascriptInterface