| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.h" | 5 #include "content/browser/renderer_host/java/gin_java_bridge_dispatcher_host.h" |
| 6 | 6 |
| 7 #include "base/android/java_handler_thread.h" | 7 #include "base/android/java_handler_thread.h" |
| 8 #include "base/android/jni_android.h" | 8 #include "base/android/jni_android.h" |
| 9 #include "base/android/scoped_java_ref.h" | 9 #include "base/android/scoped_java_ref.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "base/task_runner_util.h" | 13 #include "base/task_runner_util.h" |
| 14 #include "content/browser/renderer_host/java/gin_java_bound_object_delegate.h" | 14 #include "content/browser/renderer_host/java/gin_java_bound_object_delegate.h" |
| 15 #include "content/browser/renderer_host/java/jni_helper.h" | 15 #include "content/browser/renderer_host/java/jni_helper.h" |
| 16 #include "content/common/android/gin_java_bridge_value.h" | 16 #include "content/common/android/gin_java_bridge_value.h" |
| 17 #include "content/common/android/hash_set.h" | 17 #include "content/common/android/hash_set.h" |
| 18 #include "content/common/gin_java_bridge_messages.h" | 18 #include "content/common/gin_java_bridge_messages.h" |
| 19 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
| 20 #include "content/public/browser/render_frame_host.h" | 20 #include "content/public/browser/render_frame_host.h" |
| 21 #include "content/public/browser/web_contents.h" |
| 21 #include "ipc/ipc_message_utils.h" | 22 #include "ipc/ipc_message_utils.h" |
| 22 | 23 |
| 23 #if !defined(OS_ANDROID) | 24 #if !defined(OS_ANDROID) |
| 24 #error "JavaBridge only supports OS_ANDROID" | 25 #error "JavaBridge only supports OS_ANDROID" |
| 25 #endif | 26 #endif |
| 26 | 27 |
| 27 namespace content { | 28 namespace content { |
| 28 | 29 |
| 29 namespace { | 30 namespace { |
| 30 // The JavaBridge needs to use a Java thread so the callback | 31 // The JavaBridge needs to use a Java thread so the callback |
| (...skipping 21 matching lines...) Expand all Loading... |
| 52 retained_object_set), | 53 retained_object_set), |
| 53 allow_object_contents_inspection_(true) { | 54 allow_object_contents_inspection_(true) { |
| 54 DCHECK(retained_object_set); | 55 DCHECK(retained_object_set); |
| 55 } | 56 } |
| 56 | 57 |
| 57 GinJavaBridgeDispatcherHost::~GinJavaBridgeDispatcherHost() { | 58 GinJavaBridgeDispatcherHost::~GinJavaBridgeDispatcherHost() { |
| 58 } | 59 } |
| 59 | 60 |
| 60 void GinJavaBridgeDispatcherHost::RenderFrameCreated( | 61 void GinJavaBridgeDispatcherHost::RenderFrameCreated( |
| 61 RenderFrameHost* render_frame_host) { | 62 RenderFrameHost* render_frame_host) { |
| 62 renderers_.insert(render_frame_host); | |
| 63 for (NamedObjectMap::const_iterator iter = named_objects_.begin(); | 63 for (NamedObjectMap::const_iterator iter = named_objects_.begin(); |
| 64 iter != named_objects_.end(); | 64 iter != named_objects_.end(); |
| 65 ++iter) { | 65 ++iter) { |
| 66 render_frame_host->Send(new GinJavaBridgeMsg_AddNamedObject( | 66 render_frame_host->Send(new GinJavaBridgeMsg_AddNamedObject( |
| 67 render_frame_host->GetRoutingID(), iter->first, iter->second)); | 67 render_frame_host->GetRoutingID(), iter->first, iter->second)); |
| 68 } | 68 } |
| 69 } | 69 } |
| 70 | 70 |
| 71 void GinJavaBridgeDispatcherHost::RenderFrameDeleted( | 71 void GinJavaBridgeDispatcherHost::RenderFrameDeleted( |
| 72 RenderFrameHost* render_frame_host) { | 72 RenderFrameHost* render_frame_host) { |
| 73 renderers_.erase(render_frame_host); | |
| 74 RemoveHolder(render_frame_host, | 73 RemoveHolder(render_frame_host, |
| 75 GinJavaBoundObject::ObjectMap::iterator(&objects_), | 74 GinJavaBoundObject::ObjectMap::iterator(&objects_), |
| 76 objects_.size()); | 75 objects_.size()); |
| 77 } | 76 } |
| 78 | 77 |
| 79 GinJavaBoundObject::ObjectID GinJavaBridgeDispatcherHost::AddObject( | 78 GinJavaBoundObject::ObjectID GinJavaBridgeDispatcherHost::AddObject( |
| 80 const base::android::JavaRef<jobject>& object, | 79 const base::android::JavaRef<jobject>& object, |
| 81 const base::android::JavaRef<jclass>& safe_annotation_clazz, | 80 const base::android::JavaRef<jclass>& safe_annotation_clazz, |
| 82 bool is_named, | 81 bool is_named, |
| 83 RenderFrameHost* holder) { | 82 RenderFrameHost* holder) { |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 if (iter != named_objects_.end()) { | 174 if (iter != named_objects_.end()) { |
| 176 RemoveNamedObject(iter->first); | 175 RemoveNamedObject(iter->first); |
| 177 } | 176 } |
| 178 if (existing_object) { | 177 if (existing_object) { |
| 179 (*objects_.Lookup(object_id))->AddName(); | 178 (*objects_.Lookup(object_id))->AddName(); |
| 180 } else { | 179 } else { |
| 181 object_id = AddObject(object, safe_annotation_clazz, true, NULL); | 180 object_id = AddObject(object, safe_annotation_clazz, true, NULL); |
| 182 } | 181 } |
| 183 named_objects_[name] = object_id; | 182 named_objects_[name] = object_id; |
| 184 | 183 |
| 185 for (RendererSet::iterator iter = renderers_.begin(); | 184 web_contents()->SendToAllFrames( |
| 186 iter != renderers_.end(); ++iter) { | 185 new GinJavaBridgeMsg_AddNamedObject(MSG_ROUTING_NONE, name, object_id)); |
| 187 (*iter)->Send(new GinJavaBridgeMsg_AddNamedObject( | |
| 188 (*iter)->GetRoutingID(), name, object_id)); | |
| 189 } | |
| 190 } | 186 } |
| 191 | 187 |
| 192 void GinJavaBridgeDispatcherHost::RemoveNamedObject( | 188 void GinJavaBridgeDispatcherHost::RemoveNamedObject( |
| 193 const std::string& name) { | 189 const std::string& name) { |
| 194 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 190 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 195 NamedObjectMap::iterator iter = named_objects_.find(name); | 191 NamedObjectMap::iterator iter = named_objects_.find(name); |
| 196 if (iter == named_objects_.end()) | 192 if (iter == named_objects_.end()) |
| 197 return; | 193 return; |
| 198 | 194 |
| 199 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(iter->second)); | 195 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(iter->second)); |
| 200 named_objects_.erase(iter); | 196 named_objects_.erase(iter); |
| 201 object->RemoveName(); | 197 object->RemoveName(); |
| 202 | 198 |
| 203 // Not erasing from the objects map, as we can still receive method | 199 // Not erasing from the objects map, as we can still receive method |
| 204 // invocation requests for this object, and they should work until the | 200 // invocation requests for this object, and they should work until the |
| 205 // java object is gone. | 201 // java object is gone. |
| 206 if (!object->IsNamed()) { | 202 if (!object->IsNamed()) { |
| 207 JNIEnv* env = base::android::AttachCurrentThread(); | 203 JNIEnv* env = base::android::AttachCurrentThread(); |
| 208 base::android::ScopedJavaLocalRef<jobject> retained_object_set = | 204 base::android::ScopedJavaLocalRef<jobject> retained_object_set = |
| 209 retained_object_set_.get(env); | 205 retained_object_set_.get(env); |
| 210 if (!retained_object_set.is_null()) { | 206 if (!retained_object_set.is_null()) { |
| 211 JNI_Java_HashSet_remove( | 207 JNI_Java_HashSet_remove( |
| 212 env, retained_object_set, object->GetLocalRef(env)); | 208 env, retained_object_set, object->GetLocalRef(env)); |
| 213 } | 209 } |
| 214 } | 210 } |
| 215 | 211 |
| 216 for (RendererSet::iterator iter = renderers_.begin(); | 212 web_contents()->SendToAllFrames( |
| 217 iter != renderers_.end(); ++iter) { | 213 new GinJavaBridgeMsg_RemoveNamedObject(MSG_ROUTING_NONE, name)); |
| 218 (*iter)->Send(new GinJavaBridgeMsg_RemoveNamedObject( | |
| 219 (*iter)->GetRoutingID(), name)); | |
| 220 } | |
| 221 } | 214 } |
| 222 | 215 |
| 223 void GinJavaBridgeDispatcherHost::SetAllowObjectContentsInspection(bool allow) { | 216 void GinJavaBridgeDispatcherHost::SetAllowObjectContentsInspection(bool allow) { |
| 224 allow_object_contents_inspection_ = allow; | 217 allow_object_contents_inspection_ = allow; |
| 225 } | 218 } |
| 226 | 219 |
| 227 void GinJavaBridgeDispatcherHost::DocumentAvailableInMainFrame() { | 220 void GinJavaBridgeDispatcherHost::DocumentAvailableInMainFrame() { |
| 228 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 221 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 229 // Called when the window object has been cleared in the main frame. | 222 // Called when the window object has been cleared in the main frame. |
| 230 // That means, all sub-frames have also been cleared, so only named | 223 // That means, all sub-frames have also been cleared, so only named |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 IPC_MESSAGE_FORWARD_DELAY_REPLY(GinJavaBridgeHostMsg_InvokeMethod, | 305 IPC_MESSAGE_FORWARD_DELAY_REPLY(GinJavaBridgeHostMsg_InvokeMethod, |
| 313 &forwarder, | 306 &forwarder, |
| 314 MessageForwarder::OnInvokeMethod) | 307 MessageForwarder::OnInvokeMethod) |
| 315 IPC_MESSAGE_HANDLER(GinJavaBridgeHostMsg_ObjectWrapperDeleted, | 308 IPC_MESSAGE_HANDLER(GinJavaBridgeHostMsg_ObjectWrapperDeleted, |
| 316 OnObjectWrapperDeleted) | 309 OnObjectWrapperDeleted) |
| 317 IPC_MESSAGE_UNHANDLED(handled = false) | 310 IPC_MESSAGE_UNHANDLED(handled = false) |
| 318 IPC_END_MESSAGE_MAP() | 311 IPC_END_MESSAGE_MAP() |
| 319 return handled; | 312 return handled; |
| 320 } | 313 } |
| 321 | 314 |
| 315 namespace { |
| 316 |
| 317 class IsValidRenderFrameHostHelper |
| 318 : public base::RefCounted<IsValidRenderFrameHostHelper> { |
| 319 public: |
| 320 explicit IsValidRenderFrameHostHelper(RenderFrameHost* rfh_to_match) |
| 321 : rfh_to_match_(rfh_to_match), rfh_found_(false) {} |
| 322 |
| 323 bool rfh_found() { return rfh_found_; } |
| 324 |
| 325 void OnFrame(RenderFrameHost* rfh) { |
| 326 if (rfh_to_match_ == rfh) rfh_found_ = true; |
| 327 } |
| 328 |
| 329 private: |
| 330 friend class base::RefCounted<IsValidRenderFrameHostHelper>; |
| 331 |
| 332 ~IsValidRenderFrameHostHelper() {} |
| 333 |
| 334 RenderFrameHost* rfh_to_match_; |
| 335 bool rfh_found_; |
| 336 |
| 337 DISALLOW_COPY_AND_ASSIGN(IsValidRenderFrameHostHelper); |
| 338 }; |
| 339 |
| 340 } // namespace |
| 341 |
| 342 bool GinJavaBridgeDispatcherHost::IsValidRenderFrameHost( |
| 343 RenderFrameHost* render_frame_host) { |
| 344 scoped_refptr<IsValidRenderFrameHostHelper> helper = |
| 345 new IsValidRenderFrameHostHelper(render_frame_host); |
| 346 web_contents()->ForEachFrame( |
| 347 base::Bind(&IsValidRenderFrameHostHelper::OnFrame, helper)); |
| 348 return helper->rfh_found(); |
| 349 } |
| 350 |
| 322 void GinJavaBridgeDispatcherHost::SendReply( | 351 void GinJavaBridgeDispatcherHost::SendReply( |
| 323 RenderFrameHost* render_frame_host, | 352 RenderFrameHost* render_frame_host, |
| 324 IPC::Message* reply_msg) { | 353 IPC::Message* reply_msg) { |
| 325 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 354 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 326 if (renderers_.find(render_frame_host) != renderers_.end()) { | 355 if (IsValidRenderFrameHost(render_frame_host)) { |
| 327 render_frame_host->Send(reply_msg); | 356 render_frame_host->Send(reply_msg); |
| 328 } else { | 357 } else { |
| 329 delete reply_msg; | 358 delete reply_msg; |
| 330 } | 359 } |
| 331 } | 360 } |
| 332 | 361 |
| 333 void GinJavaBridgeDispatcherHost::OnGetMethods( | 362 void GinJavaBridgeDispatcherHost::OnGetMethods( |
| 334 RenderFrameHost* render_frame_host, | 363 RenderFrameHost* render_frame_host, |
| 335 GinJavaBoundObject::ObjectID object_id, | 364 GinJavaBoundObject::ObjectID object_id, |
| 336 IPC::Message* reply_msg) { | 365 IPC::Message* reply_msg) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 } else { | 477 } else { |
| 449 ProcessMethodInvocationObjectResult(render_frame_host, reply_msg, result); | 478 ProcessMethodInvocationObjectResult(render_frame_host, reply_msg, result); |
| 450 } | 479 } |
| 451 } | 480 } |
| 452 | 481 |
| 453 void GinJavaBridgeDispatcherHost::ProcessMethodInvocationObjectResult( | 482 void GinJavaBridgeDispatcherHost::ProcessMethodInvocationObjectResult( |
| 454 RenderFrameHost* render_frame_host, | 483 RenderFrameHost* render_frame_host, |
| 455 IPC::Message* reply_msg, | 484 IPC::Message* reply_msg, |
| 456 scoped_refptr<GinJavaMethodInvocationHelper> result) { | 485 scoped_refptr<GinJavaMethodInvocationHelper> result) { |
| 457 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 486 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 458 if (renderers_.find(render_frame_host) == renderers_.end()) { | 487 if (!IsValidRenderFrameHost(render_frame_host)) { |
| 459 delete reply_msg; | 488 delete reply_msg; |
| 460 return; | 489 return; |
| 461 } | 490 } |
| 462 base::ListValue wrapped_result; | 491 base::ListValue wrapped_result; |
| 463 if (!result->GetObjectResult().is_null()) { | 492 if (!result->GetObjectResult().is_null()) { |
| 464 GinJavaBoundObject::ObjectID returned_object_id; | 493 GinJavaBoundObject::ObjectID returned_object_id; |
| 465 if (FindObjectId(result->GetObjectResult(), &returned_object_id)) { | 494 if (FindObjectId(result->GetObjectResult(), &returned_object_id)) { |
| 466 (*objects_.Lookup(returned_object_id))->AddHolder(render_frame_host); | 495 (*objects_.Lookup(returned_object_id))->AddHolder(render_frame_host); |
| 467 } else { | 496 } else { |
| 468 returned_object_id = AddObject(result->GetObjectResult(), | 497 returned_object_id = AddObject(result->GetObjectResult(), |
| (...skipping 19 matching lines...) Expand all Loading... |
| 488 if (objects_.Lookup(object_id)) { | 517 if (objects_.Lookup(object_id)) { |
| 489 GinJavaBoundObject::ObjectMap::iterator iter(&objects_); | 518 GinJavaBoundObject::ObjectMap::iterator iter(&objects_); |
| 490 while (!iter.IsAtEnd() && iter.GetCurrentKey() != object_id) | 519 while (!iter.IsAtEnd() && iter.GetCurrentKey() != object_id) |
| 491 iter.Advance(); | 520 iter.Advance(); |
| 492 DCHECK(!iter.IsAtEnd()); | 521 DCHECK(!iter.IsAtEnd()); |
| 493 RemoveHolder(render_frame_host, iter, 1); | 522 RemoveHolder(render_frame_host, iter, 1); |
| 494 } | 523 } |
| 495 } | 524 } |
| 496 | 525 |
| 497 } // namespace content | 526 } // namespace content |
| OLD | NEW |