Cherrypick: [Android] Java Bridge with Gin: implement Java Bridge dispatcher
Original description:
> This patch adds implementation for GinJavaBridgeDispatcherHost class, which
> is responsible for serving JB requests from renderers, and fulfilling
> them with help of GinJavaBoundObject instances.
>
> This patch also enables passing a error message for method invocation
> errors back to renderers, so they can use it when raising JavaScript
> exceptions.
>
> BUG=355644
>
> Review URL: https://codereview.chromium.org/345753003
>
> git-svn-id: svn://svn.chromium.org/chrome/trunk/src@280298 0039d316-1c4b-4281-b951-d872f2087c98
Also update Android makefiles for all platforms.
Bug: 13238305
Change-Id: I06f82ded53250c055147e33455dfbd20deb7a44f
diff --git a/content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc b/content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc
new file mode 100644
index 0000000..6c6e86b
--- /dev/null
+++ b/content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc
@@ -0,0 +1,497 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.h"
+
+#include "base/android/java_handler_thread.h"
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/lazy_instance.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner_util.h"
+#include "content/browser/renderer_host/java/gin_java_bound_object_delegate.h"
+#include "content/browser/renderer_host/java/jni_helper.h"
+#include "content/common/android/gin_java_bridge_value.h"
+#include "content/common/android/hash_set.h"
+#include "content/common/gin_java_bridge_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "ipc/ipc_message_utils.h"
+
+#if !defined(OS_ANDROID)
+#error "JavaBridge only supports OS_ANDROID"
+#endif
+
+namespace content {
+
+namespace {
+// The JavaBridge needs to use a Java thread so the callback
+// will happen on a thread with a prepared Looper.
+class JavaBridgeThread : public base::android::JavaHandlerThread {
+ public:
+ JavaBridgeThread() : base::android::JavaHandlerThread("JavaBridge") {
+ Start();
+ }
+ virtual ~JavaBridgeThread() {
+ Stop();
+ }
+};
+
+base::LazyInstance<JavaBridgeThread> g_background_thread =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+GinJavaBridgeDispatcherHost::GinJavaBridgeDispatcherHost(
+ WebContents* web_contents,
+ jobject retained_object_set)
+ : WebContentsObserver(web_contents),
+ retained_object_set_(base::android::AttachCurrentThread(),
+ retained_object_set),
+ allow_object_contents_inspection_(true) {
+ DCHECK(retained_object_set);
+}
+
+GinJavaBridgeDispatcherHost::~GinJavaBridgeDispatcherHost() {
+}
+
+void GinJavaBridgeDispatcherHost::RenderFrameCreated(
+ RenderFrameHost* render_frame_host) {
+ renderers_.insert(render_frame_host);
+ for (NamedObjectMap::const_iterator iter = named_objects_.begin();
+ iter != named_objects_.end();
+ ++iter) {
+ render_frame_host->Send(new GinJavaBridgeMsg_AddNamedObject(
+ render_frame_host->GetRoutingID(), iter->first, iter->second));
+ }
+}
+
+void GinJavaBridgeDispatcherHost::RenderFrameDeleted(
+ RenderFrameHost* render_frame_host) {
+ renderers_.erase(render_frame_host);
+ RemoveHolder(render_frame_host,
+ GinJavaBoundObject::ObjectMap::iterator(&objects_),
+ objects_.size());
+}
+
+GinJavaBoundObject::ObjectID GinJavaBridgeDispatcherHost::AddObject(
+ const base::android::JavaRef<jobject>& object,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz,
+ bool is_named,
+ RenderFrameHost* holder) {
+ DCHECK(is_named || holder);
+ GinJavaBoundObject::ObjectID object_id;
+ JNIEnv* env = base::android::AttachCurrentThread();
+ JavaObjectWeakGlobalRef ref(env, object.obj());
+ if (is_named) {
+ object_id = objects_.Add(new scoped_refptr<GinJavaBoundObject>(
+ GinJavaBoundObject::CreateNamed(ref, safe_annotation_clazz)));
+ } else {
+ object_id = objects_.Add(new scoped_refptr<GinJavaBoundObject>(
+ GinJavaBoundObject::CreateTransient(
+ ref, safe_annotation_clazz, holder)));
+ }
+#if DCHECK_IS_ON
+ {
+ GinJavaBoundObject::ObjectID added_object_id;
+ DCHECK(FindObjectId(object, &added_object_id));
+ DCHECK_EQ(object_id, added_object_id);
+ }
+#endif // DCHECK_IS_ON
+ base::android::ScopedJavaLocalRef<jobject> retained_object_set =
+ retained_object_set_.get(env);
+ if (!retained_object_set.is_null()) {
+ JNI_Java_HashSet_add(env, retained_object_set, object);
+ }
+ return object_id;
+}
+
+bool GinJavaBridgeDispatcherHost::FindObjectId(
+ const base::android::JavaRef<jobject>& object,
+ GinJavaBoundObject::ObjectID* object_id) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ for (GinJavaBoundObject::ObjectMap::iterator it(&objects_); !it.IsAtEnd();
+ it.Advance()) {
+ if (env->IsSameObject(
+ object.obj(),
+ it.GetCurrentValue()->get()->GetLocalRef(env).obj())) {
+ *object_id = it.GetCurrentKey();
+ return true;
+ }
+ }
+ return false;
+}
+
+JavaObjectWeakGlobalRef GinJavaBridgeDispatcherHost::GetObjectWeakRef(
+ GinJavaBoundObject::ObjectID object_id) {
+ scoped_refptr<GinJavaBoundObject>* result = objects_.Lookup(object_id);
+ scoped_refptr<GinJavaBoundObject> object(result ? *result : NULL);
+ if (object.get())
+ return object->GetWeakRef();
+ else
+ return JavaObjectWeakGlobalRef();
+}
+
+void GinJavaBridgeDispatcherHost::RemoveHolder(
+ RenderFrameHost* holder,
+ const GinJavaBoundObject::ObjectMap::iterator& from,
+ size_t count) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ base::android::ScopedJavaLocalRef<jobject> retained_object_set =
+ retained_object_set_.get(env);
+ size_t i = 0;
+ for (GinJavaBoundObject::ObjectMap::iterator it(from);
+ !it.IsAtEnd() && i < count;
+ it.Advance(), ++i) {
+ scoped_refptr<GinJavaBoundObject> object(*it.GetCurrentValue());
+ if (object->IsNamed())
+ continue;
+ object->RemoveHolder(holder);
+ if (!object->HasHolders()) {
+ if (!retained_object_set.is_null()) {
+ JNI_Java_HashSet_remove(
+ env, retained_object_set, object->GetLocalRef(env));
+ }
+ objects_.Remove(it.GetCurrentKey());
+ }
+ }
+}
+
+void GinJavaBridgeDispatcherHost::AddNamedObject(
+ const std::string& name,
+ const base::android::JavaRef<jobject>& object,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ GinJavaBoundObject::ObjectID object_id;
+ NamedObjectMap::iterator iter = named_objects_.find(name);
+ bool existing_object = FindObjectId(object, &object_id);
+ if (existing_object && iter != named_objects_.end() &&
+ iter->second == object_id) {
+ // Nothing to do.
+ return;
+ }
+ if (iter != named_objects_.end()) {
+ RemoveNamedObject(iter->first);
+ }
+ if (existing_object) {
+ (*objects_.Lookup(object_id))->AddName();
+ } else {
+ object_id = AddObject(object, safe_annotation_clazz, true, NULL);
+ }
+ named_objects_[name] = object_id;
+
+ for (RendererSet::iterator iter = renderers_.begin();
+ iter != renderers_.end(); ++iter) {
+ (*iter)->Send(new GinJavaBridgeMsg_AddNamedObject(
+ (*iter)->GetRoutingID(), name, object_id));
+ }
+}
+
+void GinJavaBridgeDispatcherHost::RemoveNamedObject(
+ const std::string& name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ NamedObjectMap::iterator iter = named_objects_.find(name);
+ if (iter == named_objects_.end())
+ return;
+
+ scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(iter->second));
+ named_objects_.erase(iter);
+ object->RemoveName();
+
+ // Not erasing from the objects map, as we can still receive method
+ // invocation requests for this object, and they should work until the
+ // java object is gone.
+ if (!object->IsNamed()) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ base::android::ScopedJavaLocalRef<jobject> retained_object_set =
+ retained_object_set_.get(env);
+ if (!retained_object_set.is_null()) {
+ JNI_Java_HashSet_remove(
+ env, retained_object_set, object->GetLocalRef(env));
+ }
+ }
+
+ for (RendererSet::iterator iter = renderers_.begin();
+ iter != renderers_.end(); ++iter) {
+ (*iter)->Send(new GinJavaBridgeMsg_RemoveNamedObject(
+ (*iter)->GetRoutingID(), name));
+ }
+}
+
+void GinJavaBridgeDispatcherHost::SetAllowObjectContentsInspection(bool allow) {
+ allow_object_contents_inspection_ = allow;
+}
+
+void GinJavaBridgeDispatcherHost::DocumentAvailableInMainFrame() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Called when the window object has been cleared in the main frame.
+ // That means, all sub-frames have also been cleared, so only named
+ // objects survived.
+ JNIEnv* env = base::android::AttachCurrentThread();
+ base::android::ScopedJavaLocalRef<jobject> retained_object_set =
+ retained_object_set_.get(env);
+ if (!retained_object_set.is_null()) {
+ JNI_Java_HashSet_clear(env, retained_object_set);
+ }
+
+ // We also need to add back the named objects we have so far as they
+ // should survive navigations.
+ for (GinJavaBoundObject::ObjectMap::iterator it(&objects_); !it.IsAtEnd();
+ it.Advance()) {
+ scoped_refptr<GinJavaBoundObject> object(*it.GetCurrentValue());
+ if (object->IsNamed()) {
+ if (!retained_object_set.is_null()) {
+ JNI_Java_HashSet_add(
+ env, retained_object_set, object->GetLocalRef(env));
+ }
+ } else {
+ objects_.Remove(it.GetCurrentKey());
+ }
+ }
+}
+
+namespace {
+
+// TODO(mnaganov): Implement passing of a parameter into sync message handlers.
+class MessageForwarder : public IPC::Sender {
+ public:
+ MessageForwarder(GinJavaBridgeDispatcherHost* gjbdh,
+ RenderFrameHost* render_frame_host)
+ : gjbdh_(gjbdh), render_frame_host_(render_frame_host) {}
+ void OnGetMethods(GinJavaBoundObject::ObjectID object_id,
+ IPC::Message* reply_msg) {
+ gjbdh_->OnGetMethods(render_frame_host_,
+ object_id,
+ reply_msg);
+ }
+ void OnHasMethod(GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ IPC::Message* reply_msg) {
+ gjbdh_->OnHasMethod(render_frame_host_,
+ object_id,
+ method_name,
+ reply_msg);
+ }
+ void OnInvokeMethod(GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ const base::ListValue& arguments,
+ IPC::Message* reply_msg) {
+ gjbdh_->OnInvokeMethod(render_frame_host_,
+ object_id,
+ method_name,
+ arguments,
+ reply_msg);
+ }
+ virtual bool Send(IPC::Message* msg) OVERRIDE {
+ NOTREACHED();
+ return false;
+ }
+ private:
+ GinJavaBridgeDispatcherHost* gjbdh_;
+ RenderFrameHost* render_frame_host_;
+};
+
+}
+
+bool GinJavaBridgeDispatcherHost::OnMessageReceived(
+ const IPC::Message& message,
+ RenderFrameHost* render_frame_host) {
+ DCHECK(render_frame_host);
+ bool handled = true;
+ MessageForwarder forwarder(this, render_frame_host);
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(GinJavaBridgeDispatcherHost, message,
+ render_frame_host)
+ IPC_MESSAGE_FORWARD_DELAY_REPLY(GinJavaBridgeHostMsg_GetMethods,
+ &forwarder,
+ MessageForwarder::OnGetMethods)
+ IPC_MESSAGE_FORWARD_DELAY_REPLY(GinJavaBridgeHostMsg_HasMethod,
+ &forwarder,
+ MessageForwarder::OnHasMethod)
+ IPC_MESSAGE_FORWARD_DELAY_REPLY(GinJavaBridgeHostMsg_InvokeMethod,
+ &forwarder,
+ MessageForwarder::OnInvokeMethod)
+ IPC_MESSAGE_HANDLER(GinJavaBridgeHostMsg_ObjectWrapperDeleted,
+ OnObjectWrapperDeleted)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void GinJavaBridgeDispatcherHost::SendReply(
+ RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (renderers_.find(render_frame_host) != renderers_.end()) {
+ render_frame_host->Send(reply_msg);
+ } else {
+ delete reply_msg;
+ }
+}
+
+void GinJavaBridgeDispatcherHost::OnGetMethods(
+ RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ IPC::Message* reply_msg) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(render_frame_host);
+ if (!allow_object_contents_inspection_) {
+ IPC::WriteParam(reply_msg, std::set<std::string>());
+ render_frame_host->Send(reply_msg);
+ return;
+ }
+ scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
+ if (!object) {
+ LOG(ERROR) << "WebView: Unknown object: " << object_id;
+ IPC::WriteParam(reply_msg, std::set<std::string>());
+ render_frame_host->Send(reply_msg);
+ return;
+ }
+ base::PostTaskAndReplyWithResult(
+ g_background_thread.Get().message_loop()->message_loop_proxy(),
+ FROM_HERE,
+ base::Bind(&GinJavaBoundObject::GetMethodNames, object),
+ base::Bind(&GinJavaBridgeDispatcherHost::SendMethods,
+ AsWeakPtr(),
+ render_frame_host,
+ reply_msg));
+}
+
+void GinJavaBridgeDispatcherHost::SendMethods(
+ RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg,
+ const std::set<std::string>& method_names) {
+ IPC::WriteParam(reply_msg, method_names);
+ SendReply(render_frame_host, reply_msg);
+}
+
+void GinJavaBridgeDispatcherHost::OnHasMethod(
+ RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ IPC::Message* reply_msg) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(render_frame_host);
+ scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
+ if (!object) {
+ LOG(ERROR) << "WebView: Unknown object: " << object_id;
+ IPC::WriteParam(reply_msg, false);
+ render_frame_host->Send(reply_msg);
+ return;
+ }
+ base::PostTaskAndReplyWithResult(
+ g_background_thread.Get().message_loop()->message_loop_proxy(),
+ FROM_HERE,
+ base::Bind(&GinJavaBoundObject::HasMethod, object, method_name),
+ base::Bind(&GinJavaBridgeDispatcherHost::SendHasMethodReply,
+ AsWeakPtr(),
+ render_frame_host,
+ reply_msg));
+}
+
+void GinJavaBridgeDispatcherHost::SendHasMethodReply(
+ RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg,
+ bool result) {
+ IPC::WriteParam(reply_msg, result);
+ SendReply(render_frame_host, reply_msg);
+}
+
+void GinJavaBridgeDispatcherHost::OnInvokeMethod(
+ RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ const base::ListValue& arguments,
+ IPC::Message* reply_msg) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(render_frame_host);
+ scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
+ if (!object) {
+ LOG(ERROR) << "WebView: Unknown object: " << object_id;
+ base::ListValue result;
+ result.Append(base::Value::CreateNullValue());
+ IPC::WriteParam(reply_msg, result);
+ IPC::WriteParam(reply_msg, kGinJavaBridgeUnknownObjectId);
+ render_frame_host->Send(reply_msg);
+ return;
+ }
+ scoped_refptr<GinJavaMethodInvocationHelper> result =
+ new GinJavaMethodInvocationHelper(
+ make_scoped_ptr(new GinJavaBoundObjectDelegate(object))
+ .PassAs<GinJavaMethodInvocationHelper::ObjectDelegate>(),
+ method_name,
+ arguments);
+ result->Init(this);
+ g_background_thread.Get()
+ .message_loop()
+ ->message_loop_proxy()
+ ->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&GinJavaMethodInvocationHelper::Invoke, result),
+ base::Bind(
+ &GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult,
+ AsWeakPtr(),
+ render_frame_host,
+ reply_msg,
+ result));
+}
+
+void GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult(
+ RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg,
+ scoped_refptr<GinJavaMethodInvocationHelper> result) {
+ if (result->HoldsPrimitiveResult()) {
+ IPC::WriteParam(reply_msg, result->GetPrimitiveResult());
+ IPC::WriteParam(reply_msg, result->GetInvocationError());
+ SendReply(render_frame_host, reply_msg);
+ } else {
+ ProcessMethodInvocationObjectResult(render_frame_host, reply_msg, result);
+ }
+}
+
+void GinJavaBridgeDispatcherHost::ProcessMethodInvocationObjectResult(
+ RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg,
+ scoped_refptr<GinJavaMethodInvocationHelper> result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (renderers_.find(render_frame_host) == renderers_.end()) {
+ delete reply_msg;
+ return;
+ }
+ base::ListValue wrapped_result;
+ if (!result->GetObjectResult().is_null()) {
+ GinJavaBoundObject::ObjectID returned_object_id;
+ if (FindObjectId(result->GetObjectResult(), &returned_object_id)) {
+ (*objects_.Lookup(returned_object_id))->AddHolder(render_frame_host);
+ } else {
+ returned_object_id = AddObject(result->GetObjectResult(),
+ result->GetSafeAnnotationClass(),
+ false,
+ render_frame_host);
+ }
+ wrapped_result.Append(
+ GinJavaBridgeValue::CreateObjectIDValue(returned_object_id).release());
+ } else {
+ wrapped_result.Append(base::Value::CreateNullValue());
+ }
+ IPC::WriteParam(reply_msg, wrapped_result);
+ IPC::WriteParam(reply_msg, result->GetInvocationError());
+ render_frame_host->Send(reply_msg);
+}
+
+void GinJavaBridgeDispatcherHost::OnObjectWrapperDeleted(
+ RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(render_frame_host);
+ if (objects_.Lookup(object_id)) {
+ GinJavaBoundObject::ObjectMap::iterator iter(&objects_);
+ while (!iter.IsAtEnd() && iter.GetCurrentKey() != object_id)
+ iter.Advance();
+ DCHECK(!iter.IsAtEnd());
+ RemoveHolder(render_frame_host, iter, 1);
+ }
+}
+
+} // namespace content
diff --git a/content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.h b/content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.h
new file mode 100644
index 0000000..d77da3a
--- /dev/null
+++ b/content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.h
@@ -0,0 +1,123 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_BRIDGE_DISPATCHER_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_BRIDGE_DISPATCHER_HOST_H_
+
+#include <map>
+#include <set>
+
+#include "base/android/jni_weak_ref.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/renderer_host/java/gin_java_bound_object.h"
+#include "content/browser/renderer_host/java/gin_java_method_invocation_helper.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace base {
+class ListValue;
+}
+
+namespace IPC {
+class Message;
+}
+
+namespace content {
+
+// This class handles injecting Java objects into a single RenderView. The Java
+// object itself lives in the browser process on a background thread, while a
+// proxy object is created in the renderer. An instance of this class exists
+// for each RenderFrameHost.
+class GinJavaBridgeDispatcherHost
+ : public base::SupportsWeakPtr<GinJavaBridgeDispatcherHost>,
+ public WebContentsObserver,
+ public GinJavaMethodInvocationHelper::DispatcherDelegate {
+ public:
+
+ GinJavaBridgeDispatcherHost(WebContents* web_contents,
+ jobject retained_object_set);
+ virtual ~GinJavaBridgeDispatcherHost();
+
+ void AddNamedObject(
+ const std::string& name,
+ const base::android::JavaRef<jobject>& object,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz);
+ void RemoveNamedObject(const std::string& name);
+ void SetAllowObjectContentsInspection(bool allow);
+
+ // WebContentsObserver
+ virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE;
+ virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE;
+ virtual void DocumentAvailableInMainFrame() OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ RenderFrameHost* render_frame_host) OVERRIDE;
+
+ // GinJavaMethodInvocationHelper::DispatcherDelegate
+ virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
+ GinJavaBoundObject::ObjectID object_id) OVERRIDE;
+
+ void OnGetMethods(RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ IPC::Message* reply_msg);
+ void OnHasMethod(RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ IPC::Message* reply_msg);
+ void OnInvokeMethod(RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ const base::ListValue& arguments,
+ IPC::Message* reply_msg);
+
+ private:
+ typedef std::set<RenderFrameHost*> RendererSet;
+ void OnObjectWrapperDeleted(RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id);
+
+ void SendReply(RenderFrameHost* render_frame_host, IPC::Message* reply_msg);
+ void SendMethods(RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg,
+ const std::set<std::string>& method_names);
+ void SendHasMethodReply(RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg,
+ bool result);
+ void ProcessMethodInvocationResult(
+ RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg,
+ scoped_refptr<GinJavaMethodInvocationHelper> result);
+ void ProcessMethodInvocationObjectResult(
+ RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg,
+ scoped_refptr<GinJavaMethodInvocationHelper> result);
+ GinJavaBoundObject::ObjectID AddObject(
+ const base::android::JavaRef<jobject>& object,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz,
+ bool is_named,
+ RenderFrameHost* holder);
+ bool FindObjectId(const base::android::JavaRef<jobject>& object,
+ GinJavaBoundObject::ObjectID* object_id);
+ void RemoveHolder(RenderFrameHost* holder,
+ const GinJavaBoundObject::ObjectMap::iterator& from,
+ size_t count);
+
+ // Every time a GinJavaBoundObject backed by a real Java object is
+ // created/destroyed, we insert/remove a strong ref to that Java object into
+ // this set so that it doesn't get garbage collected while it's still
+ // potentially in use. Although the set is managed native side, it's owned
+ // and defined in Java so that pushing refs into it does not create new GC
+ // roots that would prevent ContentViewCore from being garbage collected.
+ JavaObjectWeakGlobalRef retained_object_set_;
+ bool allow_object_contents_inspection_;
+ RendererSet renderers_;
+ GinJavaBoundObject::ObjectMap objects_;
+ typedef std::map<std::string, GinJavaBoundObject::ObjectID> NamedObjectMap;
+ NamedObjectMap named_objects_;
+
+ DISALLOW_COPY_AND_ASSIGN(GinJavaBridgeDispatcherHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_BRIDGE_DISPATCHER_HOST_H_
diff --git a/content/browser/renderer_host/java/gin_java_method_invocation_helper.cc b/content/browser/renderer_host/java/gin_java_method_invocation_helper.cc
index d3fb138..5c60ecf 100644
--- a/content/browser/renderer_host/java/gin_java_method_invocation_helper.cc
+++ b/content/browser/renderer_host/java/gin_java_method_invocation_helper.cc
@@ -23,13 +23,6 @@
namespace {
-const char kObjectIsGone[] = "Java object is gone";
-const char kMethodNotFound[] = "Method not found";
-const char kAccessToObjectGetClassIsBlocked[] =
- "Access to java.lang.Object.getClass is blocked";
-const char kJavaExceptionRaised[] =
- "Java exception has been raised during method invocation";
-
// See frameworks/base/core/java/android/webkit/EventLogTags.logtags
const int kObjectGetClassInvocationAttemptLogTag = 70151;
@@ -41,7 +34,8 @@
const base::ListValue& arguments)
: object_(object.Pass()),
method_name_(method_name),
- arguments_(arguments.DeepCopy()) {
+ arguments_(arguments.DeepCopy()),
+ invocation_error_(kGinJavaBridgeNoError) {
}
GinJavaMethodInvocationHelper::~GinJavaMethodInvocationHelper() {}
@@ -121,14 +115,14 @@
const JavaMethod* method =
object_->FindMethod(method_name_, arguments_->GetSize());
if (!method) {
- SetInvocationFailure(kMethodNotFound);
+ SetInvocationError(kGinJavaBridgeMethodNotFound);
return;
}
if (object_->IsObjectGetClassMethod(method)) {
base::android::EventLogWriteInt(kObjectGetClassInvocationAttemptLogTag,
getuid());
- SetInvocationFailure(kAccessToObjectGetClassIsBlocked);
+ SetInvocationError(kGinJavaBridgeAccessToObjectGetClassIsBlocked);
return;
}
@@ -140,7 +134,7 @@
obj = object_->GetLocalRef(env);
}
if (obj.is_null() && cls.is_null()) {
- SetInvocationFailure(kObjectIsGone);
+ SetInvocationError(kGinJavaBridgeObjectIsGone);
return;
}
@@ -166,11 +160,11 @@
}
}
-void GinJavaMethodInvocationHelper::SetInvocationFailure(
- const char* error_message) {
+void GinJavaMethodInvocationHelper::SetInvocationError(
+ GinJavaBridgeError error) {
holds_primitive_result_ = true;
primitive_result_.reset(new base::ListValue());
- error_message_ = error_message;
+ invocation_error_ = error;
}
void GinJavaMethodInvocationHelper::SetPrimitiveResult(
@@ -205,8 +199,8 @@
return safe_annotation_clazz_;
}
-const std::string& GinJavaMethodInvocationHelper::GetErrorMessage() {
- return error_message_;
+const GinJavaBridgeError GinJavaMethodInvocationHelper::GetInvocationError() {
+ return invocation_error_;
}
void GinJavaMethodInvocationHelper::InvokeMethod(jobject object,
@@ -295,7 +289,7 @@
// methods. ScopedJavaLocalRef is liable to make such calls, so we test
// first.
if (base::android::ClearException(env)) {
- SetInvocationFailure(kJavaExceptionRaised);
+ SetInvocationError(kGinJavaBridgeJavaExceptionRaised);
return;
}
ScopedJavaLocalRef<jstring> scoped_java_string(env, java_string);
@@ -318,7 +312,7 @@
object ? env->CallObjectMethodA(object, id, parameters)
: env->CallStaticObjectMethodA(clazz, id, parameters);
if (base::android::ClearException(env)) {
- SetInvocationFailure(kJavaExceptionRaised);
+ SetInvocationError(kGinJavaBridgeJavaExceptionRaised);
return;
}
ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object);
@@ -334,7 +328,7 @@
if (!base::android::ClearException(env)) {
SetPrimitiveResult(result_wrapper);
} else {
- SetInvocationFailure(kJavaExceptionRaised);
+ SetInvocationError(kGinJavaBridgeJavaExceptionRaised);
}
}
diff --git a/content/browser/renderer_host/java/gin_java_method_invocation_helper.h b/content/browser/renderer_host/java/gin_java_method_invocation_helper.h
index 89805ca..4cdb09b 100644
--- a/content/browser/renderer_host/java/gin_java_method_invocation_helper.h
+++ b/content/browser/renderer_host/java/gin_java_method_invocation_helper.h
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "content/browser/renderer_host/java/gin_java_bound_object.h"
#include "content/browser/renderer_host/java/java_type.h"
+#include "content/common/android/gin_java_bridge_errors.h"
#include "content/common/content_export.h"
namespace content {
@@ -68,7 +69,7 @@
const base::ListValue& GetPrimitiveResult();
const base::android::JavaRef<jobject>& GetObjectResult();
const base::android::JavaRef<jclass>& GetSafeAnnotationClass();
- const std::string& GetErrorMessage();
+ const GinJavaBridgeError GetInvocationError();
private:
friend class base::RefCountedThreadSafe<GinJavaMethodInvocationHelper>;
@@ -89,7 +90,7 @@
const JavaType& return_type,
jmethodID id,
jvalue* parameters);
- void SetInvocationFailure(const char* error_message);
+ void SetInvocationError(GinJavaBridgeError error);
void SetPrimitiveResult(const base::ListValue& result_wrapper);
void SetObjectResult(
const base::android::JavaRef<jobject>& object,
@@ -104,7 +105,7 @@
ObjectRefs object_refs_;
bool holds_primitive_result_;
scoped_ptr<base::ListValue> primitive_result_;
- std::string error_message_;
+ GinJavaBridgeError invocation_error_;
base::android::ScopedJavaGlobalRef<jobject> object_result_;
base::android::ScopedJavaGlobalRef<jclass> safe_annotation_clazz_;
diff --git a/content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc b/content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc
index d763441..067a5e1 100644
--- a/content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc
+++ b/content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc
@@ -5,6 +5,7 @@
#include "content/browser/renderer_host/java/gin_java_method_invocation_helper.h"
#include "base/android/jni_android.h"
+#include "content/browser/renderer_host/java/jni_helper.h"
#include "content/common/android/gin_java_bridge_value.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -154,21 +155,73 @@
counter.AssertInvocationsCount(1, 6);
}
+namespace {
+
+class ObjectIsGoneObjectDelegate : public NullObjectDelegate {
+ public:
+ ObjectIsGoneObjectDelegate() :
+ get_local_ref_called_(false) {
+ // We need a Java Method object to create a valid JavaMethod instance.
+ JNIEnv* env = base::android::AttachCurrentThread();
+ jmethodID method_id =
+ GetMethodIDFromClassName(env, "java/lang/Object", "hashCode", "()I");
+ EXPECT_TRUE(method_id);
+ base::android::ScopedJavaLocalRef<jobject> method_obj(
+ env,
+ env->ToReflectedMethod(
+ base::android::GetClass(env, "java/lang/Object").obj(),
+ method_id,
+ false));
+ EXPECT_TRUE(method_obj.obj());
+ method_.reset(new JavaMethod(method_obj));
+ }
+
+ virtual ~ObjectIsGoneObjectDelegate() {}
+
+ virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
+ JNIEnv* env) OVERRIDE {
+ get_local_ref_called_ = true;
+ return NullObjectDelegate::GetLocalRef(env);
+ }
+
+ virtual const JavaMethod* FindMethod(const std::string& method_name,
+ size_t num_parameters) OVERRIDE {
+ return method_.get();
+ }
+
+ bool get_local_ref_called() { return get_local_ref_called_; }
+
+ const std::string& get_method_name() { return method_->name(); }
+
+ protected:
+ scoped_ptr<JavaMethod> method_;
+ bool get_local_ref_called_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ObjectIsGoneObjectDelegate);
+};
+
+} // namespace
+
TEST_F(GinJavaMethodInvocationHelperTest, HandleObjectIsGone) {
base::ListValue no_objects;
+ ObjectIsGoneObjectDelegate* object_delegate =
+ new ObjectIsGoneObjectDelegate();
scoped_refptr<GinJavaMethodInvocationHelper> helper =
new GinJavaMethodInvocationHelper(
scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
- new NullObjectDelegate()),
- "foo",
+ object_delegate),
+ object_delegate->get_method_name(),
no_objects);
NullDispatcherDelegate dispatcher;
helper->Init(&dispatcher);
- EXPECT_TRUE(helper->GetErrorMessage().empty());
+ EXPECT_FALSE(object_delegate->get_local_ref_called());
+ EXPECT_EQ(kGinJavaBridgeNoError, helper->GetInvocationError());
helper->Invoke();
+ EXPECT_TRUE(object_delegate->get_local_ref_called());
EXPECT_TRUE(helper->HoldsPrimitiveResult());
EXPECT_TRUE(helper->GetPrimitiveResult().empty());
- EXPECT_FALSE(helper->GetErrorMessage().empty());
+ EXPECT_EQ(kGinJavaBridgeObjectIsGone, helper->GetInvocationError());
}
namespace {
@@ -215,12 +268,12 @@
NullDispatcherDelegate dispatcher;
helper->Init(&dispatcher);
EXPECT_FALSE(object_delegate->find_method_called());
- EXPECT_TRUE(helper->GetErrorMessage().empty());
+ EXPECT_EQ(kGinJavaBridgeNoError, helper->GetInvocationError());
helper->Invoke();
EXPECT_TRUE(object_delegate->find_method_called());
EXPECT_TRUE(helper->HoldsPrimitiveResult());
EXPECT_TRUE(helper->GetPrimitiveResult().empty());
- EXPECT_FALSE(helper->GetErrorMessage().empty());
+ EXPECT_EQ(kGinJavaBridgeMethodNotFound, helper->GetInvocationError());
}
namespace {
@@ -273,13 +326,14 @@
helper->Init(&dispatcher);
EXPECT_FALSE(object_delegate->find_method_called());
EXPECT_FALSE(object_delegate->get_class_called());
- EXPECT_TRUE(helper->GetErrorMessage().empty());
+ EXPECT_EQ(kGinJavaBridgeNoError, helper->GetInvocationError());
helper->Invoke();
EXPECT_TRUE(object_delegate->find_method_called());
EXPECT_TRUE(object_delegate->get_class_called());
EXPECT_TRUE(helper->HoldsPrimitiveResult());
EXPECT_TRUE(helper->GetPrimitiveResult().empty());
- EXPECT_FALSE(helper->GetErrorMessage().empty());
+ EXPECT_EQ(kGinJavaBridgeAccessToObjectGetClassIsBlocked,
+ helper->GetInvocationError());
}
} // namespace content
diff --git a/content/browser/renderer_host/java/java_method.h b/content/browser/renderer_host/java/java_method.h
index 1d59bac..6477263 100644
--- a/content/browser/renderer_host/java/java_method.h
+++ b/content/browser/renderer_host/java/java_method.h
@@ -11,12 +11,13 @@
#include "base/android/scoped_java_ref.h"
#include "content/browser/renderer_host/java/java_type.h"
+#include "content/common/content_export.h"
namespace content {
// Wrapper around java.lang.reflect.Method. This class must be used on a single
// thread only.
-class JavaMethod {
+class CONTENT_EXPORT JavaMethod {
public:
explicit JavaMethod(const base::android::JavaRef<jobject>& method);
~JavaMethod();
diff --git a/content/common/android/gin_java_bridge_errors.cc b/content/common/android/gin_java_bridge_errors.cc
new file mode 100644
index 0000000..7a80801
--- /dev/null
+++ b/content/common/android/gin_java_bridge_errors.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/android/gin_java_bridge_errors.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+const char* GinJavaBridgeErrorToString(GinJavaBridgeError error) {
+ switch (error) {
+ case kGinJavaBridgeNoError:
+ return "No error";
+ case kGinJavaBridgeUnknownObjectId:
+ return "Unknown Java object ID";
+ case kGinJavaBridgeObjectIsGone:
+ return "Java object is gone";
+ case kGinJavaBridgeMethodNotFound:
+ return "Method not found";
+ case kGinJavaBridgeAccessToObjectGetClassIsBlocked:
+ return "Access to java.lang.Object.getClass is blocked";
+ case kGinJavaBridgeJavaExceptionRaised:
+ return "Java exception was raised during method invocation";
+ }
+ NOTREACHED();
+ return "Unknown error";
+}
+
+} // namespace content
diff --git a/content/common/android/gin_java_bridge_errors.h b/content/common/android/gin_java_bridge_errors.h
new file mode 100644
index 0000000..75a8970
--- /dev/null
+++ b/content/common/android/gin_java_bridge_errors.h
@@ -0,0 +1,25 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_ANDROID_GIN_JAVA_BRIDGE_ERRORS_H_
+#define CONTENT_COMMON_ANDROID_GIN_JAVA_BRIDGE_ERRORS_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+enum GinJavaBridgeError {
+ kGinJavaBridgeNoError = 0,
+ kGinJavaBridgeUnknownObjectId,
+ kGinJavaBridgeObjectIsGone,
+ kGinJavaBridgeMethodNotFound,
+ kGinJavaBridgeAccessToObjectGetClassIsBlocked,
+ kGinJavaBridgeJavaExceptionRaised,
+};
+
+CONTENT_EXPORT const char* GinJavaBridgeErrorToString(GinJavaBridgeError error);
+
+} // namespace content
+
+#endif // CONTENT_COMMON_ANDROID_GIN_JAVA_BRIDGE_ERRORS_H_
diff --git a/content/common/gin_java_bridge_messages.h b/content/common/gin_java_bridge_messages.h
index f9525b1..cbce413 100644
--- a/content/common/gin_java_bridge_messages.h
+++ b/content/common/gin_java_bridge_messages.h
@@ -7,6 +7,7 @@
// Multiply-included message file, hence no include guard.
#include "base/basictypes.h"
+#include "content/common/android/gin_java_bridge_errors.h"
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
@@ -16,6 +17,8 @@
// Messages for handling Java objects injected into JavaScript -----------------
+IPC_ENUM_TRAITS(content::GinJavaBridgeError)
+
// Sent from browser to renderer to add a Java object with the given name.
// Object IDs are generated on the browser side.
IPC_MESSAGE_ROUTED2(GinJavaBridgeMsg_AddNamedObject,
@@ -45,14 +48,16 @@
// a container to work around immutability of base::Value.
// Empty result list indicates that an error has happened on the Java side
// (either bridge-induced error or an unhandled Java exception) and an exception
-// must be thrown into JavaScript.
+// must be thrown into JavaScript. |error_code| indicates the cause of
+// the error.
// Some special value types that are not supported by base::Value are encoded
// as BinaryValues via GinJavaBridgeValue.
-IPC_SYNC_MESSAGE_ROUTED3_1(GinJavaBridgeHostMsg_InvokeMethod,
+IPC_SYNC_MESSAGE_ROUTED3_2(GinJavaBridgeHostMsg_InvokeMethod,
int32 /* object_id */,
std::string /* method_name */,
base::ListValue /* arguments */,
- base::ListValue /* result */)
+ base::ListValue /* result */,
+ content::GinJavaBridgeError /* error_code */)
// Sent from renderer to browser in two cases:
//
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 33f796f..cf7c3d0 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1287,6 +1287,8 @@
'browser/renderer_host/java/gin_java_bound_object.h',
'browser/renderer_host/java/gin_java_bound_object_delegate.cc',
'browser/renderer_host/java/gin_java_bound_object_delegate.h',
+ 'browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc',
+ 'browser/renderer_host/java/gin_java_bridge_dispatcher_host.h',
'browser/renderer_host/java/gin_java_method_invocation_helper.cc',
'browser/renderer_host/java/gin_java_method_invocation_helper.h',
'browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc',
diff --git a/content/content_browser.target.darwin-arm.mk b/content/content_browser.target.darwin-arm.mk
index fd0b8b7..95780e7 100644
--- a/content/content_browser.target.darwin-arm.mk
+++ b/content/content_browser.target.darwin-arm.mk
@@ -512,6 +512,7 @@
content/browser/renderer_host/p2p/socket_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_bound_object.cc \
content/browser/renderer_host/java/gin_java_bound_object_delegate.cc \
+ content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_method_invocation_helper.cc \
content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc \
content/browser/renderer_host/java/java_bound_object.cc \
diff --git a/content/content_browser.target.darwin-arm64.mk b/content/content_browser.target.darwin-arm64.mk
index fc10a3d..ae4bdb4 100644
--- a/content/content_browser.target.darwin-arm64.mk
+++ b/content/content_browser.target.darwin-arm64.mk
@@ -512,6 +512,7 @@
content/browser/renderer_host/p2p/socket_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_bound_object.cc \
content/browser/renderer_host/java/gin_java_bound_object_delegate.cc \
+ content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_method_invocation_helper.cc \
content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc \
content/browser/renderer_host/java/java_bound_object.cc \
diff --git a/content/content_browser.target.darwin-mips.mk b/content/content_browser.target.darwin-mips.mk
index 73750d8..53b9496 100644
--- a/content/content_browser.target.darwin-mips.mk
+++ b/content/content_browser.target.darwin-mips.mk
@@ -512,6 +512,7 @@
content/browser/renderer_host/p2p/socket_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_bound_object.cc \
content/browser/renderer_host/java/gin_java_bound_object_delegate.cc \
+ content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_method_invocation_helper.cc \
content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc \
content/browser/renderer_host/java/java_bound_object.cc \
diff --git a/content/content_browser.target.darwin-x86.mk b/content/content_browser.target.darwin-x86.mk
index 8653900..b895015 100644
--- a/content/content_browser.target.darwin-x86.mk
+++ b/content/content_browser.target.darwin-x86.mk
@@ -512,6 +512,7 @@
content/browser/renderer_host/p2p/socket_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_bound_object.cc \
content/browser/renderer_host/java/gin_java_bound_object_delegate.cc \
+ content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_method_invocation_helper.cc \
content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc \
content/browser/renderer_host/java/java_bound_object.cc \
diff --git a/content/content_browser.target.darwin-x86_64.mk b/content/content_browser.target.darwin-x86_64.mk
index 0a53750..c5a2b73 100644
--- a/content/content_browser.target.darwin-x86_64.mk
+++ b/content/content_browser.target.darwin-x86_64.mk
@@ -512,6 +512,7 @@
content/browser/renderer_host/p2p/socket_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_bound_object.cc \
content/browser/renderer_host/java/gin_java_bound_object_delegate.cc \
+ content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_method_invocation_helper.cc \
content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc \
content/browser/renderer_host/java/java_bound_object.cc \
diff --git a/content/content_browser.target.linux-arm.mk b/content/content_browser.target.linux-arm.mk
index fd0b8b7..95780e7 100644
--- a/content/content_browser.target.linux-arm.mk
+++ b/content/content_browser.target.linux-arm.mk
@@ -512,6 +512,7 @@
content/browser/renderer_host/p2p/socket_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_bound_object.cc \
content/browser/renderer_host/java/gin_java_bound_object_delegate.cc \
+ content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_method_invocation_helper.cc \
content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc \
content/browser/renderer_host/java/java_bound_object.cc \
diff --git a/content/content_browser.target.linux-arm64.mk b/content/content_browser.target.linux-arm64.mk
index fc10a3d..ae4bdb4 100644
--- a/content/content_browser.target.linux-arm64.mk
+++ b/content/content_browser.target.linux-arm64.mk
@@ -512,6 +512,7 @@
content/browser/renderer_host/p2p/socket_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_bound_object.cc \
content/browser/renderer_host/java/gin_java_bound_object_delegate.cc \
+ content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_method_invocation_helper.cc \
content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc \
content/browser/renderer_host/java/java_bound_object.cc \
diff --git a/content/content_browser.target.linux-mips.mk b/content/content_browser.target.linux-mips.mk
index 73750d8..53b9496 100644
--- a/content/content_browser.target.linux-mips.mk
+++ b/content/content_browser.target.linux-mips.mk
@@ -512,6 +512,7 @@
content/browser/renderer_host/p2p/socket_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_bound_object.cc \
content/browser/renderer_host/java/gin_java_bound_object_delegate.cc \
+ content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_method_invocation_helper.cc \
content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc \
content/browser/renderer_host/java/java_bound_object.cc \
diff --git a/content/content_browser.target.linux-x86.mk b/content/content_browser.target.linux-x86.mk
index 8653900..b895015 100644
--- a/content/content_browser.target.linux-x86.mk
+++ b/content/content_browser.target.linux-x86.mk
@@ -512,6 +512,7 @@
content/browser/renderer_host/p2p/socket_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_bound_object.cc \
content/browser/renderer_host/java/gin_java_bound_object_delegate.cc \
+ content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_method_invocation_helper.cc \
content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc \
content/browser/renderer_host/java/java_bound_object.cc \
diff --git a/content/content_browser.target.linux-x86_64.mk b/content/content_browser.target.linux-x86_64.mk
index 0a53750..c5a2b73 100644
--- a/content/content_browser.target.linux-x86_64.mk
+++ b/content/content_browser.target.linux-x86_64.mk
@@ -512,6 +512,7 @@
content/browser/renderer_host/p2p/socket_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_bound_object.cc \
content/browser/renderer_host/java/gin_java_bound_object_delegate.cc \
+ content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.cc \
content/browser/renderer_host/java/gin_java_method_invocation_helper.cc \
content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc \
content/browser/renderer_host/java/java_bound_object.cc \
diff --git a/content/content_common.gypi b/content/content_common.gypi
index d74a4ac..341cfee 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -137,6 +137,8 @@
'common/android/address_parser_internal.h',
'common/android/common_jni_registrar.cc',
'common/android/common_jni_registrar.h',
+ 'common/android/gin_java_bridge_errors.cc',
+ 'common/android/gin_java_bridge_errors.h',
'common/android/gin_java_bridge_value.cc',
'common/android/gin_java_bridge_value.h',
'common/android/hash_set.cc',
diff --git a/content/content_common.target.darwin-arm.mk b/content/content_common.target.darwin-arm.mk
index 25026d9..fd96df0 100644
--- a/content/content_common.target.darwin-arm.mk
+++ b/content/content_common.target.darwin-arm.mk
@@ -82,6 +82,7 @@
content/common/android/address_parser.cc \
content/common/android/address_parser_internal.cc \
content/common/android/common_jni_registrar.cc \
+ content/common/android/gin_java_bridge_errors.cc \
content/common/android/gin_java_bridge_value.cc \
content/common/android/hash_set.cc \
content/common/android/surface_texture_lookup.cc \
diff --git a/content/content_common.target.darwin-arm64.mk b/content/content_common.target.darwin-arm64.mk
index 077977a..7287c55 100644
--- a/content/content_common.target.darwin-arm64.mk
+++ b/content/content_common.target.darwin-arm64.mk
@@ -82,6 +82,7 @@
content/common/android/address_parser.cc \
content/common/android/address_parser_internal.cc \
content/common/android/common_jni_registrar.cc \
+ content/common/android/gin_java_bridge_errors.cc \
content/common/android/gin_java_bridge_value.cc \
content/common/android/hash_set.cc \
content/common/android/surface_texture_lookup.cc \
diff --git a/content/content_common.target.darwin-mips.mk b/content/content_common.target.darwin-mips.mk
index ba18ded..4c55363 100644
--- a/content/content_common.target.darwin-mips.mk
+++ b/content/content_common.target.darwin-mips.mk
@@ -82,6 +82,7 @@
content/common/android/address_parser.cc \
content/common/android/address_parser_internal.cc \
content/common/android/common_jni_registrar.cc \
+ content/common/android/gin_java_bridge_errors.cc \
content/common/android/gin_java_bridge_value.cc \
content/common/android/hash_set.cc \
content/common/android/surface_texture_lookup.cc \
diff --git a/content/content_common.target.darwin-x86.mk b/content/content_common.target.darwin-x86.mk
index 2d10452..556a5c2 100644
--- a/content/content_common.target.darwin-x86.mk
+++ b/content/content_common.target.darwin-x86.mk
@@ -82,6 +82,7 @@
content/common/android/address_parser.cc \
content/common/android/address_parser_internal.cc \
content/common/android/common_jni_registrar.cc \
+ content/common/android/gin_java_bridge_errors.cc \
content/common/android/gin_java_bridge_value.cc \
content/common/android/hash_set.cc \
content/common/android/surface_texture_lookup.cc \
diff --git a/content/content_common.target.darwin-x86_64.mk b/content/content_common.target.darwin-x86_64.mk
index 53c092a..c5a1624 100644
--- a/content/content_common.target.darwin-x86_64.mk
+++ b/content/content_common.target.darwin-x86_64.mk
@@ -82,6 +82,7 @@
content/common/android/address_parser.cc \
content/common/android/address_parser_internal.cc \
content/common/android/common_jni_registrar.cc \
+ content/common/android/gin_java_bridge_errors.cc \
content/common/android/gin_java_bridge_value.cc \
content/common/android/hash_set.cc \
content/common/android/surface_texture_lookup.cc \
diff --git a/content/content_common.target.linux-arm.mk b/content/content_common.target.linux-arm.mk
index 25026d9..fd96df0 100644
--- a/content/content_common.target.linux-arm.mk
+++ b/content/content_common.target.linux-arm.mk
@@ -82,6 +82,7 @@
content/common/android/address_parser.cc \
content/common/android/address_parser_internal.cc \
content/common/android/common_jni_registrar.cc \
+ content/common/android/gin_java_bridge_errors.cc \
content/common/android/gin_java_bridge_value.cc \
content/common/android/hash_set.cc \
content/common/android/surface_texture_lookup.cc \
diff --git a/content/content_common.target.linux-arm64.mk b/content/content_common.target.linux-arm64.mk
index 077977a..7287c55 100644
--- a/content/content_common.target.linux-arm64.mk
+++ b/content/content_common.target.linux-arm64.mk
@@ -82,6 +82,7 @@
content/common/android/address_parser.cc \
content/common/android/address_parser_internal.cc \
content/common/android/common_jni_registrar.cc \
+ content/common/android/gin_java_bridge_errors.cc \
content/common/android/gin_java_bridge_value.cc \
content/common/android/hash_set.cc \
content/common/android/surface_texture_lookup.cc \
diff --git a/content/content_common.target.linux-mips.mk b/content/content_common.target.linux-mips.mk
index ba18ded..4c55363 100644
--- a/content/content_common.target.linux-mips.mk
+++ b/content/content_common.target.linux-mips.mk
@@ -82,6 +82,7 @@
content/common/android/address_parser.cc \
content/common/android/address_parser_internal.cc \
content/common/android/common_jni_registrar.cc \
+ content/common/android/gin_java_bridge_errors.cc \
content/common/android/gin_java_bridge_value.cc \
content/common/android/hash_set.cc \
content/common/android/surface_texture_lookup.cc \
diff --git a/content/content_common.target.linux-x86.mk b/content/content_common.target.linux-x86.mk
index 2d10452..556a5c2 100644
--- a/content/content_common.target.linux-x86.mk
+++ b/content/content_common.target.linux-x86.mk
@@ -82,6 +82,7 @@
content/common/android/address_parser.cc \
content/common/android/address_parser_internal.cc \
content/common/android/common_jni_registrar.cc \
+ content/common/android/gin_java_bridge_errors.cc \
content/common/android/gin_java_bridge_value.cc \
content/common/android/hash_set.cc \
content/common/android/surface_texture_lookup.cc \
diff --git a/content/content_common.target.linux-x86_64.mk b/content/content_common.target.linux-x86_64.mk
index 53c092a..c5a1624 100644
--- a/content/content_common.target.linux-x86_64.mk
+++ b/content/content_common.target.linux-x86_64.mk
@@ -82,6 +82,7 @@
content/common/android/address_parser.cc \
content/common/android/address_parser_internal.cc \
content/common/android/common_jni_registrar.cc \
+ content/common/android/gin_java_bridge_errors.cc \
content/common/android/gin_java_bridge_value.cc \
content/common/android/hash_set.cc \
content/common/android/surface_texture_lookup.cc \
diff --git a/content/renderer/java/gin_java_bridge_dispatcher.cc b/content/renderer/java/gin_java_bridge_dispatcher.cc
index 88d502e..9b999f2 100644
--- a/content/renderer/java/gin_java_bridge_dispatcher.cc
+++ b/content/renderer/java/gin_java_bridge_dispatcher.cc
@@ -114,14 +114,16 @@
scoped_ptr<base::Value> GinJavaBridgeDispatcher::InvokeJavaMethod(
ObjectID object_id,
const std::string& method_name,
- const base::ListValue& arguments) {
+ const base::ListValue& arguments,
+ GinJavaBridgeError* error) {
base::ListValue result_wrapper;
render_frame()->Send(
new GinJavaBridgeHostMsg_InvokeMethod(routing_id(),
object_id,
method_name,
arguments,
- &result_wrapper));
+ &result_wrapper,
+ error));
base::Value* result;
if (result_wrapper.Get(0, &result)) {
return scoped_ptr<base::Value>(result->DeepCopy());
diff --git a/content/renderer/java/gin_java_bridge_dispatcher.h b/content/renderer/java/gin_java_bridge_dispatcher.h
index 13c6777..efbd19f 100644
--- a/content/renderer/java/gin_java_bridge_dispatcher.h
+++ b/content/renderer/java/gin_java_bridge_dispatcher.h
@@ -12,6 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
+#include "content/common/android/gin_java_bridge_errors.h"
#include "content/public/renderer/render_frame_observer.h"
namespace blink {
@@ -50,7 +51,8 @@
bool HasJavaMethod(ObjectID object_id, const std::string& method_name);
scoped_ptr<base::Value> InvokeJavaMethod(ObjectID object_id,
const std::string& method_name,
- const base::ListValue& arguments);
+ const base::ListValue& arguments,
+ GinJavaBridgeError* error);
GinJavaBridgeObject* GetObject(ObjectID object_id);
void OnGinJavaBridgeObjectDeleted(ObjectID object_id);
diff --git a/content/renderer/java/gin_java_bridge_object.cc b/content/renderer/java/gin_java_bridge_object.cc
index a153f2a..d2a2b60 100644
--- a/content/renderer/java/gin_java_bridge_object.cc
+++ b/content/renderer/java/gin_java_bridge_object.cc
@@ -5,6 +5,7 @@
#include "content/renderer/java/gin_java_bridge_object.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/common/android/gin_java_bridge_errors.h"
#include "content/common/android/gin_java_bridge_value.h"
#include "content/public/renderer/v8_value_converter.h"
#include "content/renderer/java/gin_java_bridge_value_converter.h"
@@ -125,11 +126,12 @@
}
}
- scoped_ptr<base::Value> result =
- dispatcher_->InvokeJavaMethod(object_id_, name, arguments);
+ GinJavaBridgeError error;
+ scoped_ptr<base::Value> result = dispatcher_->InvokeJavaMethod(
+ object_id_, name, arguments, &error);
if (!result.get()) {
args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
- args->isolate(), kMethodInvocationErrorMessage)));
+ args->isolate(), GinJavaBridgeErrorToString(error))));
return v8::Undefined(args->isolate());
}
if (!result->IsType(base::Value::TYPE_BINARY)) {