Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(481)

Side by Side Diff: content/browser/android/java/gin_java_bridge_dispatcher_host.cc

Issue 498633003: Cache pending JS bridge sync IPC replies, and send in case of RenderFrame deletion. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Factor out reply_msg param where possible Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 WebContents* web_contents, 49 WebContents* web_contents,
50 jobject retained_object_set) 50 jobject retained_object_set)
51 : WebContentsObserver(web_contents), 51 : WebContentsObserver(web_contents),
52 retained_object_set_(base::android::AttachCurrentThread(), 52 retained_object_set_(base::android::AttachCurrentThread(),
53 retained_object_set), 53 retained_object_set),
54 allow_object_contents_inspection_(true) { 54 allow_object_contents_inspection_(true) {
55 DCHECK(retained_object_set); 55 DCHECK(retained_object_set);
56 } 56 }
57 57
58 GinJavaBridgeDispatcherHost::~GinJavaBridgeDispatcherHost() { 58 GinJavaBridgeDispatcherHost::~GinJavaBridgeDispatcherHost() {
59 DCHECK(pending_replies_.empty());
59 } 60 }
60 61
61 void GinJavaBridgeDispatcherHost::RenderFrameCreated( 62 void GinJavaBridgeDispatcherHost::RenderFrameCreated(
62 RenderFrameHost* render_frame_host) { 63 RenderFrameHost* render_frame_host) {
63 for (NamedObjectMap::const_iterator iter = named_objects_.begin(); 64 for (NamedObjectMap::const_iterator iter = named_objects_.begin();
64 iter != named_objects_.end(); 65 iter != named_objects_.end();
65 ++iter) { 66 ++iter) {
66 render_frame_host->Send(new GinJavaBridgeMsg_AddNamedObject( 67 render_frame_host->Send(new GinJavaBridgeMsg_AddNamedObject(
67 render_frame_host->GetRoutingID(), iter->first, iter->second)); 68 render_frame_host->GetRoutingID(), iter->first, iter->second));
68 } 69 }
69 } 70 }
70 71
71 void GinJavaBridgeDispatcherHost::RenderFrameDeleted( 72 void GinJavaBridgeDispatcherHost::RenderFrameDeleted(
72 RenderFrameHost* render_frame_host) { 73 RenderFrameHost* render_frame_host) {
74 DCHECK_CURRENTLY_ON(BrowserThread::UI);
75 PendingReplyMap::const_iterator it =
76 pending_replies_.find(render_frame_host);
77 if (it != pending_replies_.end()) {
78 IPC::Message* reply_msg = it->second;
79 base::ListValue result;
80 result.Append(base::Value::CreateNullValue());
81 IPC::WriteParam(reply_msg, result);
82 IPC::WriteParam(reply_msg, kGinJavaBridgeRenderFrameDeleted);
83 render_frame_host->Send(reply_msg);
84 pending_replies_.erase(render_frame_host);
85 }
73 RemoveHolder(render_frame_host, 86 RemoveHolder(render_frame_host,
74 GinJavaBoundObject::ObjectMap::iterator(&objects_), 87 GinJavaBoundObject::ObjectMap::iterator(&objects_),
75 objects_.size()); 88 objects_.size());
76 } 89 }
77 90
78 GinJavaBoundObject::ObjectID GinJavaBridgeDispatcherHost::AddObject( 91 GinJavaBoundObject::ObjectID GinJavaBridgeDispatcherHost::AddObject(
79 const base::android::JavaRef<jobject>& object, 92 const base::android::JavaRef<jobject>& object,
80 const base::android::JavaRef<jclass>& safe_annotation_clazz, 93 const base::android::JavaRef<jclass>& safe_annotation_clazz,
81 bool is_named, 94 bool is_named,
82 RenderFrameHost* holder) { 95 RenderFrameHost* holder) {
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 RenderFrameHost* render_frame_host) { 360 RenderFrameHost* render_frame_host) {
348 scoped_refptr<IsValidRenderFrameHostHelper> helper = 361 scoped_refptr<IsValidRenderFrameHostHelper> helper =
349 new IsValidRenderFrameHostHelper(render_frame_host); 362 new IsValidRenderFrameHostHelper(render_frame_host);
350 web_contents()->ForEachFrame( 363 web_contents()->ForEachFrame(
351 base::Bind(&IsValidRenderFrameHostHelper::OnFrame, helper)); 364 base::Bind(&IsValidRenderFrameHostHelper::OnFrame, helper));
352 return helper->rfh_found(); 365 return helper->rfh_found();
353 } 366 }
354 367
355 void GinJavaBridgeDispatcherHost::SendReply( 368 void GinJavaBridgeDispatcherHost::SendReply(
356 RenderFrameHost* render_frame_host, 369 RenderFrameHost* render_frame_host,
357 IPC::Message* reply_msg) { 370 IPC::Message* reply_msg) {
boliu 2014/08/27 19:07:42 Still don't like this one. I think the erase shou
358 DCHECK_CURRENTLY_ON(BrowserThread::UI); 371 DCHECK_CURRENTLY_ON(BrowserThread::UI);
359 if (IsValidRenderFrameHost(render_frame_host)) { 372 DCHECK(IsValidRenderFrameHost(render_frame_host));
360 render_frame_host->Send(reply_msg); 373
361 } else { 374 render_frame_host->Send(reply_msg);
362 delete reply_msg; 375 pending_replies_.erase(render_frame_host);
363 }
364 } 376 }
365 377
366 void GinJavaBridgeDispatcherHost::OnGetMethods( 378 void GinJavaBridgeDispatcherHost::OnGetMethods(
367 RenderFrameHost* render_frame_host, 379 RenderFrameHost* render_frame_host,
368 GinJavaBoundObject::ObjectID object_id, 380 GinJavaBoundObject::ObjectID object_id,
369 IPC::Message* reply_msg) { 381 IPC::Message* reply_msg) {
370 DCHECK_CURRENTLY_ON(BrowserThread::UI); 382 DCHECK_CURRENTLY_ON(BrowserThread::UI);
371 DCHECK(render_frame_host); 383 DCHECK(render_frame_host);
372 if (!allow_object_contents_inspection_) { 384 if (!allow_object_contents_inspection_) {
373 IPC::WriteParam(reply_msg, std::set<std::string>()); 385 IPC::WriteParam(reply_msg, std::set<std::string>());
374 render_frame_host->Send(reply_msg); 386 render_frame_host->Send(reply_msg);
375 return; 387 return;
376 } 388 }
377 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id)); 389 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
378 if (!object) { 390 if (!object) {
379 LOG(ERROR) << "WebView: Unknown object: " << object_id; 391 LOG(ERROR) << "WebView: Unknown object: " << object_id;
380 IPC::WriteParam(reply_msg, std::set<std::string>()); 392 IPC::WriteParam(reply_msg, std::set<std::string>());
381 render_frame_host->Send(reply_msg); 393 render_frame_host->Send(reply_msg);
382 return; 394 return;
383 } 395 }
396 DCHECK(pending_replies_.find(render_frame_host) == pending_replies_.end());
397 pending_replies_[render_frame_host] = reply_msg;
384 base::PostTaskAndReplyWithResult( 398 base::PostTaskAndReplyWithResult(
385 g_background_thread.Get().message_loop()->message_loop_proxy(), 399 g_background_thread.Get().message_loop()->message_loop_proxy(),
386 FROM_HERE, 400 FROM_HERE,
387 base::Bind(&GinJavaBoundObject::GetMethodNames, object), 401 base::Bind(&GinJavaBoundObject::GetMethodNames, object),
388 base::Bind(&GinJavaBridgeDispatcherHost::SendMethods, 402 base::Bind(&GinJavaBridgeDispatcherHost::SendMethods,
389 AsWeakPtr(), 403 AsWeakPtr(),
390 render_frame_host, 404 render_frame_host));
391 reply_msg));
392 } 405 }
393 406
394 void GinJavaBridgeDispatcherHost::SendMethods( 407 void GinJavaBridgeDispatcherHost::SendMethods(
395 RenderFrameHost* render_frame_host, 408 RenderFrameHost* render_frame_host,
396 IPC::Message* reply_msg,
397 const std::set<std::string>& method_names) { 409 const std::set<std::string>& method_names) {
410 IPC::Message* reply_msg = GetPendingReply(render_frame_host);
411 if (!reply_msg) {
412 return;
413 }
398 IPC::WriteParam(reply_msg, method_names); 414 IPC::WriteParam(reply_msg, method_names);
399 SendReply(render_frame_host, reply_msg); 415 SendReply(render_frame_host, reply_msg);
400 } 416 }
401 417
402 void GinJavaBridgeDispatcherHost::OnHasMethod( 418 void GinJavaBridgeDispatcherHost::OnHasMethod(
403 RenderFrameHost* render_frame_host, 419 RenderFrameHost* render_frame_host,
404 GinJavaBoundObject::ObjectID object_id, 420 GinJavaBoundObject::ObjectID object_id,
405 const std::string& method_name, 421 const std::string& method_name,
406 IPC::Message* reply_msg) { 422 IPC::Message* reply_msg) {
407 DCHECK_CURRENTLY_ON(BrowserThread::UI); 423 DCHECK_CURRENTLY_ON(BrowserThread::UI);
408 DCHECK(render_frame_host); 424 DCHECK(render_frame_host);
409 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id)); 425 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
410 if (!object) { 426 if (!object) {
411 LOG(ERROR) << "WebView: Unknown object: " << object_id; 427 LOG(ERROR) << "WebView: Unknown object: " << object_id;
412 IPC::WriteParam(reply_msg, false); 428 IPC::WriteParam(reply_msg, false);
413 render_frame_host->Send(reply_msg); 429 render_frame_host->Send(reply_msg);
414 return; 430 return;
415 } 431 }
432 DCHECK(pending_replies_.find(render_frame_host) == pending_replies_.end());
433 pending_replies_[render_frame_host] = reply_msg;
416 base::PostTaskAndReplyWithResult( 434 base::PostTaskAndReplyWithResult(
417 g_background_thread.Get().message_loop()->message_loop_proxy(), 435 g_background_thread.Get().message_loop()->message_loop_proxy(),
418 FROM_HERE, 436 FROM_HERE,
419 base::Bind(&GinJavaBoundObject::HasMethod, object, method_name), 437 base::Bind(&GinJavaBoundObject::HasMethod, object, method_name),
420 base::Bind(&GinJavaBridgeDispatcherHost::SendHasMethodReply, 438 base::Bind(&GinJavaBridgeDispatcherHost::SendHasMethodReply,
421 AsWeakPtr(), 439 AsWeakPtr(),
422 render_frame_host, 440 render_frame_host));
423 reply_msg));
424 } 441 }
425 442
426 void GinJavaBridgeDispatcherHost::SendHasMethodReply( 443 void GinJavaBridgeDispatcherHost::SendHasMethodReply(
427 RenderFrameHost* render_frame_host, 444 RenderFrameHost* render_frame_host,
428 IPC::Message* reply_msg,
429 bool result) { 445 bool result) {
446 IPC::Message* reply_msg = GetPendingReply(render_frame_host);
447 if (!reply_msg) {
448 return;
449 }
430 IPC::WriteParam(reply_msg, result); 450 IPC::WriteParam(reply_msg, result);
431 SendReply(render_frame_host, reply_msg); 451 SendReply(render_frame_host, reply_msg);
432 } 452 }
433 453
434 void GinJavaBridgeDispatcherHost::OnInvokeMethod( 454 void GinJavaBridgeDispatcherHost::OnInvokeMethod(
435 RenderFrameHost* render_frame_host, 455 RenderFrameHost* render_frame_host,
436 GinJavaBoundObject::ObjectID object_id, 456 GinJavaBoundObject::ObjectID object_id,
437 const std::string& method_name, 457 const std::string& method_name,
438 const base::ListValue& arguments, 458 const base::ListValue& arguments,
439 IPC::Message* reply_msg) { 459 IPC::Message* reply_msg) {
440 DCHECK_CURRENTLY_ON(BrowserThread::UI); 460 DCHECK_CURRENTLY_ON(BrowserThread::UI);
441 DCHECK(render_frame_host); 461 DCHECK(render_frame_host);
442 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id)); 462 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
443 if (!object) { 463 if (!object) {
444 LOG(ERROR) << "WebView: Unknown object: " << object_id; 464 LOG(ERROR) << "WebView: Unknown object: " << object_id;
445 base::ListValue result; 465 base::ListValue result;
446 result.Append(base::Value::CreateNullValue()); 466 result.Append(base::Value::CreateNullValue());
447 IPC::WriteParam(reply_msg, result); 467 IPC::WriteParam(reply_msg, result);
448 IPC::WriteParam(reply_msg, kGinJavaBridgeUnknownObjectId); 468 IPC::WriteParam(reply_msg, kGinJavaBridgeUnknownObjectId);
449 render_frame_host->Send(reply_msg); 469 render_frame_host->Send(reply_msg);
450 return; 470 return;
451 } 471 }
472 DCHECK(pending_replies_.find(render_frame_host) == pending_replies_.end());
473 pending_replies_[render_frame_host] = reply_msg;
452 scoped_refptr<GinJavaMethodInvocationHelper> result = 474 scoped_refptr<GinJavaMethodInvocationHelper> result =
453 new GinJavaMethodInvocationHelper( 475 new GinJavaMethodInvocationHelper(
454 make_scoped_ptr(new GinJavaBoundObjectDelegate(object)) 476 make_scoped_ptr(new GinJavaBoundObjectDelegate(object))
455 .PassAs<GinJavaMethodInvocationHelper::ObjectDelegate>(), 477 .PassAs<GinJavaMethodInvocationHelper::ObjectDelegate>(),
456 method_name, 478 method_name,
457 arguments); 479 arguments);
458 result->Init(this); 480 result->Init(this);
459 g_background_thread.Get() 481 g_background_thread.Get()
460 .message_loop() 482 .message_loop()
461 ->message_loop_proxy() 483 ->message_loop_proxy()
462 ->PostTaskAndReply( 484 ->PostTaskAndReply(
463 FROM_HERE, 485 FROM_HERE,
464 base::Bind(&GinJavaMethodInvocationHelper::Invoke, result), 486 base::Bind(&GinJavaMethodInvocationHelper::Invoke, result),
465 base::Bind( 487 base::Bind(
466 &GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult, 488 &GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult,
467 AsWeakPtr(), 489 AsWeakPtr(),
468 render_frame_host, 490 render_frame_host,
469 reply_msg,
470 result)); 491 result));
471 } 492 }
472 493
473 void GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult( 494 void GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult(
474 RenderFrameHost* render_frame_host, 495 RenderFrameHost* render_frame_host,
475 IPC::Message* reply_msg,
476 scoped_refptr<GinJavaMethodInvocationHelper> result) { 496 scoped_refptr<GinJavaMethodInvocationHelper> result) {
477 if (result->HoldsPrimitiveResult()) { 497 if (result->HoldsPrimitiveResult()) {
498 IPC::Message* reply_msg = GetPendingReply(render_frame_host);
499 if (!reply_msg) {
500 return;
501 }
478 IPC::WriteParam(reply_msg, result->GetPrimitiveResult()); 502 IPC::WriteParam(reply_msg, result->GetPrimitiveResult());
479 IPC::WriteParam(reply_msg, result->GetInvocationError()); 503 IPC::WriteParam(reply_msg, result->GetInvocationError());
480 SendReply(render_frame_host, reply_msg); 504 SendReply(render_frame_host, reply_msg);
481 } else { 505 } else {
482 ProcessMethodInvocationObjectResult(render_frame_host, reply_msg, result); 506 ProcessMethodInvocationObjectResult(render_frame_host, result);
483 } 507 }
484 } 508 }
485 509
486 void GinJavaBridgeDispatcherHost::ProcessMethodInvocationObjectResult( 510 void GinJavaBridgeDispatcherHost::ProcessMethodInvocationObjectResult(
487 RenderFrameHost* render_frame_host, 511 RenderFrameHost* render_frame_host,
488 IPC::Message* reply_msg,
489 scoped_refptr<GinJavaMethodInvocationHelper> result) { 512 scoped_refptr<GinJavaMethodInvocationHelper> result) {
490 DCHECK_CURRENTLY_ON(BrowserThread::UI); 513 DCHECK_CURRENTLY_ON(BrowserThread::UI);
514
491 if (!IsValidRenderFrameHost(render_frame_host)) { 515 if (!IsValidRenderFrameHost(render_frame_host)) {
492 delete reply_msg; 516 // In this case, we must've already sent the reply when the render frame
517 // was destroyed.
518 DCHECK(pending_replies_.find(render_frame_host) == pending_replies_.end());
493 return; 519 return;
494 } 520 }
521
495 base::ListValue wrapped_result; 522 base::ListValue wrapped_result;
496 if (!result->GetObjectResult().is_null()) { 523 if (!result->GetObjectResult().is_null()) {
497 GinJavaBoundObject::ObjectID returned_object_id; 524 GinJavaBoundObject::ObjectID returned_object_id;
498 if (FindObjectId(result->GetObjectResult(), &returned_object_id)) { 525 if (FindObjectId(result->GetObjectResult(), &returned_object_id)) {
499 (*objects_.Lookup(returned_object_id))->AddHolder(render_frame_host); 526 (*objects_.Lookup(returned_object_id))->AddHolder(render_frame_host);
500 } else { 527 } else {
501 returned_object_id = AddObject(result->GetObjectResult(), 528 returned_object_id = AddObject(result->GetObjectResult(),
502 result->GetSafeAnnotationClass(), 529 result->GetSafeAnnotationClass(),
503 false, 530 false,
504 render_frame_host); 531 render_frame_host);
505 } 532 }
506 wrapped_result.Append( 533 wrapped_result.Append(
507 GinJavaBridgeValue::CreateObjectIDValue(returned_object_id).release()); 534 GinJavaBridgeValue::CreateObjectIDValue(
535 returned_object_id).release());
508 } else { 536 } else {
509 wrapped_result.Append(base::Value::CreateNullValue()); 537 wrapped_result.Append(base::Value::CreateNullValue());
510 } 538 }
539 IPC::Message* reply_msg = GetPendingReply(render_frame_host);
540 if (!reply_msg) {
541 return;
542 }
511 IPC::WriteParam(reply_msg, wrapped_result); 543 IPC::WriteParam(reply_msg, wrapped_result);
512 IPC::WriteParam(reply_msg, result->GetInvocationError()); 544 IPC::WriteParam(reply_msg, result->GetInvocationError());
513 render_frame_host->Send(reply_msg); 545 SendReply(render_frame_host, reply_msg);
514 } 546 }
515 547
516 void GinJavaBridgeDispatcherHost::OnObjectWrapperDeleted( 548 void GinJavaBridgeDispatcherHost::OnObjectWrapperDeleted(
517 RenderFrameHost* render_frame_host, 549 RenderFrameHost* render_frame_host,
518 GinJavaBoundObject::ObjectID object_id) { 550 GinJavaBoundObject::ObjectID object_id) {
519 DCHECK_CURRENTLY_ON(BrowserThread::UI); 551 DCHECK_CURRENTLY_ON(BrowserThread::UI);
520 DCHECK(render_frame_host); 552 DCHECK(render_frame_host);
521 if (objects_.Lookup(object_id)) { 553 if (objects_.Lookup(object_id)) {
522 GinJavaBoundObject::ObjectMap::iterator iter(&objects_); 554 GinJavaBoundObject::ObjectMap::iterator iter(&objects_);
523 while (!iter.IsAtEnd() && iter.GetCurrentKey() != object_id) 555 while (!iter.IsAtEnd() && iter.GetCurrentKey() != object_id)
524 iter.Advance(); 556 iter.Advance();
525 DCHECK(!iter.IsAtEnd()); 557 DCHECK(!iter.IsAtEnd());
526 RemoveHolder(render_frame_host, iter, 1); 558 RemoveHolder(render_frame_host, iter, 1);
527 } 559 }
528 } 560 }
529 561
562 IPC::Message* GinJavaBridgeDispatcherHost::GetPendingReply(
boliu 2014/08/27 19:07:42 I think this should be split. Have a bool HasPend
563 RenderFrameHost* render_frame_host) {
564 PendingReplyMap::const_iterator it = pending_replies_.find(render_frame_host);
565 if (!IsValidRenderFrameHost(render_frame_host)) {
566 DCHECK(it == pending_replies_.end());
567 return NULL;
568 }
569 DCHECK(it != pending_replies_.end());
570 return it->second;
571 }
572
530 } // namespace content 573 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/android/java/gin_java_bridge_dispatcher_host.h ('k') | content/common/android/gin_java_bridge_errors.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698