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

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: remove sendreply 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 IPC::Message* reply_msg = TakePendingReply(render_frame_host);
76 if (reply_msg != NULL) {
77 base::ListValue result;
78 result.Append(base::Value::CreateNullValue());
79 IPC::WriteParam(reply_msg, result);
80 IPC::WriteParam(reply_msg, kGinJavaBridgeRenderFrameDeleted);
81 render_frame_host->Send(reply_msg);
82 }
73 RemoveHolder(render_frame_host, 83 RemoveHolder(render_frame_host,
74 GinJavaBoundObject::ObjectMap::iterator(&objects_), 84 GinJavaBoundObject::ObjectMap::iterator(&objects_),
75 objects_.size()); 85 objects_.size());
76 } 86 }
77 87
78 GinJavaBoundObject::ObjectID GinJavaBridgeDispatcherHost::AddObject( 88 GinJavaBoundObject::ObjectID GinJavaBridgeDispatcherHost::AddObject(
79 const base::android::JavaRef<jobject>& object, 89 const base::android::JavaRef<jobject>& object,
80 const base::android::JavaRef<jclass>& safe_annotation_clazz, 90 const base::android::JavaRef<jclass>& safe_annotation_clazz,
81 bool is_named, 91 bool is_named,
82 RenderFrameHost* holder) { 92 RenderFrameHost* holder) {
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 355
346 bool GinJavaBridgeDispatcherHost::IsValidRenderFrameHost( 356 bool GinJavaBridgeDispatcherHost::IsValidRenderFrameHost(
347 RenderFrameHost* render_frame_host) { 357 RenderFrameHost* render_frame_host) {
348 scoped_refptr<IsValidRenderFrameHostHelper> helper = 358 scoped_refptr<IsValidRenderFrameHostHelper> helper =
349 new IsValidRenderFrameHostHelper(render_frame_host); 359 new IsValidRenderFrameHostHelper(render_frame_host);
350 web_contents()->ForEachFrame( 360 web_contents()->ForEachFrame(
351 base::Bind(&IsValidRenderFrameHostHelper::OnFrame, helper)); 361 base::Bind(&IsValidRenderFrameHostHelper::OnFrame, helper));
352 return helper->rfh_found(); 362 return helper->rfh_found();
353 } 363 }
354 364
355 void GinJavaBridgeDispatcherHost::SendReply(
356 RenderFrameHost* render_frame_host,
357 IPC::Message* reply_msg) {
358 DCHECK_CURRENTLY_ON(BrowserThread::UI);
359 if (IsValidRenderFrameHost(render_frame_host)) {
360 render_frame_host->Send(reply_msg);
361 } else {
362 delete reply_msg;
363 }
364 }
365
366 void GinJavaBridgeDispatcherHost::OnGetMethods( 365 void GinJavaBridgeDispatcherHost::OnGetMethods(
367 RenderFrameHost* render_frame_host, 366 RenderFrameHost* render_frame_host,
368 GinJavaBoundObject::ObjectID object_id, 367 GinJavaBoundObject::ObjectID object_id,
369 IPC::Message* reply_msg) { 368 IPC::Message* reply_msg) {
370 DCHECK_CURRENTLY_ON(BrowserThread::UI); 369 DCHECK_CURRENTLY_ON(BrowserThread::UI);
371 DCHECK(render_frame_host); 370 DCHECK(render_frame_host);
372 if (!allow_object_contents_inspection_) { 371 if (!allow_object_contents_inspection_) {
373 IPC::WriteParam(reply_msg, std::set<std::string>()); 372 IPC::WriteParam(reply_msg, std::set<std::string>());
374 render_frame_host->Send(reply_msg); 373 render_frame_host->Send(reply_msg);
375 return; 374 return;
376 } 375 }
377 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id)); 376 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
378 if (!object) { 377 if (!object) {
379 LOG(ERROR) << "WebView: Unknown object: " << object_id; 378 LOG(ERROR) << "WebView: Unknown object: " << object_id;
380 IPC::WriteParam(reply_msg, std::set<std::string>()); 379 IPC::WriteParam(reply_msg, std::set<std::string>());
381 render_frame_host->Send(reply_msg); 380 render_frame_host->Send(reply_msg);
382 return; 381 return;
383 } 382 }
383 DCHECK(!HasPendingReply(render_frame_host));;
boliu 2014/08/28 16:39:29 repeated semi colon in all of these DCHECKs
384 pending_replies_[render_frame_host] = reply_msg;
384 base::PostTaskAndReplyWithResult( 385 base::PostTaskAndReplyWithResult(
385 g_background_thread.Get().message_loop()->message_loop_proxy(), 386 g_background_thread.Get().message_loop()->message_loop_proxy(),
386 FROM_HERE, 387 FROM_HERE,
387 base::Bind(&GinJavaBoundObject::GetMethodNames, object), 388 base::Bind(&GinJavaBoundObject::GetMethodNames, object),
388 base::Bind(&GinJavaBridgeDispatcherHost::SendMethods, 389 base::Bind(&GinJavaBridgeDispatcherHost::SendMethods,
389 AsWeakPtr(), 390 AsWeakPtr(),
390 render_frame_host, 391 render_frame_host));
391 reply_msg));
392 } 392 }
393 393
394 void GinJavaBridgeDispatcherHost::SendMethods( 394 void GinJavaBridgeDispatcherHost::SendMethods(
395 RenderFrameHost* render_frame_host, 395 RenderFrameHost* render_frame_host,
396 IPC::Message* reply_msg,
397 const std::set<std::string>& method_names) { 396 const std::set<std::string>& method_names) {
397 IPC::Message* reply_msg = TakePendingReply(render_frame_host);
398 if (!reply_msg) {
399 return;
400 }
398 IPC::WriteParam(reply_msg, method_names); 401 IPC::WriteParam(reply_msg, method_names);
399 SendReply(render_frame_host, reply_msg); 402 render_frame_host->Send(reply_msg);
400 } 403 }
401 404
402 void GinJavaBridgeDispatcherHost::OnHasMethod( 405 void GinJavaBridgeDispatcherHost::OnHasMethod(
403 RenderFrameHost* render_frame_host, 406 RenderFrameHost* render_frame_host,
404 GinJavaBoundObject::ObjectID object_id, 407 GinJavaBoundObject::ObjectID object_id,
405 const std::string& method_name, 408 const std::string& method_name,
406 IPC::Message* reply_msg) { 409 IPC::Message* reply_msg) {
407 DCHECK_CURRENTLY_ON(BrowserThread::UI); 410 DCHECK_CURRENTLY_ON(BrowserThread::UI);
408 DCHECK(render_frame_host); 411 DCHECK(render_frame_host);
409 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id)); 412 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
410 if (!object) { 413 if (!object) {
411 LOG(ERROR) << "WebView: Unknown object: " << object_id; 414 LOG(ERROR) << "WebView: Unknown object: " << object_id;
412 IPC::WriteParam(reply_msg, false); 415 IPC::WriteParam(reply_msg, false);
413 render_frame_host->Send(reply_msg); 416 render_frame_host->Send(reply_msg);
414 return; 417 return;
415 } 418 }
419 DCHECK(!HasPendingReply(render_frame_host));;
420 pending_replies_[render_frame_host] = reply_msg;
416 base::PostTaskAndReplyWithResult( 421 base::PostTaskAndReplyWithResult(
417 g_background_thread.Get().message_loop()->message_loop_proxy(), 422 g_background_thread.Get().message_loop()->message_loop_proxy(),
418 FROM_HERE, 423 FROM_HERE,
419 base::Bind(&GinJavaBoundObject::HasMethod, object, method_name), 424 base::Bind(&GinJavaBoundObject::HasMethod, object, method_name),
420 base::Bind(&GinJavaBridgeDispatcherHost::SendHasMethodReply, 425 base::Bind(&GinJavaBridgeDispatcherHost::SendHasMethodReply,
421 AsWeakPtr(), 426 AsWeakPtr(),
422 render_frame_host, 427 render_frame_host));
423 reply_msg));
424 } 428 }
425 429
426 void GinJavaBridgeDispatcherHost::SendHasMethodReply( 430 void GinJavaBridgeDispatcherHost::SendHasMethodReply(
427 RenderFrameHost* render_frame_host, 431 RenderFrameHost* render_frame_host,
428 IPC::Message* reply_msg,
429 bool result) { 432 bool result) {
433 IPC::Message* reply_msg = TakePendingReply(render_frame_host);
434 if (!reply_msg) {
435 return;
436 }
430 IPC::WriteParam(reply_msg, result); 437 IPC::WriteParam(reply_msg, result);
431 SendReply(render_frame_host, reply_msg); 438 render_frame_host->Send(reply_msg);
432 } 439 }
433 440
434 void GinJavaBridgeDispatcherHost::OnInvokeMethod( 441 void GinJavaBridgeDispatcherHost::OnInvokeMethod(
435 RenderFrameHost* render_frame_host, 442 RenderFrameHost* render_frame_host,
436 GinJavaBoundObject::ObjectID object_id, 443 GinJavaBoundObject::ObjectID object_id,
437 const std::string& method_name, 444 const std::string& method_name,
438 const base::ListValue& arguments, 445 const base::ListValue& arguments,
439 IPC::Message* reply_msg) { 446 IPC::Message* reply_msg) {
440 DCHECK_CURRENTLY_ON(BrowserThread::UI); 447 DCHECK_CURRENTLY_ON(BrowserThread::UI);
441 DCHECK(render_frame_host); 448 DCHECK(render_frame_host);
442 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id)); 449 scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
443 if (!object) { 450 if (!object) {
444 LOG(ERROR) << "WebView: Unknown object: " << object_id; 451 LOG(ERROR) << "WebView: Unknown object: " << object_id;
445 base::ListValue result; 452 base::ListValue result;
446 result.Append(base::Value::CreateNullValue()); 453 result.Append(base::Value::CreateNullValue());
447 IPC::WriteParam(reply_msg, result); 454 IPC::WriteParam(reply_msg, result);
448 IPC::WriteParam(reply_msg, kGinJavaBridgeUnknownObjectId); 455 IPC::WriteParam(reply_msg, kGinJavaBridgeUnknownObjectId);
449 render_frame_host->Send(reply_msg); 456 render_frame_host->Send(reply_msg);
450 return; 457 return;
451 } 458 }
459 DCHECK(!HasPendingReply(render_frame_host));;
460 pending_replies_[render_frame_host] = reply_msg;
452 scoped_refptr<GinJavaMethodInvocationHelper> result = 461 scoped_refptr<GinJavaMethodInvocationHelper> result =
453 new GinJavaMethodInvocationHelper( 462 new GinJavaMethodInvocationHelper(
454 make_scoped_ptr(new GinJavaBoundObjectDelegate(object)) 463 make_scoped_ptr(new GinJavaBoundObjectDelegate(object))
455 .PassAs<GinJavaMethodInvocationHelper::ObjectDelegate>(), 464 .PassAs<GinJavaMethodInvocationHelper::ObjectDelegate>(),
456 method_name, 465 method_name,
457 arguments); 466 arguments);
458 result->Init(this); 467 result->Init(this);
459 g_background_thread.Get() 468 g_background_thread.Get()
460 .message_loop() 469 .message_loop()
461 ->message_loop_proxy() 470 ->message_loop_proxy()
462 ->PostTaskAndReply( 471 ->PostTaskAndReply(
463 FROM_HERE, 472 FROM_HERE,
464 base::Bind(&GinJavaMethodInvocationHelper::Invoke, result), 473 base::Bind(&GinJavaMethodInvocationHelper::Invoke, result),
465 base::Bind( 474 base::Bind(
466 &GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult, 475 &GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult,
467 AsWeakPtr(), 476 AsWeakPtr(),
468 render_frame_host, 477 render_frame_host,
469 reply_msg,
470 result)); 478 result));
471 } 479 }
472 480
473 void GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult( 481 void GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult(
474 RenderFrameHost* render_frame_host, 482 RenderFrameHost* render_frame_host,
475 IPC::Message* reply_msg,
476 scoped_refptr<GinJavaMethodInvocationHelper> result) { 483 scoped_refptr<GinJavaMethodInvocationHelper> result) {
477 if (result->HoldsPrimitiveResult()) { 484 if (result->HoldsPrimitiveResult()) {
485 IPC::Message* reply_msg = TakePendingReply(render_frame_host);
486 if (!reply_msg) {
487 return;
488 }
478 IPC::WriteParam(reply_msg, result->GetPrimitiveResult()); 489 IPC::WriteParam(reply_msg, result->GetPrimitiveResult());
479 IPC::WriteParam(reply_msg, result->GetInvocationError()); 490 IPC::WriteParam(reply_msg, result->GetInvocationError());
480 SendReply(render_frame_host, reply_msg); 491 render_frame_host->Send(reply_msg);
481 } else { 492 } else {
482 ProcessMethodInvocationObjectResult(render_frame_host, reply_msg, result); 493 ProcessMethodInvocationObjectResult(render_frame_host, result);
483 } 494 }
484 } 495 }
485 496
486 void GinJavaBridgeDispatcherHost::ProcessMethodInvocationObjectResult( 497 void GinJavaBridgeDispatcherHost::ProcessMethodInvocationObjectResult(
487 RenderFrameHost* render_frame_host, 498 RenderFrameHost* render_frame_host,
488 IPC::Message* reply_msg,
489 scoped_refptr<GinJavaMethodInvocationHelper> result) { 499 scoped_refptr<GinJavaMethodInvocationHelper> result) {
490 DCHECK_CURRENTLY_ON(BrowserThread::UI); 500 DCHECK_CURRENTLY_ON(BrowserThread::UI);
501
491 if (!IsValidRenderFrameHost(render_frame_host)) { 502 if (!IsValidRenderFrameHost(render_frame_host)) {
492 delete reply_msg; 503 // In this case, we must've already sent the reply when the render frame
504 // was destroyed.
505 DCHECK(!HasPendingReply(render_frame_host));;
493 return; 506 return;
494 } 507 }
508
495 base::ListValue wrapped_result; 509 base::ListValue wrapped_result;
496 if (!result->GetObjectResult().is_null()) { 510 if (!result->GetObjectResult().is_null()) {
497 GinJavaBoundObject::ObjectID returned_object_id; 511 GinJavaBoundObject::ObjectID returned_object_id;
498 if (FindObjectId(result->GetObjectResult(), &returned_object_id)) { 512 if (FindObjectId(result->GetObjectResult(), &returned_object_id)) {
499 (*objects_.Lookup(returned_object_id))->AddHolder(render_frame_host); 513 (*objects_.Lookup(returned_object_id))->AddHolder(render_frame_host);
500 } else { 514 } else {
501 returned_object_id = AddObject(result->GetObjectResult(), 515 returned_object_id = AddObject(result->GetObjectResult(),
502 result->GetSafeAnnotationClass(), 516 result->GetSafeAnnotationClass(),
503 false, 517 false,
504 render_frame_host); 518 render_frame_host);
505 } 519 }
506 wrapped_result.Append( 520 wrapped_result.Append(
507 GinJavaBridgeValue::CreateObjectIDValue(returned_object_id).release()); 521 GinJavaBridgeValue::CreateObjectIDValue(
522 returned_object_id).release());
508 } else { 523 } else {
509 wrapped_result.Append(base::Value::CreateNullValue()); 524 wrapped_result.Append(base::Value::CreateNullValue());
510 } 525 }
526 IPC::Message* reply_msg = TakePendingReply(render_frame_host);
527 if (!reply_msg) {
528 return;
529 }
511 IPC::WriteParam(reply_msg, wrapped_result); 530 IPC::WriteParam(reply_msg, wrapped_result);
512 IPC::WriteParam(reply_msg, result->GetInvocationError()); 531 IPC::WriteParam(reply_msg, result->GetInvocationError());
513 render_frame_host->Send(reply_msg); 532 render_frame_host->Send(reply_msg);
514 } 533 }
515 534
516 void GinJavaBridgeDispatcherHost::OnObjectWrapperDeleted( 535 void GinJavaBridgeDispatcherHost::OnObjectWrapperDeleted(
517 RenderFrameHost* render_frame_host, 536 RenderFrameHost* render_frame_host,
518 GinJavaBoundObject::ObjectID object_id) { 537 GinJavaBoundObject::ObjectID object_id) {
519 DCHECK_CURRENTLY_ON(BrowserThread::UI); 538 DCHECK_CURRENTLY_ON(BrowserThread::UI);
520 DCHECK(render_frame_host); 539 DCHECK(render_frame_host);
521 if (objects_.Lookup(object_id)) { 540 if (objects_.Lookup(object_id)) {
522 GinJavaBoundObject::ObjectMap::iterator iter(&objects_); 541 GinJavaBoundObject::ObjectMap::iterator iter(&objects_);
523 while (!iter.IsAtEnd() && iter.GetCurrentKey() != object_id) 542 while (!iter.IsAtEnd() && iter.GetCurrentKey() != object_id)
524 iter.Advance(); 543 iter.Advance();
525 DCHECK(!iter.IsAtEnd()); 544 DCHECK(!iter.IsAtEnd());
526 RemoveHolder(render_frame_host, iter, 1); 545 RemoveHolder(render_frame_host, iter, 1);
527 } 546 }
528 } 547 }
529 548
549 IPC::Message* GinJavaBridgeDispatcherHost::TakePendingReply(
550 RenderFrameHost* render_frame_host) {
551 if (!IsValidRenderFrameHost(render_frame_host)) {
552 DCHECK(!HasPendingReply(render_frame_host));
553 return NULL;
554 }
555
556 PendingReplyMap::iterator it = pending_replies_.find(render_frame_host);
557 // There may be no pending reply if we're called from RenderFrameDeleted and
558 // we already sent the reply through the regular route.
559 if (it == pending_replies_.end()) {
560 return NULL;
561 }
562
563 IPC::Message* reply_msg = it->second;
564 pending_replies_.erase(it);
565 return reply_msg;
566 }
567
568 bool GinJavaBridgeDispatcherHost::HasPendingReply(
569 RenderFrameHost* render_frame_host) const {
570 return pending_replies_.find(render_frame_host) != pending_replies_.end();
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