Skip to content

Commit

Permalink
WIP: Support for Qihoo browser
Browse files Browse the repository at this point in the history
Current support for Qihoo browser isn't perfect.
For unkown reason, JavaScript codes might be evaluated in different
contexts of WebView so that global objects aren't shared.
However, this doesn't happen if we have a clean installation and try it
for the first time.

Since it is impossible to debug this browser, we simply choose not to
solve this problem in the near future.

Also, we fix version text in logs.
  • Loading branch information
JingMatrix committed Mar 18, 2024
1 parent 45dbb14 commit eff3c14
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 9 deletions.
5 changes: 4 additions & 1 deletion app/src/main/java/org/matrix/chromext/Chrome.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ object Chrome {
var isDev = false
var isEdge = false
var isMi = false
var isQihoo = false
var isSamsung = false
var isVivaldi = false
var isCocCoc = false
Expand All @@ -60,11 +61,13 @@ object Chrome {
isDev = packageName.endsWith("canary") || packageName.endsWith("dev")
isEdge = packageName.startsWith("com.microsoft.emmx")
isMi = packageName == "com.mi.globalbrowser" || packageName == "com.android.browser"
isQihoo = packageName == "com.qihoo.contents"
isSamsung = packageName.startsWith("com.sec.android.app.sbrowser")
isVivaldi = packageName == "com.vivaldi.browser"
@Suppress("DEPRECATION") val packageInfo = ctx.packageManager?.getPackageInfo(packageName, 0)
version = packageInfo?.versionName
Log.i("Package: ${packageName}, v${version}")
version = (if (version?.startsWith("v") == true) "" else "v") + version
Log.i("Package: ${packageName}, ${version}")

setupHttpCache(ctx)
saveRedirectCookie()
Expand Down
18 changes: 12 additions & 6 deletions app/src/main/java/org/matrix/chromext/MainHook.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ val supportedPackages =
class MainHook : IXposedHookLoadPackage, IXposedHookZygoteInit {
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
Log.d(lpparam.processName + " started")
if (lpparam.packageName == "org.matrix.chromext") {
return
}
if (lpparam.packageName == "org.matrix.chromext") return
if (supportedPackages.contains(lpparam.packageName)) {
lpparam.classLoader
.loadClass("org.chromium.ui.base.WindowAndroid")
Expand All @@ -75,12 +73,12 @@ class MainHook : IXposedHookLoadPackage, IXposedHookZygoteInit {
Chrome.isMi =
lpparam.packageName == "com.mi.globalbrowser" ||
lpparam.packageName == "com.android.browser"
Chrome.isQihoo = lpparam.packageName == "com.qihoo.contents"

if (ctx == null && Chrome.isMi) return
// Wait to get the browser context of Mi Browser

if (ctx != null && lpparam.packageName != "android") {
Chrome.init(ctx, ctx.packageName)
}
if (ctx != null && lpparam.packageName != "android") Chrome.init(ctx, ctx.packageName)

if (Chrome.isMi) {
WebViewHook.WebView = Chrome.load("com.miui.webkit.WebView")
Expand All @@ -90,6 +88,14 @@ class MainHook : IXposedHookLoadPackage, IXposedHookZygoteInit {
return
}

if (Chrome.isQihoo) {
WebViewHook.WebView = Chrome.load("com.qihoo.webkit.WebView")
WebViewHook.ViewClient = Chrome.load("com.qihoo.webkit.WebViewClient")
WebViewHook.ChromeClient = Chrome.load("com.qihoo.webkit.WebChromeClient")
hookWebView()
return
}

WebViewClient::class.java.declaredConstructors[0].hookAfter {
if (it.thisObject::class != WebViewClient::class) {
WebViewHook.ViewClient = it.thisObject::class.java
Expand Down
57 changes: 57 additions & 0 deletions app/src/main/java/org/matrix/chromext/hook/ContextMenu.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.PopupWindow
import android.widget.TextView
import de.robv.android.xposed.XC_MethodHook.Unhook
import java.lang.Class
import org.matrix.chromext.Chrome
Expand All @@ -20,6 +22,7 @@ import org.matrix.chromext.utils.*
object ContextMenuHook : BaseHook() {

val erudaMenuId = 31415926
private var textView: TextView? = null

private fun openEruda(url: String) {
if (WebViewHook.isInit) {
Expand Down Expand Up @@ -50,6 +53,7 @@ object ContextMenuHook : BaseHook() {
}

private var actionModeFinder: Unhook? = null
private var popupWindowFinder: Unhook? = null

private fun hookActionMode(cls: Class<*>) {
actionModeFinder?.unhook()
Expand All @@ -73,9 +77,62 @@ object ContextMenuHook : BaseHook() {
}
}

private fun hookPopupWindow(cls: Class<*>) {
popupWindowFinder?.unhook()
cls.declaredConstructors.first().hookAfter {
val ctx = it.args[0] as Context
Resource.enrich(ctx)
val popupWindow = it.thisObject as PopupWindow
val view = popupWindow.contentView
if (!(view is ViewGroup && view.getChildAt(0) is TextView)) return@hookAfter
val sampleView = view.getChildAt(0) as TextView
textView = TextView(ctx)
textView!!.setHorizontallyScrolling(true)
textView!!.setSingleLine(true)
textView!!.ellipsize = sampleView.ellipsize
textView!!.gravity = sampleView.gravity
textView!!.transformationMethod = sampleView.transformationMethod
textView!!.layoutParams = sampleView.layoutParams
textView!!.typeface = sampleView.typeface
textView!!.setOnClickListener {
openEruda(Chrome.getUrl()!!)
popupWindow.dismiss()
}
view.addView(textView!!, view.childCount)
}
}

override fun init() {
if (Chrome.isSamsung) {
hookActionMode(Chrome.load("com.sec.terrace.content.browser.TinActionModeCallback"))
} else if (Chrome.isQihoo) {
val WebViewExtensionClient = Chrome.load("com.qihoo.webkit.extension.WebViewExtensionClient")
popupWindowFinder =
WebViewExtensionClient.declaredConstructors.first().hookAfter {
val selectionMenuWrapper = it.thisObject
val showSelectionMenu =
findMethodOrNull(selectionMenuWrapper::class.java) { name == "showSelectionMenu" }
if (showSelectionMenu == null) return@hookAfter
val selectionMenu =
selectionMenuWrapper::class.java.declaredFields.first().get(selectionMenuWrapper)
val horizontalCustomPopupDialog =
selectionMenu::class
.java
.declaredFields
.find { it.type.superclass == PopupWindow::class.java }!!
.type
hookPopupWindow(horizontalCustomPopupDialog)
showSelectionMenu.hookAfter {
val view = it.args[0]
if (WebViewHook.WebView!!.isAssignableFrom(view::class.java)) Chrome.updateTab(view)
val url = Chrome.getUrl()!!
val titleId =
if (isChromeXtFrontEnd(url)) R.string.main_menu_developer_tools
else if (isUserScript(url)) R.string.main_menu_install_script
else R.string.main_menu_eruda_console
textView?.setText(titleId)
}
}
} else if (Chrome.isMi) {
val miuiFloatingSelectPopupWindow =
Chrome.load("com.miui.org.chromium.content.browser.miui.MiuiFloatingSelectPopupWindow")
Expand Down
14 changes: 12 additions & 2 deletions app/src/main/java/org/matrix/chromext/hook/WebView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.matrix.chromext.Listener
import org.matrix.chromext.script.Local
import org.matrix.chromext.script.ScriptDbManager
import org.matrix.chromext.utils.Log
import org.matrix.chromext.utils.findField
import org.matrix.chromext.utils.findMethod
import org.matrix.chromext.utils.hookAfter
import org.matrix.chromext.utils.hookBefore
Expand Down Expand Up @@ -53,7 +54,13 @@ object WebViewHook : BaseHook() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
records
.find {
it.get()?.invokeMethod { name == "getWebChromeClient" } == chromeClient
if (Chrome.isQihoo) {
val mProvider = findField(WebView!!) { name == "mProvider" }
mProvider.get(it.get())
} else {
it.get()
}
?.invokeMethod { name == "getWebChromeClient" } == chromeClient
}
?.get()
} else Chrome.getTab()
Expand Down Expand Up @@ -81,7 +88,10 @@ object WebViewHook : BaseHook() {

findMethod(ViewClient!!, true) { name == "onPageStarted" }
// public void onPageStarted (WebView view, String url, Bitmap favicon)
.hookAfter { onUpdateUrl(it.args[1] as String, it.args[0]) }
.hookAfter {
if (Chrome.isQihoo && it.thisObject::class.java.declaredMethods.size > 1) return@hookAfter
onUpdateUrl(it.args[1] as String, it.args[0])
}

findMethod(Activity::class.java) { name == "onStop" }
.hookBefore { ScriptDbManager.updateScriptStorage() }
Expand Down

0 comments on commit eff3c14

Please sign in to comment.