- add sources.
[platform/framework/web/crosswalk.git] / src / base / android / scoped_java_ref.h
1 // Copyright (c) 2012 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 BASE_ANDROID_SCOPED_JAVA_REF_H_
6 #define BASE_ANDROID_SCOPED_JAVA_REF_H_
7
8 #include <jni.h>
9 #include <stddef.h>
10
11 #include "base/base_export.h"
12 #include "base/basictypes.h"
13
14 namespace base {
15 namespace android {
16
17 // Forward declare the generic java reference template class.
18 template<typename T> class JavaRef;
19
20 // Template specialization of JavaRef, which acts as the base class for all
21 // other JavaRef<> template types. This allows you to e.g. pass
22 // ScopedJavaLocalRef<jstring> into a function taking const JavaRef<jobject>&
23 template<>
24 class BASE_EXPORT JavaRef<jobject> {
25  public:
26   jobject obj() const { return obj_; }
27
28   bool is_null() const { return obj_ == NULL; }
29
30  protected:
31   // Initializes a NULL reference.
32   JavaRef();
33
34   // Takes ownership of the |obj| reference passed; requires it to be a local
35   // reference type.
36   JavaRef(JNIEnv* env, jobject obj);
37
38   ~JavaRef();
39
40   // The following are implementation detail convenience methods, for
41   // use by the sub-classes.
42   JNIEnv* SetNewLocalRef(JNIEnv* env, jobject obj);
43   void SetNewGlobalRef(JNIEnv* env, jobject obj);
44   void ResetLocalRef(JNIEnv* env);
45   void ResetGlobalRef();
46   jobject ReleaseInternal();
47
48  private:
49   jobject obj_;
50
51   DISALLOW_COPY_AND_ASSIGN(JavaRef);
52 };
53
54 // Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful
55 // for allowing functions to accept a reference without having to mandate
56 // whether it is a local or global type.
57 template<typename T>
58 class JavaRef : public JavaRef<jobject> {
59  public:
60   T obj() const { return static_cast<T>(JavaRef<jobject>::obj()); }
61
62  protected:
63   JavaRef() {}
64   ~JavaRef() {}
65
66   JavaRef(JNIEnv* env, T obj) : JavaRef<jobject>(env, obj) {}
67
68  private:
69   DISALLOW_COPY_AND_ASSIGN(JavaRef);
70 };
71
72 // Holds a local reference to a Java object. The local reference is scoped
73 // to the lifetime of this object.
74 // Instances of this class may hold onto any JNIEnv passed into it until
75 // destroyed. Therefore, since a JNIEnv is only suitable for use on a single
76 // thread, objects of this class must be created, used, and destroyed, on a
77 // single thread.
78 // Therefore, this class should only be used as a stack-based object and from a
79 // single thread. If you wish to have the reference outlive the current
80 // callstack (e.g. as a class member) or you wish to pass it across threads,
81 // use a ScopedJavaGlobalRef instead.
82 template<typename T>
83 class ScopedJavaLocalRef : public JavaRef<T> {
84  public:
85   ScopedJavaLocalRef() : env_(NULL) {}
86
87   // Non-explicit copy constructor, to allow ScopedJavaLocalRef to be returned
88   // by value as this is the normal usage pattern.
89   ScopedJavaLocalRef(const ScopedJavaLocalRef<T>& other)
90       : env_(other.env_) {
91     this->SetNewLocalRef(env_, other.obj());
92   }
93
94   template<typename U>
95   explicit ScopedJavaLocalRef(const U& other)
96       : env_(NULL) {
97     this->Reset(other);
98   }
99
100   // Assumes that |obj| is a local reference to a Java object and takes
101   // ownership  of this local reference.
102   ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef<T>(env, obj), env_(env) {}
103
104   ~ScopedJavaLocalRef() {
105     this->Reset();
106   }
107
108   // Overloaded assignment operator defined for consistency with the implicit
109   // copy constructor.
110   void operator=(const ScopedJavaLocalRef<T>& other) {
111     this->Reset(other);
112   }
113
114   void Reset() {
115     this->ResetLocalRef(env_);
116   }
117
118   template<typename U>
119   void Reset(const ScopedJavaLocalRef<U>& other) {
120     // We can copy over env_ here as |other| instance must be from the same
121     // thread as |this| local ref. (See class comment for multi-threading
122     // limitations, and alternatives).
123     this->Reset(other.env_, other.obj());
124   }
125
126   template<typename U>
127   void Reset(const U& other) {
128     // If |env_| was not yet set (is still NULL) it will be attached to the
129     // current thread in SetNewLocalRef().
130     this->Reset(env_, other.obj());
131   }
132
133   template<typename U>
134   void Reset(JNIEnv* env, U obj) {
135     implicit_cast<T>(obj);  // Ensure U is assignable to T
136     env_ = this->SetNewLocalRef(env, obj);
137   }
138
139   // Releases the local reference to the caller. The caller *must* delete the
140   // local reference when it is done with it.
141   T Release() {
142     return static_cast<T>(this->ReleaseInternal());
143   }
144
145  private:
146   // This class is only good for use on the thread it was created on so
147   // it's safe to cache the non-threadsafe JNIEnv* inside this object.
148   JNIEnv* env_;
149 };
150
151 // Holds a global reference to a Java object. The global reference is scoped
152 // to the lifetime of this object. This class does not hold onto any JNIEnv*
153 // passed to it, hence it is safe to use across threads (within the constraints
154 // imposed by the underlying Java object that it references).
155 template<typename T>
156 class ScopedJavaGlobalRef : public JavaRef<T> {
157  public:
158   ScopedJavaGlobalRef() {}
159
160   explicit ScopedJavaGlobalRef(const ScopedJavaGlobalRef<T>& other) {
161     this->Reset(other);
162   }
163
164   template<typename U>
165   explicit ScopedJavaGlobalRef(const U& other) {
166     this->Reset(other);
167   }
168
169   ~ScopedJavaGlobalRef() {
170     this->Reset();
171   }
172
173   void Reset() {
174     this->ResetGlobalRef();
175   }
176
177   template<typename U>
178   void Reset(const U& other) {
179     this->Reset(NULL, other.obj());
180   }
181
182   template<typename U>
183   void Reset(JNIEnv* env, U obj) {
184     implicit_cast<T>(obj);  // Ensure U is assignable to T
185     this->SetNewGlobalRef(env, obj);
186   }
187
188   // Releases the global reference to the caller. The caller *must* delete the
189   // global reference when it is done with it.
190   T Release() {
191     return static_cast<T>(this->ReleaseInternal());
192   }
193 };
194
195 }  // namespace android
196 }  // namespace base
197
198 #endif  // BASE_ANDROID_SCOPED_JAVA_REF_H_