Index: content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc |
diff --git a/content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc b/content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..82267d8f6d0ce1d2e8ac9ea175517920700c5069 |
--- /dev/null |
+++ b/content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc |
@@ -0,0 +1,280 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/renderer_host/java/gin_java_method_invocation_helper.h" |
+ |
+#include "base/android/jni_android.h" |
+#include "content/common/android/gin_java_bridge_value.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+class NullObjectDelegate |
+ : public GinJavaMethodInvocationHelper::ObjectDelegate { |
+ public: |
+ NullObjectDelegate() {} |
+ |
+ virtual ~NullObjectDelegate() {} |
+ |
+ virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef( |
+ JNIEnv* env) OVERRIDE { |
+ return base::android::ScopedJavaLocalRef<jobject>(); |
+ } |
+ |
+ virtual const JavaMethod* FindMethod(const std::string& method_name, |
+ size_t num_parameters) OVERRIDE { |
+ return NULL; |
+ } |
+ |
+ virtual bool IsObjectGetClassMethod(const JavaMethod* method) OVERRIDE { |
+ return false; |
+ } |
+ |
+ virtual const base::android::JavaRef<jclass>& GetSafeAnnotationClass() |
+ OVERRIDE { |
+ return safe_annotation_class_; |
+ } |
+ |
+ private: |
+ base::android::ScopedJavaLocalRef<jclass> safe_annotation_class_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(NullObjectDelegate); |
+}; |
+ |
+class NullDispatcherDelegate |
+ : public GinJavaMethodInvocationHelper::DispatcherDelegate { |
+ public: |
+ NullDispatcherDelegate() {} |
+ |
+ virtual ~NullDispatcherDelegate() {} |
+ |
+ virtual JavaObjectWeakGlobalRef GetObjectWeakRef( |
+ GinJavaBoundObject::ObjectID object_id) OVERRIDE { |
+ return JavaObjectWeakGlobalRef(); |
+ } |
+ |
+ DISALLOW_COPY_AND_ASSIGN(NullDispatcherDelegate); |
+}; |
+ |
+} // namespace |
+ |
+class GinJavaMethodInvocationHelperTest : public testing::Test { |
+}; |
+ |
+namespace { |
+ |
+class CountingDispatcherDelegate |
+ : public GinJavaMethodInvocationHelper::DispatcherDelegate { |
+ public: |
+ CountingDispatcherDelegate() {} |
+ |
+ virtual ~CountingDispatcherDelegate() {} |
+ |
+ virtual JavaObjectWeakGlobalRef GetObjectWeakRef( |
+ GinJavaBoundObject::ObjectID object_id) OVERRIDE { |
+ counters_[object_id]++; |
+ return JavaObjectWeakGlobalRef(); |
+ } |
+ |
+ void AssertInvocationsCount(GinJavaBoundObject::ObjectID begin_object_id, |
+ GinJavaBoundObject::ObjectID end_object_id) { |
+ EXPECT_EQ(end_object_id - begin_object_id, |
+ static_cast<int>(counters_.size())); |
+ for (GinJavaBoundObject::ObjectID i = begin_object_id; |
+ i < end_object_id; ++i) { |
+ EXPECT_LT(0, counters_[i]) << "ObjectID: " << i; |
+ } |
+ } |
+ |
+ private: |
+ typedef std::map<GinJavaBoundObject::ObjectID, int> Counters; |
+ Counters counters_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(CountingDispatcherDelegate); |
+}; |
+ |
+} // namespace |
+ |
+TEST_F(GinJavaMethodInvocationHelperTest, RetrievalOfObjectsNoObjects) { |
+ base::ListValue no_objects; |
+ for (int i = 0; i < 10; ++i) { |
+ no_objects.AppendInteger(i); |
+ } |
+ |
+ scoped_refptr<GinJavaMethodInvocationHelper> helper = |
+ new GinJavaMethodInvocationHelper( |
+ scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>( |
+ new NullObjectDelegate()), |
+ "foo", |
+ no_objects); |
+ CountingDispatcherDelegate counter; |
+ helper->Init(&counter); |
+ counter.AssertInvocationsCount(0, 0); |
+} |
+ |
+TEST_F(GinJavaMethodInvocationHelperTest, RetrievalOfObjectsHaveObjects) { |
+ base::ListValue objects; |
+ objects.AppendInteger(100); |
+ objects.Append(GinJavaBridgeValue::CreateObjectIDValue(1).release()); |
+ base::ListValue* sub_list = new base::ListValue(); |
+ sub_list->AppendInteger(200); |
+ sub_list->Append(GinJavaBridgeValue::CreateObjectIDValue(2).release()); |
+ objects.Append(sub_list); |
+ base::DictionaryValue* sub_dict = new base::DictionaryValue(); |
+ sub_dict->SetInteger("1", 300); |
+ sub_dict->Set("2", GinJavaBridgeValue::CreateObjectIDValue(3).release()); |
+ objects.Append(sub_dict); |
+ base::ListValue* sub_list_with_dict = new base::ListValue(); |
+ base::DictionaryValue* sub_sub_dict = new base::DictionaryValue(); |
+ sub_sub_dict->Set("1", GinJavaBridgeValue::CreateObjectIDValue(4).release()); |
+ sub_list_with_dict->Append(sub_sub_dict); |
+ objects.Append(sub_list_with_dict); |
+ base::DictionaryValue* sub_dict_with_list = new base::DictionaryValue(); |
+ base::ListValue* sub_sub_list = new base::ListValue(); |
+ sub_sub_list->Append(GinJavaBridgeValue::CreateObjectIDValue(5).release()); |
+ sub_dict_with_list->Set("1", sub_sub_list); |
+ objects.Append(sub_dict_with_list); |
+ |
+ scoped_refptr<GinJavaMethodInvocationHelper> helper = |
+ new GinJavaMethodInvocationHelper( |
+ scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>( |
+ new NullObjectDelegate()), |
+ "foo", |
+ objects); |
+ CountingDispatcherDelegate counter; |
+ helper->Init(&counter); |
+ counter.AssertInvocationsCount(1, 6); |
+} |
+ |
+TEST_F(GinJavaMethodInvocationHelperTest, HandleObjectIsGone) { |
+ base::ListValue no_objects; |
+ scoped_refptr<GinJavaMethodInvocationHelper> helper = |
+ new GinJavaMethodInvocationHelper( |
+ scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>( |
+ new NullObjectDelegate()), |
+ "foo", |
+ no_objects); |
+ NullDispatcherDelegate dispatcher; |
+ helper->Init(&dispatcher); |
+ EXPECT_TRUE(helper->GetErrorMessage().empty()); |
+ helper->Invoke(); |
+ EXPECT_TRUE(helper->HoldsPrimitiveResult()); |
+ EXPECT_TRUE(helper->GetPrimitiveResult().empty()); |
+ EXPECT_FALSE(helper->GetErrorMessage().empty()); |
+} |
+ |
+namespace { |
+ |
+class MethodNotFoundObjectDelegate : public NullObjectDelegate { |
+ public: |
+ MethodNotFoundObjectDelegate() : find_method_called_(false) {} |
+ |
+ virtual ~MethodNotFoundObjectDelegate() {} |
+ |
+ virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef( |
+ JNIEnv* env) OVERRIDE { |
+ return base::android::ScopedJavaLocalRef<jobject>( |
+ env, static_cast<jobject>(env->FindClass("java/lang/String"))); |
+ } |
+ |
+ virtual const JavaMethod* FindMethod(const std::string& method_name, |
+ size_t num_parameters) OVERRIDE { |
+ find_method_called_ = true; |
+ return NULL; |
+ } |
+ |
+ bool find_method_called() const { return find_method_called_; } |
+ |
+ protected: |
+ bool find_method_called_; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(MethodNotFoundObjectDelegate); |
+}; |
+ |
+} // namespace |
+ |
+TEST_F(GinJavaMethodInvocationHelperTest, HandleMethodNotFound) { |
+ base::ListValue no_objects; |
+ MethodNotFoundObjectDelegate* object_delegate = |
+ new MethodNotFoundObjectDelegate(); |
+ scoped_refptr<GinJavaMethodInvocationHelper> helper = |
+ new GinJavaMethodInvocationHelper( |
+ scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>( |
+ object_delegate), |
+ "foo", |
+ no_objects); |
+ NullDispatcherDelegate dispatcher; |
+ helper->Init(&dispatcher); |
+ EXPECT_FALSE(object_delegate->find_method_called()); |
+ EXPECT_TRUE(helper->GetErrorMessage().empty()); |
+ helper->Invoke(); |
+ EXPECT_TRUE(object_delegate->find_method_called()); |
+ EXPECT_TRUE(helper->HoldsPrimitiveResult()); |
+ EXPECT_TRUE(helper->GetPrimitiveResult().empty()); |
+ EXPECT_FALSE(helper->GetErrorMessage().empty()); |
+} |
+ |
+namespace { |
+ |
+class GetClassObjectDelegate : public MethodNotFoundObjectDelegate { |
+ public: |
+ GetClassObjectDelegate() : get_class_called_(false) {} |
+ |
+ virtual ~GetClassObjectDelegate() {} |
+ |
+ virtual const JavaMethod* FindMethod(const std::string& method_name, |
+ size_t num_parameters) OVERRIDE { |
+ find_method_called_ = true; |
+ return kFakeGetClass; |
+ } |
+ |
+ virtual bool IsObjectGetClassMethod(const JavaMethod* method) OVERRIDE { |
+ get_class_called_ = true; |
+ return kFakeGetClass == method; |
+ } |
+ |
+ bool get_class_called() const { return get_class_called_; } |
+ |
+ private: |
+ static const JavaMethod* kFakeGetClass; |
+ bool get_class_called_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(GetClassObjectDelegate); |
+}; |
+ |
+// We don't expect GinJavaMethodInvocationHelper to actually invoke the |
+// method, since the point of the test is to verify whether calls to |
+// 'getClass' get blocked. |
+const JavaMethod* GetClassObjectDelegate::kFakeGetClass = |
+ (JavaMethod*)0xdeadbeef; |
+ |
+} // namespace |
+ |
+TEST_F(GinJavaMethodInvocationHelperTest, HandleGetClassInvocation) { |
+ base::ListValue no_objects; |
+ GetClassObjectDelegate* object_delegate = |
+ new GetClassObjectDelegate(); |
+ scoped_refptr<GinJavaMethodInvocationHelper> helper = |
+ new GinJavaMethodInvocationHelper( |
+ scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>( |
+ object_delegate), |
+ "foo", |
+ no_objects); |
+ NullDispatcherDelegate dispatcher; |
+ helper->Init(&dispatcher); |
+ EXPECT_FALSE(object_delegate->find_method_called()); |
+ EXPECT_FALSE(object_delegate->get_class_called()); |
+ EXPECT_TRUE(helper->GetErrorMessage().empty()); |
+ helper->Invoke(); |
+ EXPECT_TRUE(object_delegate->find_method_called()); |
+ EXPECT_TRUE(object_delegate->get_class_called()); |
+ EXPECT_TRUE(helper->HoldsPrimitiveResult()); |
+ EXPECT_TRUE(helper->GetPrimitiveResult().empty()); |
+ EXPECT_FALSE(helper->GetErrorMessage().empty()); |
+} |
+ |
+} // namespace content |