Android WebView 技术原理
appium 是如何做 webview 自动化测试的
- chromedriver 启动
- chromedriver 根据 chrome option 完成对 android 手机的控制
- 利用 adb 寻找/proc/net/unix 下的 domain socket
- 根据 socket 名字中的 pid 寻找进程名,用于生成对应的 context 名字
- 利用 adb forward 将 domain socket 映射为到 pc 机器上的 tcp socket
- chromedriver 与 tcp socket(devtool 协议)交互
通过 UNIX domain sockets 发现 webview 进程
#getContextHandles的原理,webview进程
ceshiren.com: android-apidemos seveniruby$ adb shell cat /proc/net/unix | grep webview
Num RefCount Protocol Flags Type St Inode Path
0000000000000000: 00000002 00000000 00010000 0001 01 30196220 @webview_devtools_remote_19281
0000000000000000: 00000002 00000000 00010000 0001 01 30098752 @webview_devtools_remote_11395
0000000000000000: 00000003 00000000 00000000 0001 02 0 @webview_devtools_remote_11395
0000000000000000: 00000003 00000000 00000000 0001 02 0 @webview_devtools_remote_11395
0000000000000000: 00000003 00000000 00000000 0001 02 0 @webview_devtools_remote_11395
#浏览器进程
ceshiren.com: android-apidemos seveniruby$ adb shell cat /proc/net/unix | grep chrome
0000000000000000: 00000002 00000000 00010000 0001 01 28684857 @chrome_devtools_remote
0000000000000000: 00000003 00000000 00000000 0001 03 30273863 @chrome_devtools_remote
0000000000000000: 00000003 00000000 00000000 0001 03 30273858 @chrome_devtools_remote
0000000000000000: 00000003 00000000 00000000 0001 03 30273864 @chrome_devtools_remote
0000000000000000: 00000003 00000000 00000000 0001 03 30273865 @chrome_devtools_remote
查找所有的 webview 与浏览器开启的 domain sockets
ceshiren.com: android-apidemos seveniruby$ adb shell cat /proc/net/unix | awk 'NR==1 || /devtools/'
Num RefCount Protocol Flags Type St Inode Path
0000000000000000: 00000002 00000000 00010000 0001 01 30196220 @webview_devtools_remote_19281
0000000000000000: 00000002 00000000 00010000 0001 01 28684857 @chrome_devtools_remote
0000000000000000: 00000003 00000000 00000000 0001 03 30273863 @chrome_devtools_remote
0000000000000000: 00000003 00000000 00000000 0001 02 0 @webview_devtools_remote_19281
0000000000000000: 00000003 00000000 00000000 0001 03 30273858 @chrome_devtools_remote
0000000000000000: 00000003 00000000 00000000 0001 03 30273864 @chrome_devtools_remote
0000000000000000: 00000003 00000000 00000000 0001 02 0 @webview_devtools_remote_19281
0000000000000000: 00000003 00000000 00000000 0001 02 0 @webview_devtools_remote_19281
0000000000000000: 00000003 00000000 00000000 0001 03 30273865 @chrome_devtools_remote
0000000000000000: 00000003 00000000 00000000 0001 02 0 @webview_devtools_remote_19281
分析 domain socket 归属进程
ceshiren.com: android-apidemos seveniruby$ adb shell cat /proc/net/unix | grep webview
0000000000000000: 00000002 00000000 00010000 0001 01 30196220 @webview_devtools_remote_19281
ceshiren.com: android-apidemos seveniruby$ adb shell ps 19281
USER PID PPID VSZ RSS WCHAN ADDR S NAME
u0_a187 19281 699 6321568 161788 0 0 S io.appium.android.api
连接 domain sockets--context 切换的原理
#把domain socket映射为本地的socket端口
adb forward tcp:$port localabstract:webview_devtools_remote_$pid
adb forward tcp:9001 localabstract:webview_devtools_remote_19281
9001
domain sockets 的通讯协议分析
ceshiren.com: android-apidemos seveniruby$ curl http://localhost:9001/
<html><head><title>WebView remote debugging</title></head><body>Please use <a href='chrome://inspect'>chrome://inspect</a></body></html>
ceshiren.com: android-apidemos seveniruby$ curl http://localhost:9001/json
[ {
"description": "{\"attached\":true,\"empty\":false,\"height\":2408,\"never_attached\":false,\"screenX\":0,\"screenY\":292,\"visible\":true,\"width\":1228}",
"devtoolsFrontendUrl": "https://chrome-devtools-frontend.appspot.com/serve_rev/@30dcf3520abaf635bfb2064039f4078afd12cec7/inspector.html?ws=localhost:9001/devtools/page/51E00D7C2B3C8785879A63D98099B002",
"id": "51E00D7C2B3C8785879A63D98099B002",
"title": "I am a page title",
"type": "page",
"url": "file:///android_asset/html/index.html",
"webSocketDebuggerUrl": "ws://localhost:9001/devtools/page/51E00D7C2B3C8785879A63D98099B002"
} ]
系统内置与 app 内置 webview 的不同
#胸痛内置webview
ceshiren.com: android-apidemos seveniruby$ adb shell dumpsys package com.android.webview | grep versionName
ceshiren.com: android-apidemos seveniruby$ adb shell dumpsys package com.android.chrome | grep versionName
versionName=76.0.3809.132
#app使用的webview
ceshiren.com: android-apidemos seveniruby$ curl http://localhost:9001/json/version
{
"Android-Package": "io.appium.android.apis",
"Browser": "Chrome/88.0.4324.93",
"Protocol-Version": "1.3",
"User-Agent": "Mozilla/5.0 (Linux; Android 10; JAD-AL50 Build/HUAWEIJAD-AL50; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/88.0.4324.93 Mobile Safari/537.36",
"V8-Version": "8.8.278.14",
"WebKit-Version": "537.36 (@30dcf3520abaf635bfb2064039f4078afd12cec7)",
"webSocketDebuggerUrl": "ws://localhost:9001/devtools/browser"
}


总结
- 熟悉 webview 自动化测试的关键技术点
- 辅助 webview 测试问题排查
- chrome driver、devtools 是 webview 自动化测试的核心