1 // Copyright (c) 2013 Intel Corporation. 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.
5 #include "xwalk/extensions/common/android/xwalk_extension_android.h"
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_array.h"
11 #include "base/bind.h"
12 #include "base/logging.h"
13 #include "jni/XWalkExtensionAndroid_jni.h"
14 #include "xwalk/extensions/common/xwalk_extension.h"
15 #include "xwalk/runtime/browser/xwalk_browser_main_parts_android.h"
16 #include "xwalk/runtime/browser/xwalk_content_browser_client.h"
19 namespace extensions {
21 XWalkExtensionAndroid::XWalkExtensionAndroid(JNIEnv* env, jobject obj,
22 jstring name, jstring js_api,
23 jobjectArray js_entry_points)
26 next_instance_id_(1) {
27 const char *str = env->GetStringUTFChars(name, 0);
29 env->ReleaseStringUTFChars(name, str);
31 str = env->GetStringUTFChars(js_api, 0);
32 set_javascript_api(str);
33 env->ReleaseStringUTFChars(js_api, str);
35 std::vector<std::string> entry_points;
36 base::android::AppendJavaStringArrayToStringVector(
37 env, js_entry_points, &entry_points);
39 if (!entry_points.size())
42 set_entry_points(entry_points);
45 XWalkExtensionAndroid::~XWalkExtensionAndroid() {
46 // The |instances_| holds references to the instances created from this
47 // extension, but it doesn't own the object. The instance deletion is
48 // transferred to XWalkExtensionServer.
52 bool XWalkExtensionAndroid::is_valid() {
53 if (instances_.empty() || javascript_api().empty()) {
60 void XWalkExtensionAndroid::PostMessage(JNIEnv* env, jobject obj,
61 jint instance, jstring msg) {
62 if (!is_valid()) return;
64 InstanceMap::iterator it = instances_.find(instance);
65 if (it == instances_.end()) {
66 LOG(WARNING) << "Instance(" << instance << ") not found ";
70 const char* str = env->GetStringUTFChars(msg, 0);
71 it->second->PostMessageWrapper(str);
72 env->ReleaseStringUTFChars(msg, str);
75 void XWalkExtensionAndroid::BroadcastMessage(JNIEnv* env, jobject obj,
77 if (!is_valid()) return;
79 const char* str = env->GetStringUTFChars(msg, 0);
80 for (InstanceMap::iterator it = instances_.begin();
81 it != instances_.end(); ++it) {
82 it->second->PostMessageWrapper(str);
84 env->ReleaseStringUTFChars(msg, str);
87 void XWalkExtensionAndroid::DestroyExtension(JNIEnv* env, jobject obj) {
88 // Since XWalkExtensionServer owns this native object, and it won't be deleted
89 // at this point even if the corresponding Java-side object is destroyed.
90 // Instead, we only reset the java reference to the Java-side object and id
91 // counter. See comments in xwalk_extension_android.h.
93 next_instance_id_ = 1;
96 XWalkExtensionInstance* XWalkExtensionAndroid::CreateInstance() {
97 JNIEnv* env = base::android::AttachCurrentThread();
98 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
103 XWalkExtensionAndroidInstance* instance =
104 new XWalkExtensionAndroidInstance(this, java_ref_, next_instance_id_);
105 instances_[next_instance_id_] = instance;
109 // Here we return the raw pointer to its caller XWalkExtensionServer. Since
110 // XWalkExtensionServer has a map to maintain all instances created, the
111 // ownership is also transferred to XWalkExtensionServer so that the instance
112 // should be deleted by XWalkExtensionServer.
116 void XWalkExtensionAndroid::RemoveInstance(int instance) {
117 JNIEnv* env = base::android::AttachCurrentThread();
118 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
123 InstanceMap::iterator it = instances_.find(instance);
124 if (it == instances_.end()) {
125 LOG(WARNING) << "Instance(" << instance << ") not found ";
129 instances_.erase(instance);
132 void XWalkExtensionAndroid::BindToJavaObject(JNIEnv* env, jobject obj) {
133 JavaObjectWeakGlobalRef ref(env, obj);
137 XWalkExtensionAndroidInstance::XWalkExtensionAndroidInstance(
138 XWalkExtensionAndroid* extension,
139 const JavaObjectWeakGlobalRef& java_ref,
141 : extension_(extension),
146 XWalkExtensionAndroidInstance::~XWalkExtensionAndroidInstance() {
147 extension_->RemoveInstance(id_);
150 void XWalkExtensionAndroidInstance::HandleMessage(
151 scoped_ptr<base::Value> msg) {
154 if (!msg->GetAsString(&value)) {
158 JNIEnv* env = base::android::AttachCurrentThread();
159 ScopedJavaLocalRef<jstring> buffer(env, env->NewStringUTF(value.c_str()));
160 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
162 LOG(ERROR) << "No valid Java object is referenced for message routing";
166 Java_XWalkExtensionAndroid_handleMessage(
167 env, obj.obj(), getID(), buffer.obj());
170 void XWalkExtensionAndroidInstance::HandleSyncMessage(
171 scoped_ptr<base::Value> msg) {
172 base::StringValue* ret_val = base::Value::CreateStringValue("");
175 if (!msg->GetAsString(&value)) {
176 SendSyncReplyToJS(scoped_ptr<base::Value>(ret_val));
180 JNIEnv* env = base::android::AttachCurrentThread();
181 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
183 LOG(ERROR) << "No valid Java object is referenced for sync message routing";
184 SendSyncReplyToJS(scoped_ptr<base::Value>(ret_val));
188 ScopedJavaLocalRef<jstring> buffer(env, env->NewStringUTF(value.c_str()));
189 ScopedJavaLocalRef<jstring> ret =
190 Java_XWalkExtensionAndroid_handleSyncMessage(
191 env, obj.obj(), getID(), buffer.obj());
193 const char *str = env->GetStringUTFChars(ret.obj(), 0);
194 ret_val = base::Value::CreateStringValue(str);
195 env->ReleaseStringUTFChars(ret.obj(), str);
197 SendSyncReplyToJS(scoped_ptr<base::Value>(ret_val));
200 static jint GetOrCreateExtension(JNIEnv* env, jobject obj, jstring name,
201 jstring js_api, jobjectArray js_entry_points) {
202 xwalk::XWalkBrowserMainPartsAndroid* main_parts =
203 ToAndroidMainParts(XWalkContentBrowserClient::Get()->main_parts());
205 const char *str = env->GetStringUTFChars(name, 0);
206 XWalkExtension* extension = main_parts->LookupExtension(str);
207 env->ReleaseStringUTFChars(name, str);
209 // Create a new extension object if no existing one is found.
211 extension = new XWalkExtensionAndroid(env, obj, name,
212 js_api, js_entry_points);
213 main_parts->RegisterExtension(scoped_ptr<XWalkExtension>(extension));
215 static_cast<XWalkExtensionAndroid*>(extension)->BindToJavaObject(env, obj);
218 return reinterpret_cast<jint>(extension);
221 bool RegisterXWalkExtensionAndroid(JNIEnv* env) {
222 return RegisterNativesImpl(env) >= 0;
225 } // namespace extensions