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

Side by Side Diff: content/browser/web_contents/render_view_host_manager.cc

Issue 10154004: re-use WebUIs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: WeakPtr solution Created 8 years, 7 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 | Annotate | Revision Log
OLDNEW
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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 199
200 void RenderViewHostManager::DidNavigateMainFrame( 200 void RenderViewHostManager::DidNavigateMainFrame(
201 RenderViewHost* render_view_host) { 201 RenderViewHost* render_view_host) {
202 if (!cross_navigation_pending_) { 202 if (!cross_navigation_pending_) {
203 DCHECK(!pending_render_view_host_); 203 DCHECK(!pending_render_view_host_);
204 204
205 // We should only hear this from our current renderer. 205 // We should only hear this from our current renderer.
206 DCHECK(render_view_host == render_view_host_); 206 DCHECK(render_view_host == render_view_host_);
207 207
208 // Even when there is no pending RVH, there may be a pending Web UI. 208 // Even when there is no pending RVH, there may be a pending Web UI.
209 if (pending_web_ui_.get()) 209 if (pending_web_ui())
210 CommitPending(); 210 CommitPending();
211 return; 211 return;
212 } 212 }
213 213
214 if (render_view_host == pending_render_view_host_) { 214 if (render_view_host == pending_render_view_host_) {
215 // The pending cross-site navigation completed, so show the renderer. 215 // The pending cross-site navigation completed, so show the renderer.
216 // If it committed without sending network requests (e.g., data URLs), 216 // If it committed without sending network requests (e.g., data URLs),
217 // then we still need to swap out the old RVH first and run its unload 217 // then we still need to swap out the old RVH first and run its unload
218 // handler. OK for that to happen in the background. 218 // handler. OK for that to happen in the background.
219 if (pending_render_view_host_->GetPendingRequestId() == -1) { 219 if (pending_render_view_host_->GetPendingRequestId() == -1) {
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 } 351 }
352 } 352 }
353 353
354 bool RenderViewHostManager::ShouldTransitionCrossSite() { 354 bool RenderViewHostManager::ShouldTransitionCrossSite() {
355 // True if we are using process-per-site-instance (default) or 355 // True if we are using process-per-site-instance (default) or
356 // process-per-site (kProcessPerSite). 356 // process-per-site (kProcessPerSite).
357 return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab); 357 return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab);
358 } 358 }
359 359
360 bool RenderViewHostManager::ShouldSwapProcessesForNavigation( 360 bool RenderViewHostManager::ShouldSwapProcessesForNavigation(
361 const NavigationEntry* cur_entry, 361 const NavigationEntry* curr_entry,
362 const NavigationEntryImpl* new_entry) const { 362 const NavigationEntryImpl* new_entry) const {
363 DCHECK(new_entry); 363 DCHECK(new_entry);
364 364
365 // Check for reasons to swap processes even if we are in a process model that 365 // Check for reasons to swap processes even if we are in a process model that
366 // doesn't usually swap (e.g., process-per-tab). 366 // doesn't usually swap (e.g., process-per-tab).
367 367
368 // For security, we should transition between processes when one is a Web UI 368 // For security, we should transition between processes when one is a Web UI
369 // page and one isn't. If there's no cur_entry, check the current RVH's 369 // page and one isn't. If there's no curr_entry, check the current RVH's
370 // site, which might already be committed to a Web UI URL (such as the NTP). 370 // site, which might already be committed to a Web UI URL (such as the NTP).
371 const GURL& current_url = (cur_entry) ? cur_entry->GetURL() : 371 const GURL& current_url = (curr_entry) ? curr_entry->GetURL() :
372 render_view_host_->GetSiteInstance()->GetSite(); 372 render_view_host_->GetSiteInstance()->GetSite();
373 content::BrowserContext* browser_context = 373 content::BrowserContext* browser_context =
374 delegate_->GetControllerForRenderManager().GetBrowserContext(); 374 delegate_->GetControllerForRenderManager().GetBrowserContext();
375 const WebUIControllerFactory* web_ui_factory = 375 const WebUIControllerFactory* web_ui_factory =
376 content::GetContentClient()->browser()->GetWebUIControllerFactory(); 376 content::GetContentClient()->browser()->GetWebUIControllerFactory();
377 if (web_ui_factory) { 377 if (web_ui_factory) {
378 if (web_ui_factory->UseWebUIForURL(browser_context, current_url)) { 378 if (web_ui_factory->UseWebUIForURL(browser_context, current_url)) {
379 // Force swap if it's not an acceptable URL for Web UI. 379 // Force swap if it's not an acceptable URL for Web UI.
380 // Here, data URLs are never allowed. 380 // Here, data URLs are never allowed.
381 if (!web_ui_factory->IsURLAcceptableForWebUI(browser_context, 381 if (!web_ui_factory->IsURLAcceptableForWebUI(browser_context,
382 new_entry->GetURL(), false)) 382 new_entry->GetURL(), false))
383 return true; 383 return true;
384 } else { 384 } else {
385 // Force swap if it's a Web UI URL. 385 // Force swap if it's a Web UI URL.
386 if (web_ui_factory->UseWebUIForURL(browser_context, new_entry->GetURL())) 386 if (web_ui_factory->UseWebUIForURL(browser_context, new_entry->GetURL()))
387 return true; 387 return true;
388 } 388 }
389 } 389 }
390 390
391 if (content::GetContentClient()->browser()->ShouldSwapProcessesForNavigation( 391 if (content::GetContentClient()->browser()->ShouldSwapProcessesForNavigation(
392 cur_entry ? cur_entry->GetURL() : GURL(), new_entry->GetURL())) { 392 curr_entry ? curr_entry->GetURL() : GURL(), new_entry->GetURL())) {
393 return true; 393 return true;
394 } 394 }
395 395
396 if (!cur_entry) 396 if (!curr_entry)
397 return false; 397 return false;
398 398
399 // We can't switch a RenderView between view source and non-view source mode 399 // We can't switch a RenderView between view source and non-view source mode
400 // without screwing up the session history sometimes (when navigating between 400 // without screwing up the session history sometimes (when navigating between
401 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat 401 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat
402 // it as a new navigation). So require a view switch. 402 // it as a new navigation). So require a view switch.
403 if (cur_entry->IsViewSourceMode() != new_entry->IsViewSourceMode()) 403 if (curr_entry->IsViewSourceMode() != new_entry->IsViewSourceMode())
404 return true; 404 return true;
405 405
406 return false; 406 return false;
407 } 407 }
408 408
409 bool RenderViewHostManager::ShouldReuseWebUI(
410 const NavigationEntry* curr_entry,
411 const NavigationEntryImpl* new_entry) const {
412 NavigationControllerImpl& controller =
413 delegate_->GetControllerForRenderManager();
414 WebUIControllerFactory* factory =
415 content::GetContentClient()->browser()->GetWebUIControllerFactory();
416 return curr_entry && web_ui_.get() &&
417 (factory->GetWebUIType(controller.GetBrowserContext(),
418 curr_entry->GetURL()) ==
419 factory->GetWebUIType(controller.GetBrowserContext(),
420 new_entry->GetURL()));
421 }
422
409 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( 423 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
410 const NavigationEntryImpl& entry, 424 const NavigationEntryImpl& entry,
411 SiteInstance* curr_instance) { 425 SiteInstance* curr_instance) {
412 // NOTE: This is only called when ShouldTransitionCrossSite is true. 426 // NOTE: This is only called when ShouldTransitionCrossSite is true.
413 427
414 const GURL& dest_url = entry.GetURL(); 428 const GURL& dest_url = entry.GetURL();
415 NavigationControllerImpl& controller = 429 NavigationControllerImpl& controller =
416 delegate_->GetControllerForRenderManager(); 430 delegate_->GetControllerForRenderManager();
417 content::BrowserContext* browser_context = controller.GetBrowserContext(); 431 content::BrowserContext* browser_context = controller.GetBrowserContext();
418 432
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 } else { 588 } else {
575 CancelPending(); 589 CancelPending();
576 } 590 }
577 return success; 591 return success;
578 } 592 }
579 593
580 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, 594 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host,
581 const NavigationEntryImpl& entry) { 595 const NavigationEntryImpl& entry) {
582 // If the pending navigation is to a WebUI, tell the RenderView about any 596 // If the pending navigation is to a WebUI, tell the RenderView about any
583 // bindings it will need enabled. 597 // bindings it will need enabled.
584 if (pending_web_ui_.get()) 598 if (pending_web_ui())
585 render_view_host->AllowBindings(pending_web_ui_->GetBindings()); 599 render_view_host->AllowBindings(pending_web_ui()->GetBindings());
586 600
587 return delegate_->CreateRenderViewForRenderManager(render_view_host); 601 return delegate_->CreateRenderViewForRenderManager(render_view_host);
588 } 602 }
589 603
590 void RenderViewHostManager::CommitPending() { 604 void RenderViewHostManager::CommitPending() {
591 // First check whether we're going to want to focus the location bar after 605 // First check whether we're going to want to focus the location bar after
592 // this commit. We do this now because the navigation hasn't formally 606 // this commit. We do this now because the navigation hasn't formally
593 // committed yet, so if we've already cleared |pending_web_ui_| the call chain 607 // committed yet, so if we've already cleared |pending_web_ui_| the call chain
594 // this triggers won't be able to figure out what's going on. 608 // this triggers won't be able to figure out what's going on.
595 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); 609 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
596 610
597 // Next commit the Web UI, if any. 611 // Next commit the Web UI, if any. Either replace |web_ui_| with
598 web_ui_.swap(pending_web_ui_); 612 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
599 if (web_ui_.get() && pending_web_ui_.get() && !pending_render_view_host_) 613 // leave |web_ui_| as is if reusing it.
600 web_ui_->GetController()->DidBecomeActiveForReusedRenderView(); 614 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get()));
601 pending_web_ui_.reset(); 615 if (pending_web_ui_.get())
616 web_ui_.reset(pending_web_ui_.release());
617 else if (!pending_and_current_web_ui_.get())
618 web_ui_.reset();
602 619
603 // It's possible for the pending_render_view_host_ to be NULL when we aren't 620 // It's possible for the pending_render_view_host_ to be NULL when we aren't
604 // crossing process boundaries. If so, we just needed to handle the Web UI 621 // crossing process boundaries. If so, we just needed to handle the Web UI
605 // committing above and we're done. 622 // committing above and we're done.
606 if (!pending_render_view_host_) { 623 if (!pending_render_view_host_) {
607 if (will_focus_location_bar) 624 if (will_focus_location_bar)
608 delegate_->SetFocusToLocationBar(false); 625 delegate_->SetFocusToLocationBar(false);
609 return; 626 return;
610 } 627 }
611 628
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate( 702 RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
686 const NavigationEntryImpl& entry) { 703 const NavigationEntryImpl& entry) {
687 // If we are cross-navigating, then we want to get back to normal and navigate 704 // If we are cross-navigating, then we want to get back to normal and navigate
688 // as usual. 705 // as usual.
689 if (cross_navigation_pending_) { 706 if (cross_navigation_pending_) {
690 if (pending_render_view_host_) 707 if (pending_render_view_host_)
691 CancelPending(); 708 CancelPending();
692 cross_navigation_pending_ = false; 709 cross_navigation_pending_ = false;
693 } 710 }
694 711
695 // This will possibly create (set to NULL) a Web UI object for the pending
696 // page. We'll use this later to give the page special access. This must
697 // happen before the new renderer is created below so it will get bindings.
698 // It must also happen after the above conditional call to CancelPending(),
699 // otherwise CancelPending may clear the pending_web_ui_ and the page will
700 // not have it's bindings set appropriately.
701 pending_web_ui_.reset(delegate_->CreateWebUIForRenderManager(entry.GetURL()));
702
703 // render_view_host_ will not be deleted before the end of this method, so we 712 // render_view_host_ will not be deleted before the end of this method, so we
704 // don't have to worry about this SiteInstance's ref count dropping to zero. 713 // don't have to worry about this SiteInstance's ref count dropping to zero.
705 SiteInstance* curr_instance = render_view_host_->GetSiteInstance(); 714 SiteInstance* curr_instance = render_view_host_->GetSiteInstance();
706 715
707 // Determine if we need a new SiteInstance for this entry. 716 // Determine if we need a new SiteInstance for this entry.
708 // Again, new_instance won't be deleted before the end of this method, so it 717 // Again, new_instance won't be deleted before the end of this method, so it
709 // is safe to use a normal pointer here. 718 // is safe to use a normal pointer here.
710 SiteInstance* new_instance = curr_instance; 719 SiteInstance* new_instance = curr_instance;
711 bool force_swap = ShouldSwapProcessesForNavigation( 720 const content::NavigationEntry* curr_entry =
712 delegate_->GetLastCommittedNavigationEntryForRenderManager(), &entry); 721 delegate_->GetLastCommittedNavigationEntryForRenderManager();
722 bool force_swap = ShouldSwapProcessesForNavigation(curr_entry, &entry);
713 if (ShouldTransitionCrossSite() || force_swap) 723 if (ShouldTransitionCrossSite() || force_swap)
714 new_instance = GetSiteInstanceForEntry(entry, curr_instance); 724 new_instance = GetSiteInstanceForEntry(entry, curr_instance);
715 725
716 if (new_instance != curr_instance || force_swap) { 726 if (new_instance != curr_instance || force_swap) {
717 // New SiteInstance. 727 // New SiteInstance.
718 DCHECK(!cross_navigation_pending_); 728 DCHECK(!cross_navigation_pending_);
719 729
730 // 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
732 // 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(),
734 // otherwise CancelPending may clear the pending_web_ui_ and the page will
735 // not have its bindings set appropriately.
736 pending_web_ui_.reset(
737 delegate_->CreateWebUIForRenderManager(entry.GetURL()));
738 pending_and_current_web_ui_.reset();
739
720 // Create a pending RVH and navigate it. 740 // Create a pending RVH and navigate it.
721 bool success = CreatePendingRenderView(entry, new_instance); 741 bool success = CreatePendingRenderView(entry, new_instance);
722 if (!success) 742 if (!success)
723 return NULL; 743 return NULL;
724 744
725 // Check if our current RVH is live before we set up a transition. 745 // Check if our current RVH is live before we set up a transition.
726 if (!render_view_host_->IsRenderViewLive()) { 746 if (!render_view_host_->IsRenderViewLive()) {
727 if (!cross_navigation_pending_) { 747 if (!cross_navigation_pending_) {
728 // The current RVH is not live. There's no reason to sit around with a 748 // The current RVH is not live. There's no reason to sit around with a
729 // sad tab or a newly created RVH while we wait for the pending RVH to 749 // sad tab or a newly created RVH while we wait for the pending RVH to
(...skipping 29 matching lines...) Expand all
759 DCHECK(!cross_navigation_pending_); 779 DCHECK(!cross_navigation_pending_);
760 cross_navigation_pending_ = true; 780 cross_navigation_pending_ = true;
761 781
762 // Tell the old render view to run its onbeforeunload handler, since it 782 // Tell the old render view to run its onbeforeunload handler, since it
763 // doesn't otherwise know that the cross-site request is happening. This 783 // doesn't otherwise know that the cross-site request is happening. This
764 // will trigger a call to ShouldClosePage with the reply. 784 // will trigger a call to ShouldClosePage with the reply.
765 render_view_host_->FirePageBeforeUnload(true); 785 render_view_host_->FirePageBeforeUnload(true);
766 786
767 return pending_render_view_host_; 787 return pending_render_view_host_;
768 } else { 788 } else {
769 if (pending_web_ui_.get() && render_view_host_->IsRenderViewLive()) 789 if (ShouldReuseWebUI(curr_entry, &entry)) {
770 pending_web_ui_->GetController()->RenderViewReused(render_view_host_); 790 pending_web_ui_.reset();
791 pending_and_current_web_ui_ = web_ui_->AsWeakPtr();
792 } else {
793 pending_and_current_web_ui_.reset();
794 pending_web_ui_.reset(
795 delegate_->CreateWebUIForRenderManager(entry.GetURL()));
796 }
797
798 if (pending_web_ui() && render_view_host_->IsRenderViewLive())
799 pending_web_ui()->GetController()->RenderViewReused(render_view_host_);
771 800
772 // The renderer can exit view source mode when any error or cancellation 801 // The renderer can exit view source mode when any error or cancellation
773 // happen. We must overwrite to recover the mode. 802 // happen. We must overwrite to recover the mode.
774 if (entry.IsViewSourceMode()) { 803 if (entry.IsViewSourceMode()) {
775 render_view_host_->Send( 804 render_view_host_->Send(
776 new ViewMsg_EnableViewSourceMode(render_view_host_->GetRoutingID())); 805 new ViewMsg_EnableViewSourceMode(render_view_host_->GetRoutingID()));
777 } 806 }
778 } 807 }
779 808
780 // Same SiteInstance can be used. Navigate render_view_host_ if we are not 809 // Same SiteInstance can be used. Navigate render_view_host_ if we are not
(...skipping 23 matching lines...) Expand all
804 833
805 // We can pass -1,-1 because there is no pending response in the 834 // We can pass -1,-1 because there is no pending response in the
806 // ResourceDispatcherHost to unpause. 835 // ResourceDispatcherHost to unpause.
807 pending_render_view_host->SwapOut(-1, -1); 836 pending_render_view_host->SwapOut(-1, -1);
808 } else { 837 } else {
809 // We won't be coming back, so shut this one down. 838 // We won't be coming back, so shut this one down.
810 pending_render_view_host->Shutdown(); 839 pending_render_view_host->Shutdown();
811 } 840 }
812 841
813 pending_web_ui_.reset(); 842 pending_web_ui_.reset();
843 pending_and_current_web_ui_.reset();
814 } 844 }
815 845
816 void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) { 846 void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) {
817 // We are doing this in order to work around and to track a crasher 847 // We are doing this in order to work around and to track a crasher
818 // (http://crbug.com/23411) where it seems that pending_render_view_host_ is 848 // (http://crbug.com/23411) where it seems that pending_render_view_host_ is
819 // deleted (not sure from where) but not NULLed. 849 // deleted (not sure from where) but not NULLed.
820 if (rvh == pending_render_view_host_) { 850 if (rvh == pending_render_view_host_) {
821 // If you hit this NOTREACHED, please report it in the following bug 851 // If you hit this NOTREACHED, please report it in the following bug
822 // http://crbug.com/23411 Make sure to include what you were doing when it 852 // http://crbug.com/23411 Make sure to include what you were doing when it
823 // happened (navigating to a new page, closing a tab...) and if you can 853 // happened (navigating to a new page, closing a tab...) and if you can
(...skipping 17 matching lines...) Expand all
841 } 871 }
842 } 872 }
843 873
844 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) { 874 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) {
845 if (!rvh->GetSiteInstance()) 875 if (!rvh->GetSiteInstance())
846 return false; 876 return false;
847 877
848 return swapped_out_hosts_.find(rvh->GetSiteInstance()->GetId()) != 878 return swapped_out_hosts_.find(rvh->GetSiteInstance()->GetId()) !=
849 swapped_out_hosts_.end(); 879 swapped_out_hosts_.end();
850 } 880 }
OLDNEW
« no previous file with comments | « content/browser/web_contents/render_view_host_manager.h ('k') | content/browser/web_contents/web_contents_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698