Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / android / java / gin_java_method_invocation_helper_unittest.cc
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/android/java/gin_java_method_invocation_helper.h"
6
7 #include "base/android/jni_android.h"
8 #include "content/browser/android/java/jni_helper.h"
9 #include "content/common/android/gin_java_bridge_value.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace content {
13
14 namespace {
15
16 class NullObjectDelegate
17     : public GinJavaMethodInvocationHelper::ObjectDelegate {
18  public:
19   NullObjectDelegate() {}
20
21   virtual ~NullObjectDelegate() {}
22
23   virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
24       JNIEnv* env) override {
25     return base::android::ScopedJavaLocalRef<jobject>();
26   }
27
28   virtual base::android::ScopedJavaLocalRef<jclass> GetLocalClassRef(
29       JNIEnv* env) override {
30     return base::android::ScopedJavaLocalRef<jclass>();
31   }
32
33   virtual const JavaMethod* FindMethod(const std::string& method_name,
34                                        size_t num_parameters) override {
35     return NULL;
36   }
37
38   virtual bool IsObjectGetClassMethod(const JavaMethod* method) override {
39     return false;
40   }
41
42   virtual const base::android::JavaRef<jclass>& GetSafeAnnotationClass()
43       override {
44     return safe_annotation_class_;
45   }
46
47  private:
48   base::android::ScopedJavaLocalRef<jclass> safe_annotation_class_;
49
50   DISALLOW_COPY_AND_ASSIGN(NullObjectDelegate);
51 };
52
53 class NullDispatcherDelegate
54     : public GinJavaMethodInvocationHelper::DispatcherDelegate {
55  public:
56   NullDispatcherDelegate() {}
57
58   virtual ~NullDispatcherDelegate() {}
59
60   virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
61       GinJavaBoundObject::ObjectID object_id) override {
62     return JavaObjectWeakGlobalRef();
63   }
64
65   DISALLOW_COPY_AND_ASSIGN(NullDispatcherDelegate);
66 };
67
68 }  // namespace
69
70 class GinJavaMethodInvocationHelperTest : public testing::Test {
71 };
72
73 namespace {
74
75 class CountingDispatcherDelegate
76     : public GinJavaMethodInvocationHelper::DispatcherDelegate {
77  public:
78   CountingDispatcherDelegate() {}
79
80   virtual ~CountingDispatcherDelegate() {}
81
82   virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
83       GinJavaBoundObject::ObjectID object_id) override {
84     counters_[object_id]++;
85     return JavaObjectWeakGlobalRef();
86   }
87
88   void AssertInvocationsCount(GinJavaBoundObject::ObjectID begin_object_id,
89                               GinJavaBoundObject::ObjectID end_object_id) {
90     EXPECT_EQ(end_object_id - begin_object_id,
91               static_cast<int>(counters_.size()));
92     for (GinJavaBoundObject::ObjectID i = begin_object_id;
93          i < end_object_id; ++i) {
94       EXPECT_LT(0, counters_[i]) << "ObjectID: " << i;
95     }
96   }
97
98  private:
99   typedef std::map<GinJavaBoundObject::ObjectID, int> Counters;
100   Counters counters_;
101
102   DISALLOW_COPY_AND_ASSIGN(CountingDispatcherDelegate);
103 };
104
105 }  // namespace
106
107 TEST_F(GinJavaMethodInvocationHelperTest, RetrievalOfObjectsNoObjects) {
108   base::ListValue no_objects;
109   for (int i = 0; i < 10; ++i) {
110     no_objects.AppendInteger(i);
111   }
112
113   scoped_refptr<GinJavaMethodInvocationHelper> helper =
114       new GinJavaMethodInvocationHelper(
115           scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
116               new NullObjectDelegate()),
117           "foo",
118           no_objects);
119   CountingDispatcherDelegate counter;
120   helper->Init(&counter);
121   counter.AssertInvocationsCount(0, 0);
122 }
123
124 TEST_F(GinJavaMethodInvocationHelperTest, RetrievalOfObjectsHaveObjects) {
125   base::ListValue objects;
126   objects.AppendInteger(100);
127   objects.Append(GinJavaBridgeValue::CreateObjectIDValue(1).release());
128   base::ListValue* sub_list = new base::ListValue();
129   sub_list->AppendInteger(200);
130   sub_list->Append(GinJavaBridgeValue::CreateObjectIDValue(2).release());
131   objects.Append(sub_list);
132   base::DictionaryValue* sub_dict = new base::DictionaryValue();
133   sub_dict->SetInteger("1", 300);
134   sub_dict->Set("2", GinJavaBridgeValue::CreateObjectIDValue(3).release());
135   objects.Append(sub_dict);
136   base::ListValue* sub_list_with_dict = new base::ListValue();
137   base::DictionaryValue* sub_sub_dict = new base::DictionaryValue();
138   sub_sub_dict->Set("1", GinJavaBridgeValue::CreateObjectIDValue(4).release());
139   sub_list_with_dict->Append(sub_sub_dict);
140   objects.Append(sub_list_with_dict);
141   base::DictionaryValue* sub_dict_with_list = new base::DictionaryValue();
142   base::ListValue* sub_sub_list = new base::ListValue();
143   sub_sub_list->Append(GinJavaBridgeValue::CreateObjectIDValue(5).release());
144   sub_dict_with_list->Set("1", sub_sub_list);
145   objects.Append(sub_dict_with_list);
146
147   scoped_refptr<GinJavaMethodInvocationHelper> helper =
148       new GinJavaMethodInvocationHelper(
149           scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
150               new NullObjectDelegate()),
151           "foo",
152           objects);
153   CountingDispatcherDelegate counter;
154   helper->Init(&counter);
155   counter.AssertInvocationsCount(1, 6);
156 }
157
158 namespace {
159
160 class ObjectIsGoneObjectDelegate : public NullObjectDelegate {
161  public:
162   ObjectIsGoneObjectDelegate() :
163       get_local_ref_called_(false) {
164     // We need a Java Method object to create a valid JavaMethod instance.
165     JNIEnv* env = base::android::AttachCurrentThread();
166     jmethodID method_id =
167         GetMethodIDFromClassName(env, "java/lang/Object", "hashCode", "()I");
168     EXPECT_TRUE(method_id);
169     base::android::ScopedJavaLocalRef<jobject> method_obj(
170         env,
171         env->ToReflectedMethod(
172             base::android::GetClass(env, "java/lang/Object").obj(),
173             method_id,
174             false));
175     EXPECT_TRUE(method_obj.obj());
176     method_.reset(new JavaMethod(method_obj));
177   }
178
179   virtual ~ObjectIsGoneObjectDelegate() {}
180
181   virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
182       JNIEnv* env) override {
183     get_local_ref_called_ = true;
184     return NullObjectDelegate::GetLocalRef(env);
185   }
186
187   virtual const JavaMethod* FindMethod(const std::string& method_name,
188                                        size_t num_parameters) override {
189     return method_.get();
190   }
191
192   bool get_local_ref_called() { return get_local_ref_called_; }
193
194   const std::string& get_method_name() { return method_->name(); }
195
196  protected:
197   scoped_ptr<JavaMethod> method_;
198   bool get_local_ref_called_;
199
200  private:
201   DISALLOW_COPY_AND_ASSIGN(ObjectIsGoneObjectDelegate);
202 };
203
204 }  // namespace
205
206 TEST_F(GinJavaMethodInvocationHelperTest, HandleObjectIsGone) {
207   base::ListValue no_objects;
208   ObjectIsGoneObjectDelegate* object_delegate =
209       new ObjectIsGoneObjectDelegate();
210   scoped_refptr<GinJavaMethodInvocationHelper> helper =
211       new GinJavaMethodInvocationHelper(
212           scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
213               object_delegate),
214           object_delegate->get_method_name(),
215           no_objects);
216   NullDispatcherDelegate dispatcher;
217   helper->Init(&dispatcher);
218   EXPECT_FALSE(object_delegate->get_local_ref_called());
219   EXPECT_EQ(kGinJavaBridgeNoError, helper->GetInvocationError());
220   helper->Invoke();
221   EXPECT_TRUE(object_delegate->get_local_ref_called());
222   EXPECT_TRUE(helper->HoldsPrimitiveResult());
223   EXPECT_TRUE(helper->GetPrimitiveResult().empty());
224   EXPECT_EQ(kGinJavaBridgeObjectIsGone, helper->GetInvocationError());
225 }
226
227 namespace {
228
229 class MethodNotFoundObjectDelegate : public NullObjectDelegate {
230  public:
231   MethodNotFoundObjectDelegate() : find_method_called_(false) {}
232
233   virtual ~MethodNotFoundObjectDelegate() {}
234
235   virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
236       JNIEnv* env) override {
237     return base::android::ScopedJavaLocalRef<jobject>(
238         env, static_cast<jobject>(env->FindClass("java/lang/String")));
239   }
240
241   virtual const JavaMethod* FindMethod(const std::string& method_name,
242                                        size_t num_parameters) override {
243     find_method_called_ = true;
244     return NULL;
245   }
246
247   bool find_method_called() const { return find_method_called_; }
248
249  protected:
250   bool find_method_called_;
251
252  private:
253   DISALLOW_COPY_AND_ASSIGN(MethodNotFoundObjectDelegate);
254 };
255
256 }  // namespace
257
258 TEST_F(GinJavaMethodInvocationHelperTest, HandleMethodNotFound) {
259   base::ListValue no_objects;
260   MethodNotFoundObjectDelegate* object_delegate =
261       new MethodNotFoundObjectDelegate();
262   scoped_refptr<GinJavaMethodInvocationHelper> helper =
263       new GinJavaMethodInvocationHelper(
264           scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
265               object_delegate),
266           "foo",
267           no_objects);
268   NullDispatcherDelegate dispatcher;
269   helper->Init(&dispatcher);
270   EXPECT_FALSE(object_delegate->find_method_called());
271   EXPECT_EQ(kGinJavaBridgeNoError, helper->GetInvocationError());
272   helper->Invoke();
273   EXPECT_TRUE(object_delegate->find_method_called());
274   EXPECT_TRUE(helper->HoldsPrimitiveResult());
275   EXPECT_TRUE(helper->GetPrimitiveResult().empty());
276   EXPECT_EQ(kGinJavaBridgeMethodNotFound, helper->GetInvocationError());
277 }
278
279 namespace {
280
281 class GetClassObjectDelegate : public MethodNotFoundObjectDelegate {
282  public:
283   GetClassObjectDelegate() : get_class_called_(false) {}
284
285   virtual ~GetClassObjectDelegate() {}
286
287   virtual const JavaMethod* FindMethod(const std::string& method_name,
288                                        size_t num_parameters) override {
289     find_method_called_ = true;
290     return kFakeGetClass;
291   }
292
293   virtual bool IsObjectGetClassMethod(const JavaMethod* method) override {
294     get_class_called_ = true;
295     return kFakeGetClass == method;
296   }
297
298   bool get_class_called() const { return get_class_called_; }
299
300  private:
301   static const JavaMethod* kFakeGetClass;
302   bool get_class_called_;
303
304   DISALLOW_COPY_AND_ASSIGN(GetClassObjectDelegate);
305 };
306
307 // We don't expect GinJavaMethodInvocationHelper to actually invoke the
308 // method, since the point of the test is to verify whether calls to
309 // 'getClass' get blocked.
310 const JavaMethod* GetClassObjectDelegate::kFakeGetClass =
311     (JavaMethod*)0xdeadbeef;
312
313 }  // namespace
314
315 TEST_F(GinJavaMethodInvocationHelperTest, HandleGetClassInvocation) {
316   base::ListValue no_objects;
317   GetClassObjectDelegate* object_delegate =
318       new GetClassObjectDelegate();
319   scoped_refptr<GinJavaMethodInvocationHelper> helper =
320       new GinJavaMethodInvocationHelper(
321           scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
322               object_delegate),
323           "foo",
324           no_objects);
325   NullDispatcherDelegate dispatcher;
326   helper->Init(&dispatcher);
327   EXPECT_FALSE(object_delegate->find_method_called());
328   EXPECT_FALSE(object_delegate->get_class_called());
329   EXPECT_EQ(kGinJavaBridgeNoError, helper->GetInvocationError());
330   helper->Invoke();
331   EXPECT_TRUE(object_delegate->find_method_called());
332   EXPECT_TRUE(object_delegate->get_class_called());
333   EXPECT_TRUE(helper->HoldsPrimitiveResult());
334   EXPECT_TRUE(helper->GetPrimitiveResult().empty());
335   EXPECT_EQ(kGinJavaBridgeAccessToObjectGetClassIsBlocked,
336             helper->GetInvocationError());
337 }
338
339 }  // namespace content