| 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" |
| 11 #include "content/browser/child_process_security_policy_impl.h" | |
| 12 #include "content/browser/debugger/devtools_manager_impl.h" | 11 #include "content/browser/debugger/devtools_manager_impl.h" |
| 13 #include "content/browser/renderer_host/render_view_host_factory.h" | 12 #include "content/browser/renderer_host/render_view_host_factory.h" |
| 14 #include "content/browser/renderer_host/render_view_host_impl.h" | 13 #include "content/browser/renderer_host/render_view_host_impl.h" |
| 15 #include "content/browser/site_instance_impl.h" | 14 #include "content/browser/site_instance_impl.h" |
| 16 #include "content/browser/web_contents/navigation_controller_impl.h" | 15 #include "content/browser/web_contents/navigation_controller_impl.h" |
| 17 #include "content/browser/web_contents/navigation_entry_impl.h" | 16 #include "content/browser/web_contents/navigation_entry_impl.h" |
| 18 #include "content/browser/webui/web_ui_impl.h" | 17 #include "content/browser/webui/web_ui_impl.h" |
| 19 #include "content/common/view_messages.h" | 18 #include "content/common/view_messages.h" |
| 20 #include "content/port/browser/render_widget_host_view_port.h" | 19 #include "content/port/browser/render_widget_host_view_port.h" |
| 21 #include "content/public/browser/content_browser_client.h" | 20 #include "content/public/browser/content_browser_client.h" |
| 22 #include "content/public/browser/notification_service.h" | 21 #include "content/public/browser/notification_service.h" |
| 23 #include "content/public/browser/notification_types.h" | 22 #include "content/public/browser/notification_types.h" |
| 24 #include "content/public/browser/web_contents_view.h" | 23 #include "content/public/browser/web_contents_view.h" |
| 25 #include "content/public/browser/web_ui_controller.h" | 24 #include "content/public/browser/web_ui_controller.h" |
| 26 #include "content/public/browser/web_ui_controller_factory.h" | 25 #include "content/public/browser/web_ui_controller_factory.h" |
| 27 #include "content/public/common/bindings_policy.h" | |
| 28 #include "content/public/common/content_switches.h" | 26 #include "content/public/common/content_switches.h" |
| 29 #include "content/public/common/url_constants.h" | 27 #include "content/public/common/url_constants.h" |
| 30 | 28 |
| 31 using content::NavigationController; | 29 using content::NavigationController; |
| 32 using content::NavigationEntry; | 30 using content::NavigationEntry; |
| 33 using content::NavigationEntryImpl; | 31 using content::NavigationEntryImpl; |
| 34 using content::RenderViewHost; | 32 using content::RenderViewHost; |
| 35 using content::RenderViewHostImpl; | 33 using content::RenderViewHostImpl; |
| 36 using content::RenderWidgetHostView; | 34 using content::RenderWidgetHostView; |
| 37 using content::RenderWidgetHostViewPort; | 35 using content::RenderWidgetHostViewPort; |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 NOTREACHED(); | 351 NOTREACHED(); |
| 354 } | 352 } |
| 355 } | 353 } |
| 356 | 354 |
| 357 bool RenderViewHostManager::ShouldTransitionCrossSite() { | 355 bool RenderViewHostManager::ShouldTransitionCrossSite() { |
| 358 // True if we are using process-per-site-instance (default) or | 356 // True if we are using process-per-site-instance (default) or |
| 359 // process-per-site (kProcessPerSite). | 357 // process-per-site (kProcessPerSite). |
| 360 return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab); | 358 return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab); |
| 361 } | 359 } |
| 362 | 360 |
| 363 bool RenderViewHostManager::ShouldSwapBrowsingInstanceForNavigation( | 361 bool RenderViewHostManager::ShouldSwapProcessesForNavigation( |
| 364 const NavigationEntry* current_entry, | 362 const NavigationEntry* curr_entry, |
| 365 const NavigationEntryImpl* new_entry) const { | 363 const NavigationEntryImpl* new_entry) const { |
| 366 DCHECK(new_entry); | 364 DCHECK(new_entry); |
| 367 | 365 |
| 368 // If new_entry already has a SiteInstance, assume it is correct and use it. | |
| 369 if (new_entry->site_instance()) | |
| 370 return false; | |
| 371 | |
| 372 // Check for reasons to swap processes even if we are in a process model that | 366 // Check for reasons to swap processes even if we are in a process model that |
| 373 // doesn't usually swap (e.g., process-per-tab). Any time we return true, | 367 // doesn't usually swap (e.g., process-per-tab). |
| 374 // the new_entry will be rendered in a new SiteInstance AND BrowsingInstance. | |
| 375 | 368 |
| 376 // For security, we should transition between processes when one is a Web UI | 369 // For security, we should transition between processes when one is a Web UI |
| 377 // page and one isn't. If there's no current_entry, check the current RVH's | 370 // page and one isn't. If there's no curr_entry, check the current RVH's |
| 378 // site, which might already be committed to a Web UI URL (such as the NTP). | 371 // site, which might already be committed to a Web UI URL (such as the NTP). |
| 379 const GURL& current_url = current_entry ? current_entry->GetURL() : | 372 const GURL& current_url = (curr_entry) ? curr_entry->GetURL() : |
| 380 render_view_host_->GetSiteInstance()->GetSite(); | 373 render_view_host_->GetSiteInstance()->GetSite(); |
| 381 const GURL& new_url = new_entry->GetURL(); | |
| 382 content::BrowserContext* browser_context = | 374 content::BrowserContext* browser_context = |
| 383 delegate_->GetControllerForRenderManager().GetBrowserContext(); | 375 delegate_->GetControllerForRenderManager().GetBrowserContext(); |
| 384 const WebUIControllerFactory* web_ui_factory = | 376 const WebUIControllerFactory* web_ui_factory = |
| 385 content::GetContentClient()->browser()->GetWebUIControllerFactory(); | 377 content::GetContentClient()->browser()->GetWebUIControllerFactory(); |
| 386 if (web_ui_factory) { | 378 if (web_ui_factory) { |
| 387 int enabled_bindings = render_view_host_->GetEnabledBindings(); | 379 if (web_ui_factory->UseWebUIForURL(browser_context, current_url)) { |
| 388 | 380 // Force swap if it's not an acceptable URL for Web UI. |
| 389 // Check if we're currently in a WebUI RenderViewHost, based on either URL | |
| 390 // or bindings. | |
| 391 if (enabled_bindings & content::BINDINGS_POLICY_WEB_UI || | |
| 392 web_ui_factory->UseWebUIForURL(browser_context, current_url)) { | |
| 393 // If so, force a swap if destination not an acceptable URL for Web UI. | |
| 394 // Here, data URLs are never allowed. | 381 // Here, data URLs are never allowed. |
| 395 if (!web_ui_factory->IsURLAcceptableForWebUI(browser_context, new_url, | 382 if (!web_ui_factory->IsURLAcceptableForWebUI(browser_context, |
| 396 false)) | 383 new_entry->GetURL(), false)) |
| 397 return true; | 384 return true; |
| 398 } else { | 385 } else { |
| 399 // Force a swap if it's a Web UI URL. | 386 // Force swap if it's a Web UI URL. |
| 400 if (web_ui_factory->UseWebUIForURL(browser_context, new_url)) | 387 if (web_ui_factory->UseWebUIForURL(browser_context, new_entry->GetURL())) |
| 401 return true; | 388 return true; |
| 402 } | 389 } |
| 403 } | 390 } |
| 404 | 391 |
| 405 // Also let the embedder decide if a BrowsingInstance swap is required. | 392 if (content::GetContentClient()->browser()->ShouldSwapProcessesForNavigation( |
| 406 if (content::GetContentClient()->browser()-> | 393 curr_entry ? curr_entry->GetURL() : GURL(), new_entry->GetURL())) { |
| 407 ShouldSwapBrowsingInstanceForNavigation(browser_context, | |
| 408 current_url, new_url)) { | |
| 409 return true; | 394 return true; |
| 410 } | 395 } |
| 411 | 396 |
| 397 if (!curr_entry) |
| 398 return false; |
| 399 |
| 412 // We can't switch a RenderView between view source and non-view source mode | 400 // We can't switch a RenderView between view source and non-view source mode |
| 413 // without screwing up the session history sometimes (when navigating between | 401 // without screwing up the session history sometimes (when navigating between |
| 414 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat | 402 // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat |
| 415 // it as a new navigation). So require a BrowsingInstance switch. | 403 // it as a new navigation). So require a view switch. |
| 416 if (current_entry && | 404 if (curr_entry->IsViewSourceMode() != new_entry->IsViewSourceMode()) |
| 417 current_entry->IsViewSourceMode() != new_entry->IsViewSourceMode()) { | |
| 418 return true; | 405 return true; |
| 419 } | |
| 420 | 406 |
| 421 return false; | 407 return false; |
| 422 } | 408 } |
| 423 | 409 |
| 424 bool RenderViewHostManager::ShouldReuseWebUI( | 410 bool RenderViewHostManager::ShouldReuseWebUI( |
| 425 const NavigationEntry* curr_entry, | 411 const NavigationEntry* curr_entry, |
| 426 const NavigationEntryImpl* new_entry) const { | 412 const NavigationEntryImpl* new_entry) const { |
| 427 NavigationControllerImpl& controller = | 413 NavigationControllerImpl& controller = |
| 428 delegate_->GetControllerForRenderManager(); | 414 delegate_->GetControllerForRenderManager(); |
| 429 WebUIControllerFactory* factory = | 415 WebUIControllerFactory* factory = |
| 430 content::GetContentClient()->browser()->GetWebUIControllerFactory(); | 416 content::GetContentClient()->browser()->GetWebUIControllerFactory(); |
| 431 return curr_entry && web_ui_.get() && | 417 return curr_entry && web_ui_.get() && |
| 432 (factory->GetWebUIType(controller.GetBrowserContext(), | 418 (factory->GetWebUIType(controller.GetBrowserContext(), |
| 433 curr_entry->GetURL()) == | 419 curr_entry->GetURL()) == |
| 434 factory->GetWebUIType(controller.GetBrowserContext(), | 420 factory->GetWebUIType(controller.GetBrowserContext(), |
| 435 new_entry->GetURL())); | 421 new_entry->GetURL())); |
| 436 } | 422 } |
| 437 | 423 |
| 438 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( | 424 SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( |
| 439 const NavigationEntryImpl& entry, | 425 const NavigationEntryImpl& entry, |
| 440 SiteInstance* curr_instance, | 426 SiteInstance* curr_instance) { |
| 441 bool force_swap) { | 427 // NOTE: This is only called when ShouldTransitionCrossSite is true. |
| 442 // Determine which SiteInstance to use for navigating to |entry|. | 428 |
| 443 const GURL& dest_url = entry.GetURL(); | 429 const GURL& dest_url = entry.GetURL(); |
| 444 NavigationControllerImpl& controller = | 430 NavigationControllerImpl& controller = |
| 445 delegate_->GetControllerForRenderManager(); | 431 delegate_->GetControllerForRenderManager(); |
| 446 content::BrowserContext* browser_context = controller.GetBrowserContext(); | 432 content::BrowserContext* browser_context = controller.GetBrowserContext(); |
| 447 | 433 |
| 448 // If a swap is required, we need to force the SiteInstance AND | |
| 449 // BrowsingInstance to be different ones. This addresses special cases where | |
| 450 // we use a single BrowsingInstance for all pages of a certain type (e.g., New | |
| 451 // Tab Pages), keeping them in the same process. When you navigate away from | |
| 452 // that page, we want to explicity ignore that BrowsingInstance and group this | |
| 453 // page into the appropriate SiteInstance for its URL. | |
| 454 if (force_swap) { | |
| 455 // We shouldn't be forcing a swap if an entry already has a SiteInstance. | |
| 456 DCHECK(!entry.site_instance()); | |
| 457 return SiteInstance::CreateForURL(browser_context, dest_url); | |
| 458 } | |
| 459 | |
| 460 // If the entry has an instance already we should use it. | 434 // If the entry has an instance already we should use it. |
| 461 if (entry.site_instance()) | 435 if (entry.site_instance()) |
| 462 return entry.site_instance(); | 436 return entry.site_instance(); |
| 463 | 437 |
| 464 // (UGLY) HEURISTIC, process-per-site only: | 438 // (UGLY) HEURISTIC, process-per-site only: |
| 439 // |
| 465 // If this navigation is generated, then it probably corresponds to a search | 440 // If this navigation is generated, then it probably corresponds to a search |
| 466 // query. Given that search results typically lead to users navigating to | 441 // query. Given that search results typically lead to users navigating to |
| 467 // other sites, we don't really want to use the search engine hostname to | 442 // other sites, we don't really want to use the search engine hostname to |
| 468 // determine the site instance for this navigation. | 443 // determine the site instance for this navigation. |
| 444 // |
| 469 // NOTE: This can be removed once we have a way to transition between | 445 // NOTE: This can be removed once we have a way to transition between |
| 470 // RenderViews in response to a link click. | 446 // RenderViews in response to a link click. |
| 447 // |
| 471 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerSite) && | 448 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerSite) && |
| 472 entry.GetTransitionType() == content::PAGE_TRANSITION_GENERATED) | 449 entry.GetTransitionType() == content::PAGE_TRANSITION_GENERATED) |
| 473 return curr_instance; | 450 return curr_instance; |
| 474 | 451 |
| 475 SiteInstanceImpl* curr_site_instance = | 452 SiteInstanceImpl* curr_site_instance = |
| 476 static_cast<SiteInstanceImpl*>(curr_instance); | 453 static_cast<SiteInstanceImpl*>(curr_instance); |
| 477 | 454 |
| 478 // If we haven't used our SiteInstance (and thus RVH) yet, then we can use it | 455 // If we haven't used our SiteInstance (and thus RVH) yet, then we can use it |
| 479 // for this entry. We won't commit the SiteInstance to this site until the | 456 // for this entry. We won't commit the SiteInstance to this site until the |
| 480 // navigation commits (in DidNavigate), unless the navigation entry was | 457 // navigation commits (in DidNavigate), unless the navigation entry was |
| (...skipping 22 matching lines...) Expand all Loading... |
| 503 // | 480 // |
| 504 // In the case of session restore, as it loads all the pages immediately | 481 // In the case of session restore, as it loads all the pages immediately |
| 505 // we need to set the site first, otherwise after a restore none of the | 482 // we need to set the site first, otherwise after a restore none of the |
| 506 // pages would share renderers in process-per-site. | 483 // pages would share renderers in process-per-site. |
| 507 if (entry.restore_type() != NavigationEntryImpl::RESTORE_NONE) | 484 if (entry.restore_type() != NavigationEntryImpl::RESTORE_NONE) |
| 508 curr_site_instance->SetSite(dest_url); | 485 curr_site_instance->SetSite(dest_url); |
| 509 | 486 |
| 510 return curr_site_instance; | 487 return curr_site_instance; |
| 511 } | 488 } |
| 512 | 489 |
| 513 // Otherwise, only create a new SiteInstance for a cross-site navigation. | 490 // Otherwise, only create a new SiteInstance for cross-site navigation. |
| 514 | 491 |
| 515 // TODO(creis): Once we intercept links and script-based navigations, we | 492 // TODO(creis): Once we intercept links and script-based navigations, we |
| 516 // will be able to enforce that all entries in a SiteInstance actually have | 493 // will be able to enforce that all entries in a SiteInstance actually have |
| 517 // the same site, and it will be safe to compare the URL against the | 494 // the same site, and it will be safe to compare the URL against the |
| 518 // SiteInstance's site, as follows: | 495 // SiteInstance's site, as follows: |
| 519 // const GURL& current_url = curr_instance->site(); | 496 // const GURL& current_url = curr_instance->site(); |
| 520 // For now, though, we're in a hybrid model where you only switch | 497 // For now, though, we're in a hybrid model where you only switch |
| 521 // SiteInstances if you type in a cross-site URL. This means we have to | 498 // SiteInstances if you type in a cross-site URL. This means we have to |
| 522 // compare the entry's URL to the last committed entry's URL. | 499 // compare the entry's URL to the last committed entry's URL. |
| 523 NavigationEntry* curr_entry = controller.GetLastCommittedEntry(); | 500 NavigationEntry* curr_entry = controller.GetLastCommittedEntry(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 544 // See http://crbug.com/123007. | 521 // See http://crbug.com/123007. |
| 545 if (curr_entry && | 522 if (curr_entry && |
| 546 curr_entry->IsViewSourceMode() != entry.IsViewSourceMode()) { | 523 curr_entry->IsViewSourceMode() != entry.IsViewSourceMode()) { |
| 547 return SiteInstance::CreateForURL(browser_context, dest_url); | 524 return SiteInstance::CreateForURL(browser_context, dest_url); |
| 548 } | 525 } |
| 549 | 526 |
| 550 // Use the current SiteInstance for same site navigations, as long as the | 527 // Use the current SiteInstance for same site navigations, as long as the |
| 551 // process type is correct. (The URL may have been installed as an app since | 528 // process type is correct. (The URL may have been installed as an app since |
| 552 // the last time we visited it.) | 529 // the last time we visited it.) |
| 553 if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) && | 530 if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) && |
| 554 !curr_site_instance->HasWrongProcessForURL(dest_url)) { | 531 !static_cast<SiteInstanceImpl*>(curr_instance)->HasWrongProcessForURL( |
| 532 dest_url)) { |
| 555 return curr_instance; | 533 return curr_instance; |
| 534 } else if (ShouldSwapProcessesForNavigation(curr_entry, &entry)) { |
| 535 // When we're swapping, we need to force the site instance AND browsing |
| 536 // instance to be different ones. This addresses special cases where we use |
| 537 // a single BrowsingInstance for all pages of a certain type (e.g., New Tab |
| 538 // Pages), keeping them in the same process. When you navigate away from |
| 539 // that page, we want to explicity ignore that BrowsingInstance and group |
| 540 // this page into the appropriate SiteInstance for its URL. |
| 541 return SiteInstance::CreateForURL(browser_context, dest_url); |
| 542 } else { |
| 543 // Start the new renderer in a new SiteInstance, but in the current |
| 544 // BrowsingInstance. It is important to immediately give this new |
| 545 // SiteInstance to a RenderViewHost (if it is different than our current |
| 546 // SiteInstance), so that it is ref counted. This will happen in |
| 547 // CreateRenderView. |
| 548 return curr_instance->GetRelatedSiteInstance(dest_url); |
| 556 } | 549 } |
| 557 | |
| 558 // Otherwise start the new renderer in a new SiteInstance, but in the current | |
| 559 // BrowsingInstance. It is important to immediately give this new | |
| 560 // SiteInstance to a RenderViewHost (if it is different than our current | |
| 561 // SiteInstance), so that it is ref counted. This will happen in | |
| 562 // CreateRenderView. | |
| 563 return curr_instance->GetRelatedSiteInstance(dest_url); | |
| 564 } | 550 } |
| 565 | 551 |
| 566 int RenderViewHostManager::CreateRenderView( | 552 int RenderViewHostManager::CreateRenderView( |
| 567 SiteInstance* instance, | 553 SiteInstance* instance, |
| 568 int opener_route_id, | 554 int opener_route_id, |
| 569 bool swapped_out) { | 555 bool swapped_out) { |
| 570 CHECK(instance); | 556 CHECK(instance); |
| 571 | 557 |
| 572 // Check if we've already created an RVH for this SiteInstance. If so, try | 558 // Check if we've already created an RVH for this SiteInstance. If so, try |
| 573 // to re-use the existing one, which has already been initialized. We'll | 559 // to re-use the existing one, which has already been initialized. We'll |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 if (!swapped_out) | 593 if (!swapped_out) |
| 608 pending_render_view_host_ = new_render_view_host; | 594 pending_render_view_host_ = new_render_view_host; |
| 609 | 595 |
| 610 return new_render_view_host->GetRoutingID(); | 596 return new_render_view_host->GetRoutingID(); |
| 611 } | 597 } |
| 612 | 598 |
| 613 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, | 599 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, |
| 614 int opener_route_id) { | 600 int opener_route_id) { |
| 615 // If the pending navigation is to a WebUI, tell the RenderView about any | 601 // If the pending navigation is to a WebUI, tell the RenderView about any |
| 616 // bindings it will need enabled. | 602 // bindings it will need enabled. |
| 617 if (pending_web_ui()) { | 603 if (pending_web_ui()) |
| 618 render_view_host->AllowBindings(pending_web_ui()->GetBindings()); | 604 render_view_host->AllowBindings(pending_web_ui()->GetBindings()); |
| 619 } else { | |
| 620 // Ensure that we don't create an unprivileged view in a WebUI-enabled | |
| 621 // process. | |
| 622 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( | |
| 623 render_view_host->GetProcess()->GetID())); | |
| 624 } | |
| 625 | 605 |
| 626 return delegate_->CreateRenderViewForRenderManager(render_view_host, | 606 return delegate_->CreateRenderViewForRenderManager(render_view_host, |
| 627 opener_route_id); | 607 opener_route_id); |
| 628 } | 608 } |
| 629 | 609 |
| 630 void RenderViewHostManager::CommitPending() { | 610 void RenderViewHostManager::CommitPending() { |
| 631 // First check whether we're going to want to focus the location bar after | 611 // First check whether we're going to want to focus the location bar after |
| 632 // this commit. We do this now because the navigation hasn't formally | 612 // this commit. We do this now because the navigation hasn't formally |
| 633 // committed yet, so if we've already cleared |pending_web_ui_| the call chain | 613 // committed yet, so if we've already cleared |pending_web_ui_| the call chain |
| 634 // this triggers won't be able to figure out what's going on. | 614 // this triggers won't be able to figure out what's going on. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 old_render_view_host->Shutdown(); | 700 old_render_view_host->Shutdown(); |
| 721 } | 701 } |
| 722 | 702 |
| 723 // Let the task manager know that we've swapped RenderViewHosts, since it | 703 // Let the task manager know that we've swapped RenderViewHosts, since it |
| 724 // might need to update its process groupings. | 704 // might need to update its process groupings. |
| 725 delegate_->NotifySwappedFromRenderManager(); | 705 delegate_->NotifySwappedFromRenderManager(); |
| 726 } | 706 } |
| 727 | 707 |
| 728 RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate( | 708 RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate( |
| 729 const NavigationEntryImpl& entry) { | 709 const NavigationEntryImpl& entry) { |
| 730 // If we are currently navigating cross-process, we want to get back to normal | 710 // If we are cross-navigating, then we want to get back to normal and navigate |
| 731 // and then navigate as usual. | 711 // as usual. |
| 732 if (cross_navigation_pending_) { | 712 if (cross_navigation_pending_) { |
| 733 if (pending_render_view_host_) | 713 if (pending_render_view_host_) |
| 734 CancelPending(); | 714 CancelPending(); |
| 735 cross_navigation_pending_ = false; | 715 cross_navigation_pending_ = false; |
| 736 } | 716 } |
| 737 | 717 |
| 738 // render_view_host_'s SiteInstance and new_instance will not be deleted | 718 // render_view_host_ will not be deleted before the end of this method, so we |
| 739 // before the end of this method, so we don't have to worry about their ref | 719 // don't have to worry about this SiteInstance's ref count dropping to zero. |
| 740 // counts dropping to zero. | |
| 741 SiteInstance* curr_instance = render_view_host_->GetSiteInstance(); | 720 SiteInstance* curr_instance = render_view_host_->GetSiteInstance(); |
| 721 |
| 722 // Determine if we need a new SiteInstance for this entry. |
| 723 // Again, new_instance won't be deleted before the end of this method, so it |
| 724 // is safe to use a normal pointer here. |
| 742 SiteInstance* new_instance = curr_instance; | 725 SiteInstance* new_instance = curr_instance; |
| 743 | |
| 744 // Determine if we need a new BrowsingInstance for this entry. If true, | |
| 745 // this implies it will get a new SiteInstance (and likely process), and | |
| 746 // that other tabs in the current BrowsingInstance will be unable to script | |
| 747 // it. This is used for cases that require a process swap even in the | |
| 748 // process-per-tab model, such as WebUI pages. | |
| 749 const content::NavigationEntry* curr_entry = | 726 const content::NavigationEntry* curr_entry = |
| 750 delegate_->GetLastCommittedNavigationEntryForRenderManager(); | 727 delegate_->GetLastCommittedNavigationEntryForRenderManager(); |
| 751 bool force_swap = ShouldSwapBrowsingInstanceForNavigation(curr_entry, | 728 bool force_swap = ShouldSwapProcessesForNavigation(curr_entry, &entry); |
| 752 &entry); | |
| 753 if (ShouldTransitionCrossSite() || force_swap) | 729 if (ShouldTransitionCrossSite() || force_swap) |
| 754 new_instance = GetSiteInstanceForEntry(entry, curr_instance, force_swap); | 730 new_instance = GetSiteInstanceForEntry(entry, curr_instance); |
| 755 | 731 |
| 756 // If force_swap is true, we must use a different SiteInstance. If we didn't, | 732 if (new_instance != curr_instance || force_swap) { |
| 757 // we would have two RenderViewHosts in the same SiteInstance and the same | 733 // New SiteInstance. |
| 758 // tab, resulting in page_id conflicts for their NavigationEntries. | |
| 759 if (force_swap) | |
| 760 CHECK_NE(new_instance, curr_instance); | |
| 761 | |
| 762 if (new_instance != curr_instance) { | |
| 763 // New SiteInstance: create a pending RVH to navigate. | |
| 764 DCHECK(!cross_navigation_pending_); | 734 DCHECK(!cross_navigation_pending_); |
| 765 | 735 |
| 766 // This will possibly create (set to NULL) a Web UI object for the pending | 736 // This will possibly create (set to NULL) a Web UI object for the pending |
| 767 // page. We'll use this later to give the page special access. This must | 737 // page. We'll use this later to give the page special access. This must |
| 768 // happen before the new renderer is created below so it will get bindings. | 738 // happen before the new renderer is created below so it will get bindings. |
| 769 // It must also happen after the above conditional call to CancelPending(), | 739 // It must also happen after the above conditional call to CancelPending(), |
| 770 // otherwise CancelPending may clear the pending_web_ui_ and the page will | 740 // otherwise CancelPending may clear the pending_web_ui_ and the page will |
| 771 // not have its bindings set appropriately. | 741 // not have its bindings set appropriately. |
| 772 pending_web_ui_.reset( | 742 pending_web_ui_.reset( |
| 773 delegate_->CreateWebUIForRenderManager(entry.GetURL())); | 743 delegate_->CreateWebUIForRenderManager(entry.GetURL())); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 824 // We now have a pending RVH. | 794 // We now have a pending RVH. |
| 825 DCHECK(!cross_navigation_pending_); | 795 DCHECK(!cross_navigation_pending_); |
| 826 cross_navigation_pending_ = true; | 796 cross_navigation_pending_ = true; |
| 827 | 797 |
| 828 // Tell the old render view to run its onbeforeunload handler, since it | 798 // Tell the old render view to run its onbeforeunload handler, since it |
| 829 // doesn't otherwise know that the cross-site request is happening. This | 799 // doesn't otherwise know that the cross-site request is happening. This |
| 830 // will trigger a call to ShouldClosePage with the reply. | 800 // will trigger a call to ShouldClosePage with the reply. |
| 831 render_view_host_->FirePageBeforeUnload(true); | 801 render_view_host_->FirePageBeforeUnload(true); |
| 832 | 802 |
| 833 return pending_render_view_host_; | 803 return pending_render_view_host_; |
| 804 } else { |
| 805 if (ShouldReuseWebUI(curr_entry, &entry)) { |
| 806 pending_web_ui_.reset(); |
| 807 pending_and_current_web_ui_ = web_ui_->AsWeakPtr(); |
| 808 } else { |
| 809 pending_and_current_web_ui_.reset(); |
| 810 pending_web_ui_.reset( |
| 811 delegate_->CreateWebUIForRenderManager(entry.GetURL())); |
| 812 } |
| 813 |
| 814 if (pending_web_ui() && render_view_host_->IsRenderViewLive()) |
| 815 pending_web_ui()->GetController()->RenderViewReused(render_view_host_); |
| 816 |
| 817 // The renderer can exit view source mode when any error or cancellation |
| 818 // happen. We must overwrite to recover the mode. |
| 819 if (entry.IsViewSourceMode()) { |
| 820 render_view_host_->Send( |
| 821 new ViewMsg_EnableViewSourceMode(render_view_host_->GetRoutingID())); |
| 822 } |
| 834 } | 823 } |
| 835 | 824 |
| 836 // Otherwise the same SiteInstance can be used. Navigate render_view_host_. | 825 // Same SiteInstance can be used. Navigate render_view_host_ if we are not |
| 826 // cross navigating. |
| 837 DCHECK(!cross_navigation_pending_); | 827 DCHECK(!cross_navigation_pending_); |
| 838 if (ShouldReuseWebUI(curr_entry, &entry)) { | |
| 839 pending_web_ui_.reset(); | |
| 840 pending_and_current_web_ui_ = web_ui_->AsWeakPtr(); | |
| 841 } else { | |
| 842 pending_and_current_web_ui_.reset(); | |
| 843 pending_web_ui_.reset( | |
| 844 delegate_->CreateWebUIForRenderManager(entry.GetURL())); | |
| 845 } | |
| 846 | |
| 847 if (pending_web_ui() && render_view_host_->IsRenderViewLive()) | |
| 848 pending_web_ui()->GetController()->RenderViewReused(render_view_host_); | |
| 849 | |
| 850 // The renderer can exit view source mode when any error or cancellation | |
| 851 // happen. We must overwrite to recover the mode. | |
| 852 if (entry.IsViewSourceMode()) { | |
| 853 render_view_host_->Send( | |
| 854 new ViewMsg_EnableViewSourceMode(render_view_host_->GetRoutingID())); | |
| 855 } | |
| 856 | |
| 857 return render_view_host_; | 828 return render_view_host_; |
| 858 } | 829 } |
| 859 | 830 |
| 860 void RenderViewHostManager::CancelPending() { | 831 void RenderViewHostManager::CancelPending() { |
| 861 RenderViewHostImpl* pending_render_view_host = pending_render_view_host_; | 832 RenderViewHostImpl* pending_render_view_host = pending_render_view_host_; |
| 862 pending_render_view_host_ = NULL; | 833 pending_render_view_host_ = NULL; |
| 863 | 834 |
| 864 content::DevToolsManagerImpl::GetInstance()->OnCancelPendingNavigation( | 835 content::DevToolsManagerImpl::GetInstance()->OnCancelPendingNavigation( |
| 865 pending_render_view_host, | 836 pending_render_view_host, |
| 866 render_view_host_); | 837 render_view_host_); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 925 } | 896 } |
| 926 | 897 |
| 927 RenderViewHost* RenderViewHostManager::GetSwappedOutRenderViewHost( | 898 RenderViewHost* RenderViewHostManager::GetSwappedOutRenderViewHost( |
| 928 SiteInstance* instance) { | 899 SiteInstance* instance) { |
| 929 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); | 900 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); |
| 930 if (iter != swapped_out_hosts_.end()) | 901 if (iter != swapped_out_hosts_.end()) |
| 931 return iter->second; | 902 return iter->second; |
| 932 | 903 |
| 933 return NULL; | 904 return NULL; |
| 934 } | 905 } |
| OLD | NEW |