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/android/java/gin_java_bridge_dispatcher_host.h" | 5 #include "content/browser/android/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/android/java/gin_java_bound_object_delegate.h" | 14 #include "content/browser/android/java/gin_java_bound_object_delegate.h" |
15 #include "content/browser/android/java/jni_helper.h" | 15 #include "content/browser/android/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 |