Permalink
Browse files

DO NOT MERGE Control access to inherited methods of jsinterface objects

Bug: 7073422

Use a flag and annotation for allowing access to inherited methods of
jsinterface objects. When flag is false, no annotation is needed. When
flag is true, annotation is needed for allowing access to inherited methods.

Clean cherry pick of f2d8c5b

Change-Id: I226ef92e75df49293f6543abfcd17895abe76adc
  • Loading branch information...
1 parent 465864a commit 66ad15e4f5452b9275777e9284b3369cde8aa306 Selim Gurun committed Sep 4, 2012
@@ -206,7 +206,7 @@ JavaValue convertNPVariantToJavaValue(NPVariant value, const String& javaClass)
break;
}
- result.m_objectValue = adoptRef(new JavaInstanceJobject(javaArray));
+ result.m_objectValue = adoptRef(new JavaInstanceJobject(javaArray, false));
env->DeleteLocalRef(javaArray);
}
break;
@@ -421,15 +421,23 @@ void convertJavaValueToNPVariant(JavaValue value, NPVariant* result)
}
}
+#if PLATFORM(ANDROID)
+JavaValue jvalueToJavaValue(const jvalue& value, const JavaType& type, bool requireAnnotation)
+#else
JavaValue jvalueToJavaValue(const jvalue& value, const JavaType& type)
+#endif
{
JavaValue result;
result.m_type = type;
switch (result.m_type) {
case JavaTypeVoid:
break;
case JavaTypeObject:
+#if PLATFORM(ANDROID)
+ result.m_objectValue = new JavaInstanceJobject(value.l, requireAnnotation);
+#else
result.m_objectValue = new JavaInstanceJobject(value.l);
+#endif
break;
case JavaTypeString:
{
@@ -41,7 +41,11 @@ class JavaValue;
JavaValue convertNPVariantToJavaValue(NPVariant, const String& javaClass);
void convertJavaValueToNPVariant(JavaValue, NPVariant*);
+#if PLATFORM(ANDROID)
+JavaValue jvalueToJavaValue(const jvalue&, const JavaType&, bool requireAnnotation);
+#else
JavaValue jvalueToJavaValue(const jvalue&, const JavaType&);
+#endif
jvalue javaValueToJvalue(const JavaValue&);
} // namespace Bindings
@@ -33,7 +33,18 @@
using namespace JSC::Bindings;
+#if PLATFORM(ANDROID)
+const char kJavaScriptInterfaceAnnotation[] = "android/webkit/JavascriptInterface";
+const char kIsAnnotationPresent[] = "isAnnotationPresent";
+const char kGetMethods[] = "getMethods";
+
+static jclass safeAnnotationClazz = NULL;
+
+JavaClassJobject::JavaClassJobject(jobject anInstance, bool requireAnnotation)
+ : m_requireAnnotation(requireAnnotation)
+#else
JavaClassJobject::JavaClassJobject(jobject anInstance)
+#endif
{
jobject aClass = callJNIMethod<jobject>(anInstance, "getClass", "()Ljava/lang/Class;");
@@ -57,15 +68,28 @@ JavaClassJobject::JavaClassJobject(jobject anInstance)
// Get the methods
jarray methods = static_cast<jarray>(callJNIMethod<jobject>(aClass, "getMethods", "()[Ljava/lang/reflect/Method;"));
int numMethods = env->GetArrayLength(methods);
+#if PLATFORM(ANDROID)
+ jmethodID isAnnotationPresentMethodID = getAnnotationMethodID(env);
+ if (!isAnnotationPresentMethodID) {
+ LOG_ERROR("unable to find method %s on instance %p", kIsAnnotationPresent, anInstance);
+ return;
+ }
+#endif
for (int i = 0; i < numMethods; i++) {
jobject aJMethod = env->GetObjectArrayElement(static_cast<jobjectArray>(methods), i);
- JavaMethod* aMethod = new JavaMethodJobject(env, aJMethod); // deleted in the JavaClass destructor
- MethodList* methodList = m_methods.get(aMethod->name());
- if (!methodList) {
- methodList = new MethodList();
- m_methods.set(aMethod->name(), methodList);
+#if PLATFORM(ANDROID)
+ if (jsAccessAllowed(env, isAnnotationPresentMethodID, aJMethod)) {
+#endif
+ JavaMethod* aMethod = new JavaMethodJobject(env, aJMethod); // deleted in the JavaClass destructor
+ MethodList* methodList = m_methods.get(aMethod->name());
+ if (!methodList) {
+ methodList = new MethodList();
+ m_methods.set(aMethod->name(), methodList);
+ }
+ methodList->append(aMethod);
+#if PLATFORM(ANDROID)
}
- methodList->append(aMethod);
+#endif
env->DeleteLocalRef(aJMethod);
}
env->DeleteLocalRef(fields);
@@ -87,6 +111,44 @@ JavaClassJobject::~JavaClassJobject()
m_methods.clear();
}
+#if PLATFORM(ANDROID)
+bool JavaClassJobject::jsAccessAllowed(JNIEnv* env, jmethodID mid, jobject aJMethod)
+{
+ if (!m_requireAnnotation)
+ return true;
+ bool accessAllowed = env->CallBooleanMethod(aJMethod, mid, safeAnnotationClazz);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return false;
+ }
+ return accessAllowed;
+}
+
+jmethodID JavaClassJobject::getAnnotationMethodID(JNIEnv* env)
+{
+ jclass methodClass = env->FindClass("java/lang/reflect/Method");
+ jmethodID mid = 0;
+ if (methodClass)
+ mid = env->GetMethodID(methodClass, kIsAnnotationPresent, "(Ljava/lang/Class;)Z");
+ if (!methodClass || !mid) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ env->DeleteLocalRef(methodClass);
+ return mid;
+}
+
+bool JavaClassJobject::RegisterJavaClassJobject(JNIEnv* env) {
+ safeAnnotationClazz = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass(kJavaScriptInterfaceAnnotation)));
+ if (!safeAnnotationClazz) {
+ LOG_ERROR("failed to register %s", kJavaScriptInterfaceAnnotation);
+ return false;
+ }
+ return true;
+}
+#endif
+
MethodList JavaClassJobject::methodsNamed(const char* name) const
{
MethodList* methodList = m_methods.get(name);
@@ -37,17 +37,33 @@ namespace Bindings {
class JavaClassJobject : public JavaClass {
public:
+#if PLATFORM(ANDROID)
+ JavaClassJobject(jobject, bool);
+#else
JavaClassJobject(jobject);
+#endif
virtual ~JavaClassJobject();
// JavaClass implementation
virtual MethodList methodsNamed(const char* name) const;
virtual JavaField* fieldNamed(const char* name) const;
+#if PLATFORM(ANDROID)
+ static bool RegisterJavaClassJobject(JNIEnv* env);
+#endif
+
private:
+#if PLATFORM(ANDROID)
+ bool jsAccessAllowed(JNIEnv* env, jmethodID mid, jobject aJMethod);
+ jmethodID getAnnotationMethodID(JNIEnv* env);
+#endif
+
typedef HashMap<WTF::String, MethodList*> MethodListMap;
MethodListMap m_methods;
FieldMap m_fields;
+#if PLATFORM(ANDROID)
+ bool m_requireAnnotation;
+#endif
};
} // namespace Bindings
@@ -41,8 +41,15 @@
using namespace JSC::Bindings;
+#if PLATFORM(ANDROID)
+JavaInstanceJobject::JavaInstanceJobject(jobject instance, bool requireAnnotation)
+#else
JavaInstanceJobject::JavaInstanceJobject(jobject instance)
+#endif
: m_instance(new JobjectWrapper(instance))
+#if PLATFORM(ANDROID)
+ , m_requireAnnotation(requireAnnotation)
+#endif
{
}
@@ -61,7 +68,11 @@ void JavaInstanceJobject::end()
JavaClass* JavaInstanceJobject::getClass() const
{
if (!m_class)
+#if PLATFORM(ANDROID)
+ m_class = adoptPtr(new JavaClassJobject(javaInstance(), m_requireAnnotation));
+#else
m_class = adoptPtr(new JavaClassJobject(javaInstance()));
+#endif
return m_class.get();
}
@@ -86,7 +97,7 @@ JavaValue JavaInstanceJobject::invokeMethod(const JavaMethod* method, JavaValue*
return JavaValue();
}
- return jvalueToJavaValue(result, method->returnType());
+ return jvalueToJavaValue(result, method->returnType(), m_requireAnnotation);
// END ANDROID
}
@@ -113,7 +124,11 @@ JavaValue JavaInstanceJobject::getField(const JavaField* field)
appendClassName(signature, field->typeClassName());
signature.append(';');
}
+#if PLATFORM(ANDROID)
+ return jvalueToJavaValue(getJNIField(javaInstance(), field->type(), field->name().utf8().data(), signature.toString().utf8().data()), field->type(), m_requireAnnotation);
+#else
return jvalueToJavaValue(getJNIField(javaInstance(), field->type(), field->name().utf8().data(), signature.toString().utf8().data()), field->type());
+#endif
}
#endif // ENABLE(JAVA_BRIDGE)
@@ -48,8 +48,11 @@ namespace Bindings {
class JavaInstanceJobject : public JavaInstance {
public:
+#if PLATFORM(ANDROID)
+ JavaInstanceJobject(jobject instance, bool requireAnnotation);
+#else
JavaInstanceJobject(jobject instance);
-
+#endif
// JavaInstance implementation
virtual JavaClass* getClass() const;
// ANDROID
@@ -64,6 +67,9 @@ class JavaInstanceJobject : public JavaInstance {
protected:
RefPtr<JobjectWrapper> m_instance;
mutable OwnPtr<JavaClass> m_class;
+#if PLATFORM(ANDROID)
+ bool m_requireAnnotation;
+#endif
};
} // namespace Bindings
@@ -60,6 +60,7 @@
#include "IconDatabase.h"
#include "Image.h"
#include "InspectorClientAndroid.h"
+#include "JavaClassJobjectV8.h"
#include "JavaNPObjectV8.h"
#include "JavaInstanceJobjectV8.h"
#include "KURL.h"
@@ -1505,14 +1506,14 @@ static jobject StringByEvaluatingJavaScriptFromString(JNIEnv *env, jobject obj,
// and virtualEnd and swap the weak reference for the real object.
class WeakJavaInstance : public JavaInstanceJobject {
public:
- static PassRefPtr<WeakJavaInstance> create(jobject obj)
+ static PassRefPtr<WeakJavaInstance> create(jobject obj, bool requireAnnotation)
{
- return adoptRef(new WeakJavaInstance(obj));
+ return adoptRef(new WeakJavaInstance(obj, requireAnnotation));
}
private:
- WeakJavaInstance(jobject instance)
- : JavaInstanceJobject(instance)
+ WeakJavaInstance(jobject instance, bool requireAnnotation)
+ : JavaInstanceJobject(instance, requireAnnotation)
, m_beginEndDepth(0)
{
JNIEnv* env = getJNIEnv();
@@ -1569,7 +1570,7 @@ class WeakJavaInstance : public JavaInstanceJobject {
};
static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePointer,
- jobject javascriptObj, jstring interfaceName)
+ jobject javascriptObj, jstring interfaceName, jboolean requireAnnotation)
{
WebCore::Frame* pFrame = 0;
if (nativeFramePointer == 0)
@@ -1583,7 +1584,8 @@ static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePoi
ALOGV("::WebCore:: addJSInterface: %p", pFrame);
if (pFrame) {
- RefPtr<JavaInstance> addedObject = WeakJavaInstance::create(javascriptObj);
+ RefPtr<JavaInstance> addedObject = WeakJavaInstance::create(javascriptObj,
+ requireAnnotation);
const char* name = getCharactersFromJStringInEnv(env, interfaceName);
// Pass ownership of the added object to bindToWindowObject.
NPObject* npObject = JavaInstanceToNPObject(addedObject.get());
@@ -1951,7 +1953,7 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = {
(void*) Reload },
{ "nativeGoBackOrForward", "(I)V",
(void*) GoBackOrForward },
- { "nativeAddJavascriptInterface", "(ILjava/lang/Object;Ljava/lang/String;)V",
+ { "nativeAddJavascriptInterface", "(ILjava/lang/Object;Ljava/lang/String;Z)V",
(void*) AddJavascriptInterface },
{ "stringByEvaluatingJavaScriptFromString",
"(Ljava/lang/String;)Ljava/lang/String;",
@@ -1986,6 +1988,8 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = {
int registerWebFrame(JNIEnv* env)
{
+ JavaClassJobject::RegisterJavaClassJobject(env);
+
jclass clazz = env->FindClass("android/webkit/BrowserFrame");
ALOG_ASSERT(clazz, "Cannot find BrowserFrame");
gFrameField = env->GetFieldID(clazz, "mNativeFrame", "I");

0 comments on commit 66ad15e

Please sign in to comment.