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 #ifndef CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BOUND_OBJECT_H_
6 #define CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BOUND_OBJECT_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <map>
12 #include <memory>
13 #include <set>
14 
15 #include "base/android/jni_weak_ref.h"
16 #include "base/android/scoped_java_ref.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/values.h"
19 #include "content/browser/android/java/java_method.h"
20 
21 namespace content {
22 
23 class GinJavaBoundObject
24     : public base::RefCountedThreadSafe<GinJavaBoundObject> {
25  public:
26   typedef int32_t ObjectID;
27 
28   static GinJavaBoundObject* CreateNamed(
29       const JavaObjectWeakGlobalRef& ref,
30       const base::android::JavaRef<jclass>& safe_annotation_clazz);
31   static GinJavaBoundObject* CreateTransient(
32       const JavaObjectWeakGlobalRef& ref,
33       const base::android::JavaRef<jclass>& safe_annotation_clazz,
34       int32_t holder);
35 
36   // The following methods can be called on any thread.
GetWeakRef()37   JavaObjectWeakGlobalRef& GetWeakRef() { return ref_; }
GetLocalRef(JNIEnv * env)38   base::android::ScopedJavaLocalRef<jobject> GetLocalRef(JNIEnv* env) {
39     return ref_.get(env);
40   }
41 
IsNamed()42   bool IsNamed() { return names_count_ > 0; }
AddName()43   void AddName() { ++names_count_; }
RemoveName()44   void RemoveName() { --names_count_; }
45 
46   // The following methods are called on the background thread.
HasHolders()47   bool HasHolders() { return !holders_.empty(); }
AddHolder(int32_t holder)48   void AddHolder(int32_t holder) { holders_.insert(holder); }
RemoveHolder(int32_t holder)49   void RemoveHolder(int32_t holder) { holders_.erase(holder); }
50 
51   std::set<std::string> GetMethodNames();
52   bool HasMethod(const std::string& method_name);
53   const JavaMethod* FindMethod(const std::string& method_name,
54                                size_t num_parameters);
55   bool IsObjectGetClassMethod(const JavaMethod* method);
56   const base::android::JavaRef<jclass>& GetSafeAnnotationClass();
57   base::android::ScopedJavaLocalRef<jclass> GetLocalClassRef(JNIEnv* env);
58 
59  private:
60   friend class base::RefCountedThreadSafe<GinJavaBoundObject>;
61 
62   GinJavaBoundObject(
63       const JavaObjectWeakGlobalRef& ref,
64       const base::android::JavaRef<jclass>& safe_annotation_clazz);
65   GinJavaBoundObject(
66       const JavaObjectWeakGlobalRef& ref,
67       const base::android::JavaRef<jclass>& safe_annotation_clazz,
68       const std::set<int32_t>& holders);
69   ~GinJavaBoundObject();
70 
71   // The following methods are called on the background thread.
72   void EnsureMethodsAreSetUp();
73 
74   JavaObjectWeakGlobalRef ref_;
75 
76   // An object must be kept in retained_object_set_ either if it has
77   // names or if it has a non-empty holders set.
78   int names_count_;
79   std::set<int32_t> holders_;
80 
81   // The following fields are accessed on the background thread.
82   using JavaMethodMap = std::multimap<std::string, std::unique_ptr<JavaMethod>>;
83   JavaMethodMap methods_;
84   bool are_methods_set_up_;
85   base::android::ScopedJavaGlobalRef<jclass> safe_annotation_clazz_;
86 };
87 
88 }  // namespace content
89 
90 #endif  // CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BOUND_OBJECT_H_
91