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"
7 #include "base/android/jni_android.h"
9 #include "base/logging.h"
10 #include "jni/XWalkExtensionAndroid_jni.h"
11 #include "xwalk/extensions/common/xwalk_extension.h"
12 #include "xwalk/runtime/browser/xwalk_browser_main_parts_android.h"
13 #include "xwalk/runtime/browser/xwalk_content_browser_client.h"
16 namespace extensions {
18 XWalkExtensionAndroid::XWalkExtensionAndroid(JNIEnv* env, jobject obj,
19 jstring name, jstring js_api)
22 next_instance_id_(1) {
23 const char *str = env->GetStringUTFChars(name, 0);
25 env->ReleaseStringUTFChars(name, str);
27 str = env->GetStringUTFChars(js_api, 0);
28 set_javascript_api(str);
29 env->ReleaseStringUTFChars(js_api, str);
32 XWalkExtensionAndroid::~XWalkExtensionAndroid() {
33 // The |instances_| holds references to the instances created from this
34 // extension, but it doesn't own the object. The instance deletion is
35 // transferred to XWalkExtensionServer.
39 bool XWalkExtensionAndroid::is_valid() {
40 if (instances_.empty() || javascript_api().empty()) {
47 void XWalkExtensionAndroid::PostMessage(JNIEnv* env, jobject obj,
48 jint instance, jstring msg) {
49 if (!is_valid()) return;
51 InstanceMap::iterator it = instances_.find(instance);
52 if (it == instances_.end()) {
53 LOG(WARNING) << "Instance(" << instance << ") not found ";
57 const char* str = env->GetStringUTFChars(msg, 0);
58 it->second->PostMessageWrapper(str);
59 env->ReleaseStringUTFChars(msg, str);
62 void XWalkExtensionAndroid::BroadcastMessage(JNIEnv* env, jobject obj,
64 if (!is_valid()) return;
66 const char* str = env->GetStringUTFChars(msg, 0);
67 for (InstanceMap::iterator it = instances_.begin();
68 it != instances_.end(); ++it) {
69 it->second->PostMessageWrapper(str);
71 env->ReleaseStringUTFChars(msg, str);
74 void XWalkExtensionAndroid::DestroyExtension(JNIEnv* env, jobject obj) {
75 // Since XWalkExtensionServer owns this native object, and it won't be deleted
76 // at this point even if the corresponding Java-side object is destroyed.
77 // Instead, we only reset the java reference to the Java-side object and id
78 // counter. See comments in xwalk_extension_android.h.
80 next_instance_id_ = 1;
83 XWalkExtensionInstance* XWalkExtensionAndroid::CreateInstance() {
84 JNIEnv* env = base::android::AttachCurrentThread();
85 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
90 XWalkExtensionAndroidInstance* instance =
91 new XWalkExtensionAndroidInstance(this, java_ref_, next_instance_id_);
92 instances_[next_instance_id_] = instance;
96 // Here we return the raw pointer to its caller XWalkExtensionServer. Since
97 // XWalkExtensionServer has a map to maintain all instances created, the
98 // ownership is also transferred to XWalkExtensionServer so that the instance
99 // should be deleted by XWalkExtensionServer.
103 void XWalkExtensionAndroid::RemoveInstance(int instance) {
104 JNIEnv* env = base::android::AttachCurrentThread();
105 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
110 InstanceMap::iterator it = instances_.find(instance);
111 if (it == instances_.end()) {
112 LOG(WARNING) << "Instance(" << instance << ") not found ";
116 instances_.erase(instance);
119 void XWalkExtensionAndroid::BindToJavaObject(JNIEnv* env, jobject obj) {
120 JavaObjectWeakGlobalRef ref(env, obj);
124 XWalkExtensionAndroidInstance::XWalkExtensionAndroidInstance(
125 XWalkExtensionAndroid* extension,
126 const JavaObjectWeakGlobalRef& java_ref,
128 : extension_(extension),
133 XWalkExtensionAndroidInstance::~XWalkExtensionAndroidInstance() {
134 extension_->RemoveInstance(id_);
137 void XWalkExtensionAndroidInstance::HandleMessage(
138 scoped_ptr<base::Value> msg) {
141 if (!msg->GetAsString(&value)) {
145 JNIEnv* env = base::android::AttachCurrentThread();
146 jstring buffer = env->NewStringUTF(value.c_str());
147 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
149 LOG(ERROR) << "No valid Java object is referenced for message routing";
153 Java_XWalkExtensionAndroid_handleMessage(env, obj.obj(), getID(), buffer);
156 void XWalkExtensionAndroidInstance::HandleSyncMessage(
157 scoped_ptr<base::Value> msg) {
158 base::StringValue* ret_val = base::Value::CreateStringValue("");
161 if (!msg->GetAsString(&value)) {
162 SendSyncReplyToJS(scoped_ptr<base::Value>(ret_val));
166 JNIEnv* env = base::android::AttachCurrentThread();
167 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
169 LOG(ERROR) << "No valid Java object is referenced for sync message routing";
170 SendSyncReplyToJS(scoped_ptr<base::Value>(ret_val));
174 jstring buffer = env->NewStringUTF(value.c_str());
175 ScopedJavaLocalRef<jstring> ret =
176 Java_XWalkExtensionAndroid_handleSyncMessage(
177 env, obj.obj(), getID(), buffer);
179 const char *str = env->GetStringUTFChars(ret.obj(), 0);
180 ret_val = base::Value::CreateStringValue(str);
181 env->ReleaseStringUTFChars(ret.obj(), str);
183 SendSyncReplyToJS(scoped_ptr<base::Value>(ret_val));
186 static jint GetOrCreateExtension(JNIEnv* env, jobject obj,
187 jstring name, jstring js_api) {
188 xwalk::XWalkBrowserMainPartsAndroid* main_parts =
189 ToAndroidMainParts(XWalkContentBrowserClient::Get()->main_parts());
191 const char *str = env->GetStringUTFChars(name, 0);
192 XWalkExtension* extension = main_parts->LookupExtension(str);
193 env->ReleaseStringUTFChars(name, str);
195 // Create a new extension object if no existing one is found.
197 extension = new XWalkExtensionAndroid(env, obj, name, js_api);
198 main_parts->RegisterExtension(scoped_ptr<XWalkExtension>(extension));
200 static_cast<XWalkExtensionAndroid*>(extension)->BindToJavaObject(env, obj);
203 return reinterpret_cast<jint>(extension);
206 bool RegisterXWalkExtensionAndroid(JNIEnv* env) {
207 return RegisterNativesImpl(env) >= 0;
210 } // namespace extensions