| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/web_contents/render_view_host_manager.h" | 5 #include "content/browser/web_contents/render_view_host_manager.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 void RenderViewHostManager::Init(content::BrowserContext* browser_context, | 68 void RenderViewHostManager::Init(content::BrowserContext* browser_context, |
| 69 SiteInstance* site_instance, | 69 SiteInstance* site_instance, |
| 70 int routing_id) { | 70 int routing_id) { |
| 71 // Create a RenderViewHost, once we have an instance. It is important to | 71 // Create a RenderViewHost, once we have an instance. It is important to |
| 72 // immediately give this SiteInstance to a RenderViewHost so that it is | 72 // immediately give this SiteInstance to a RenderViewHost so that it is |
| 73 // ref counted. | 73 // ref counted. |
| 74 if (!site_instance) | 74 if (!site_instance) |
| 75 site_instance = SiteInstance::Create(browser_context); | 75 site_instance = SiteInstance::Create(browser_context); |
| 76 render_view_host_ = static_cast<RenderViewHostImpl*>( | 76 render_view_host_ = static_cast<RenderViewHostImpl*>( |
| 77 RenderViewHostFactory::Create( | 77 RenderViewHostFactory::Create( |
| 78 site_instance, render_view_delegate_, routing_id, delegate_-> | 78 site_instance, render_view_delegate_, routing_id, false, delegate_-> |
| 79 GetControllerForRenderManager().GetSessionStorageNamespace())); | 79 GetControllerForRenderManager().GetSessionStorageNamespace())); |
| 80 | 80 |
| 81 // Keep track of renderer processes as they start to shut down. | 81 // Keep track of renderer processes as they start to shut down. |
| 82 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSING, | 82 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSING, |
| 83 content::NotificationService::AllSources()); | 83 content::NotificationService::AllSources()); |
| 84 } | 84 } |
| 85 | 85 |
| 86 RenderViewHostImpl* RenderViewHostManager::current_host() const { | 86 RenderViewHostImpl* RenderViewHostManager::current_host() const { |
| 87 return render_view_host_; | 87 return render_view_host_; |
| 88 } | 88 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 105 if (!dest_render_view_host) | 105 if (!dest_render_view_host) |
| 106 return NULL; // We weren't able to create a pending render view host. | 106 return NULL; // We weren't able to create a pending render view host. |
| 107 | 107 |
| 108 // If the current render_view_host_ isn't live, we should create it so | 108 // If the current render_view_host_ isn't live, we should create it so |
| 109 // that we don't show a sad tab while the dest_render_view_host fetches | 109 // that we don't show a sad tab while the dest_render_view_host fetches |
| 110 // its first page. (Bug 1145340) | 110 // its first page. (Bug 1145340) |
| 111 if (dest_render_view_host != render_view_host_ && | 111 if (dest_render_view_host != render_view_host_ && |
| 112 !render_view_host_->IsRenderViewLive()) { | 112 !render_view_host_->IsRenderViewLive()) { |
| 113 // Note: we don't call InitRenderView here because we are navigating away | 113 // Note: we don't call InitRenderView here because we are navigating away |
| 114 // soon anyway, and we don't have the NavigationEntry for this host. | 114 // soon anyway, and we don't have the NavigationEntry for this host. |
| 115 delegate_->CreateRenderViewForRenderManager(render_view_host_); | 115 delegate_->CreateRenderViewForRenderManager(render_view_host_, |
| 116 MSG_ROUTING_NONE); |
| 116 } | 117 } |
| 117 | 118 |
| 118 // If the renderer crashed, then try to create a new one to satisfy this | 119 // If the renderer crashed, then try to create a new one to satisfy this |
| 119 // navigation request. | 120 // navigation request. |
| 120 if (!dest_render_view_host->IsRenderViewLive()) { | 121 if (!dest_render_view_host->IsRenderViewLive()) { |
| 121 if (!InitRenderView(dest_render_view_host, entry)) | 122 if (!InitRenderView(dest_render_view_host, MSG_ROUTING_NONE)) |
| 122 return NULL; | 123 return NULL; |
| 123 | 124 |
| 124 // Now that we've created a new renderer, be sure to hide it if it isn't | 125 // Now that we've created a new renderer, be sure to hide it if it isn't |
| 125 // our primary one. Otherwise, we might crash if we try to call Show() | 126 // our primary one. Otherwise, we might crash if we try to call Show() |
| 126 // on it later. | 127 // on it later. |
| 127 if (dest_render_view_host != render_view_host_ && | 128 if (dest_render_view_host != render_view_host_ && |
| 128 dest_render_view_host->GetView()) { | 129 dest_render_view_host->GetView()) { |
| 129 dest_render_view_host->GetView()->Hide(); | 130 dest_render_view_host->GetView()->Hide(); |
| 130 } else { | 131 } else { |
| 131 // This is our primary renderer, notify here as we won't be calling | 132 // This is our primary renderer, notify here as we won't be calling |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 // a single BrowsingInstance for all pages of a certain type (e.g., New Tab | 537 // a single BrowsingInstance for all pages of a certain type (e.g., New Tab |
| 537 // Pages), keeping them in the same process. When you navigate away from | 538 // Pages), keeping them in the same process. When you navigate away from |
| 538 // that page, we want to explicity ignore that BrowsingInstance and group | 539 // that page, we want to explicity ignore that BrowsingInstance and group |
| 539 // this page into the appropriate SiteInstance for its URL. | 540 // this page into the appropriate SiteInstance for its URL. |
| 540 return SiteInstance::CreateForURL(browser_context, dest_url); | 541 return SiteInstance::CreateForURL(browser_context, dest_url); |
| 541 } else { | 542 } else { |
| 542 // Start the new renderer in a new SiteInstance, but in the current | 543 // Start the new renderer in a new SiteInstance, but in the current |
| 543 // BrowsingInstance. It is important to immediately give this new | 544 // BrowsingInstance. It is important to immediately give this new |
| 544 // SiteInstance to a RenderViewHost (if it is different than our current | 545 // SiteInstance to a RenderViewHost (if it is different than our current |
| 545 // SiteInstance), so that it is ref counted. This will happen in | 546 // SiteInstance), so that it is ref counted. This will happen in |
| 546 // CreatePendingRenderView. | 547 // CreateRenderView. |
| 547 return curr_instance->GetRelatedSiteInstance(dest_url); | 548 return curr_instance->GetRelatedSiteInstance(dest_url); |
| 548 } | 549 } |
| 549 } | 550 } |
| 550 | 551 |
| 551 bool RenderViewHostManager::CreatePendingRenderView( | 552 int RenderViewHostManager::CreateRenderView( |
| 552 const NavigationEntryImpl& entry, SiteInstance* instance) { | 553 SiteInstance* instance, |
| 553 NavigationEntry* curr_entry = | 554 int opener_route_id, |
| 554 delegate_->GetControllerForRenderManager().GetLastCommittedEntry(); | 555 bool swapped_out) { |
| 555 if (curr_entry) { | 556 CHECK(instance); |
| 556 DCHECK(!curr_entry->GetContentState().empty()); | 557 |
| 557 // TODO(creis): Should send a message to the RenderView to let it know | 558 // Check if we've already created an RVH for this SiteInstance. If so, try |
| 558 // we're about to switch away, so that it sends an UpdateState message. | 559 // to re-use the existing one, which has already been initialized. We'll |
| 560 // remove it from the list of swapped out hosts if it commits. |
| 561 RenderViewHostImpl* new_render_view_host = static_cast<RenderViewHostImpl*>( |
| 562 GetSwappedOutRenderViewHost(instance)); |
| 563 if (new_render_view_host) { |
| 564 // Prevent the process from exiting while we're trying to use it. |
| 565 new_render_view_host->GetProcess()->AddPendingView(); |
| 566 } else { |
| 567 // Create a new RenderViewHost if we don't find an existing one. |
| 568 new_render_view_host = static_cast<RenderViewHostImpl*>( |
| 569 RenderViewHostFactory::Create(instance, |
| 570 render_view_delegate_, MSG_ROUTING_NONE, swapped_out, delegate_-> |
| 571 GetControllerForRenderManager().GetSessionStorageNamespace())); |
| 572 |
| 573 // Prevent the process from exiting while we're trying to use it. |
| 574 new_render_view_host->GetProcess()->AddPendingView(); |
| 575 |
| 576 // Store the new RVH as swapped out if necessary. |
| 577 if (swapped_out) |
| 578 swapped_out_hosts_[instance->GetId()] = new_render_view_host; |
| 579 |
| 580 bool success = InitRenderView(new_render_view_host, opener_route_id); |
| 581 if (success) { |
| 582 // Don't show the view until we get a DidNavigate from it. |
| 583 new_render_view_host->GetView()->Hide(); |
| 584 } else if (!swapped_out) { |
| 585 CancelPending(); |
| 586 } |
| 559 } | 587 } |
| 560 | 588 |
| 561 // Check if we've already created an RVH for this SiteInstance. | 589 // Use this as our new pending RVH if it isn't swapped out. |
| 562 CHECK(instance); | 590 if (!swapped_out) |
| 563 RenderViewHostMap::iterator iter = | 591 pending_render_view_host_ = new_render_view_host; |
| 564 swapped_out_hosts_.find(instance->GetId()); | |
| 565 if (iter != swapped_out_hosts_.end()) { | |
| 566 // Re-use the existing RenderViewHost, which has already been initialized. | |
| 567 // We'll remove it from the list of swapped out hosts if it commits. | |
| 568 pending_render_view_host_ = iter->second; | |
| 569 | 592 |
| 570 // Prevent the process from exiting while we're trying to use it. | 593 return new_render_view_host->GetRoutingID(); |
| 571 pending_render_view_host_->GetProcess()->AddPendingView(); | |
| 572 | |
| 573 return true; | |
| 574 } | |
| 575 | |
| 576 pending_render_view_host_ = static_cast<RenderViewHostImpl*>( | |
| 577 RenderViewHostFactory::Create( | |
| 578 instance, render_view_delegate_, MSG_ROUTING_NONE, delegate_-> | |
| 579 GetControllerForRenderManager().GetSessionStorageNamespace())); | |
| 580 | |
| 581 // Prevent the process from exiting while we're trying to use it. | |
| 582 pending_render_view_host_->GetProcess()->AddPendingView(); | |
| 583 | |
| 584 bool success = InitRenderView(pending_render_view_host_, entry); | |
| 585 if (success) { | |
| 586 // Don't show the view until we get a DidNavigate from it. | |
| 587 pending_render_view_host_->GetView()->Hide(); | |
| 588 } else { | |
| 589 CancelPending(); | |
| 590 } | |
| 591 return success; | |
| 592 } | 594 } |
| 593 | 595 |
| 594 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, | 596 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, |
| 595 const NavigationEntryImpl& entry) { | 597 int opener_route_id) { |
| 596 // If the pending navigation is to a WebUI, tell the RenderView about any | 598 // If the pending navigation is to a WebUI, tell the RenderView about any |
| 597 // bindings it will need enabled. | 599 // bindings it will need enabled. |
| 598 if (pending_web_ui()) | 600 if (pending_web_ui()) |
| 599 render_view_host->AllowBindings(pending_web_ui()->GetBindings()); | 601 render_view_host->AllowBindings(pending_web_ui()->GetBindings()); |
| 600 | 602 |
| 601 return delegate_->CreateRenderViewForRenderManager(render_view_host); | 603 return delegate_->CreateRenderViewForRenderManager(render_view_host, |
| 604 opener_route_id); |
| 602 } | 605 } |
| 603 | 606 |
| 604 void RenderViewHostManager::CommitPending() { | 607 void RenderViewHostManager::CommitPending() { |
| 605 // First check whether we're going to want to focus the location bar after | 608 // First check whether we're going to want to focus the location bar after |
| 606 // this commit. We do this now because the navigation hasn't formally | 609 // this commit. We do this now because the navigation hasn't formally |
| 607 // committed yet, so if we've already cleared |pending_web_ui_| the call chain | 610 // committed yet, so if we've already cleared |pending_web_ui_| the call chain |
| 608 // this triggers won't be able to figure out what's going on. | 611 // this triggers won't be able to figure out what's going on. |
| 609 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); | 612 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); |
| 610 | 613 |
| 611 // Next commit the Web UI, if any. Either replace |web_ui_| with | 614 // Next commit the Web UI, if any. Either replace |web_ui_| with |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 // This will possibly create (set to NULL) a Web UI object for the pending | 733 // This will possibly create (set to NULL) a Web UI object for the pending |
| 731 // page. We'll use this later to give the page special access. This must | 734 // page. We'll use this later to give the page special access. This must |
| 732 // happen before the new renderer is created below so it will get bindings. | 735 // happen before the new renderer is created below so it will get bindings. |
| 733 // It must also happen after the above conditional call to CancelPending(), | 736 // It must also happen after the above conditional call to CancelPending(), |
| 734 // otherwise CancelPending may clear the pending_web_ui_ and the page will | 737 // otherwise CancelPending may clear the pending_web_ui_ and the page will |
| 735 // not have its bindings set appropriately. | 738 // not have its bindings set appropriately. |
| 736 pending_web_ui_.reset( | 739 pending_web_ui_.reset( |
| 737 delegate_->CreateWebUIForRenderManager(entry.GetURL())); | 740 delegate_->CreateWebUIForRenderManager(entry.GetURL())); |
| 738 pending_and_current_web_ui_.reset(); | 741 pending_and_current_web_ui_.reset(); |
| 739 | 742 |
| 740 // Create a pending RVH and navigate it. | 743 // Ensure that we have created RVHs for the new RVH's opener chain if |
| 741 bool success = CreatePendingRenderView(entry, new_instance); | 744 // we are staying in the same BrowsingInstance. This allows the pending RVH |
| 742 if (!success) | 745 // to send cross-process script calls to its opener(s). |
| 746 int opener_route_id = MSG_ROUTING_NONE; |
| 747 if (new_instance->IsRelatedSiteInstance(curr_instance)) { |
| 748 opener_route_id = |
| 749 delegate_->CreateOpenerRenderViewsForRenderManager(new_instance); |
| 750 } |
| 751 |
| 752 // Create a non-swapped-out pending RVH with the given opener and navigate |
| 753 // it. |
| 754 int route_id = CreateRenderView(new_instance, opener_route_id, false); |
| 755 if (route_id == MSG_ROUTING_NONE) |
| 743 return NULL; | 756 return NULL; |
| 744 | 757 |
| 745 // Check if our current RVH is live before we set up a transition. | 758 // Check if our current RVH is live before we set up a transition. |
| 746 if (!render_view_host_->IsRenderViewLive()) { | 759 if (!render_view_host_->IsRenderViewLive()) { |
| 747 if (!cross_navigation_pending_) { | 760 if (!cross_navigation_pending_) { |
| 748 // The current RVH is not live. There's no reason to sit around with a | 761 // The current RVH is not live. There's no reason to sit around with a |
| 749 // sad tab or a newly created RVH while we wait for the pending RVH to | 762 // sad tab or a newly created RVH while we wait for the pending RVH to |
| 750 // navigate. Just switch to the pending RVH now and go back to non | 763 // navigate. Just switch to the pending RVH now and go back to non |
| 751 // cross-navigating (Note that we don't care about on{before}unload | 764 // cross-navigating (Note that we don't care about on{before}unload |
| 752 // handlers if the current RVH isn't live.) | 765 // handlers if the current RVH isn't live.) |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 } | 884 } |
| 872 } | 885 } |
| 873 | 886 |
| 874 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) { | 887 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) { |
| 875 if (!rvh->GetSiteInstance()) | 888 if (!rvh->GetSiteInstance()) |
| 876 return false; | 889 return false; |
| 877 | 890 |
| 878 return swapped_out_hosts_.find(rvh->GetSiteInstance()->GetId()) != | 891 return swapped_out_hosts_.find(rvh->GetSiteInstance()->GetId()) != |
| 879 swapped_out_hosts_.end(); | 892 swapped_out_hosts_.end(); |
| 880 } | 893 } |
| 894 |
| 895 RenderViewHost* RenderViewHostManager::GetSwappedOutRenderViewHost( |
| 896 SiteInstance* instance) { |
| 897 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); |
| 898 if (iter != swapped_out_hosts_.end()) |
| 899 return iter->second; |
| 900 |
| 901 return NULL; |
| 902 } |
| OLD | NEW |