源码是AddJavascriptInterfaceDetector.java
接下来我们来看看是如何实现的
Detector.JavaPsiScanner
- 用于实现java源码检测的接口
- 取代了之前的Detector.JavaScanner
private static final String WEB_VIEW = "android.webkit.WebView";
private static final String ADD_JAVASCRIPT_INTERFACE = "addJavascriptInterface";
// ---- Implements JavaScanner ----
@Nullable
@Override
public List<String> getApplicableMethodNames() {
return Collections.singletonList(ADD_JAVASCRIPT_INTERFACE);
}
@Override
public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor,
@NonNull PsiMethodCallExpression node, @NonNull PsiMethod method) {
// Ignore the issue if we never build for any API less than 17.
if (context.getMainProject().getMinSdk() >= 17) {
return;
}
JavaEvaluator evaluator = context.getEvaluator();
if (!evaluator.methodMatches(method, WEB_VIEW, true, TYPE_OBJECT, TYPE_STRING)) {
return;
}
String message = "`WebView.addJavascriptInterface` should not be called with minSdkVersion < 17 for security reasons: " +
"JavaScript can use reflection to manipulate application";
context.report(ISSUE, node, context.getNameLocation(node), message);
}
核心代码
- getApplicableMethodNames()
这个方法用来返回你感兴趣的那些方法调用列表,所以这里设置
的是字符addJavascriptInterface,此方法配合以下方法使用
- visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression node, @NonNull PsiMethod method)
addJavascriptInterface被调用时,会触发此方法。
JavaContext 上下文
需要注意的一些方法
获取项目信息
Project project = context.getMainProject();获取项目build.gradle中配置的minSdkVersion
int minSdk= project.getMinSdk();
以上判断如果minSDK大于17则不显示提示JavaEvaluator
求值类
JavaEvaluator evaluator = context.getEvaluator();
接下来判断调用addJavascriptInterface的对象是不是Android系统提供的WebView
public boolean methodMatches(PsiMethod method,String className, boolean allowInherit,String... argumentTypes)
method
visitMethod中的method
className
addJavascriptInterface的类名如android.webkit.WebView
allowInherit
是否支持指定类的子类校验,比如WebView的子类
argumentTypes
指定方法中参数的类型
public void addJavascriptInterface(Object object, String name)
所以上面第一个参数为TYPE_OBJECT和TYPE_STRING
创建提示类Issue
Issue类提供了工厂方法创建issue
public static Issue create(String id,String briefDescription,String
explanation,Category category,int priority, Severity
severity,Implementation implementation)
id Issue的自定义名字,如: AddJavascriptInterfaceLogUtilsNotUsed
briefDescription ,explanation.描述性(不解释)
category 类型 如Category.USABILITY
priority 优先级(1-10)
severity 安全级别(Severity.ERROR报错)
implementation Issue的实现类,如 new Implementation( AddJavascriptInterfaceDetector.class, Scope.JAVA_FILE_SCOPE)),第一个参数为类名。
发送报告
Context(子类JavaContext,ClassContext)
public void report(Issue issue,Location location,String message)
- issue 用Issue.create创建的类
- location位置 context.getNameLocation(node)
- message 提示消息