OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/tab_contents/render_view_host_manager.h" | 5 #include "content/browser/tab_contents/render_view_host_manager.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "content/browser/browser_context.h" |
9 #include "content/browser/debugger/devtools_manager_impl.h" | 10 #include "content/browser/debugger/devtools_manager_impl.h" |
10 #include "content/browser/renderer_host/render_view_host.h" | 11 #include "content/browser/renderer_host/render_view_host.h" |
11 #include "content/browser/renderer_host/render_view_host_delegate.h" | 12 #include "content/browser/renderer_host/render_view_host_delegate.h" |
12 #include "content/browser/renderer_host/render_view_host_factory.h" | 13 #include "content/browser/renderer_host/render_view_host_factory.h" |
13 #include "content/browser/renderer_host/render_widget_host_view.h" | 14 #include "content/browser/renderer_host/render_widget_host_view.h" |
14 #include "content/browser/site_instance.h" | 15 #include "content/browser/site_instance.h" |
15 #include "content/browser/tab_contents/navigation_controller.h" | 16 #include "content/browser/tab_contents/navigation_controller.h" |
16 #include "content/browser/tab_contents/navigation_entry.h" | 17 #include "content/browser/tab_contents/navigation_entry.h" |
17 #include "content/browser/tab_contents/tab_contents_view.h" | 18 #include "content/browser/tab_contents/tab_contents_view.h" |
18 #include "content/browser/webui/web_ui.h" | 19 #include "content/browser/webui/web_ui.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 // ref counted. | 65 // ref counted. |
65 if (!site_instance) | 66 if (!site_instance) |
66 site_instance = SiteInstance::CreateSiteInstance(browser_context); | 67 site_instance = SiteInstance::CreateSiteInstance(browser_context); |
67 render_view_host_ = RenderViewHostFactory::Create( | 68 render_view_host_ = RenderViewHostFactory::Create( |
68 site_instance, render_view_delegate_, routing_id, delegate_-> | 69 site_instance, render_view_delegate_, routing_id, delegate_-> |
69 GetControllerForRenderManager().session_storage_namespace()); | 70 GetControllerForRenderManager().session_storage_namespace()); |
70 | 71 |
71 // Keep track of renderer processes as they start to shut down. | 72 // Keep track of renderer processes as they start to shut down. |
72 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSING, | 73 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSING, |
73 content::NotificationService::AllSources()); | 74 content::NotificationService::AllSources()); |
| 75 |
| 76 browser_context_ = browser_context; |
74 } | 77 } |
75 | 78 |
76 RenderWidgetHostView* RenderViewHostManager::GetRenderWidgetHostView() const { | 79 RenderWidgetHostView* RenderViewHostManager::GetRenderWidgetHostView() const { |
77 if (!render_view_host_) | 80 if (!render_view_host_) |
78 return NULL; | 81 return NULL; |
79 return render_view_host_->view(); | 82 return render_view_host_->view(); |
80 } | 83 } |
81 | 84 |
82 RenderViewHost* RenderViewHostManager::Navigate(const NavigationEntry& entry) { | 85 RenderViewHost* RenderViewHostManager::Navigate(const NavigationEntry& entry) { |
83 // Create a pending RenderViewHost. It will give us the one we should use | 86 // Create a pending RenderViewHost. It will give us the one we should use |
84 RenderViewHost* dest_render_view_host = UpdateRendererStateForNavigate(entry); | 87 RenderViewHost* dest_render_view_host = UpdateRendererStateForNavigate(entry); |
85 if (!dest_render_view_host) | 88 if (!dest_render_view_host) |
86 return NULL; // We weren't able to create a pending render view host. | 89 return NULL; // We weren't able to create a pending render view host. |
87 | 90 |
88 // If the current render_view_host_ isn't live, we should create it so | 91 // If the current render_view_host_ isn't live, we should create it so |
89 // that we don't show a sad tab while the dest_render_view_host fetches | 92 // that we don't show a sad tab while the dest_render_view_host fetches |
90 // its first page. (Bug 1145340) | 93 // its first page. (Bug 1145340) |
91 if (dest_render_view_host != render_view_host_ && | 94 if (dest_render_view_host != render_view_host_ && |
92 !render_view_host_->IsRenderViewLive()) { | 95 !render_view_host_->IsRenderViewLive()) { |
93 // Note: we don't call InitRenderView here because we are navigating away | 96 // Note: we don't call InitRenderView here because we are navigating away |
94 // soon anyway, and we don't have the NavigationEntry for this host. | 97 // soon anyway, and we don't have the NavigationEntry for this host. |
95 delegate_->CreateRenderViewForRenderManager(render_view_host_); | 98 delegate_->CreateRenderViewForRenderManager(render_view_host_, |
| 99 MSG_ROUTING_NONE); |
96 } | 100 } |
97 | 101 |
98 // If the renderer crashed, then try to create a new one to satisfy this | 102 // If the renderer crashed, then try to create a new one to satisfy this |
99 // navigation request. | 103 // navigation request. |
100 if (!dest_render_view_host->IsRenderViewLive()) { | 104 if (!dest_render_view_host->IsRenderViewLive()) { |
101 if (!InitRenderView(dest_render_view_host, entry)) | 105 if (!InitRenderView(dest_render_view_host, entry, MSG_ROUTING_NONE)) |
102 return NULL; | 106 return NULL; |
103 | 107 |
104 // Now that we've created a new renderer, be sure to hide it if it isn't | 108 // Now that we've created a new renderer, be sure to hide it if it isn't |
105 // our primary one. Otherwise, we might crash if we try to call Show() | 109 // our primary one. Otherwise, we might crash if we try to call Show() |
106 // on it later. | 110 // on it later. |
107 if (dest_render_view_host != render_view_host_ && | 111 if (dest_render_view_host != render_view_host_ && |
108 dest_render_view_host->view()) { | 112 dest_render_view_host->view()) { |
109 dest_render_view_host->view()->Hide(); | 113 dest_render_view_host->view()->Hide(); |
110 } else { | 114 } else { |
111 // This is our primary renderer, notify here as we won't be calling | 115 // This is our primary renderer, notify here as we won't be calling |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 // Start the new renderer in a new SiteInstance, but in the current | 486 // Start the new renderer in a new SiteInstance, but in the current |
483 // BrowsingInstance. It is important to immediately give this new | 487 // BrowsingInstance. It is important to immediately give this new |
484 // SiteInstance to a RenderViewHost (if it is different than our current | 488 // SiteInstance to a RenderViewHost (if it is different than our current |
485 // SiteInstance), so that it is ref counted. This will happen in | 489 // SiteInstance), so that it is ref counted. This will happen in |
486 // CreatePendingRenderView. | 490 // CreatePendingRenderView. |
487 return curr_instance->GetRelatedSiteInstance(dest_url); | 491 return curr_instance->GetRelatedSiteInstance(dest_url); |
488 } | 492 } |
489 } | 493 } |
490 | 494 |
491 bool RenderViewHostManager::CreatePendingRenderView( | 495 bool RenderViewHostManager::CreatePendingRenderView( |
492 const NavigationEntry& entry, SiteInstance* instance) { | 496 const NavigationEntry& entry, SiteInstance* instance, int opener_route_id) { |
493 NavigationEntry* curr_entry = | 497 NavigationEntry* curr_entry = |
494 delegate_->GetControllerForRenderManager().GetLastCommittedEntry(); | 498 delegate_->GetControllerForRenderManager().GetLastCommittedEntry(); |
495 if (curr_entry) { | 499 if (curr_entry) { |
496 DCHECK(!curr_entry->content_state().empty()); | 500 DCHECK(!curr_entry->content_state().empty()); |
497 // TODO(creis): Should send a message to the RenderView to let it know | 501 // TODO(creis): Should send a message to the RenderView to let it know |
498 // we're about to switch away, so that it sends an UpdateState message. | 502 // we're about to switch away, so that it sends an UpdateState message. |
499 } | 503 } |
500 | 504 |
501 // Check if we've already created an RVH for this SiteInstance. | 505 // Check if we've already created an RVH for this SiteInstance. |
502 CHECK(instance); | 506 CHECK(instance); |
(...skipping 10 matching lines...) Expand all Loading... |
513 return true; | 517 return true; |
514 } | 518 } |
515 | 519 |
516 pending_render_view_host_ = RenderViewHostFactory::Create( | 520 pending_render_view_host_ = RenderViewHostFactory::Create( |
517 instance, render_view_delegate_, MSG_ROUTING_NONE, delegate_-> | 521 instance, render_view_delegate_, MSG_ROUTING_NONE, delegate_-> |
518 GetControllerForRenderManager().session_storage_namespace()); | 522 GetControllerForRenderManager().session_storage_namespace()); |
519 | 523 |
520 // Prevent the process from exiting while we're trying to use it. | 524 // Prevent the process from exiting while we're trying to use it. |
521 pending_render_view_host_->process()->AddPendingView(); | 525 pending_render_view_host_->process()->AddPendingView(); |
522 | 526 |
523 bool success = InitRenderView(pending_render_view_host_, entry); | 527 bool success = InitRenderView(pending_render_view_host_, entry, |
| 528 opener_route_id); |
524 if (success) { | 529 if (success) { |
525 // Don't show the view until we get a DidNavigate from it. | 530 // Don't show the view until we get a DidNavigate from it. |
526 pending_render_view_host_->view()->Hide(); | 531 pending_render_view_host_->view()->Hide(); |
527 } else { | 532 } else { |
528 CancelPending(); | 533 CancelPending(); |
529 } | 534 } |
530 return success; | 535 return success; |
531 } | 536 } |
532 | 537 |
533 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, | 538 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, |
534 const NavigationEntry& entry) { | 539 const NavigationEntry& entry, |
| 540 int opener_route_id) { |
535 // If the pending navigation is to a WebUI, tell the RenderView about any | 541 // If the pending navigation is to a WebUI, tell the RenderView about any |
536 // bindings it will need enabled. | 542 // bindings it will need enabled. |
537 if (pending_web_ui_.get()) | 543 if (pending_web_ui_.get()) |
538 render_view_host->AllowBindings(pending_web_ui_->bindings()); | 544 render_view_host->AllowBindings(pending_web_ui_->bindings()); |
539 | 545 |
540 return delegate_->CreateRenderViewForRenderManager(render_view_host); | 546 return delegate_->CreateRenderViewForRenderManager(render_view_host, |
| 547 opener_route_id); |
541 } | 548 } |
542 | 549 |
543 void RenderViewHostManager::CommitPending() { | 550 void RenderViewHostManager::CommitPending() { |
544 // First check whether we're going to want to focus the location bar after | 551 // First check whether we're going to want to focus the location bar after |
545 // this commit. We do this now because the navigation hasn't formally | 552 // this commit. We do this now because the navigation hasn't formally |
546 // committed yet, so if we've already cleared |pending_web_ui_| the call chain | 553 // committed yet, so if we've already cleared |pending_web_ui_| the call chain |
547 // this triggers won't be able to figure out what's going on. | 554 // this triggers won't be able to figure out what's going on. |
548 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); | 555 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); |
549 | 556 |
550 // Next commit the Web UI, if any. | 557 // Next commit the Web UI, if any. |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 | 666 |
660 // Determine if we need a new SiteInstance for this entry. | 667 // Determine if we need a new SiteInstance for this entry. |
661 // Again, new_instance won't be deleted before the end of this method, so it | 668 // Again, new_instance won't be deleted before the end of this method, so it |
662 // is safe to use a normal pointer here. | 669 // is safe to use a normal pointer here. |
663 SiteInstance* new_instance = curr_instance; | 670 SiteInstance* new_instance = curr_instance; |
664 bool force_swap = ShouldSwapProcessesForNavigation( | 671 bool force_swap = ShouldSwapProcessesForNavigation( |
665 delegate_->GetLastCommittedNavigationEntryForRenderManager(), &entry); | 672 delegate_->GetLastCommittedNavigationEntryForRenderManager(), &entry); |
666 if (ShouldTransitionCrossSite() || force_swap) | 673 if (ShouldTransitionCrossSite() || force_swap) |
667 new_instance = GetSiteInstanceForEntry(entry, curr_instance); | 674 new_instance = GetSiteInstanceForEntry(entry, curr_instance); |
668 | 675 |
| 676 int opener_route_id = MSG_ROUTING_NONE; |
| 677 |
669 if (new_instance != curr_instance || force_swap) { | 678 if (new_instance != curr_instance || force_swap) { |
670 // New SiteInstance. | 679 // New SiteInstance. |
671 DCHECK(!cross_navigation_pending_); | 680 DCHECK(!cross_navigation_pending_); |
672 | 681 |
| 682 // Create proxies for the RenderView's opener chain. |
| 683 // TODO(supersat): This current only creates a proxy for the direct opener. |
| 684 if (entry.opener_content_frame_id() != -1) { |
| 685 content::ContentFrame* opener_frame = |
| 686 browser_context_->frame_mapper()->FindFrame( |
| 687 entry.opener_content_frame_id()); |
| 688 // TODO(supersat): Don't use the testing method. |
| 689 RenderViewHostManager* opener_rvhm = |
| 690 opener_frame->tab_contents().render_manager_for_testing(); |
| 691 RenderViewHost* opener_rvh = opener_rvhm->SwappedOutRVHForNavigationEntry( |
| 692 entry, MSG_ROUTING_NONE); |
| 693 opener_route_id = opener_rvh->routing_id(); |
| 694 } |
| 695 |
673 // Create a pending RVH and navigate it. | 696 // Create a pending RVH and navigate it. |
674 bool success = CreatePendingRenderView(entry, new_instance); | 697 bool success = CreatePendingRenderView(entry, new_instance, |
| 698 opener_route_id); |
675 if (!success) | 699 if (!success) |
676 return NULL; | 700 return NULL; |
677 | 701 |
678 // Check if our current RVH is live before we set up a transition. | 702 // Check if our current RVH is live before we set up a transition. |
679 if (!render_view_host_->IsRenderViewLive()) { | 703 if (!render_view_host_->IsRenderViewLive()) { |
680 if (!cross_navigation_pending_) { | 704 if (!cross_navigation_pending_) { |
681 // The current RVH is not live. There's no reason to sit around with a | 705 // The current RVH is not live. There's no reason to sit around with a |
682 // sad tab or a newly created RVH while we wait for the pending RVH to | 706 // sad tab or a newly created RVH while we wait for the pending RVH to |
683 // navigate. Just switch to the pending RVH now and go back to non | 707 // navigate. Just switch to the pending RVH now and go back to non |
684 // cross-navigating (Note that we don't care about on{before}unload | 708 // cross-navigating (Note that we don't care about on{before}unload |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 } | 829 } |
806 } | 830 } |
807 | 831 |
808 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) { | 832 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) { |
809 if (!rvh->site_instance()) | 833 if (!rvh->site_instance()) |
810 return false; | 834 return false; |
811 | 835 |
812 return swapped_out_hosts_.find(rvh->site_instance()->id()) != | 836 return swapped_out_hosts_.find(rvh->site_instance()->id()) != |
813 swapped_out_hosts_.end(); | 837 swapped_out_hosts_.end(); |
814 } | 838 } |
| 839 |
| 840 RenderViewHost* RenderViewHostManager::SwappedOutRVHForNavigationEntry( |
| 841 const NavigationEntry& entry, int opener_route_id) { |
| 842 SiteInstance* site_instance = GetSiteInstanceForEntry( |
| 843 entry, render_view_host_->site_instance()); |
| 844 |
| 845 // If we already have a swapped out RVH. |
| 846 RenderViewHostMap::iterator iter = |
| 847 swapped_out_hosts_.find(site_instance->id()); |
| 848 if (iter != swapped_out_hosts_.end()) |
| 849 return iter->second; |
| 850 |
| 851 RenderViewHost* rvh = RenderViewHostFactory::Create( |
| 852 site_instance, render_view_delegate_, MSG_ROUTING_NONE, delegate_-> |
| 853 GetControllerForRenderManager().session_storage_namespace()); |
| 854 |
| 855 // TODO(supersat): Do we need to call this? |
| 856 // Prevent the process from exiting while we're trying to use it. |
| 857 //rvh->process()->AddPendingView(); |
| 858 |
| 859 bool success = InitRenderView(rvh, entry, opener_route_id); |
| 860 if (success) { |
| 861 content::ContentFrame* frame = browser_context_->frame_mapper()->FindFrame( |
| 862 entry.opener_content_frame_id()); |
| 863 browser_context_->frame_mapper()->AddSwappedOutRendererToFrame(frame, |
| 864 rvh->process()->GetID(), rvh->routing_id(), -1); |
| 865 |
| 866 rvh->view()->Hide(); |
| 867 // We're not swapping in a new RenderView, so the new ids are set to -1. |
| 868 rvh->SwapOutAndProxy(-1, -1, entry.opener_content_frame_id()); |
| 869 swapped_out_hosts_[site_instance->id()] = rvh; |
| 870 return rvh; |
| 871 } else { |
| 872 return NULL; |
| 873 } |
| 874 } |
OLD | NEW |