OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/browser/renderer_host/java/gin_java_method_invocation_helper.h
" |
| 6 |
| 7 #include "base/android/jni_android.h" |
| 8 #include "content/common/android/gin_java_bridge_value.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 |
| 11 namespace content { |
| 12 |
| 13 namespace { |
| 14 |
| 15 class NullObjectDelegate |
| 16 : public GinJavaMethodInvocationHelper::ObjectDelegate { |
| 17 public: |
| 18 NullObjectDelegate() {} |
| 19 |
| 20 virtual ~NullObjectDelegate() {} |
| 21 |
| 22 virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef( |
| 23 JNIEnv* env) OVERRIDE { |
| 24 return base::android::ScopedJavaLocalRef<jobject>(); |
| 25 } |
| 26 |
| 27 virtual const JavaMethod* FindMethod(const std::string& method_name, |
| 28 size_t num_parameters) OVERRIDE { |
| 29 return NULL; |
| 30 } |
| 31 |
| 32 virtual bool IsObjectGetClassMethod(const JavaMethod* method) OVERRIDE { |
| 33 return false; |
| 34 } |
| 35 |
| 36 virtual const base::android::JavaRef<jclass>& GetSafeAnnotationClass() |
| 37 OVERRIDE { |
| 38 return safe_annotation_class_; |
| 39 } |
| 40 |
| 41 private: |
| 42 base::android::ScopedJavaLocalRef<jclass> safe_annotation_class_; |
| 43 |
| 44 DISALLOW_COPY_AND_ASSIGN(NullObjectDelegate); |
| 45 }; |
| 46 |
| 47 class NullDispatcherDelegate |
| 48 : public GinJavaMethodInvocationHelper::DispatcherDelegate { |
| 49 public: |
| 50 NullDispatcherDelegate() {} |
| 51 |
| 52 virtual ~NullDispatcherDelegate() {} |
| 53 |
| 54 virtual JavaObjectWeakGlobalRef GetObjectWeakRef( |
| 55 GinJavaBoundObject::ObjectID object_id) OVERRIDE { |
| 56 return JavaObjectWeakGlobalRef(); |
| 57 } |
| 58 |
| 59 DISALLOW_COPY_AND_ASSIGN(NullDispatcherDelegate); |
| 60 }; |
| 61 |
| 62 } // namespace |
| 63 |
| 64 class GinJavaMethodInvocationHelperTest : public testing::Test { |
| 65 }; |
| 66 |
| 67 namespace { |
| 68 |
| 69 class CountingDispatcherDelegate |
| 70 : public GinJavaMethodInvocationHelper::DispatcherDelegate { |
| 71 public: |
| 72 CountingDispatcherDelegate() {} |
| 73 |
| 74 virtual ~CountingDispatcherDelegate() {} |
| 75 |
| 76 virtual JavaObjectWeakGlobalRef GetObjectWeakRef( |
| 77 GinJavaBoundObject::ObjectID object_id) OVERRIDE { |
| 78 counters_[object_id]++; |
| 79 return JavaObjectWeakGlobalRef(); |
| 80 } |
| 81 |
| 82 void AssertInvocationsCount(GinJavaBoundObject::ObjectID begin_object_id, |
| 83 GinJavaBoundObject::ObjectID end_object_id) { |
| 84 EXPECT_EQ(end_object_id - begin_object_id, |
| 85 static_cast<int>(counters_.size())); |
| 86 for (GinJavaBoundObject::ObjectID i = begin_object_id; |
| 87 i < end_object_id; ++i) { |
| 88 EXPECT_LT(0, counters_[i]) << "ObjectID: " << i; |
| 89 } |
| 90 } |
| 91 |
| 92 private: |
| 93 typedef std::map<GinJavaBoundObject::ObjectID, int> Counters; |
| 94 Counters counters_; |
| 95 |
| 96 DISALLOW_COPY_AND_ASSIGN(CountingDispatcherDelegate); |
| 97 }; |
| 98 |
| 99 } // namespace |
| 100 |
| 101 TEST_F(GinJavaMethodInvocationHelperTest, RetrievalOfObjectsNoObjects) { |
| 102 base::ListValue no_objects; |
| 103 for (int i = 0; i < 10; ++i) { |
| 104 no_objects.AppendInteger(i); |
| 105 } |
| 106 |
| 107 scoped_refptr<GinJavaMethodInvocationHelper> helper = |
| 108 new GinJavaMethodInvocationHelper( |
| 109 scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>( |
| 110 new NullObjectDelegate()), |
| 111 "foo", |
| 112 no_objects); |
| 113 CountingDispatcherDelegate counter; |
| 114 helper->Init(&counter); |
| 115 counter.AssertInvocationsCount(0, 0); |
| 116 } |
| 117 |
| 118 TEST_F(GinJavaMethodInvocationHelperTest, RetrievalOfObjectsHaveObjects) { |
| 119 base::ListValue objects; |
| 120 objects.AppendInteger(100); |
| 121 objects.Append(GinJavaBridgeValue::CreateObjectIDValue(1).release()); |
| 122 base::ListValue* sub_list = new base::ListValue(); |
| 123 sub_list->AppendInteger(200); |
| 124 sub_list->Append(GinJavaBridgeValue::CreateObjectIDValue(2).release()); |
| 125 objects.Append(sub_list); |
| 126 base::DictionaryValue* sub_dict = new base::DictionaryValue(); |
| 127 sub_dict->SetInteger("1", 300); |
| 128 sub_dict->Set("2", GinJavaBridgeValue::CreateObjectIDValue(3).release()); |
| 129 objects.Append(sub_dict); |
| 130 base::ListValue* sub_list_with_dict = new base::ListValue(); |
| 131 base::DictionaryValue* sub_sub_dict = new base::DictionaryValue(); |
| 132 sub_sub_dict->Set("1", GinJavaBridgeValue::CreateObjectIDValue(4).release()); |
| 133 sub_list_with_dict->Append(sub_sub_dict); |
| 134 objects.Append(sub_list_with_dict); |
| 135 base::DictionaryValue* sub_dict_with_list = new base::DictionaryValue(); |
| 136 base::ListValue* sub_sub_list = new base::ListValue(); |
| 137 sub_sub_list->Append(GinJavaBridgeValue::CreateObjectIDValue(5).release()); |
| 138 sub_dict_with_list->Set("1", sub_sub_list); |
| 139 objects.Append(sub_dict_with_list); |
| 140 |
| 141 scoped_refptr<GinJavaMethodInvocationHelper> helper = |
| 142 new GinJavaMethodInvocationHelper( |
| 143 scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>( |
| 144 new NullObjectDelegate()), |
| 145 "foo", |
| 146 objects); |
| 147 CountingDispatcherDelegate counter; |
| 148 helper->Init(&counter); |
| 149 counter.AssertInvocationsCount(1, 6); |
| 150 } |
| 151 |
| 152 TEST_F(GinJavaMethodInvocationHelperTest, HandleObjectIsGone) { |
| 153 base::ListValue no_objects; |
| 154 scoped_refptr<GinJavaMethodInvocationHelper> helper = |
| 155 new GinJavaMethodInvocationHelper( |
| 156 scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>( |
| 157 new NullObjectDelegate()), |
| 158 "foo", |
| 159 no_objects); |
| 160 NullDispatcherDelegate dispatcher; |
| 161 helper->Init(&dispatcher); |
| 162 EXPECT_TRUE(helper->GetErrorMessage().empty()); |
| 163 helper->Invoke(); |
| 164 EXPECT_TRUE(helper->HoldsPrimitiveResult()); |
| 165 EXPECT_TRUE(helper->GetPrimitiveResult().empty()); |
| 166 EXPECT_FALSE(helper->GetErrorMessage().empty()); |
| 167 } |
| 168 |
| 169 namespace { |
| 170 |
| 171 class MethodNotFoundObjectDelegate : public NullObjectDelegate { |
| 172 public: |
| 173 MethodNotFoundObjectDelegate() : find_method_called_(false) {} |
| 174 |
| 175 virtual ~MethodNotFoundObjectDelegate() {} |
| 176 |
| 177 virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef( |
| 178 JNIEnv* env) OVERRIDE { |
| 179 return base::android::ScopedJavaLocalRef<jobject>( |
| 180 env, static_cast<jobject>(env->FindClass("java/lang/String"))); |
| 181 } |
| 182 |
| 183 virtual const JavaMethod* FindMethod(const std::string& method_name, |
| 184 size_t num_parameters) OVERRIDE { |
| 185 find_method_called_ = true; |
| 186 return NULL; |
| 187 } |
| 188 |
| 189 bool find_method_called() const { return find_method_called_; } |
| 190 |
| 191 protected: |
| 192 bool find_method_called_; |
| 193 |
| 194 private: |
| 195 DISALLOW_COPY_AND_ASSIGN(MethodNotFoundObjectDelegate); |
| 196 }; |
| 197 |
| 198 } // namespace |
| 199 |
| 200 TEST_F(GinJavaMethodInvocationHelperTest, HandleMethodNotFound) { |
| 201 base::ListValue no_objects; |
| 202 MethodNotFoundObjectDelegate* object_delegate = |
| 203 new MethodNotFoundObjectDelegate(); |
| 204 scoped_refptr<GinJavaMethodInvocationHelper> helper = |
| 205 new GinJavaMethodInvocationHelper( |
| 206 scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>( |
| 207 object_delegate), |
| 208 "foo", |
| 209 no_objects); |
| 210 NullDispatcherDelegate dispatcher; |
| 211 helper->Init(&dispatcher); |
| 212 EXPECT_FALSE(object_delegate->find_method_called()); |
| 213 EXPECT_TRUE(helper->GetErrorMessage().empty()); |
| 214 helper->Invoke(); |
| 215 EXPECT_TRUE(object_delegate->find_method_called()); |
| 216 EXPECT_TRUE(helper->HoldsPrimitiveResult()); |
| 217 EXPECT_TRUE(helper->GetPrimitiveResult().empty()); |
| 218 EXPECT_FALSE(helper->GetErrorMessage().empty()); |
| 219 } |
| 220 |
| 221 namespace { |
| 222 |
| 223 class GetClassObjectDelegate : public MethodNotFoundObjectDelegate { |
| 224 public: |
| 225 GetClassObjectDelegate() : get_class_called_(false) {} |
| 226 |
| 227 virtual ~GetClassObjectDelegate() {} |
| 228 |
| 229 virtual const JavaMethod* FindMethod(const std::string& method_name, |
| 230 size_t num_parameters) OVERRIDE { |
| 231 find_method_called_ = true; |
| 232 return kFakeGetClass; |
| 233 } |
| 234 |
| 235 virtual bool IsObjectGetClassMethod(const JavaMethod* method) OVERRIDE { |
| 236 get_class_called_ = true; |
| 237 return kFakeGetClass == method; |
| 238 } |
| 239 |
| 240 bool get_class_called() const { return get_class_called_; } |
| 241 |
| 242 private: |
| 243 static const JavaMethod* kFakeGetClass; |
| 244 bool get_class_called_; |
| 245 |
| 246 DISALLOW_COPY_AND_ASSIGN(GetClassObjectDelegate); |
| 247 }; |
| 248 |
| 249 // We don't expect GinJavaMethodInvocationHelper to actually invoke the |
| 250 // method, since the point of the test is to verify whether calls to |
| 251 // 'getClass' get blocked. |
| 252 const JavaMethod* GetClassObjectDelegate::kFakeGetClass = |
| 253 (JavaMethod*)0xdeadbeef; |
| 254 |
| 255 } // namespace |
| 256 |
| 257 TEST_F(GinJavaMethodInvocationHelperTest, HandleGetClassInvocation) { |
| 258 base::ListValue no_objects; |
| 259 GetClassObjectDelegate* object_delegate = |
| 260 new GetClassObjectDelegate(); |
| 261 scoped_refptr<GinJavaMethodInvocationHelper> helper = |
| 262 new GinJavaMethodInvocationHelper( |
| 263 scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>( |
| 264 object_delegate), |
| 265 "foo", |
| 266 no_objects); |
| 267 NullDispatcherDelegate dispatcher; |
| 268 helper->Init(&dispatcher); |
| 269 EXPECT_FALSE(object_delegate->find_method_called()); |
| 270 EXPECT_FALSE(object_delegate->get_class_called()); |
| 271 EXPECT_TRUE(helper->GetErrorMessage().empty()); |
| 272 helper->Invoke(); |
| 273 EXPECT_TRUE(object_delegate->find_method_called()); |
| 274 EXPECT_TRUE(object_delegate->get_class_called()); |
| 275 EXPECT_TRUE(helper->HoldsPrimitiveResult()); |
| 276 EXPECT_TRUE(helper->GetPrimitiveResult().empty()); |
| 277 EXPECT_FALSE(helper->GetErrorMessage().empty()); |
| 278 } |
| 279 |
| 280 } // namespace content |
OLD | NEW |