summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSelim Gurun <sgurun@google.com>2012-09-04 16:31:02 -0700
committerSelim Gurun <sgurun@google.com>2012-10-08 14:11:06 -0700
commit66ad15e4f5452b9275777e9284b3369cde8aa306 (patch)
treeac6feeb9190793a53e1e3740f44afa5877a69dbf
parent465864a6d72a2505b7a725ddaadfff05cdece8fc (diff)
downloadexternal_webkit-66ad15e4f5452b9275777e9284b3369cde8aa306.zip
external_webkit-66ad15e4f5452b9275777e9284b3369cde8aa306.tar.gz
external_webkit-66ad15e4f5452b9275777e9284b3369cde8aa306.tar.bz2
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 f2d8c5bed31609d7d6e3ae77f33e90ea7f888eb3 Change-Id: I226ef92e75df49293f6543abfcd17895abe76adc
-rw-r--r--Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp10
-rw-r--r--Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h4
-rw-r--r--Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp74
-rw-r--r--Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.h16
-rw-r--r--Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp17
-rw-r--r--Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h8
-rw-r--r--Source/WebKit/android/jni/WebCoreFrameBridge.cpp18
7 files changed, 131 insertions, 16 deletions
diff --git a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp
index 15b4bda..c6e0a6c 100644
--- a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp
+++ b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp
@@ -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,7 +421,11 @@ 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;
@@ -429,7 +433,11 @@ JavaValue jvalueToJavaValue(const jvalue& value, const JavaType& 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:
{
diff --git a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h
index 0282904..47ee45a 100644
--- a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h
+++ b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h
@@ -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
diff --git a/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp b/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp
index 40bfd63..669eb49 100644
--- a/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp
+++ b/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp
@@ -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);
diff --git a/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.h b/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.h
index d27ca97..e4035aa 100644
--- a/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.h
+++ b/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.h
@@ -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
diff --git a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp
index e7b854d..c97a67f 100644
--- a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp
+++ b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp
@@ -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)
diff --git a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h
index 255c190..77dcf28 100644
--- a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h
+++ b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h
@@ -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 @@ public:
protected:
RefPtr<JobjectWrapper> m_instance;
mutable OwnPtr<JavaClass> m_class;
+#if PLATFORM(ANDROID)
+ bool m_requireAnnotation;
+#endif
};
} // namespace Bindings
diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
index 4ce3d8e..16d397a 100644
--- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
+++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
@@ -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 @@ private:
};
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");