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